为什么我无法从A?
访问'x'属性A = {}; B = {y: 'y'}; C = {x: 'x'}; A.prototype = B; B.prototype = C; A.x
答案 0 :(得分:8)
对象的原型不会被prototype
属性反映出来(虽然可能会令人困惑)。实际上,在创建对象之后,没有标准的,直接的方法来设置对象的原型(而且最近才有检索对象的原型的任何标准方法)。在您引用的代码中,您所做的就是在对象上创建一个名为prototype
的普通属性;它也可能被称为foo
。 : - )
是JavaScript中的一个特殊prototype
属性,但它位于函数上:它是将被指定为由对象创建的对象的原型的对象。该函数如果与new
关键字一起使用(例如,作为构造函数)。实际上,直到最近,将原型分配给对象的唯一方法是通过构造函数:
function makeA() {
}
makeA.prototype.x = "foo";
A = new makeA();
alert(A.x); // alerts "foo"
......而且这仍然是唯一得到广泛支持的手段。
使用新的ECMAScript 5th edition specification,情况会略有变化,但您仍然只能在创建对象时设置对象的原型,而不是在事后。新东西的作用是让它可以直接执行,而不是通过构造函数来完成它。这是第15.2.3.5节中的新Object.create
功能,但尚未得到广泛支持。 (第5版还有其他几个漂亮的功能,包括通过Object.getPrototypeOf
获取对象原型的能力;但事后却无法改变它。)
有一些非标准属性,某些实现(如Firefox的SpiderMonkey引擎)提供__proto__
,但它不受广泛支持,并且未包含在最新规范中。
使用新的Object.create
,你可以这样做:
var C = {x: 'x'};
var B = Object.create(C);
B.y = 'y';
var A = Object.create(B);
alert(A.x); // alerts "x"
...但是由于Object.create
是如此新颖,你会发现在大多数实现中,你需要创建它,因为它不在那里。如果我们忽略它的第二个参数(只能部分模拟),这很容易:
if (!Object.create) {
// An *incomplete* emulation of Object.create, doesn't support the optional
// second parameter defined by the spec.
Object.create = function(proto) {
var obj;
// There's no point in calling this with a null or otherwise "falsy"
// prototype, but let's handle it if you do
if (!proto) {
return {}; // Just a generic object
}
// Define a constructor object that uses
// the prototype
function ctor() {
}
ctor.prototype = proto;
// Create and return the object
return new ctor();
};
}