因为我没Vue+Es6的经验,所以360问的比较基础。
1.由对象的拷贝引申到浅拷贝和深拷贝是如何实现的
除了基本类型跟null,对象之间的赋值,只是将地址指向同一个,而不是真正意义上的拷贝,被复制的对象改变值,另一个值会跟着改变。
要实现浅拷贝可以通过for in循环,例如:
var obj = {a:10};
function copy(obj){
var newobj = {};
for ( var attr in obj) {
newobj[attr] = obj[attr];
}
return newobj;
}
var obj2 = copy(obj);
obj2.a = 20;
alert(obj.a); //10
ES6的Object.assign()方法也是浅拷贝。
深拷贝实现方法(递归原理)
var obj ={a:{b:1}};
function deepCopy(obj){
if(typeof obj !=Object){
return obj;
}
var newObj={};
for(var arr in obj){
newObj[arr] = deepCopy(obj[arr]);
}
reurn newObj;
}
2.js实现继承有哪几种?
①原型链继承
function SuperType(){
this.property = true;
}
SuperType.prototype.getSuperValue = function(){
return this.property;
}
function SubType(){
this.property = false;
}
//继承了SuperType
SubType.prototype= new SuperType();
SubType.prototype.getSubValue = function(){
return this.subproperty;
};
var instance =new SubType();
console.log(instance.getSuperValue)//true
实现原型链继承的本质是:重写原型对象,代之以一个新类型的实例,换句话说原来存在于SuperType的实例中属性和方法也存在于SubType.prototype中了。此时instance.constructor指向SuperType.
确定原型和实例的关系
第一种使用instanceof操作符
alert(instance instanceof Object);//true
alert(instance instanceof SuperType);//true
alert(instance instanceof SubType);//true
instance本质:A instacne B就是判断B.prototype是否存在于A的原型链上。Object.getPrototypeOf(A) === B.prototype(即A.proto=== B.prototype);
第二种使用isPrototypeOf()方法,isPrototypeOf() 方法允许你检查一个对象是否存在于另一个对象的原型链上。
alert(Object.prototype.isPrototypeOf(instance));//true;
alert(SuperType.prototype.isPrototypeOf(instance));//true;
alert(SubType.prototype.isPrototypeOf(instance));//true;
原型链的问题
1.原型属性会被所有实例所共享,一个实例更改了原型属性,会导致所有实例引用的属性更改。
2.在创建子类型的实例时,不能向超类型的构造函数中传递参数。
②构造函数继承
即在子类型的构造函数中调用超类型的构造函数
function SuperType(){
this.colors =['red','blue','green'];
}
function SubType(){
//继承了SuperType
SuperType.call(this);
}
var instance1 = new SubType();
instance1.colors.push('black');
alert(instance.colors)//red,blue,green,black
var instance2 = new SubType();
alert(instance.colors)//red,blue,green
构造函数的问题
方法都在构造函数中定义,无法实现函数复用,而且在超类型中定义的方法,对于子类型是不可见的。
③组合继承
function SuperType(name){
this.name = name;
this.colors =['red','blue','green'];
};
SuperType.prototype.sayName = function(){
alert(this.name);
};
function SubType(name,age){
SuperType.call(this,name);
this.age = age;
}
//继承方法
SubType.prototype = new SuperType();
SubType.prototype.constructor = SubType;
SubType.prototype.sayAge = function(){
alert(this.age);
}
var instance1 = new SubType('Nicholas',29);
instance1.colors.push('black');
alert(instance1.colors)//red,blue,green,black
instance1.sayName();// 'Nicholas'
instance1.sayAge();//29
var instance2 = new SubType('Greg',27);
instance2.sayName();// 'Greg'
instance2.sayAge();//27
组合继承避免了原型链和借用构造函数的缺陷,成为JS最常用的继承模式
④原型式继承,借助原型基于已有的对象创建新对象
function object(o){
function F(){}
F.prototype = o;
return new F();
}
//例子
var person = {
name:'Nicholas',
friends:['Shelby','Court',''Van]
}
var anotherPerson = object(person);
anotherPerson.name = 'Greg';
anotherPerson.friends.push('Rob');
var yetAnotherPerson = object(person);
yetAnotherPerson .name = 'Linda';
yetAnotherPerson .friends.push('Barbie');
alert(person.friends);//'Shelly','Court','Van','Rob','Barbie'
通过例子可以看出,实例是共享person对象的。
ES5通过新增Object.create()方法规范了原型式继承。这个方法接受两个参数:一个用作新对象原型的对象(可选)一个为新对象定义额外属性的对象。在传入一个参数时,Object.create()和object()方法行为一致。
var person = {
name:'Nicholas',
friends:['Shelby','Court',''Van]
}
var anotherPerson = Object.create(person);
anotherPerson.name = 'Greg';
anotherPerson.friends.push('Rob');
var yetAnotherPerson = Object.create(person);
yetAnotherPerson .name = 'Linda';
yetAnotherPerson .friends.push('Barbie');
alert(person.friends);//'Shelly','Court','Van','Rob','Barbie'
当Object.create()传入两个参数时:
var person = {
name:'Nicholas',
friends:['Shelby','Court',''Van]
}
var anotherPerson = Object.create(person,{
name:{
value:'Greg'
}
})
alert(anotherPerson.name);//'Greg'
⑤寄生式继承
寄生式继承与原型式继承紧密相关。创建一个仅用于封装继承过程的函数,该函数内部以某种方式来增强对象,最后返回这个对象。
function createAnother(original){
var clone = object(original)//或者Object.create(original);
clone.sayHi = function(){
alert('Hi');
};
return clone;
}
var person = {
name:'Nicholas',
friends:['Shelly','Court','Van']
}
var anotherPerson = createAnother(person);
anotherPerson.sayHi();//Hi
在考虑对象不是自定义类型以及不是构造函数的情况下,寄生式继承是一种有用的模式。
寄生式继承的问题
不能做到函数复用而降低效率,与构造函数模式类似。
⑥寄生组合式继承
构造函数和原型链组合继承存在一个问题:调用两次构造函数,属性会同时存在实例和原型对象上。使用寄生和构造函数组合式继承可以解决这个问题。
function inheritPrototype(SubType,SuperType){
var prototype = object(SuperType.prototype);
prototype.constructor = SubType;
subType.prototype= prototype;
}
function SuperType(name){
this.name = name;
this.colors =['red','blue','green']
}
SuperType.prototype.sayName = function(){
alert(this.name)
}
function SubType(name,age){
SuperType.call(this,name);
this.age = age;
}
//关键代码
inheritPrototype(SubType,SuperType);
SubType.prototype.sayAge= function(){
alert(this.age);
}
2.数组的去重
①利用lastIndexOf,不借助对象
var arr1=[],arr=[1,2,2,2,3,4];
arr.filter(function(value,key){
if(arr.lastIndexOf(value) ==key){
return true;
}else{
return false;
}
})
②利用数组的sort和reduce方法
var arr=[1,2,1,2,3,3,4,4,5,6,7];
var nArr = arr.sort().reduce(function(initValue,current){
if(initValue[initValue.length-1]!==current){
initValue.push(current);
}
return initValue;
},[])
3.闭包题
function A(){
var i=0;
return function B(){
console.log(i++);
}
}
var a = A();
a();//0
a();//1
var b = A();
b();//0
b();//1
4.正则匹配电话号码
表示以1开头,第二位可能是3/4/5/7/8等的任意一个,在加上后面的\d表示数字[0-9]的9位,总共加起来11位结束。
/^1(3|4|5|7|8)\d{9}$/
5.js异步编程有哪些
ES 6以前:
- 回调函数
- 事件监听(事件发布/订阅)
- Promise对象
ES 6:
- Generator函数(协程coroutine)
ES 7:
- async和await
①回调函数
这个很熟悉了,暂不展开
②事件监听(观察者模式),解决模块间的信息通信
首先需要把观察者对象创建出来,他有一个消息容器和三个方法,分别是订阅消息方法,取消订阅消息方法、发布订阅消息方法。
//将观察者放在闭包中,当页面加载便立即执行
var Observer = (function(){
//防止消息队列暴露而被篡改故将消息容器作为静态私有变量保存
var _message ={};
return{
//注册消息接口
register:function(type,fn){
//如果消息不存在
if(typeof _message[type] ==='undefined'){
_message[type] =[];
}
_message[type].push(fn);
},
//发布消息接口
fire:function(type,args){
//如果消息没有被注册,则返回
if(!_message[type])
return;
//定义消息信息
var events ={
type:type,
args:args||[]
},
i=0,len = _message[type].length;
//遍历消息动作
for(;i<len;i++){
//依次执行注册的消息对应的队列
_message[type][i](events);
}
},
//移除信息接口
remove:function(type,fn){
//如果消息动作队列存在
if(_message[type] instanceof Array){
//从最后一个消息动作遍历
var i= _message[type].length-1;
for(;i>=0;i--){
_message[type][i] ===fn&&_message[type].splice(i,1);
}
}
}
}
})()
Observer.register('test',function(e){console.log(e.type,e.args.msg)});
Observer.fire('test',{msg:'chu'})
// test chu
③promise相关知识,由于这部分知识比较熟悉,暂不展开
④Generator 函数
http://es6.ruanyifeng.com/#docs/generator(Generator函数的具体讲解)
⑤ES 7中的async和await
6.getElementByClassName的兼容性问题(如何兼容IE8)
function getclass(classn) {//创建函数 传入形参
if(!document.getElementsByClassName) {//判断document.getElementsByClassName方法是否支持
var list = document.getElementsByTagName("*");//先取得所有的dom标签元素
// alert(list.length)
var temp = [];//创建临时数组
for(var i = 0; i < list.length; i++) {//循环每一个dom元素
if(list[i].className == classn) {//判断当前这个元素的class名称是否等于box
temp.push(list[i])//如果等于,将该元素添加到数组中去
}
}
return temp;//;返回给函数
}
else{
return document.getElementsByClassName(classn);
}
}
7.实现左右定宽,中间自适应的三栏布局
①利用绝对定位
//css
.left{
width: 100px;
background: red;
position: absolute;
top: 0;
bottom: 0;
left: 0;
}
.right{
width: 100px;
background: blue;
position: absolute;
top: 0;
bottom: 0;
right: 0;
}
.center{
background: green;
margin-left: 100px;
margin-right: 100px;
top: 0;
bottom:0;
}
//html
<div class="left">1</div>
<div class="center">2</div>
<div class="right">3</div>
②利用浮动,左边左浮动,右边右浮动
//css
.left{
float: left;
width: 100px;
background: red;
}
.right{
float: right;
width: 100px;
background: green;
}
//html(注意html的排列顺序,中间的元素放在了最后面)
<div class="left">1</div>
<div class="right">3</div>
<div class="center">2</div>
如果不使中间的元素放在最后面可为中间元素加上此样式
.center{
display:inline-block;
}
③使用弹性盒布局
//css
.main{
display: flex;
}
.left{
width: 100px;
background: red
}
.center{
flex:1;
}
.right{
width: 100px;
background: blue;
}
//html
<div class="main">
<div class="left">1</div>
<div class="center">2</div>
<div class="right">3</div>
</div>
网友评论