只要是对象就有原型, 并且原型也是对象, 因此只要定义了一个对象, 那么就可以找到他的原型, 如此反复, 就可以构成一个对象的序列, 这个结构就被成为原型链
JS中原型链,说简单也简单。
首先明确: 函数(Function)才有prototype属性,对象(除Object)拥有__proto__。
首先,我画了一张图。
所谓原型链,指的就是图中的proto这一条指针链!
原型链的顶层就是Object.prototype,而这个对象的是没有原型对象的。
可在chrome的控制台里面输入:
Object.__proto__
输出是:
function Empty() {}
原型链,如此而已。
一、prototype和__proto__的区别
var a = {};
console.log(a.prototype); //undefined
console.log(a.__proto__); //Object {}
var b = function(){}
console.log(b.prototype); //b {}
console.log(b.__proto__); //function() {}
/*1、字面量方式*/
var a = {};
console.log(a.__proto__); //Object {}
console.log(a.__proto__ === a.constructor.prototype); //true
/*2、构造器方式*/
var A = function(){};
var a = new A();
console.log(a.__proto__); //A {}
console.log(a.__proto__ === a.constructor.prototype); //true
/*3、Object.create()方式*/
var a1 = {a:1}
var a2 = Object.create(a1);
console.log(a2.__proto__); //Object {a: 1}
console.log(a.__proto__ === a.constructor.prototype); //false(此处即为图1中的例外情况)
var A = function(){}; var a = new A(); console.log(a.__proto__); //A {}(即构造器function A 的原型对象) console.log(a.__proto__.__proto__); //Object {}(即构造器function Object 的原型对象) console.log(a.__proto__.__proto__.__proto__); //null
prototype
VS __proto__
清楚了上面的概念之后再来看prototype
:
Each function has two properties:
length
andprototype
prototype
和length
是每一个函数类型自带的两个属性,而其它非函数类型并没有(开头的例子已经说明),这一点之所以比较容易被忽略或误解,是因为所有类型的构造函数本身也是函数,所以它们自带了prototype
属性:
1 2 3 4 |
|
除了prototype
之外,Js中的所有对象(undefined
、null
等特殊情况除外)都有一个内置的[[Prototype]]
属性,指向它“父类”的prototype
,这个内置属性在ECMA标准中并没有给出明确的获取方式,但是许多Js的实现(如Node、大部分浏览器等)都提供了一个__proto__
属性来指代这一[[Prototype]]
,我们通过下面的例子来说明实例中的__proto__
是如何指向构造函数的prototype
的:
1 2 3 4 5 6 7 8 9 10 11 |
|
上面的代码示例可以用下图解释:
Person
是一个函数类型的变量,因此自带了prototype
属性,prototype
属性中的constructor
又指向Person
本身;通过new
关键字生成的Person
类的实例p1
,通过__proto__
属性指向了Person
的原型。这里的__proto__
只是为了说明实例p1
在内部实现的时候与父类之间存在的关联(指向父类的原型),在实际操作过程中实例可以直接通过.
获取父类原型中的属性,从而实现了继承的功能。
原文:https://www.cnblogs.com/libin-1/p/5820550.htm