一张图让你理清javascript中__proto__, prototype, 以及constructor之间的关系
如下图所示
画的有点不太好看, 但是关系还是很清楚的

此处有一点需要注意: Foo.prototype默认有一个公有并且不可枚举的属性.constructor, 这个属性引用的是对象关联的函数. 例如上图的例子f1 = new Foo(), 虽然f1.constructor确实指向Foo函数, 但是这个属性并不是表示f1由Foo“构造”.
看起来f1.constructor === Foo为真意味着f1确实有一个指向Foo的.constructor属性, 但事实不是这样.
这是一个很不幸的误解. 实际上, .constructor引用同样被委托给了Foo.prototype, 而Foo.prototype.constructor默认指向Foo.
把.constructor属性指向Foo看作是f1对象由Foo构造非常容易理解, 但这只不过是一种虚假的安全感. f1.constructor只是通过默认的[[Prototype]]委托指向Foo, 这和构造毫无关系, 相反, 对于.constructor的错误理解很容易对你自己产生误导.
举例来说, Foo.prototype的.constructor属性只是Foo函数在声明时的默认属性. 如果你创建了一个新对象并替换了函数默认的.prototype对象引用, 那么新对象并不会自动获得.constructor属性.
那么我们怎么判断原型呢
1. ES3 isPrototypeOf()
isPrototypeOf() 方法用于测试一个对象是否存在于另一个对象的原型链上。
// 例子
function Foo() {}
function Bar() {}
function Baz() {}
Bar.prototype = Object.create(Foo.prototype);
Baz.prototype = Object.create(Bar.prototype);
var baz = new Baz();
console.log(Baz.prototype.isPrototypeOf(baz)); // true
console.log(Bar.prototype.isPrototypeOf(baz)); // true bar是baz的原型吗? 是就返回true
console.log(Foo.prototype.isPrototypeOf(baz)); // true
console.log(Object.prototype.isPrototypeOf(baz)); // true
2. ES5 Object.getPrototypeOf()
Object.getPrototypeOf() 方法返回指定对象的原型(内部[[Prototype]]属性的值)
// 例
var proto = {};
var obj = Object.create(proto);
Object.getPrototypeOf(obj) === proto; // true
var reg = /a/;
Object.getPrototypeOf(reg) === RegExp.prototype; // true
// 这里再注意一下
Object.getPrototypeOf(Object) === Function.prototype; // true
3. ES6 __proto__
ES6规范更加直接,为对象添加了一个__proto__属性,通过这个属性就可以获得对象的原型,所以在支持__proto__的浏览器中,o.__proto__ === Object.prototype也会返回true。
更多推荐

所有评论(0)