原型规则和原型链

203 阅读2分钟

原型规则

  1. 所有的引用类型(数组、对象、函数),都具有对象特性,即可自由扩展属性(除了 “null”  除外)
  2. 所有的引用类型(数组、对象、函数),都有一个 __proto__ 属性,属性值是一个普通的对象
  3. 所有的函数,都有一个 prototype 属性,属性值也是一个普通的对象
  4. 所有的引用类型(数组、对象、函数),__proto__ 属性值指向它的构造函数的 “prototype” 属性值
  5. 当试图得到一个对象的某个属性时,如果这个对象本身没有这个属性,那么会去它的__proto__(即它的构造函数的 prototype )中寻找

__proto__ 和 prototype 的区别

由上面的规则我们便可知道,__proto__ 是每个对象(数组、对象、函数)都具有的属性,而prototype 是只有函数才有的属性

对象具有属性 __proto__,可称为隐式原型,一个对象的隐式原型指向构造该对象的构造函数的原型,这也保证了实例能够访问在构造函数原型中定义的属性和方法

示例

var obj = {}; obj.a = 10;
var arr = []; arr.a = 10;
function fn() {}; fn.a = 10;

console.log(obj.__proto__ === Object.prototype)  //true
console.log(arr.__proto__ === Array.prototype)   //true
console.log(fn.__proto__ === Function.prototype) //true

示例分析

obj 是构造函数 Object 的实例对象,故实例对象 obj 的隐式原型 __proto__ 指向其构造函数Object 的 prototype 属性,obj 可以访问 Object 原型中定义的属性和方法

arr和fn分析同上


原型链

示例

//构造函数
function Foo(name) {
    this.name = name
}
var f = new Foo('xiaoming')

分析

如上示例中,f是构造函数Foo的实例对象,故有

f的属性 __proto__ 指向 Foo 的属性 prototype,Foo 是引用类型,具有 __proto__ 属性,这里的属性 __proto__ 指向它的构造函数 Function 的 prototype

Function 的构造函数是它本身,但引用类型的 prototype 值是对象,所以Function.prototype 有 __proto__ 属性,Function.prototype.__proto__ 指向Object.prototype,最后,Object.prototype 的 __proto__ 属性指向null。

Foo.prototype 值的属性是对象,所以也有 Foo.prototype.__proto__ 指向 Object.prototype

所以有如下原型链