进来刷题!
题目 1: 变量提升与暂时性死区
console.log(a);
let a = 5;
var b = 10;
console.log(b);
问题:这段代码的输出是什么?为什么?
题目 2: 块级作用域陷阱
for (var i = 0; i < 3; i++) {
setTimeout(() => console.log(i), 100);
}
for (let j = 0; j < 3; j++) {
setTimeout(() => console.log(j), 100);
}
问题:两个循环的输出分别是什么?解释差异原因。
题目 3: 函数作用域链
var x = 10;
function outer() {
console.log(x);
var x = 20;
function inner() {
console.log(x);
}
inner();
}
outer();
问题:这段代码的输出顺序是什么?解释每个输出值的来源。
题目 4: const 的意外行为
const obj = { a: 1 };
obj.a = 2;
obj.b = 3;
console.log(obj);
const arr = [1];
arr.push(2);
console.log(arr);
问题:这段代码会报错吗?输出结果是什么?解释 const 的这种行为。
题目 5: 闭包与循环
function createFunctions() {
var result = [];
for (var i = 0; i < 3; i++) {
result[i] = function() {
return i;
};
}
return result;
}
var funcs = createFunctions();
console.log(funcs[0](), funcs[1](), funcs[2]());
问题:输出结果是什么?如何修改才能输出 0,1,2?
题目 6: 全局变量污染
function foo() {
a = 1;
var b = 2;
}
foo();
console.log(a);
console.log(b);
问题:这段代码的输出是什么?为什么?
题目 7: 箭头函数的作用域
var name = 'global';
const obj = {
name: 'object',
say: () => {
console.log(this.name);
}
};
obj.say();
问题:输出结果是什么?解释箭头函数的 this 绑定规则。
题目 8: 变量遮蔽
let x = 1;
{
let x = 2;
console.log(x);
}
console.log(x);
问题:输出结果是什么?解释 let 的块级作用域特性。
题目 9: 函数声明 vs 函数表达式
foo();
bar();
function foo() {
console.log('foo');
}
var bar = function() {
console.log('bar');
};
问题:这段代码的执行结果是什么?解释函数声明和函数表达式的区别。
题目 10: 动态作用域陷阱
var a = 1;
function outer() {
var a = 2;
inner();
}
function inner() {
console.log(a);
}
outer();
问题:输出结果是什么?JavaScript 是静态作用域还是动态作用域?
- 报错,10
for (var i = 0; i < 3; i++) {
setTimeout(() => console.log(i), 100); // 输出3次3
}
for (let j = 0; j < 3; j++) {
setTimeout(() => console.log(j), 100); // 输出0,1,2
}
解析:var
声明的 i
是函数级作用域,循环结束后值为3,所有回调都引用同一个 i
, let
声明的 j
是块级作用域,每次循环都创建新的 j
,回调捕获各自的 j
值, 这是经典的循环+闭包问题,let
解决了 var
的作用域缺陷
var x = 10;
function outer() {
console.log(x); // undefined
var x = 20;
function inner() {
console.log(x); // 20
}
inner();
}
outer();
//1. 第一个 `console.log` 输出 `undefined`:由于函数内 `var x` 提升,但未赋值
1. `inner()` 输出 `20`:沿作用域链找到最近的 `x`(outer函数内的 `x`)
1. 全局 `x=10` 被遮蔽,未被使用
- {a:2,b:3},[1,2].解释:是引用不可变,不是值不可变 5.3,3,3
//**解决方案**:
//1. **使用IIFE创建闭包**:
for (var i = 0; i < 3; i++) {
(function(i) {
result[i] = function() { return i; };
})(i);
}
//1. **改用let**(最佳方案):
for (let i = 0; i < 3; i++) {
result[i] = function() { return i; };
}
function foo() {
a = 1; // 意外创建全局变量
var b = 2; // 局部变量
}
foo();
console.log(a); // 1
console.log(b); // ReferenceError: b is not defined
//解析:
//1. 未声明直接赋值的变量(`a=1`)会成为全局变量(严格模式下会报错)
//1. `var b` 是函数局部变量,外部不可访问
- global
1. 箭头函数的 `this` 绑定定义时的上下文(此处是全局作用域)
1. 普通函数的 `this` 指向调用对象(若用 `function(){}` 会输出 'object')
箭头函数this绑定规则 **继承自定义时的外围作用域**(词法作用域)
**在定义时就已经确定**,且**永远不会改变**
- 2,1
foo(); // 'foo'
bar(); // TypeError: bar is not a function
function foo() {
console.log('foo');
}
var bar = function() {
console.log('bar');
};
1. 函数声明(`function foo`)会整体提升,可在声明前调用
1. 函数表达式(`var bar = function`)只有变量声明提升,赋值不提升
- 1
JavaScript 采用**静态作用域**(词法作用域)(即:函数的作用域在函数定义时确定,与函数在哪里调用无关(动态作用域则与调用位置相关))
`inner` 的 `a` 在定义时绑定到全局 `a`,而非调用位置的 `a`
动态作用域语言会输出2,但JavaScript不是动态作用域