javascript原型与原型链

121 阅读2分钟

1. 什么是原型

在javascript中,原型是一个prototype对象,表示类型之间的关系。
其用途是为每个实例对象添加或者公有的属性和方法,它只是一个普通对象

在javascript中,每个对象都有prototype属性,可以看到如下数组对象

image.png

在这个例子中可以看到 array 对象的原型,其内容包括数组的所有属性和方法,如:pop、push、length等。

2.什么是原型链

Javascript中,有句话叫万物皆对象。当然null和undefinde就不是对象,除了这两个其他都是对象。
而对象与对象之间都有其联系,并不是孤立存在的。
对象之间的继承关系,在javascript是通过prototype对象指向父类对象,直到指向了Object为止,这种关系就叫做原型链。

在下面例子中,创建了一个名"myObj"的构造函数,且在这个构造函数的原型中新增了一个方法 并且有两个test对象分别是 test1和test2,是myObj构造函数创建出来的

    let myObj = function(name){
        this.name = name
    }
    myObj.prototype.getName = function(){
        return this.name
    }
    let test1 = new myObj('ywpb')
    let test2 = new myObj('juejin')
    
    myObj.prototype === test1.__proto__  //true
    myObj.prototype === test2.__proto__  //true
    
    typeof myObj.prototype === 'object'   //true

image.png

可以看到,在这个例子中,test1和test2实例都继承了myObj的原型,都有一个自定义的原型对象方法 getName()

总结: 构造函数的prototype属性值就是对象的原型
构造函数的prototype属性类型是 object类型 (typeof myObj.prototype === 'object') 对象的原型链终点为null (Object.prototype.__proto__ === null) 对象的__proto__的属性值就是对象的原型(Object.prototype === test1.__proto__)

3.[[prototype]]

在上面的例子中每个对象都有一个特殊的[[prototype]]的内置属性,这个内置属性其实就是对其他对象的引用
但是它的工作方式或者说这个[[prototype]]引用有什么用呢?

    let myObject = {
        a:2
     }
     myObject.a   //2

在上面这个例子中,创建一个myObject对象,设置对象的属性,并且对属性进行引用 在对象中,当试图引用一个属性,都会触发一个[[Get]]操作。 比如myObject.a,对于javascript中对象的[[Get]]默认方法的第一步是检查自身有没有这个属性,如果有就使用

    let newObj = {
      a:2
    }
    
    //让myObj关联到newObj对象
    let myObj = Object.create(newObj)
    myObj.a   //2
      

image.png

在这个新例子中,创建了一个名为newObj的对象,并让myObj关联到newObj对象上。 在myObj对象中,尽管属性a并不存在,但是还是成功返回了a的值。

这是因为对于[[Get]]来说,当对象自身不存在属性并且[[prototype]]原型链不为空时,会继续查找下去,知道找到这个被引用的属性,或者没有找到这个属性同时返回undefinde