我正在使用Three.js编写脚本,其中很多变量取决于鼠标位置。是否在每次移动事件触发时不断将变量设置为相同的值是否重要,还是仅在检测到更改时才设置变量?
假设我想将变量“ quadrant”设置为1,2,3或4,具体取决于鼠标悬停在屏幕的哪一部分...我应该使用以下命令:
var quadrant;
function mouseMove(e){
var mouse;
mouse.x = e.clientX;
mouse.y = e.clientY;
if(mouse.x < window.innerWidth / 2){
if(mouse.y < window.innerHeight / 2){
quadrant = 1;
} else {
quadrant = 3;
}
} else {
if(mouse.y < window.innerHeight / 2){
quadrant = 2;
} else {
quadrant = 4;
}
}
};
window.addEventListener('mousemove', mouseMove);
每当事件触发时,它将重置变量。或者我应该仅在检测到更改时设置变量,例如:
var quadrant;
function mouseMove(e){
var mouse;
mouse.x = e.clientX;
mouse.y = e.clientY;
if(mouse.x < window.innerWidth / 2){
if(mouse.y < window.innerHeight / 2){
if(quadrant != 1){
quadrant = 1;
}
} else {
if(quadrant != 3){
quadrant = 3;
};
}
} else {
if(mouse.y < window.innerHeight / 2){
if(quadrant != 2){
quadrant = 2;
};
} else {
if(quadrant != 4){
quadrant = 4;
};
}
}
};
window.addEventListener('mousemove', mouseMove);
将变量设置到内存的行为(即使它的值相同)是否会比读取添加条件所需的额外代码行花费的更多?我本能地执行后者,因为它看起来比较整洁,并且在运行时需要较少的工作,但是我真的不知道这实际上如何转换为性能。我似乎记得读过,每当在js中设置一个变量时,它实际上是在创建自己的实例,这看起来像是在工作……但是也许我误解了。
正如评论中所指出的,较简单的版本很有可能会更快-并且更易于阅读且不易出错。
当我得到您时,让我建议一种完全不同的方法:计算象限,而不使用一堆if
语句。
// Calculate the quadrant for a given x and y and width and height.
// The quadrants are defined like this:
//
// +---+---+
// | 1 | 2 |
// +---+---+
// | 3 | 4 |
// +---+---+
function getQuadrant( x, y, width, height ) {
return 1 +
( x >= width / 2 ) +
( y >= height / 2 ) * 2;
}
console.log( getQuadrant( 25, 25, 100, 100 ) ); // 1
console.log( getQuadrant( 75, 25, 100, 100 ) ); // 2
console.log( getQuadrant( 25, 75, 100, 100 ) ); // 3
console.log( getQuadrant( 75, 75, 100, 100 ) ); // 4
该代码之所以有效,是因为当您对布尔值使用算术运算符时,它将false
值转换为,0
而true
值转换为1
。
我不知道这是快还是慢(您必须对其进行基准测试才能发现),但是由于您正在寻找解决问题的不同方法,因此我认为您可能会发现它很有趣。
您可能会想:“这些乘除除不是很慢吗?” 但是,像大多数优化编译器一样,现代JavaScript引擎也可以将乘以2的乘方或除法转换为非常快速的移位操作。
让我们看一下V8为该getQuadrant
功能生成的机器代码(仅显示代码的核心部分,而不是功能设置和拆卸)。
当我们输入此代码时,四个功能参数存储在这些寄存器中:
r8
是x
。
r11
是y
。
rdx
是width
。
rdi
是height
。
这是编译后的代码:
; Divide height and width by 2 for the comparisons below
sarl rdi, 1
sarl rdx, 1
; Compare y with half the height and set rcx to 0 or 1
cmpl rdi,r11
setlel cl
movzxbl rcx,rcx
; Compare x with half the width and set rdx to 0 or 1
cmpl rdx,r8
setlel dl
movzxbl rdx,rdx
; Set rdx to the final result, calculated in a single instruction
leal rdx,[rdx+rcx*2+0x1]
一种可能的性能优势是此代码避免了if
语句使用的分支。在现代CPU上,当您可以避免分支时,通常可以提高性能。
但是同样,这些方法中的任何一种都可能足够快!如果您感兴趣,只需发布此替代方法即可。
如果您想知道如何获得该机器代码清单,可以创建一个名为JavaScript的独立文件quadrants.js
,内容如下:
function getQuadrant( x, y, width, height ) {
return 1 +
( x >= width / 2 ) +
( y >= height / 2 ) * 2;
}
// We need to actually do something with the result returned by getQuadrant,
// otherwise the JavaScript engine may notice that the result is unused and
// it may skip compiling the function body entirely.
quadrants = [];
for( let i = 0; i < 1000000; ++i ) {
quadrants.push( getQuadrant( 25, 25, 100, 100 ) );
quadrants.push( getQuadrant( 75, 25, 100, 100 ) );
quadrants.push( getQuadrant( 25, 75, 100, 100 ) );
quadrants.push( getQuadrant( 75, 75, 100, 100 ) );
}
// Log the first few results as a sanity check
console.log( quadrants.length );
for( let i = 0; i < 16; ++i ) {
console.log( quadrants[i] );
}
然后我使用以下命令运行它:
node --print-opt-code --code-comments quadrants.js >code.txt
然后,我浏览了生成的code.txt
文件以查找该getQuadrant
功能的代码。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句