开发者

'this' context during object creation

I am trying to do something like this:

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

but it doe开发者_高级运维sn't work. How can I access the test.a from within test.c? Is it possible?


It's not possible to reference "this" in an expression specifying an object literal. Either do it in a following line or use a constructor like this:

function myobj(a,b) {
  this.a = a;
  this.b = b;
  this.c = this.a + this.b;
}

var test = new myobj(10,20);

In response to which method is faster, creation with the object constructor is faster. Here's a simple test case comparison. Run it yourself on JSBIN.

The results show that the object creation with a constructor vs an object literal is almost twice as fast:

0.450s : testObjectLiteral

0.506s : testObjectLiteralWithFunction

0.280s : testConstructor

Here's the test code inlined as well:

// 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");


It's not possible within an object literal since this cannot be made to refer to an object that has not yet been created. Your best option is to assign the c property in a separate step:

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

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


You simply can't do this when declaring an object literal, the closest you can do is:

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

In your context this refers to whatever parent context you're in, not the test object...and even if it did, you can't declare members like that, for example this is also invalid:

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

...because test, a and b aren't defined yet, since it's a single statement that hasn't completed.


Why not make c a function so that it always returns the current value of a+b?

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

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜