一道面试题引发的讨论
2018-07-27 本文已影响32人
诺之林
本文的示例代码参考scope
目录
面试题
已知代码如下
for (var i = 0; i < 5; i++) {
(function (i) {
setTimeout(function () {
console.log(i);
}, i * 100)
})(i)
}
此时输出结果
A. 0,0,0,0,0
B. 1,1,1,1,1
C. 5,5,5,5,5
D. 0,1,2,3,4
想知道正确答案? 复制运行上述代码即可
作用域
cat >> var-01.js << EOF
for (var i = 0; i < 5; i++) {
setTimeout(function () {
console.log(i);
}, i * 100)
}
EOF
node var-01.js # 5 5 5 5 5
var定义的变量的在整个作用域内都有效
变量提升
cat >> var-02.js << EOF
var i;
for (i = 0; i < 5; i++) {
setTimeout(function () {
console.log(i);
}, i * 100)
}
EOF
node var-02.js # 5 5 5 5 5
var定义的变量的声明会提升到作用域的前面
块作用域
cat >> block-01.js << EOF
for (let i = 0; i < 5; i++) {
setTimeout(function () {
console.log(i);
}, i * 100)
}
EOF
node block-01.js # 0 1 2 3 4
let/const定义的变量/常量会绑定到所在的块中(通常即{...}内部)
重新绑定
cat >> block-02.js << EOF
var i;
for (i = 0; i < 5; i++) {
const j = i;
setTimeout(function () {
console.log(j);
}, j * 100)
}
EOF
node block-02.js # 0 1 2 3 4
重新绑定是实现每次迭代时绑定块作用域的语法糖
函数作用域
cat >> function-01.js << EOF
for (var i = 0; i < 5; i++) {
(function () {
setTimeout(function () {
console.log(i);
}, i * 100)
})()
}
EOF
node function-01.js # 5 5 5 5 5
"i * 100"存在于setTimeout函数作用域
立即执行函数表达式
cat >> function-02.js << EOF
for (var i = 0; i < 5; i++) {
(function (j) {
setTimeout(function () {
console.log(j);
}, j * 100)
})(i)
}
EOF
node function-02.js # 0 1 2 3 4
立即执行函数表达式 = Immediately Invoked Function Expression (IIFE)
挑战题
已知代码如下
for (var i = 0; i < 5; i++) {
let j = i;
(function (j) {
setTimeout(function () {
console.log(j);
}, j * 100)
})(j)
}
此时 每行代码的变量的作用域分别是?
想知道正确答案? 联系笔者交流我们的理解