JavaScript中的原型链问题

Van*_*uel 4 javascript

为什么我不能从A访问'x'属性?

A = {}; B = {y: 'y'}; C = {x: 'x'}; A.prototype = B; B.prototype = C; A.x
Run Code Online (Sandbox Code Playgroud)

T.J*_*der 8

对象的原型不会被prototype属性反映(虽然可能会令人困惑).实际上,在创建对象之后,没有标准的,直接的方法来设置对象的原型(并且最近才有任何标准方法来检索对象的原型).在您引用的代码中,您所做的就是创建一个prototype在对象上调用的普通属性; 它也可能被称为foo.:-)

这里一个特殊prototype的JavaScript属性,但它的功能:它是一个将被指定为通过该函数创建的,如果你与使用它的对象的原型对象new的关键字(例如,作为一个构造函数).事实上,直到最近,将原型分配给对象的唯一方法是通过构造函数:

function makeA() {
}
makeA.prototype.x = "foo";

A = new makeA();
alert(A.x); // alerts "foo"
Run Code Online (Sandbox Code Playgroud)

......而且这仍然是唯一得到广泛支持的手段.

新的ECMAScript第5版规范略有改变,但您仍然可以在创建对象时设置对象的原型,而不是事后.新东西的作用是让它可以直接执行,而不是通过构造函数来完成它.这是Object.create第15.2.3.5节中的新功能,但尚未得到广泛支持.(第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"
Run Code Online (Sandbox Code Playgroud)

...但是由于它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();
    };
}
Run Code Online (Sandbox Code Playgroud)