【问题标题】:variable within a object not updating in javascript对象中的变量未在 javascript 中更新
【发布时间】:2014-08-14 02:09:56
【问题描述】:

我有一个像这样初始化的对象

  var x = function(){
       var result = 5,
       clear = function(){
          result = 0;
        };
      return {
        result: result,
        clear: clear      
     }           
  }

稍后我将使用var y = new x(); 创建x 的新实例

但是当我尝试设置value y.result = 5; 并想将result 值清除为0 我打电话给y.clear();

但是它没有将y.result 重置为0...不知道为什么?

我做错了什么?

【问题讨论】:

  • 数字是不可变的,顶部的result 与您返回的对象中的result 不同。做一个getter函数。
  • 您应该使用var y = x();,而不是var y = new x();x 不是构造函数。 (它不会写信给this。)
  • 那会是什么样子?
  • clear 是一个设置器,因为它设置了result 变量。 getter 将返回 result 变量。
  • 女士们先生们,这就是 Douglas Crockford 不喜欢新的原因。

标签: javascript


【解决方案1】:

在您的职能范围内:

var x = function(){
       var result = 5,
       clear = function(){
          result = 0;

此函数中的标识符 result 对外部函数(即外部执行上下文)中的变量 result 有一个闭包。

        };
      return {
        result: result,

这会将 变量 命名结果的值分配给 对象属性 命名结果。

        clear: clear      
     }           
  }

所以稍后当您调用 y.clear() 时,您正在设置闭包中保存的变量的值,这不会更新名为 result 的对象属性。

如果你想让 x 成为构造函数,那么:

function X() {
  this.result = 5;
  this.clear = function() {
    this.result = 0;
  }
}

那么现在:

var y = new X();
y.clear();
console.log(y.result); // 0

请注意,构造函数的名称以大写字母开头是惯例。您可以在MDN 上了解有关如何使用 new 运算符的更多信息。

要利用 ECMAScript 继承,请将 clear 函数放在构造函数的原型上,以便所有实例都继承一个方法,而不是每个实例都有自己的方法:

function X() {
  this.result = 5;
}

X.prototype.clear = function() {
  this.result = 0;
}

【讨论】:

    【解决方案2】:

    问题是数字是按值引用的。从clear 函数为result 变量赋值不会改变新x 实例上result 的值。

    有几种方法可以解决这个问题:

    1. 将数据存储在this,然后在构造函数和方法中对其进行修改,我发现它更易于理解且更具可读性。这可能是您想要开始的:

      function x () {
          this.result = 5;
      }
      
      x.prototype.clear = function () {
          this.result = 0;
      }
      
      var z = new x();
      // z.result === 5
      z.clear()
      // z.result === 0;
      
    2. 在返回的对象上定义 getter 和 setter,所以实例 result 将返回\set 闭包变量:

      function x () {
          var result = 5;
      
          function clear () {
              result = 0;
          }
      
          var out = {
              clear: clear
          };
      
          Object.defineProperty(out, "result", {
              get: function () {
                  return result;
              },
              set: function (value) {
                  result = value;
              }
          });
      
          return out;
      }
      
      var z = new x();
      // z.result === 5
      z.clear()
      // z.result === 0;
      z.result = 10
      // z.result === 10;
      z.clear()
      // z.result === 0;
      

    【讨论】:

    • 不是,IE7/8 不支持对象的defineProperty。不过,第一个解决方案应该在那里工作得很好。如果你真的想使用封闭的 var 方法,那么所有对结果的外部访问都应该使用函数来完成。
    猜你喜欢
    • 2017-09-11
    • 1970-01-01
    • 1970-01-01
    • 2020-06-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多