【02】块级作用域

【02】块级作用域

魔芋总结:
为什么要有块级作用域?
  • 01,内层变量覆盖外层变量,因为变量提升。函数提升。
  • 02,用来计数的循环变量泄露为全局变量。循环结束后,它并没有消失,泄露成了全局变量。

03, ES6允许块级作用域的任意嵌套。
04, 内层作用域可以和外层作用域定义同名的变量。
05, 立即执行匿名函数(IIFE)不再必要了。
06, 函数的作用域,在其定义的块级作用域之内。

需要注意的是,如果在严格模式下,函数只能在顶层作用域和函数内声明,其他情况(比如if代码块、循环代码块)的声明都会报错。





块级作用域
为什么需要块级作用域?
ES5只有全局作用域和函数作用域,没有块级作用域,这带来很多不合理的场景。

第一种场景,内层变量可能会覆盖外层变量。
var tmp = new Date();

function f(){
  console.log(tmp);
  if (false){
    var tmp = "hello world";
  }
}

f() // undefined

上面代码中,函数f执行后,输出结果为 undefined ,原因在于变量提升,导致内层的tmp变量覆盖了外层的tmp变量。


第二种场景,用来计数的循环变量泄露为全局变量。
var s = 'hello';

for (var i = 0; i < s.length; i++){
  console.log(s[i]);
}

console.log(i); // 5

上面代码中,变量i只用来控制循环,但是循环结束后,它并没有消失,泄露成了全局变量。

ES6的块级作用域
let 实际上为JavaScript新增了块级作用域。
function f1() {
  let n = 5;
  if (true) {
    let n = 10;
  }
  console.log(n); // 5
}

上面的函数有两个代码块,都声明了变量 n ,运行后输出5。这表示外层代码块不受内层代码块的影响。如果使用 var 定义变量 n ,最后输出的值就是10。

ES6允许块级作用域的任意嵌套。
{{{{{let insane = 'Hello World'}}}}};

上面代码使用了一个五层的块级作用域。外层作用域无法读取内层作用域的变量。
{{{{{let insane = 'Hello World'}
  console.log(insane); // 报错
}}}};

内层作用域可以定义外层作用域的同名变量。
{{{{let insane = 'Hello World';{let insane = 'Hello World';}}}}};





块级作用域的出现,实际上使得获得广泛应用的立即执行匿名函数(IIFE)不再必要了。
// IIFE写法
(function () {var tmp = ...;...}());
// 块级作用域写法
{let tmp = ...;...}




另外,ES6也规定,函数本身的作用域,在其所在的块级作用域之内。
function f() {
	console.log('I am outside!');
}
(function () {
	if (false) { // 重复声明一次函数f
		function f() {
			console.log('I am inside!');
		}
	}
	f();
}());


上面代码在ES5中运行,会得到“I am inside!”,但是在ES6中运行,会得到“I am outside!”。这是因为ES5存在函数提升,不管会不会进入  if 代码块,函数声明都会提升到当前作用域的顶部,得到执行;而ES6支持块级作用域,不管会不会进入if代码块,其内部声明的函数皆不会影响到作用域的外部。

{
  let a = 'secret';
  function f() {
    return a;
  }
}
f() // 报错

上面代码中,块级作用域外部,无法调用块级作用域内部定义的函数。如果确实需要调用,就要像下面这样处理。
let f;{let a = 'secret';
  f = function () {return a;}}f(); // "secret"



**

猜你喜欢

转载自www.cnblogs.com/moyuling/p/8992514.html