到底JavaScript原型以及原型链是什么?

原型是JavaScript这门语言最重要的部分之一 ,理解原型以及原型机制对于学习这门语言来说事半功倍。这篇博客帮助你理解。

构造函数与实例

    Person.prototype.lastName = 'chen';
    function Person(){
        firstName = 'Joe';
    }
    var person = new Person();
    console.log(person.lastName); 
    //output:'chen';   

 prototype

在JS中,每个函数上面会有一个属性叫 "prototype" ,它指向了一个名为原型对象的对象,这个对象为由函数创建的实例提供了一个原型模板,也就是说这个对象是实例的 原型 实例会继承原型对象的属性和方法,原型对象包含两个属性,一个是 "consturctor",它会指向这个函数,是函数默认取得的属性,至于为什么要指向这个函数,下文有提到,其他的属性都是继承自Object。

consturctor

prototype上面的属性"constructor" 指向函数本身,但是它的作用其实是为实例指明自己的构造函数是谁(个人认为),当实例访问属性contructor时,其实实例是没有这个属性的,找不到就会去实例原型里也就是prototype指向的对象里找,而这个原型对象里的contructor指向的是构造函数,在原型链中constructor属性不一定真正的能代表构造函数,这一点要注意。

    console.log(Person.prototype.constructor==Person);
    //true

    console.log(person.constructor==Person)
    //true

__proto__

当用new运算符来调用构造函数来构造出一个实例后,实例会有一个属性__proto__它指向了构造函数的原型对象,《JavaScript高级程序设计》里面有这样一段话描写这个属性

        ECMA-262第五版中管这个指针叫[[ Prototype ]],虽然在脚本中没有标准的方式访问[[ Prototype ]],但Firefox,Safari,Chrome           在每一个对象上都支持一个属性__proto__;而在其他实现中,这个属性对脚本则是完全不可见的。

意思是JS中每个对象都会有一个__proto__属性,但是在不同的浏览器上面存在不同的实现方式,貌似最新版本的IE11也实现了对它的访问,

    console.log(Person.prototype.__proto__ == Object.prototype)
    //output:true

原型链

我们说到prototype是一个对象,那么它会不会有一个__proto__属性,指向它的构造函数的原型对象呢?答案是肯定的。它指向的是Object的原型对象Object.prototype,而这个原型对象的__proto__指向的是 null ,这就是personF的原型链的尽头。

    console.log(Object.prototype.__proto__== null);
    //output:true

值得注意的是在上面的例子中函数也是有一个__proto__属性的,它指向的是Function.prototype。Person.__proto__要和Person.prototype.__proto__区分开来前者指向的函数的原型,后者指向的是函数原型的原型。

 

Object上面也有__proto__属性,它指向的是Function.prototype。最为难以理解的地方来咯,下图为Function和Object之间的关系,三条红色虚线最为难以理解,下面我阐述一下我个人的理解,仅代表我个人观点,因为我是一个初学者。。。。 

第一条红色的虚线标识Functionprototype__proto__指向同一个地方,这样做,我认为是因为Function已经是顶级的构造器的,顶级的构造师哪里需要什么参考原型。

    console.log(Function.prototype == Function.__proto__);
    //output:true

第二条红色虚线标识Function.prototype指向Object.prototype,这样做,是要符合所有对象的原型都是Object的原则,从名字上来看也可以知道"Object"应该是所有对象的祖先,也包括Function.prototype这个原型对象。

   
    console.log(Function.prototype.__proto__ == Object.prototype)
    //output:true

第三条红色虚线也是讲的这个道理,Object.prototype是所有对象的祖先,它是不需要有原型的,所有对象的对象都会继承object.prototype的属性和方法。

     console.log(Object.prototype.__proto__);
    //output:null

hasOwnProperty()和"in"

对象会从原型链上继承属性,判断属性是存在与实例上,还是原型链上,用hasOwnProperty()方法。'in'运算符则会判断属性是否可以访问,无论是在实例上还是在原型链上,

    console.log(person.hasOwnProperty("firstName"));
    //true
    console.log(person.hasOwnProperty("lastName"));
    //false

    console.log("firstName" in person);
    //true
    console.log("lastName" in person);
    //true

参考,掘金冴羽大佬的深入JS系列,红宝书,知乎藕粉海大佬的深入原型。

//欢迎在评论区留言讨论。

 

 

 

猜你喜欢

转载自blog.csdn.net/qq_41995398/article/details/103949004