Ade*_*lin 9 javascript performance var let
为了使一个极端的总结,之间的差异var
,并let
是一个范围之内他们的生活.
(function() {
for (var i = 0; i < 5; i++) {
setTimeout(function() {
console.log(`i: ${i}`);
}, i * 100);
}
// 5, 5, 5, 5, 5
for (let j = 0; j < 5; j++) {
setTimeout(function() {
console.log(`j: ${j}`);
}, 1000 + j * 100);
}
// 0, 1, 2, 3, 4
}());
Run Code Online (Sandbox Code Playgroud)
i
(声明var
)生活在整个function
j
(声明着let
)仅存在于for
循环内.对我来说,这意味着javascript,在每次迭代之后,除了声明和赋值给变量之外,let
还需要执行额外的步骤:清理j
但如果我正在阅读规范,那么还有更多:
var
,执行以下步骤:IterationStatement:for(Expressionopt; Expressionopt; Expressionopt)语句
- 如果存在第一个表达式,那么
- 设exprRef是评估第一个Expression的结果.
- 设exprValue为GetValue(exprRef).
- ReturnIfAbrupt(exprValue).
- 返回ForBodyEvaluation(第二个Expression,第三个Expression,Statement,«»,labelSet).
但在这种情况下let
,执行了大量的12个步骤,包括新声明环境的创建.
IterationStatement:for(LexicalDeclaration Expressionopt; Expressionopt)语句
- 让oldEnv成为正在运行的执行上下文的LexicalEnvironment.
- 设loopEnv为NewDeclarativeEnvironment(oldEnv).
- 让isConst成为执行IsConstantDeclaration> 1. LexicalDeclaration的结果.
- 让boundNames成为LexicalDeclaration的BoundNames.
- 对于boundNames的每个元素dn
- 如果isConst为真,那么
- 执行loopEnv.CreateImmutableBinding(dn,true).
- 其他,
- 执行loopEnv.CreateMutableBinding(dn,false).
- 断言:上面对CreateMutableBinding的调用永远不会返回突然完成.
- 将正在运行的执行上下文的LexicalEnvironment设置为loopEnv.
- 让forDcl成为评估LexicalDeclaration的结果.
- 如果forDcl突然完成,那么
- 将正在运行的执行上下文的LexicalEnvironment设置为oldEnv.
- 返回完成(forDcl).
- 如果isConst为false,则让perIterationLets为boundNames,否则perIterationLets为«».
- 让bodyResult成为ForBodyEvaluation(第一个Expression,第二个Expression,Statement,perIterationLets,labelSet).
- 将正在运行的执行上下文的LexicalEnvironment设置为oldEnv.
- 返回完成(bodyResult).
那么为什么在运行以下测试时(我从之前引用的同一个问题中得到),var
执行速度比let
我预期的要慢,反之亦然?
(function() {
let varTime = performance.now()
for (var i = 0; i < 100000000; i++) {}
varTime = performance.now() - varTime;
console.log('var', varTime)
let letTime = performance.now()
for (let i = 0; i < 100000000; i++) {}
letTime = performance.now() - letTime;
console.log('let', letTime)
}).call({});
Run Code Online (Sandbox Code Playgroud)
TEST 1
var: 147.500ms
let: 138.200ms
TEST 2
var: 141.600ms
let: 127.100ms
TEST 3
var: 147.600ms
let: 122.200ms
Run Code Online (Sandbox Code Playgroud)
我同意@Derek \xe6\x9c\x95\xe6\x9c\x83\xe5\x8a\x9f\xe5\xa4\xab 的观点,如果不深入研究实现,真的很难推理。
\n\n但是,如果出现以下情况,您可能会错过一些步骤var
:
在 的情况下var
,实际上执行了更多步骤:
\n\n\n迭代语句:for (Expressionopt;Expressionopt;Expressionopt)语句
\n\n\n
\n- 如果第一个表达式存在,则\n \n
\n\n
- 令 exprRef 为计算第一个表达式的结果。
\n- 令 exprValue 为GetValue (exprRef)。
\n- \n
\n
- 如果突然返回(V)。
\n- \n
\n
- 如果 Type(V) 不是 Reference,则返回 V。
\n- \n
\n
- 令基数为 GetBase(V)。
\n- \n
\n
- 如果 IsUnresolvableReference(V),则抛出 ReferenceError 异常。
\n- \n
\n
- 如果 IsPropertyReference(V),则
\n- \n
\n
- \n
\n
- 如果 HasPrimitiveBase(V) 为 true,则
\n- \n
\n
- \n
\n
- \n
\n
- 断言:在这种情况下,base 永远不会为 null 或未定义。
\n- \n
\n
- \n
\n
- \n
\n
- 令base 为ToObject(base)。
\n- \n
\n
- \n
\n
- 返回基数。[[Get]](GetReferencedName(V), GetThisValue(V))。
\n- \n
\n
- 否则基础必须是环境记录,
\n- \n
\n
- \n
\n
- 返回base.GetBindingValue(GetReferencedName(V), IsStrictReference(V))(参见8.1.1)。
\n- ReturnIfAbrupt(exprValue)。
\n- 返回ForBodyEvaluation(第二个表达式,第三个表达式,语句,\xc2\xab\xc2\xbb,labelSet)。
\n
稍微额外的处理可能来自GetValue。
\n 归档时间: |
|
查看次数: |
182 次 |
最近记录: |