原型及原型链

什么是原型

js中的原型指的是一个对象可以从另一个对象继承特性。每个对象都有一个原型对象,对象以其原型对象为模板,继承其属性,方法。原型对象也有自己的原型对象,这样一层一层,通常称为原型链。

准确来说,这些属性和方法,定义在对象的构造函数(constructor functions)之上的prototype属性上面,而不是对象实例本身。

js中链接对象实例和原型的是_proto_,它是从构造函数的prototype派生的,之后上溯到原型链,在构造器中找到这些属性和方法。

js中不是所有的对象都可以作为原型对象,每个对象都是继承自Object,但是我们主动设置一个对象的原型为另一个对象。

prototype属性

继承的属性和方法被定义在prototype属性上,prototype属性的值是一个对象。

constructor属性

每个实例对象都从原型中继承了一个constructor属性,该属性指向了用于构造此实例对象的构造函数。


构造函数,原型,实例之间的关系


下面我们将通过一些例子来看一下

    //构造函数1
    function Person( name,age ){
      this.name = name;
      this.age = age;
    };
    //构造函数2
    function Test (){

    }
    //实例1
    var person1 = new Person("小明", 21);
    //原型链为: person1 ====> Person  ====> Object ====> null

    console.log(person1.constructor);
    /*output:
    person1.constructor指向构造函数Person
    ƒ Person(name, age) {
      this.name = name;
      this.age = age;
    }
    */
    console.log(person1.__proto__);
    console.log(Person.prototype);
    /*output:
    {
      constructor: ƒ Person(name, age)
      __proto__: Object
    }
     */
    console.log(person1.__proto__ === Person.prototype); //true
  
    //实例2;
    var person2 = new Test();
    //把实例person1作为person2的原型
    person2.__proto__ = person1;
    //原型链为: person2 ====> person1 ===> Person ===> Object ====>null
    console.log(person2.name) //小明,继承自person1
    console.log(person2.constructor);
    /*output:
    ƒ Person(name, age) {
      this.name = name;
      this.age = age;
    }
    */
    console.log(person2.__proto__);
    /*output:
    {
    Person 
      age: 21
      name: "小明"
      __proto__:
      {
      constructor: ƒ Person(name, age)
      __proto__: Object
      }
    }
     */
    console.log(person2.__proto__.__proto__ === Person.prototype); //true

    //实例3
    //create() 实际做的是从指定原型对象创建一个新的对象。这里以 person1 为原型对象创建了 person3 对象。
    var person3 = Object.create(person1);
    //原型链为: person3 ====> person1 ===> Person ===> Object ====>null

    console.log(person3.__proto__);
    /*output:
    {
    Person 
      age: 21
      name: "小明"
      __proto__:
      {
      constructor: ƒ Person(name, age)
      __proto__: Object
      }
    }
     */

不改变对象的原型链继承另一个对象的方法

    //构造函数1
    function Person( name,age ){
      this.name = name;
      this.age = age;
    };
    //构造函数2
    function Test (){

    }

    //方法一:
    var person4 = new Test();
    //用call或者apply来改变this,在person4的作用域里面去执行Person
    //Person.call(person4);
    Person.apply(person4);
    console.log(person4.__proto__);
    /*
    constructor: ƒ Test()
    __proto__: Object
    */

  //方法二: 可以直接在构造函数里面使用apply或者call
  //比如:
  function Test (){
    Person.call(this);
  }


四个拓展原型链的方法

https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Inheritance_and_the_prototype_chain#%E6%80%BB%E7%BB%93%EF%BC%9A4_%E4%B8%AA%E7%94%A8%E4%BA%8E%E6%8B%93%E5%B1%95%E5%8E%9F%E5%9E%8B%E9%93%BE%E7%9A%84%E6%96%B9%E6%B3%95


new操作符做了什么事情

//new 的过程
var obj = new Object(); //创建一个新对象
obj.__proto__ = A.prototype;  //让obj的__proto__指向A.prototype
A.call(obj)   //在obj的作用环境执行构造函数的代码,使this指向obj
return obj    //返回实例对象
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容