首先说明__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
构造函数指向关系见下图:
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
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