美文网首页技术知识饥人谷技术博客
日夜谈——this 原型链 与 继承

日夜谈——this 原型链 与 继承

作者: Sheldon_Yee | 来源:发表于2017-02-10 14:24 被阅读26次

    Part1:this

    1.apply、call 有什么作用,什么区别

    apply和call的作用是给function函数去指定this和参数;

    apply语法:func.apply(thisValue, [arg1, arg2, ...]);
    
    call语法:func.call(thisValue, arg1, arg2, ...)
    
    this.value
    在func运行时指定的this值。需要注意的是,指定的 this 值并不一定是该函数执行时真正的 this 值
    ,如果这个函数处于非严格模式下,则指定为 null 或 undefined 时会自动指向全局对象(浏览器中就是window对象),
    同时值为原始值(数字,字符串,布尔值)的 this 会指向该原始值的自动包装对象。
    

    apply和call的区别:
    apply函数的语法与call的语法几乎完全相同,唯一的区别在于,call方法接受的是一个参数列表,而apply方法接受的是一个包含多个参数的数组(或类数组对象)

    2. 以下代码输出什么?
    var john = { 
      firstName: "John" 
    }
    function func() { 
      alert(this.firstName + ": hi!")
    }
    john.sayHi = func
    john.sayHi()           
    //输出John: hi! 
    this指向对象john
    
    3.下面代码输出什么,为什么
    func() 
    function func() { 
      alert(this)
    }
    输出为[Object window],.//因为func函数在全局对象中运行
    
    4.下面代码输出什么
    document.addEventListener('click', function(e){
        console.log(this);//document,在事件处理程序中,this代表事件源的DOM对象
        setTimeout(function(){
            console.log(this);//window ,setTimeout和setInterval这两个方法执行
    的函数指向全局对象
        }, 200);
    }, false);
    
    5.下面代码输出什么,why
    var john = { 
      firstName: "John" 
    }
    
    function func() { 
      alert( this.firstName )
    }
    func.call(john)
    输出:Jhon,因为使用call这个方法将func的this绑定在john这个对象上
    
    6.以下代码有什么问题,如何修改
    var module= {
      bind: function(){
        $btn.on('click', function(){
          console.log(this) //this指$btn这个DOM对象,因此此时的this不在指向module,所有找不到
    showMsg这个方法
          this.showMsg();
        })
      },  
      showMsg: function(){
        console.log('饥人谷');
      }
    }
    -----------------------------------------------------
    修改:
    var module= {
      bind: function(){
       var _this = this;
        $btn.on('click', function(){
          console.log(this) //$btn
          _this.showMsg();
        })
      },  
      showMsg: function(){
        console.log('饥人谷');
      }
    }
    

    Part2:原型链

    7.有如下代码,解释Person、 prototype、proto、p、constructor之间的关联。
    function Person(name){
        this.name = name;
    }
    Person.prototype.sayName = function(){
        console.log('My name is :' + this.name);
    }
    var p = new Person("若愚")
    p.sayName();
    
    1. Person是一个构造函数,也是一个 对象,这个对象里存在一个prototype属性,而构造函数内部定义了一些属性和方法,这些属性和方法是属于该类的所有实例的特征;

    2. prototype是一个构造函数的原型对象,其拥有constructor和proto属性,而constructor这个属性是指向构造函数Person,而proto指向该对象的原型;

    3. p是通过构造函数Person构造出来的实例,也是拥有proto属性。所以p.proto === Person.prototype;

    8.上例中,对对象 p可以这样调用 p.toString()。toString是哪里来的? 画出原型图?并解释什么是原型链。

    p调用toString()时,首先会从自己查看toString()这个方法,如果没有则会沿着proto这个属性进入Person的prototype里面查看,如果还是没有找到toString()这个方法,会沿着prototype.proto的属性去到Object的prototype里查看,最后找到toString(),然后调用。

    原型链:由于原型对象本身也是对象,而每个javascript对象都有一个原型对象,每个对象都有一个隐藏的proto属性,原型对象也有自己的原型,而它自己的原型对象又可以有自己的原型,这样就组成了一条链,这个就是原型链。在访问对象的属性时,如果在对象本身中没有找到,则会去原型链中查找,如果找到,直接返回值,如果整个链都遍历且没有找到属性,则返回undefined。原型链一般实现为一个链表,这样就可以按照一定的顺序来查找。

    img1.png
    9.对String做扩展,实现如下方式获取字符串中频率最高的字符
        String.prototype.getMostOften = function(){
            var obj = {},
                most = 0,
                which; 
            for(var i=0 ,str; i<this.length;i++){
                str = this[i];
                if(obj[str]){
                    obj[str] += 1;
                }else{
                    obj[str] = 1;
                }
            }
            for(var key in obj){
                if(obj[key] > most){
                    most = obj[key];
                    which = key;
                }
            }
            return which;
        }
    var str = 'ahbbccdeddddfg';
    var ch = str.getMostOften();
    console.log(ch); //d , 因为d 出现了5次
    
    10. instanceOf有什么作用?内部逻辑是如何实现的?

    instanceOf的作用是用来判断对象是否是另一个的对象的实例,并返回布尔值。

    Object.prototype.instaceOf = function(obj1,obj2){
            var obj1 = obj1.__proto__;
            while(obj1.__proto__){
              if(obj1 === obj2.prototype){
                       return true;
              }else{
                  obj1 = obj1.__proto__;
                 }
                    return false;
            }
    
    11.继承有什么作用?
    1. 可以使子类共享父类的属性和方法;
    2. 可以覆盖和扩展父类的属性和方法。
    12.下面两种写法有什么区别?
    //方法1
    function People(name, sex){
        this.name = name;
        this.sex = sex;
        this.printName = function(){
            console.log(this.name);
        }
    }
    var p1 = new People('饥人谷', 2)
    
    //方法2
    function Person(name, sex){
        this.name = name;
        this.sex = sex;
    }
    
    Person.prototype.printName = function(){
        console.log(this.name);
    }
    var p1 = new Person('若愚', 27);
    

    区别:
    方法一将printName方法定义在构造函数People内,如果构建的对象比较多,代码就会很多,对性能造成负面影响;
    方法二将printNmae方法定义在Person的原型对象内,这样构建出来的对象,即使内部没有定义,还是能够通过原型链得到此方法,节约了内存。这种方法比较先进。

    13.Object.create 有什么作用?兼容性如何?

    Object.create() 方法创建一个拥有指定原型和若干个指定属性的对象。Object.create是在ES5中规定的,IE9以下无效。

    14 hasOwnProperty有什么作用? 如何使用?

    hasOwnPerpertyObject.prototype的一个方法,可以判断一个对象是否包含自定义属性而不是原型链上的属性,hasOwnProperty是JavaScript中唯一一个处理属性但是不查找原型链的函数。
    用法

    obj.hasOwnPerperty('key') // true or false;
    ex:
    Person.hasOwnPerperty('name')//true;
    
    15.如下代码中call的作用是什么?
    function Person(name, sex){
        this.name = name;
        this.sex = sex;
    }
    function Male(name, sex, age){
        Person.call(this, name, sex);    ////调用Person函数,使Male函数能够执行Person上的初始化代码,实现构造函数继承,
    并且使Person执行时的this指向Male;
        this.age = age;
    }
    
    16.补全代码,实现继承
            function Person(name, sex){
                this.name = name;
                this.sex = sex;
            }
    
            Person.prototype.printName = function(){
                console.log(this.name);
            };    
    
            function Male(name, sex, age){
               Person.apply(this,[name,sex]);
               this.age = age;
            }
    
            Male.prototype = Object.create(Person.prototype) ;
    
            Male.prototype.constructor = Male;
    
            Male.prototype.getAge = function(){
                console.log(this.age);
            };
    
            var ruoyu = new Male('若愚', '男', 27);
            ruoyu.printName();
    

    感谢瓜子观众!!!-。-

    福利福利

    相关文章

      网友评论

        本文标题:日夜谈——this 原型链 与 继承

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