контекст this при создании объекта - PullRequest
1 голос
/ 11 ноября 2010

Я пытаюсь сделать что-то вроде этого:

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

но это не работает. Как я могу получить доступ к test.a из test.c? Возможно ли это?

Ответы [ 4 ]

5 голосов
/ 11 ноября 2010

Невозможно ссылаться на «это» в выражении, определяющем литерал объекта.Либо сделайте это в следующей строке, либо используйте конструктор, подобный следующему:

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

var test = new myobj(10,20);

В ответ на то, какой метод быстрее, создание с помощью конструктора объекта происходит быстрее.Вот простое сравнение тестовых случаев. Запустите его самостоятельно на JSBIN .

Результаты показывают, что создание объекта с помощью конструктора по сравнению с литералом объекта происходит почти в два раза быстрее:

0,450 с: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");

2 голосов
/ 11 ноября 2010

Это невозможно в пределах литерала объекта, поскольку this нельзя сделать ссылкой на объект, который еще не создан. Лучше всего назначить свойство c на отдельном шаге:

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

test.c = test.a + test.b;
0 голосов
/ 11 ноября 2010

Почему бы не сделать функцию CA так, чтобы она всегда возвращала текущее значение a + b?

var test = {
    a: 5,
    b: 1,
    c: function() {
        return this.a + this.b;
    }
}
0 голосов
/ 11 ноября 2010

Вы просто не можете сделать это, когда объявляете литерал объекта, самое близкое, что вы можете сделать:

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 };

... потому что test, a и b еще не определены, так как это один оператор, который еще не завершен.

...