那些关于js原型继承中的prototype,__proto__,constructor属性

836 阅读4分钟

前言

原型和原型链是js中的重难点,你是否经常看见prototype__proto__constructor这三个搞怪的家伙,并对此有很多疑惑,今天我们就来搞定他们.

说明:__proto__是两边各有两个下划线构成,实际上,该属性在ES标准定义中的名字应该是[[Prototype]],谷歌浏览器的实现就是将[[Prototype]]命名为__proto__,所以大家不用担心他们是没有功能差异的.

原型

我们先来看一个原型的例子.

//创建一个构造函数
function Foo(name,age){  
        this.name = name;
        this.age = age;
}
//所有的函数都有一个'prototype'属性,这个属性也是一个对象
Foo.prototype={
    showName:function(){
    console.log(this.name);
    },
    showAge:function(){
    console.log(this.age);
    }
  }
var fn = new Foo('小华',20);
//当你想得到一个对象的属性时,如果这个对象本身不存在这个属性,那么就会到他构造函数的'prototype'属性中查找.
fn.showName();  //小华
fn.showAge();  // 20

以上代码表示创建一个构造函数Foo(),并用new关键字实例化该构造函数得到一个实例化对象fn. 虽然代码很简单,但在其背后的关系却很复杂.不着急,我们一个一个研究.

prototype 属性

2A212CD1E5EE204E718CCCD43C0BA666.png

定义

原型(prototype)是function对象的一个属性,它定义了[构造函数]构造出的对象的公共祖先。通过该构造函数产生的对象,可以继承该原型的属性和方法。

重点

  1. 首先我们必须知道,'prototype'属性是函数独有的!'prototype'属性是函数独有的!'prototype'属性是函数独有的!重要的事情说三遍.它是从一个函数指向一个对象
  2. 当代码读取某个对象的某个属性的时候,都会执行一遍搜索,目标是具有给定名字的属性,搜索首先从对象实例开始,如果在实例中找到该属性则返回,如果没有则查找prototype,如果还是没有找到则继续递归prototype的prototype对象,直到找到为止,如果递归到object仍然没有则返回错误。(向上查找
  3. 如果在实例中定义如prototype同名的属性或函数,则会覆盖prototype的属性或函数。

__proto__属性

777D1E4D104425D37E7F94B44E7BB9F9.png

定义

在官方的es5中,定义了一个名叫[[prototype]]的属性,每个对象都拥有这样一个属性,这个属性是一个指针,它指向一个名叫原型对象的内存堆。而原型对象也是对象,因此又含有自己的[[prototype]]的属性,又指向下一个原型对象。 那么终点是哪? 当然是我们的Object.prototype对象。

重点

  1. 上面我们得知'prototype'属性是函数独有的.,而__proto__属性是对象所独有的.(通过上面的代码段我们也知道,'prototypt'也是对象属性),所以它是由一个对象指向另一个对象.
  2. 从中我们可以引入原型链的解释:
    当fn调用showName()和showAge()时,JS发现fn中没有这个方法,于是它就去Foo.prototype中去找,找到了,就调用此方法;如果没找到,就继续向上查找Object.prototype,如果还没找到就继续向上...这就是原型链,fn能够调用Foo.prototype中的方法正是因为存在原型链的机制。

'constructor'属性

9FD539873A9A7366C97BCF3A012126E2.png

定义(重点)

'constructor'(构造器),也是对象才拥有的,它是从一个对象指向一个函数,含义就是指向该对象的构造函数.所有函数(此时看成对象了)最终的构造函数都指向Function。

总结

  1. null和undefined没有原型.
  2. 如果在实例中定义如prototype同名的属性或函数,则会覆盖prototype的属性或函数。
  3. 所有普通对象都有内置的Object.prototype属性,指向原型链的顶端,如果在原型链中找不到指定的属性就会停止.
  4. prototype是函数所独有,__proto__constructor是对象独有的.但是函数也是对象,所以函数拥有以上三个属性的特质.

引用

[js中的原型和原型链]((47条消息) JS中的原型和原型链(图解)_d_ph的博客-CSDN博客_js 原型链)