【问题标题】:'this' context during object creation对象创建期间的“this”上下文
【发布时间】:2011-05-08 15:36:54
【问题描述】:

我正在尝试做这样的事情:

var test = {
    a: 10,
    b: 20,
    c: (this.a+this.b)
};

但它不起作用。如何从 test.c 中访问 test.a? 有可能吗?

【问题讨论】:

    标签: javascript object scope closures this


    【解决方案1】:

    不可能在对象字面量中使用,因为无法使 this 引用尚未创建的对象。您最好的选择是在单独的步骤中分配 c 属性:

    var test = {
        a: 10,
        b: 20
    };
    
    test.c = test.a + test.b;
    

    【讨论】:

      【解决方案2】:

      在声明对象字面量时你根本不能这样做,你可以做的最接近的是:

      var test = {
          a: 10,
          b: 20
      };
      test.c = test.a + test.b;
      

      在您的上下文中,this 指的是您所在的任何父上下文,而不是 test 对象......即使这样做,您也不能这样声明成员,例如这也是无效的:

      var test = { a: 10, b: 20, test.c: test.a + test.b };
      

      ...因为 testab 尚未定义,因为它是一个尚未完成的语句。

      【讨论】:

        【解决方案3】:

        不可能在指定对象字面量的表达式中引用“this”。要么在下面的行中执行,要么使用这样的构造函数:

        function myobj(a,b) {
          this.a = a;
          this.b = b;
          this.c = this.a + this.b;
        }
        
        var test = new myobj(10,20);
        

        响应哪个方法更快,使用对象构造函数创建更快。这是一个简单的测试用例比较。 Run it yourself on JSBIN.

        结果表明,使用构造函数创建对象的速度几乎是对象文字的两倍:

        0.450s : testObjectLiteral

        0.506s : testObjectLiteralWithFunction

        0.280s : testConstructor

        这也是内联的测试代码:

        // timer function
        function time(scope){ 
          time.scope = time.scope || {}; 
          if(time.scope[scope]) {
            var duration = (new Date()).getTime()-time.scope[scope]; 
            time.scope[scope] = null; 
            var results = document.getElementById("results");
            results.innerHTML = results.innerHTML + '<p>'+(duration/1000).toFixed(3)+'s : '+scope+'</p>';
          } else { 
            time.scope[scope] = (new Date()).getTime();
          } 
        }  
        
        // object creation function with constructor
        function myobj(a,b) {
          this.a = a;
          this.b = b;
          this.c = this.a + this.b;
        }
        
        function testConstructor(iterations) {
          var objs = new Array(iterations);
          for(i=0;i<iterations;i++) {
            objs[i] = new myobj(i,i+1);
          }
          return objs;
        }
        
        function testObjectLiteralWithFunction(iterations) {
          var objs = new Array(iterations);
          for(i=0;i<iterations;i++) {
            objs[i] = {
              a: i,
              b: i+1,
              c: function() {
                return this.a + this.b;
              }
            };
          }  
          return objs;
        }
        
        
        function testObjectLiteral(iterations) {
          var objs = new Array(iterations);
          for(i=0;i<iterations;i++) {
            var item = {
              a: i,
              b: i+1
            };
            item.c = item.a + item.b;
            objs[i] = item;
          }  
          return objs;
        }
        
        var ITERATIONS = 1000000;
        time("testObjectLiteral");
        testObjectLiteral(ITERATIONS);
        time("testObjectLiteral");
        
        time("testObjectLiteralWithFunction");
        testObjectLiteralWithFunction(ITERATIONS);
        time("testObjectLiteralWithFunction");
        
        time("testConstructor");
        testConstructor(ITERATIONS);
        time("testConstructor");
        

        【讨论】:

        • 感谢您的帮助。另一个问题:这种声明对象的方式是否比“var myObj = {a:4, b:5....};”更快一个?
        • @dizzy_fingers 查看我添加到答案中的性能测试用例
        【解决方案4】:

        为什么不让 c 成为一个函数,让它总是返回 a+b 的当前值?

        var test = {
            a: 5,
            b: 1,
            c: function() {
                return this.a + this.b;
            }
        }
        

        【讨论】:

        • 感谢您的建议。但是性能问题呢?在 c: 声明后添加闭包是否会产生额外开销?
        • 好吧,我想是这样 - 每次调用 c() 时,它都会评估 a+b,而不是简单地检索变量的值。但是,根据您的情况,这种差异可能可以忽略不计。如果您正在执行的加法操作涉及大量值,并且/或者您引用 c() 的次数很多,那么最好在初始化时只执行一次此计算,在这种情况下,mbrevoort 的解决方案如下可能更有用。最终归结为您的情况以及 a/b 是否会在执行期间发生变化。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-03-22
        相关资源
        最近更新 更多