一、立即执行函数表达式(IIFE)
var a = 2;
(function IIFE(global) {
var a = 3;
console.log(a); // 【注意】:3
console.log(global.a); // 【注意】:2
})(window);
console.log(a); //【注意】: 2
说明:
(function IIFE(){...})()
- 第一个()括号: 将【函数】变成了【表达式】
- 第二个()括号: 【执行了这个函数】
二、块作用域
- let
- const
- try... catch
总结:
- 【 var 变量】,不管写在哪里都是一样的,因为它们都会属于【外部作用域】
- 注意:【外部作用域】!==【全局作用域】
(一) let 和 var 对比
【例一】的问题:【对于for循环,var i = 0;】为什么在“外部”访问 i 时,结果是 10呢?【重要】
答:因为 用 var i ,此时 i 会绑定在【外部作用域(“函数作用域”或“全局作用域”)】,因此
在【for外部】,仍然会有 i,结果为 10
// 【例一】
for( var i= 0; i < 10; i++){
console.log( i ); // 0 , 1, 2, 3, .... 9
}
console.log( i ); //【注意】 10
【例二】的问题:【对于for循环,let i = 0;】为什么在“外部”i 会报错呢?【重要】
答:因为 用 let i ,此时 i 为【块级作用域】,因此,在【for外部】,没法访问到 i
// 【例二】
for( let i= 0; i < 10; i++){
console.log( i ); // 0 , 1, 2, 3, .... 9
}
console.log( '外部:',i ); // 【注意:报错了】Uncaught ReferenceError: i is not defined
【例三】的问题:为什么在“if外部”可以访问到 bar 呢?
答:因为 即使在 "if内部" 声明bar【var bar】, bar 还是属于【if外部作用域】,因此
【if外部】和【if内部】都可以访问到 bar 变量。
// 【例三】
var foo = true;
if(foo){
var bar = foo * 2;
console.log( bar ); // 2
}
console.log( bar );// 2
var foo = true;
if (foo) {
var bar = 5;
console.log(bar); // 5
}
console.log(bar); // 5
【例四】的问题:为什么在“if外部”访问 bar 会报错呢?
答:因为 let 是“块作用域”,尽在“块内部”有效。
// 【例四】
var foo = true;
if(foo){
let bar = foo * 2;
console.log( bar ); // 2
}
console.log( bar );// 【报错】Uncaught ReferenceError: bar is not defined
【例五】的问题:为什么在“let 变量”前面/上面“访问该变量” 会报错呢?
答:因为出现了【暂时性死区】, let 是“块作用域”,不会进行“变量提升”。
console.log( bar); // 【报错了】Uncaught ReferenceError: Cannot access 'bar' before initialization
let bar = 2;
(二) const
说明:const 用来创建【块作用域】常量,
什么是“常量”?
答:“常量”的值是【固定】的, 【修改值】会【引起错误】,但也有例外(TODO)
(三) try ... catch
说明:在try/catch的【 catch分句 】会创建一个【块作用域】,其中【声明的变量】仅在【catch内部有效】
例子:
try {
undefined(); // 执行一个【非法操作】来强制【制造一个“异常”】
}catch( err ){
console.log( err ); // 能够“正常执行”此时 catch 声明了【变量err】】仅在catch内部有效
}
console.log( err ); // 【报错了】Uncaught ReferenceError: err is not defined