gpt4 book ai didi

javascript - 如何访问原型(prototype)上的阴影 JavaScript 对象字段?

转载 作者:行者123 更新时间:2023-11-30 12:05:08 25 4
gpt4 key购买 nike

使用以下 ES2015 (ES6) 类定义:

class Card {
constructor(val) {
this.val = val;
}
val(){
return this.val;
}
}

(或等效的 ES5 和更早的代码)

但是,执行以下方法调用:

new Card(val).val()

抛出 TypeError: Card.val 不是函数

Card.x.call(Card)

似乎有同样的问题。

鉴于这两个名称应该保持不变,我如何才能正确引用原型(prototype)的 val 方法而不是对象的 val 字段?

最佳答案

I'm just trying to get inspiration of how we can effectively avoid such conflict in javascript, assuming that we have to name them in this way.

为避免混淆,我们将其称为 val你有原型(prototype)“proto val”和你在构造函数中分配的原型(prototype)“instance val”。

对象(“实例 val”)的属性不能与其原型(prototype)(“proto val”)的属性同名,并且不能通过对象引用直接访问它们,根据上下文获取一个或另一个。这不是 JavaScript 所具有的功能。这是 JavaScript 属性查找工作方式所固有的,事实上 JavaScript 的“方法”只是引用函数的属性。

下面的选项,但让我们更仔细地看看为什么“instance val”会覆盖“proto val”:

对于上述代码的任一更正版本,此行:

var c = new Card(42);

在内存中给了我们这个(省略了一些细节):

      +------------------------------------------+      |                                          |      \   +------------+                         |Card>--+->| (function) |                         |          +------------+       +-------------+   |          | prototype  |>---+->|  (object)   |   |          +------------+   /   +-------------+   |                           |   | constructor |>--+   +------------+                           |   | val         |>----->| (function) |                           |   +-------------+       +------------+                            |      +---------------+    |c>--->|   (object)    |    |      +---------------+    |      | [[Prototype]] |>---+      | val: 42       |      +---------------+

The identifier Card (effectively a variable) refers to a function. That function's prototype property refers to an object that we've put the "proto val" method on. The variable c refers to an instance which has what the spec calls an "internal slot" called [[Prototype]] which refers to its prototype, which it got from Card.prototype when we did new Card. The prototype has a val property pointing to the method, and also a constructor property that points to back to the function Card points to.

When we ask the JavaScript engine to look up the val property on c, it finds it on the object c refers to, and uses it from there; the "instance val" has overridden the "proto val". If the "instance val" weren't there, the JavaScript engine wouldn't find it on the object c points to and would look to the object's prototype (what the object's [[Prototype]] internal slot points to), and then it would find the val property pointing to the function. But the "instance val" is in the way.

You basically have three options:

  1. Do what you've said you don't want to do: Give them different names. The data property ("instance val") could be _val for instance, or the method ("proto val") could be getVal (as method names should generally be verbs), or both (which would be quite common), etc.

  2. Create the val method in the constructor and don't have a val data property at all:

    // ES2015 (ES6) and higher
    class Card {
    constructor(val) {
    this.val = function() {
    return val;
    };
    }
    }

    // ES5 and earlier
    function Card(val) {
    this.val = function() {
    return val;
    };
    }

    自数据val根本不再是实例的属性,与方法 val 没有冲突.

    这是有效的,因为 val方法现在是对 Card 调用上下文的闭包,因此它可以持久访问 val争论。但是,没有原型(prototype)方法可以直接访问它;他们必须使用 this.val()得到它。

  3. 做你现在正在做的事情,在原型(prototype)而不是实例上查找“proto val”:

    var c = new Card(val).val()
    Object.getPrototypeOf(c).val.call(c); // ES5+

    (不太可靠)

    var c = new Card(val).val()
    Card.prototype.val.call(c);

    (更不可靠)

    var c = new Card(val).val()
    c.constructor.prototype.val.call(c);

    ...如您所见,这非常痛苦。它之所以有效,是因为在这些示例中我没有在 val 上查找“proto c” (因为“实例val”在路上);我直接在 c 的原型(prototype)上查找它(当然,在第一个示例中;可能在第二个示例中;希望在第三个示例中)。

关于javascript - 如何访问原型(prototype)上的阴影 JavaScript 对象字段?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35451662/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com