2010-11-11 174 views
1

在“本”方面,我正在尝试做这样的事情:对象创建

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

,但它不工作。我如何从test.c中访问test.a? 这可能吗?

回答

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

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

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

+0

+1为OOP解决方案。 – zzzzBov 2010-11-11 18:18:19

+0

感谢您的帮助。另一个问题:这种方式是否比“var myObj = {a:4,b:5 ....}”更快地声明一个对象;“一? – 2010-11-12 00:23:50

+0

@dizzy_fingers查看我添加到我的答案中的性能测试用例 – mbrevoort 2010-11-12 18:34:57

2

在对象文字中不可能这样做,因为this不能用于引用尚未创建的对象。你最好的选择是将c财产在单独的步骤分配:

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

test.c = test.a + test.b; 
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 }; 

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

-2

为什么不能使C的功能,以便它总是返回A + B的当前值?

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

感谢您的建议。但是性能问题呢?是否在c:声明之后添加了一个闭包额外的开销? – 2010-11-12 00:25:09

+0

那么我会想象如此 - 每次调用c()时,它都在评估a + b,而不是简单地检索变量的值。但是,根据您的情况,这种差异可能可以忽略不计。如果您正在执行的加法操作涉及大量值,并且/或者您正在引用c()很多次,则最好在初始化时只进行一次该计算,在这种情况下,mbrevoort的解决方案低于可能更有用。最终归结为您的情况,以及在执行期间a/b是否会发生变化。 – 2010-11-12 10:29:55

+0

-1这个答案是否正确? – gath 2010-11-19 12:21:06