了解 Javascript 个原型链

Understanding Javascript prototype chains

如果我有一个 String 的实例,并且我修改了它的构造函数的原型,那么每个 String 实例的原型都具有 属性(正如预期的那样)。

 "test string".constructor.prototype.thing = function() {return this;}
 console.log("new string".thing());//prints "new string"

但是,如果我修改了 String 构造函数的构造函数原型,那么这将不再有效:

String.constructor.prototype.thing = function() {return this;}
console.log("new string".thing());//returns "new string".thing() is not a function

如果我使用 String.proto 语法也是一样。为什么是这样?我的印象是 JavaScript 在寻找 属性 时会沿着原型链一直往上走。如果我将 属性 添加到 String.constructor.prototype,那么 String 将不会有那个 属性,但它的父对象会有,对吗?因此,String 的所有实例也应该可以访问 属性。我的想法哪里错了?

However, if I modify the String constructor's constructor's prototype, then this no longer works:

构造函数是一个函数,所以任何构造函数的构造函数都是Function

这意味着 "the String constructor's constructor's prototype" 是 Function.prototype

如果您向 Function.prototype 添加内容,它将显示为任何函数的成员,而不是任何字符串的成员。


您可以尝试 Object.getPrototypeOf 来获得灵感。

$ (Object.getPrototypeOf(Object(""))
String {length: 0, [[PrimitiveValue]]: ""}
$ Object.getPrototypeOf(Object.getPrototypeOf(Object("")))
Object {}
$ Object.getPrototypeOf(Object.getPrototypeOf(Object.getPrototypeOf(Object(""))))
null

原始字符串的对象值 is-a String which is-an object which is end of原型链。

如果你想创建长于一个的原型链,以支持从超级class继承,通常的做法是将构造函数的原型设置为一个 class 实例,它本身从原型继承。以下示例演示了这一点:

function c1(b) {
    this.b = b;
}
c1.prototype = {a:111};

x = new c1(222);

function c2(c) {
    this.c = c;
}
c2.prototype = x;

y = new c2(333);

alert(y.a + ", " + y.b + ", " + y.c);

y中的三个变量是:

a   inherited from c1's prototype, via c2's prototype
b   inherited from c2's prototype
c   stored directly in y

请注意,它沿着原型链上升 2 层以从 y 访问 a

这就是您想知道的方法吗?