【问题标题】:JavaScript "Class" "Private" Variable ScopeJavaScript“类”“私有”变量范围
【发布时间】:2017-11-18 12:01:46
【问题描述】:

正如我们所知,您可以通过执行以下操作在 JavaScript 中将“类”变量设为“私有”:

function ClassName(attribute){
    var privateAttribute = attribute;

    this.accessor = function(){
        return privateAttribute;
    }

    this.mutator = function(x){
        privateAttribute = x;
    }
}

我知道这行得通,而且我以前用过。但这有点打破了我的理解。局部变量不应该在函数执行结束时超出范围吗?根据 JavaScript 作用域的工作方式,当您尝试从 ClassName 实例调用访问器时,var privateAttribute 不应该是不可访问的吗?

https://www.w3schools.com/js/js_scope.asp

【问题讨论】:

标签: javascript scope private


【解决方案1】:

您缺少的是可以通过多种方式调用函数的事实...

如果你的函数是作为函数调用的,那么,是的,当函数结束时,它的所有本地数据都没有了。

但是,如果函数被称为“构造函数”:

var myObj = new ClassName(data);

然后该函数创建一个对象实例,该实例存储在myObj 对象变量中,并且该函数的所有私有数据都可用(当然在内部),直到对象变量超出范围。

除此之外,如果一个函数包含一个“闭包”(一个嵌套范围,它引用来自更高范围的变量)并且该嵌套函数最终具有比更高变量所在的更高范围更长的生命周期,那么即使定义它的函数确实存在,该变量也不能超出范围。这个概念一开始会让很多人感到困惑,但它非常有意义 - 如果(假设)返回的函数依赖于在其块终止时通常会超出范围的数据,但返回的函数的寿命比这更长,那么数据不会也不能被垃圾收集。

最后,要明确一点,JavaScript 实际上没有类。它有原型,对象将从这些原型继承。由于原型和继承在 JavaScript 中的工作方式,您的示例代码实际上将使用附加到原型的方法编写,因此对象的所有实例(通过构造函数调用创建)不必存储相同的函数(因此,减少了这些实例的内存占用)。

function ClassName(attribute){
    // A regular variable will act as a private "class field"
    var privateAttribute = attribute;

    // But members that are attached to 'this' become instance fields
    this.exposedPrivateData = privateAttribute;
}

// Methods get attached to the underlying prototype object that
// all instances of your object will inherit from
ClassName.prototype.accessor = function(){
        return this.exposedPrivateData;
};

ClassName.mutator = function(x){
        this.exposedPrivateData = x;
}

【讨论】:

  • @user3496058 实际上,它一点也不乱,但需要一点时间来适应,因为 JavaScript 不像大多数其他语言。 JavaScript 有“词法范围”,一旦你明白了这一点,很多事情就会变得清晰。
猜你喜欢
  • 1970-01-01
  • 2012-09-03
  • 2013-01-16
  • 1970-01-01
  • 1970-01-01
  • 2012-06-17
  • 2010-12-21
  • 1970-01-01
相关资源
最近更新 更多