【问题标题】:How can a JavaScript object refer to values in itself? [duplicate]JavaScript 对象如何引用自身的值? [复制]
【发布时间】:2011-02-16 18:02:37
【问题描述】:

假设我有以下 JavaScript:

var obj = {
 key1 : "it ",
 key2 : key1 + " works!"
};
alert(obj.key2);

“key1 未定义”的错误。我试过了

this.key1
this[key1]
obj.key1
obj[key1]
this["key1"]
obj["key1"]

它们似乎从未被定义过。

如何让 key2 引用 key1 的值?

【问题讨论】:

  • 非常旧的 Firefox 版本(我尝试了 Firefox 4,它给出了警告但接受了它)允许您使用 #N= 和 #N# 来引用同一表达式中的现有对象,但这不适用于原语;你只需要复制那些。
  • 其实有一个俗气的解决方法,你可以把原语装箱,然后用尖变量引用装箱的值:var obj = { key1: #1= (new String("it ")), key2: #1# + "works!" }; alert(obj.key2)
  • key2 在定义对象时在对象内部定义。因此,在定义 key2 时还没有 key1。只有赋值后key1才存在。你引用的东西还不存在。
  • this(双关语)现在可以在 ES6 中使用,在对象字面量函数中可以使用“this”

标签: javascript object


【解决方案1】:

也许您可以考虑删除函数的属性。我的意思是这样的:

var obj = {
  key1: "it ",
  key2: function() {
    return this.key1 + " works!";
  }
};

alert(obj.key2());

【讨论】:

  • 只有当你有一个公寓 obj 时它才有效,就像你的例子中的那样。如果您有嵌套键,它将不起作用。
  • @Green 是的,但您始终可以在对象创建后立即将其分配给绑定函数。 var obj = { ... }; obj.nested.func = function() { ... }.bind(obj);
  • 在 ES6 中,您可以将 key2 : function() {...} 替换为 get key2() {...},然后在调用时无需使用括号:alert(obj.key2);
  • 知道为什么如果使用匿名函数会返回 undefined 吗? key2: ()=>this.key1+" works!"
  • @OmarSharaki,pencilCake 的函数和你的函数都是匿名的。你的不起作用的原因是你使用了一个看不到this的箭头函数。这比我在这里解释的要多得多,但 Sean Vieira 对this question 的回答很好地解释了它。
【解决方案2】:

这不是JSON 对象,而是通过对象文字表示法创建的Javascript 对象。 (JSON 是用于数据交换的文本表示法 (more)。如果您处理的是 JavaScript 源代码,而不是处理 字符串,那么您就没有处理JSON。)

在对象初始化器中无法引用正在初始化的对象的另一个键,因为在初始化器完成之前无法获取对正在创建的对象的引用。 (对于这种情况,没有类似于 this 的关键字。)

【讨论】:

    【解决方案3】:

    另一种选择是使用 getter/setter 方法。

    例如,如果您只关心读取计算值:

    var book  = {}
    
    Object.defineProperties(book,{
        key1: { value: "it", enumerable: true },
        key2: {
            enumerable: true,
            get: function(){
                return this.key1 + " works!";
            }
        }
    });
    
    console.log(book.key2); //prints "it works!"
    

    不过,上面的代码不允许您为 key2 定义另一个值。

    因此,如果您还想重新定义 key2 的值​​,事情会变得有点复杂。它始终是一个计算值。这很可能就是您想要的。

    但是,如果您希望能够重新定义 key2 的值​​,那么您将需要一个独立于计算的地方来缓存其值。

    有点像这样:

    var book  = { _key2: " works!" }
    
    Object.defineProperties(book,{
        key1: { value: "it", enumerable: true},
        _key2: { enumerable: false},
        key2: {
            enumerable: true,
            get: function(){
                return this.key1 + this._key2;
            },
            set: function(newValue){
                this._key2 = newValue;
            }
        }
    });
    
    console.log(book.key2); //it works!
    
    book.key2 = " doesn't work!";
    console.log(book.key2); //it doesn't work!
    
    for(var key in book){
        //prints both key1 and key2, but not _key2
        console.log(key + ":" + book[key]); 
    }
    

    另一个有趣的替代方法是使用自初始化对象:

    var obj = ({
      x: "it",
      init: function(){
        this.y = this.x + " works!";
        return this;
      }
    }).init();
    
    console.log(obj.y); //it works!
    

    【讨论】:

    • 我喜欢自初始化对象的方式。谢谢
    【解决方案4】:

    您也可以在函数内部引用obj 而不是this

    var obj = {
        key1: "it",
        key2: function(){return obj.key1 + " works!"}
    };
    alert(obj.key2());
    

    【讨论】:

    • 我认为这个答案优于“最佳答案”。 obj.key1 始终是“它”,而 this.key1 可以是其他值,具体取决于调用 obj.key2 函数的位置。例如setTimeout(obj.key2, 100); this 指的是窗口对象。
    • 这始终是有效的解决方案。有什么缺点吗?人们为什么要这样做?在某些情况下,执行上下文是动态的且难以操作。
    • 我认为解决方案是最接近问题的答案。简单而优雅。当然,其他答案都很好,除了这个之外,其他答案都是正确的。请让我知道这是否有任何缺点,因为我在我的一个项目中使用了这个概念。
    • 当您尝试访问数组内的属性时,这不起作用。
    【解决方案5】:

    这可以通过使用构造函数而不是文字来实现

    var o = new function() {
      this.foo = "it";
      this.bar = this.foo + " works"
    }
    
    alert(o.bar)
    

    【讨论】:

      【解决方案6】:

      因为定义obj 的语句还没有结束,所以key1 还不存在。考虑这个解决方案:

      var obj = { key1: "it" };
      obj.key2 = obj.key1 + ' ' + 'works!';
      // obj.key2 is now 'it works!'
      

      【讨论】:

      • 很好的解决方案,对象尚未完成其执行阶段是有道理的,因此在其中调用键将是未定义的。对象是函数,因此在执行阶段结束之前不会在内存中定义其中的键
      【解决方案7】:

      在初始化对象之前,您不能引用该对象的属性;使用外部变量。

      var key1 = "it";
      var obj = {
        key1 : key1,
        key2 : key1 + " works!"
      };
      

      另外,这不是“JSON 对象”;它是一个 Javascript 对象。 JSON 是一种用字符串表示对象的方法(恰好是有效的 Javascript 代码)。

      【讨论】:

        【解决方案8】:

        这不是JSON。 JSON 的设计很简单;允许任意表达并不简单。

        在完整的 JavaScript 中,我认为您不能直接执行此操作。在完全构造名为 obj 的对象之前,您不能引用 this。所以你需要一个解决方法,一个比我提供更多 JavaScript-fu 的人。

        【讨论】:

          猜你喜欢
          • 2011-04-17
          • 2012-01-18
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2023-04-08
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多