在对象创建期间'this'上下文

时间:2010-11-11 18:11:37

标签: javascript object scope closures this

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

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

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

4 个答案:

答案 0 :(得分:5)

在指定对象文字的表达式中引用“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");

答案 1 :(得分:2)

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

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

test.c = test.a + test.b;

答案 2 :(得分:0)

在声明对象文字时,你根本无法做到这一点,你可以做的最接近的是:

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 :(得分:-2)

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

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