在阅读这篇http://www.html5rocks.com/en/tutorials/speed/v8/时,有必要在运行时更改变量的类型,迫使浏览器更加努力地工作,而不是保持它们的一致性。
这是否意味着这不是一个好主意:
var x = {
alpha: null,
bravo: null,
charlie: null,
delta: null,
echo: null
}
x.alpha = {a:1, b:true}
x.bravo = 13
x.charlie = true
x.delta = [1,2,3]
x.echo = 'abc'
因为这里的类型从null开始,然后变为object,int,boolean arrary。
为了简单起见,之后这些类型永远不会改变。
或者效率更高:
var x = {
alpha: {},
bravo: 0,
charlie: false,
delta: [],
echo: ''
}
x.alpha = {a:1, b:true}
x.bravo = 13
x.charlie = true
x.delta = [1,2,3]
x.echo = 'abc'
我可以理解从数字到数组的更改类型不是一个好主意。如何在执行期间从null更改为类型?
我读过的书籍和博客主要是说,当值只在运行时知道时,用null定义变量(而不是undefined)。从表面看,这似乎是错误的,因为用空类型定义可以避免类型更改。
答案 0 :(得分:6)
对这个问题感兴趣,我设置了一个小提琴,看看一些不同用例的表现。
打开控制台以查看此小提琴中的数据
http://jsfiddle.net/kmiklas/MFNak/14/
Chrome v32的典型结果,n = 100000000:
number no init: 97.070ms
number init to null: 98.023ms
number init to number: 97.246ms
array no init: 457.494ms
array init to null: 458.301ms
array init to number: 455.166ms
array init to array: 836.710ms
object no init: 508.268ms
object init to null: 512.312ms
object init to object: 754.562ms
number to object: 455.733ms
array to object: 834.169ms
object to array: 751.498ms
~~~~~~~~~~~~~~~~~~~~~~~~~~~
代码相当冗长,但根据SO要求包含在下面。
n = 100000000;
console.time("number no init");
for (var i = n; i >= 0; i--) { var x; x = 42; };
console.timeEnd("number no init");
console.time("number init to null");
for (var i = n; i >= 0; i--) { var x = null; x = 42; };
console.timeEnd("number init to null");
console.time("number init to number");
for (var i = n; i >= 0; i--) { var x = 1; x = 42; };
console.timeEnd("number init to number");
console.time("array no init");
for (var i = n; i >= 0; i--) { var a; a = [42]; };
console.timeEnd("array no init");
console.time("array init to null");
for (var i = n; i >= 0; i--) { var a = null; a = [42]; };
console.timeEnd("array init to null");
console.time("array init to number");
for (var i = n; i >= 0; i--) { var a = 1; a = [42]; };
console.timeEnd("array init to number");
console.time("array init to array");
for (var i = n; i >= 0; i--) { var a = []; a = [42]; };
console.timeEnd("array init to array");
console.time("object no init");
for (var i = n; i >= 0; i--) { var a; a = {n:42}; };
console.timeEnd("object no init");
console.time("object init to null");
for (var i = n; i >= 0; i--) { var a = null; a = {n:42}; };
console.timeEnd("object init to null");
console.time("object init to object");
for (var i = n; i >= 0; i--) { var a = {}; a = {n:42}; };
console.timeEnd("object init to object");
console.time("number to object");
for (var i = n; i >= 0; i--) { var a = 1; a = {n:42}; };
console.timeEnd("number to object");
console.time("array to object");
for (var i = n; i >= 0; i--) { var a = []; a = {n:42}; };
console.timeEnd("array to object");
console.time("object to array");
for (var i = n; i >= 0; i--) { var a = {}; a = [42]; };
console.timeEnd("object to array");
console.log('~~~~~~~~~~~~~~~~~~~~~~~~~~~');
编辑:
请注意,我仅在Chrome 32中测试过。要准确得出这个结论,最好加载这个小提琴并在更受欢迎的桌面和移动浏览器中查看结果;特别是IE和Safari Mobile。
答案 1 :(得分:3)
在初始化时,所有javascript变量都会被提升到范围的顶部,其值为undefined
。直到为变量赋值,才能分配特定类型。
所以你在这里做的是有效地重新分配变量的值和类型两次。性能成本可能可以忽略不计,但声明其值未知的对象的首选做法是使用对象文字:
var x = {};
如果您尝试访问不存在的对象的属性,您将得到未定义(这与null
一样容易测试)。但是,如果您说在运行时之前已知 属性,则没有理由不立即分配这些属性,因此......
x.alpha = {a:1, b:true}
x.bravo = 13
x.charlie = true
x.delta = [1,2,3]
...变为
var x = {
alpha: {a:1, b:true},
bravo: 13,
charlie: true,
delta: [1,2,3]
};