原型、原型链的理解

332 阅读2分钟

JS中原型和原型链的几个要点

先理解以下几个要点:

  • 所有的引用类型(数组、对象、函数)都可以进行自由扩展(除null外)。
  • 所有的引用类型都有一个_proto_属性(隐式原型,是一个指针,指向一个普通的对象)。
  • 所有的函数都有一个prototype属性(显式原型,是一个指针,指向一个普通对象)。
  • 所有引用类型,它的_proto_属性指向它的构造函数的prototype属性。
  • 当试图得到一个对象的属性时,如果这个对象本身不存在这个属性,那么它就会去_proto_属性(他构造函数的prototype属性)中去寻找。

JS中的原型

例子

 function Person(name,age){
    this.name = name;
    this.age = age;
 }
 Person.prototype = {
     showName: function(){
         console.log("I'm"+this.name);
     },
     showAge: function(){
         console.log("And I'm"+this.age);
     }
 }
 
 var person = new Person('小明',19);
 person.showName();// I'm 小明
 person.showAge();// And I'm 19

通过上面的例子可以看出构造函数 Person 和实例对象 person

  • prototype
    每个函数都有protype属性,每一个javascript对象(null除外) 在创建的时候都会与之 关联另一个对象,这个对象就是我们所说的原型,每一个对象都会从原型“继承”属性。

8711acaf6d28b623a5668c6abe3114ba.png

  • __proto__
    每一个javascript对象(null除外)都有__proto__属性,这个属性会指向该对象的原型

6adff0dcd6657f623e1f7d5d0f5c847c.png

也就是说 person.__proto__ === Person.prototype

  • constructor
    每个原型都有一个constructor属性指向关联的构造函数 原型指向构造函数 即Person === Person.prototype.constructor

image.png

JS中的原型链

原型链的概念,有点类似作用域链,就是把原型连成一条链。js每一次获取对象的属性都是一次查询过程,如果在自有的属性中找不到就会去原型对象中去查找,如果原型对象中还找不到,就去原型对象的原型去查找,直到找到原型链的顶端。 我们看个例子:

    function Foo(name,age){
        this.name = name;
        this.age = age;
    }
    Object.prototype.toString = function(){
        console.log("I'm " + this.name + " And I'm " + this.age);
    }
    var fn = new Foo('小明'19);
   fn.toString(); //I'm 小明 And I'm 19

通过下面的图来看: image.png

fn的构造函数是Foo(),所以
fn.__proto__ === Foo.prototype
Foo.prototype.__proto__ === object.prototype
通过上述代码,我们知道toString()这个方法在Object.prototype里面,当调用这个对象的本身不存在该方法时,就会有一层一层的往上找,一直找到null为止。