JS原型链来龙去脉

25 阅读2分钟

首先说明__proto__和prototype的区别:

1) __proto__指的是对象的[[prototype]]属性,只不过在主流浏览器都实现了非Javascript标准的__proto__来访问对象的[[prototype]]属性,现在比较推荐使用Object.getPrototype() 和 Object.setPrototype()来访问和设置对象的[[prototype]]属性;每个对象都有__proto__属性,它指向该对象继承的原型对象;

2)prototype:他是函数才拥有的属性,代表该函数的原型对象(指函数自身,不是他继承的原型);

1.构造函数指向

实例可以通过.constructor属性找到自己的构造器

// 构造函数
function Person(){}
// 通过构造函数创建 实例
var p1 = new Person();

// 实例可以通过constructor找到构造器
console.log('实例的constructor是否是Person',p1.constructor === Person) //true

// 实例通过 隐式的 __proto__找到原型,获取共享的数据
console.log('实例或原型上','constructor' in p1); // true
console.log('实例上',p1.hasOwnProperty('constructor')); // false
console.log(p1.__proto__ === Person.prototype) //true

构造函数指向关系见下图: 01_构造函数指向.png

2. Object(既可以是对象也可以是函数)的原型链

万物皆对象,所有实例都可以找到对象层面,而对象的Object.prototype.__proto__也就是原型链的终点,值是null

function Object(){}
var obj = new Object();
             // 隐式原型         显式原型
console.log(obj.__proto__ === Object.prototype)

// 对象.__proto__ 
// 方法.prototype                      // 原型向上查找
console.log(Object.prototype === Person.prototype.__proto__);

// 原型链的终点
console.log(Object.prototype.__proto__) // null

02_关于Object.png

3.Function 的原型链

当Object作为一个函数时,Function是原型链的又一个顶端,但是Function().constructor可以无限的指向Function自身

var f1 = new Function();

console.log('函数对象', f1); // 函数对象 ƒ anonymous() {}
console.log('原型', f1.__proto__); // 原型 ƒ () { [native code] }

console.log(Function.prototype.__proto__ === Object.prototype) // true,这里说明函数最后也指向了对象

// Function 和 Person在原型上的关系,与Object.prototype是一致的

// 把Object当作一个函数来看,那么和Function又会有什么关系
// new Object(); // 是不是一个方法?
console.log(Object.constructor, Object.prototype.constructor)// ƒ Function() { [native code] } ƒ Object() { [native code] }

console.log('Function.constructor:', Function.constructor === Function); // Function.constructor: true

03_关于Function(最难).png

4. 最后,放一张总体原型链图

04_总体原型链.png