【问题标题】:javascript: can I define a "private" variable using prototype?javascript:我可以使用原型定义一个“私有”变量吗?
【发布时间】:2020-06-12 15:06:48
【问题描述】:

我想为每个“实例”使用一个唯一的私有变量(我希望这是 Javascript 中的正确术语),但两个实例似乎都使用相同的私有变量。

func = function(myName)
{
    this.name = myName
    secret = myName

    func.prototype.tellSecret = function()
    {   return "the secret of "+this.name+" is "+secret
    }
}

f1 = new func("f_One")
f3 = new func("f_3")

console.log(f3.tellSecret()) // "the secret of f_3 is f_3" OK
console.log(f1.tellSecret()) // "the secret of f_One is f_3" (not OK for me)

我看到了solution 但是

这意味着在每个实例上复制该函数,并且 函数存在于实例上,而不是原型上。

另一位作者说the same solution

这仍然不是很传统的经典 Javascript,它只会在 Account.prototype 上定义一次方法。

那么,有没有办法解决

  • 每个实例都可以有 secret 的唯一值
  • secret 仅可用于构造函数中定义的方法 和
  • 函数不会为每个实例重复

?

【问题讨论】:

  • secret = myName -> let secret = myNameconst secret = myName。您目前正在分配给一个全局变量。
  • @VLAZ 只是添加这行不通,因为原型方法在每次调用new func时都会被覆盖
  • @adiga 是的,我后来意识到了这一点。我撤回了我的近距离投票。我最初误读了这个问题。
  • 您需要将func.prototype.tellSecret 方法移到外部,并设法将secret 值移到外部(就像在您链接的问题中一样)
  • @VLAZ tbh 我也为此困惑了整整两分钟

标签: javascript closures prototype


【解决方案1】:

问题是每次调用构造函数时你都在替换原型函数。

使用旧式的基于闭包的隐私,您不能从原型方法访问“私有”成员,因为只有在构造函数中定义的关闭它们的函数才能使用它们。所以你最终会为每个实例重新创建函数(这并不像听起来那么糟糕,但也不是很好)。

function Example(name) {
    this.name = name;
    var secret = name; // Using `var` here on the basis this is ES5-level code

    // This can't be a prototype function
    this.tellSecret = function() {
        return "the secret of " + this.name + " is " + secret;
    };
}

两种选择:

1) 使用像 Babel 这样的转译器、class 语法和私有字段(可能在 ES2021 中,现在通过转译使用了相当长的一段时间):

class Example {
    #secret;

    constructor(name) {
        this.name = name;
        this.#secret = name;
    }

    tellSecret() {
        return "the secret of " + this.name + " is " + this.#secret;
    }
}

const f1 = new Example("f_One");
const f3 = new Example("f_3");

console.log(f3.tellSecret()) // "the secret of f_3 is f_3"
console.log(f1.tellSecret()) // "the secret of f_One is f_One"

2) 使用包含机密信息的WeakMap (ES2015+)

const secrets = new WeakMap();
class Example {
    constructor(name) {
        this.name = name;
        secrets.set(this, name);
    }

    tellSecret() {
        return "the secret of " + this.name + " is " + secrets.get(this);
    }
}

const f1 = new Example("f_One");
const f3 = new Example("f_3");

console.log(f3.tellSecret()) // "the secret of f_3 is f_3"
console.log(f1.tellSecret()) // "the secret of f_One is f_One"

你把secrets放在只有Example可以访问它的地方。

您也可以使用WeakMap 而不使用class 语法,但如果您要创建具有关联原型的构造函数,classfunction Example 和分配给Example.prototype 上的属性更简单。

【讨论】:

  • 我没有想到要使用这样的 WeakMap。回想起来完全有道理,但仍然如此。非常好的解决方案。此外,私有字段现在在 Chrome 中可用,但在 Firefox 中还没有。
  • @VLAZ - :-) 对我来说不是原创,如果我没记错的话,这是WeakMap 的动机之一。是的,我们如此接近他们进入第 4 阶段。这就是为什么我确信他们很快就会出现在编辑器的草案规范中,并保证在 ES2021 截止日期之前很好。
  • 谢谢 T.J.克劳德!我认为 WeakMap 会为我工作,我稍后会看看 Babel。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-08-02
  • 2011-07-10
  • 2021-12-27
  • 2023-01-20
  • 1970-01-01
  • 2013-08-03
  • 1970-01-01
相关资源
最近更新 更多