1 var obj1 = {
2 }
3
4 var obj2 = {
5 __proto__:obj1
6 }
7
8 var obj3 = {
9 __proto__:obj2
10 }
11
12 console.log(obj2.isPrototypeOf(obj3)); //true
13 console.log(obj1.isPrototypeOf(obj3)); //true
14 console.log(Object.prototype.isPrototypeOf(obj3)); //true
在 ES5 当中拥有标准方法 Object.getPrototypeOf() 可以供我们获得一个对象的原型,在ES6 当中拥有新的方法 Object.setPrototypeOf() 可以设置一个对象的原型,不过在使用之前请先查看浏览器兼容性。
1 var obj1 = {
2 x:1
3 }
4
5 var obj2 = {
6 y:2
7 }
8
9 Object.setPrototypeOf(obj2, obj1);
10
11 console.log(Object.getPrototypeOf(obj2) === obj1); //true
我们现在知道,通过 new 操作符创建的对象,其原型会关联到函数的 [[prototype]] 上面,实际上这是一个很糟糕的写法,一味的贴合面向对象风格的编程模式,使得很多人无法领域 JavaScript 当中的精髓。许多书籍都会写到 JavaScript 中有许多奇怪的地方,然后教你如何避开这些地雷,实际上这不是一个好的做法,并不是因为 JavaScript 是一门稀奇古怪的语言,而是我们不愿意去面对它的特性,正确的理解这些特性,才能让我们写出更加高效的程序。Object.create() 方法对于对象之间的关联和原型链的机制更加清晰,比 new 操作符更加能够理解 JavaScript 的继承机制。该方法创建一个新对象,并使新对象的原型关联到参数对象当中:
1 var obj1 = {
2 x:1
3 }
4
5 var obj2 = Object.create(obj1);
6
7 console.log(obj1.isPrototypeOf(obj2)); //true
不过使用的时候还需要注意浏览器的兼容性,下面给出 MDN 上面的 polyfill:
1 (function() {
2 if (typeof Object.create != 'function') {
3 Object.create = (function() {
4 function Temp() {}
5 var hasOwn = Object.prototype.hasOwnProperty;
6 return function(O) {
7 if (typeof O != 'object') {
8 throw TypeError('Object prototype may only be an Object or null');
9 }
10 Temp.prototype = O;
11 var obj = new Temp();
12 Temp.prototype = null;
13 if (arguments.length > 1) {
14 var Properties = Object(arguments[1]);
15 for (var prop in Properties) {
16 if (hasOwn.call(Properties, prop)) {
17 obj[prop] = Properties[prop];
18 }
19 }
20 }
21 return obj;
22 };
23 })();
24 }
25 })();