美文网首页让前端飞Web前端之路
浅析JavaScript中的原型链与继承

浅析JavaScript中的原型链与继承

作者: cce117b0a0ce | 来源:发表于2018-01-26 20:02 被阅读16次

    在JavaScript中,ES6之前不存在class,所以JavaScript的继承是基于原型链实现的。每一个实例的 __proto__ 都指向自己构造函数的prototype 属性。MDN上这样解释:

    当谈到继承时,JavaScript只有一种结构:对象。每个对象都有一个私有属性(称之为 [[Prototype]]),它持有一个连接到另一个称为其 prototype 对象(原型对象)的链接。该 prototype 对象又具有一个自己的原型,层层向上直到一个对象的原型为 null

    构造函数与实例

    function Person() {
    
    }
    
    let person = new Person();
    person.__proto__ == Person.prototype; // true
    Person.__proto__.constructor == Person; // true;
    

    在上面代码中,Person为构造函数,person 为构造函数的一个实例对象,person.prpto 指向了Person.prototype 属性。

    当读取实例属性的时候,如果找不到,就会查找原型中的属性(即person.__proto__ ),也就是在Person.prototype中去查找。如果还找不到就去查找原型的原型(即Person.prototype.__proto__),而它又是什么呢?因为原型也是一个对象,typeof(Person.prototype) == Object,所以Person.prototype.__proto__ == Object.prototype,如果此时还找不到,则去查找Object.prototype.__proto__,最终返回null。举个栗子:

    function Person() {
    
    }
    let person = new Person();
    person.name = 'black';
    console.log(person.name); //1. black
    
    // 此时删除person.name
    delete person.name;
    Person.prototype.name = '古月';
    console.log(person.name); // 2.古月
    
    // 此时删除Person.prototype.name
    delete Person.prototype.name;
    console.log(person.name); // 3.undefined
    
    1. person.name有值时,首先查找person.name ,查找成功。
    2. person.name 查找不到时,查找person.__proto__.name,也就是查找Person.prototype.name,查找成功。
    3. person.name 查找不到时,查找person.__proto__.name,也就是查找Person.prototype.name, 查找不到时,查找Person.prototype.__proto__,继续向上查找,查找到Object.prototype.name,查找失败,返回undefined

    通过原型模拟new的实现

    new作用:

    new 运算符创建一个自定义对象或具有构造函数的内置对象的实例。

    function Person(name) {
      this.name = name;
    }
    
    Person.prototype.sayHi = function() {
      console.log(`hi, I am ${this.name}`);
    }
    
    function _new(fn) {
      var obj = {}
      obj.__proto__ = fn.prototype;   
      fn.apply(obj, [].slice.call(arguments, 1));
      return obj;
    }
    
    let test = _new(Person, 'black')
    console.log(test.name);
    test.sayHi();
    
    let test2 = new Person('black')
    console.log(test2.name);
    test2.sayHi();
    
    1. 新建一个对象obj
    2. obj的原型指向构造函数
    3. 使用apply,改变构造函数this的指向到obj
    4. 返回obj

    相关文章

      网友评论

        本文标题:浅析JavaScript中的原型链与继承

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