美文网首页
2018-04-27 360总结

2018-04-27 360总结

作者: 范晓坤 | 来源:发表于2018-05-08 17:41 被阅读0次

    因为我没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>
    

    相关文章

      网友评论

          本文标题:2018-04-27 360总结

          本文链接:https://www.haomeiwen.com/subject/kktvrftx.html