try{
throw 2;
}catch(a){
console.log( a ); // 2
}
console.log( a ); // ReferenceError
在 ES6 中引入了 let 关键字(var 关键字的表亲),用来在任意代码块中声明变量。if (..) { let a = 2; } 会声明一个劫持了 if 的 { .. } 块的变量,并且将变量添加到这个块中。
let 进行的声明不会在块作用域中进行提升。声明的代码被运行之前,声明并不“存在”。
{ console.log( bar ); // ReferenceError!
let bar = 2;
}
除了 let 以外,ES6 还引入了 const,同样可以用来创建块作用域变量,但其值是固定的(常量)
var foo = true;
if (foo) {
var a = 2;
const b = 3; // 包含在 if 中的块作用域常量
a = 3; // 正常!
b = 4; // 错误!
}
console.log( a ); // 3
console.log( b ); // ReferenceError!
foo();
function foo() { //提升
console.log( a ); //undefined
var a = 2;
}
foo(); // 不是 ReferenceError, 而是 TypeError!
var foo = function bar() { //不提升
// ...
};
即使是具名的函数表达式,名称标识符在赋值之前也无法在所在作用域中使用
foo(); // TypeError
bar(); // ReferenceError
var foo = function bar() {
// ...
};
这个代码片段经过提升后,实际上会被理解为以下形式:
var foo;
foo(); // TypeError
bar(); // ReferenceError
foo = function() {
var bar = ...self... // ...
}
函数会首先被提升,然后才是变量。
要注意避免重复声明,特别是当普通的 var 声明和函数声明混合在一起的时候,否则会引起很多危险的问题!
第五章 作用域闭包
function foo() {
var a = 2;
function bar() {
console.log( a );
}
return bar;
}
var baz = foo(); //执行后 foo()不会回收
baz(); // 2 —— 这就是闭包的效果。
第一章 作用域是什么
var a=2; 变量的赋值操作会执行两个动作,首先编译器会在当前作用域中声明一个变量(如 果之前没有声明过),然后在运行时引擎会在作用域中查找该变量,如果能够找到就会对 它赋值。(var a; a=2;)
遍历嵌套作用域链的规则很简单:引擎从当前的执行作用域开始查找变量,如果找不到, 就向上一级继续查找。当抵达最外层的全局作用域时,无论找到还是没找到,查找过程都 会停止。
第二章 词法作用域
js 函数作用域 “欺骗”词法作用域:eval(..) 和 with eval() 严格模式下执行有自己的作用域,非严格模式下全局作用域, with 副作用
性能问题 使用了 eval(..) 或 with JS引擎对代码的优化没有任何意义
第三章 函数作用域和块作用域
函数作用域的含义是指,属于这个函数的全部变量都可以在整个函数的范围内使用及复用(事实上在嵌套的作用域中也可以使用) IIFE (function(){ .. }()) 跟 (function(){…})() 一样 没有本质区别 块作用域 从 ES3 开始,try/catch 结构在 catch 分句中具有块作用域。
在 ES6 中引入了 let 关键字(var 关键字的表亲),用来在任意代码块中声明变量。if (..) { let a = 2; } 会声明一个劫持了 if 的 { .. } 块的变量,并且将变量添加到这个块中。 let 进行的声明不会在块作用域中进行提升。声明的代码被运行之前,声明并不“存在”。
除了 let 以外,ES6 还引入了 const,同样可以用来创建块作用域变量,但其值是固定的(常量)
函数作用域和块作用域的行为是一样的,可以总结为:任何声明在某个作用域内的变量,都将附属于这个作用域。
第四章 提升
变量和函数在内的所有声明都会在任何代码被执行前首先被处理。 只有声明本身会被提升,而赋值或其他运行逻辑会留在原地。 函数声明会被提升,但是函数表达式却不会被提升.
即使是具名的函数表达式,名称标识符在赋值之前也无法在所在作用域中使用
函数会首先被提升,然后才是变量。 要注意避免重复声明,特别是当普通的 var 声明和函数声明混合在一起的时候,否则会引起很多危险的问题!
第五章 作用域闭包
拜bar() 所声明的位置所赐,它拥有涵盖 foo() 内部作用域的闭包,使得该作用域能够一直存活,以供 bar() 在之后任何时间进行引用。 bar() 依然持有对该作用域的引用,而这个引用就叫作闭包。
闭包的出现往往是函数式编程的语言里 闭包的本质是静态作用域。因为 JavaScript 没有动态作用域,所以函数访问的都是定义时的作用域,所以闭包才得以实现。
作用如下: