这是该系列的第2篇笔记!
让学习“上瘾”,成为更好的自己!!!
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>块级作用域</title>
</head>
<body>
<script>
/*
ES5只有全局作用域和函数作用域,没有块级作用域
*/
// 1,为什么需要块级作用域?
// for one: 内层变量可能会覆盖外层变量
// var tmp = new Date();
// function f() {
// console.log(tmp);
// if (false) {
// var tmp = 'hello world';
// }
// }
// f(); // undefined --> why? 变量提升导致内层的temp变量覆盖了外层的tmp变量
// for two: 用来计数的循坏变量泄漏为全局变量
// var s = 'hello';
// for (var i = 0; i < s.length; i++) {
// console.log(s[i]);
// }
// console.log(i); // 5 --> 变量i原本只用来控制循坏,但是循坏结束后,并没有消失,而是泄漏为全局变量
// 2, ES6的块级作用域
// (1) let实际上为JavaScript新增了块级作用域
// function f1() {
// let n = 5;
// if (true) {
// let n = 10;
// }
// console.log(n); // 5
// }
// f1();
// (2)ES6允许块级作用域的任意嵌套
// 外层作用域无法读取内层作用域的变量!
// {{{{
// {let insane = 'hello world';}
// console.log(insane); // error
// }}}};
// 内层作用域可以定义外层作用域的同名变量
// {{{{
// let insane = 'hehfje';
// {let insane = 'hello world';}
// console.log(insane);
// }}}};
// 立即执行匿名函数(IIFE)与块级作用域
// IIFE
// (function(){
// var temp = 2333;
// }());
// // 块级作用域写法
// {
// let temp = 23243;
// }
// 3,块级作用域与函数声明
// (1)ES5规定,函数只能在顶层作用域和函数作用域之中声明,不能在块级作用域中声明
// case 1:
// if(true){
// function(){
// }
// }
// case 2:
// try {
// function f(){
// //
// }
// } catch(e){
// //
// }
// 以上两种都是ES5中非法的写法,但浏览器为了兼容旧代码,这两种情况都可以运行
// (2) ES6引入块级作用域,明确规定在块级作用域中声明函数
// --> ES6规定,在块级作用域中,函数声明语句的行为类似于let,在块级作用域之外不可引用
// ES5中
// function f(){
// console.log('i am outside!');
// }
// (function(){
// // function f(){console.log('i am inside!'); } // 正常
// if (false){
// function f(){console.log('i am inside!'); } // error
// }
// f();
// }());
// ES6中
// 改变块级作用域内声明的函数的处理机制,会对旧代码产生影响
// 为了减轻因此产生的不兼容问题:ES6规定:
// a, 允许在块级作用域内声明函数
// b, 函数声明类似var,即会提升至全局作用域或函数作用域的头部
// c, 同时,函数声明还会提升到所在块级作用域的头部
//【注意】这3条规则只对ES6的浏览器的实现有效,其他环境下的实现不用遵守,仍旧将块级作用域的函数声明当作let处理即可
// 浏览器ES6的环境 --> 以下的代码在ES6环境中都会报错
// function f(){
// console.log('i am outside!');
// }
// (function(){
// if (false){
// f();
// function f(){console.log('i am inside!'); } // error
// }
// f(); // Uncaught TypeError: f is not a function
// }());
// ES6中实际运行的代码为:
// function f(){
// console.log('i am outside!');
// }
// (function(){
// var f ; // 函数声明类似var,即会提升至全局作用域或函数作用域的头部
// if(false){
// function f(){ console.log('i am inside!!'); }
// f(); // 同时,函数声明还会提升到所在块级作用域的头部
// }
// f();
// }());
// 【注意】考虑到导致行为差异太大,应该避免在块级作用域内声明函数!!!
// 如果确实需要,要写成函数表达式的形式,而不是函数声明的语句
// 不报错写法(函数表达式)
// function f(){
// console.log('i am outside!');
// }
// (function(){
// if(false){
// let f = function(){ console.log('i am inside!!'); }
// }
// f();
// }());
// 函数声明的语句
// {
// let a = 'secret';
// function f() {
// return a;
// }
// }
// ===等价于====
// 函数表达式的语句
// {
// let a = 'secret';
// let f = function() {
// return a;
// };
// }
// ES6的块级作用域允许声明函数的规则只在使用大括号的情况下成立,如果没有使用大括号,则会报错(严格模式下)
// 不报错
// 'use strict';
// if(true){
// function f(){}
// }
// // 报错
// 'use strict';
// if(true)
// function f(){}
// 4,do表达式(只是提案!!)
// 本质上,块级作用域是一个语句,将多个操作封装在一起,没有返回值
// {
// let t = 32;
// t = t + 12;
// }
// 【改变】
// 在块级作用域之前加上do,可以是块级作用域变成do表达式,即可以返回值
// let x = do {
// let t = 32;
// t = t + 12;
// };
// console.log(x);
// test
// 为了减轻因此产生的不兼容问题:ES6规定:
// a, 允许在块级作用域内声明函数
// b, 函数声明类似var,即会提升至全局作用域或函数作用域的头部
// c, 同时,函数声明还会提升到所在块级作用域的头部
//
// console.log(f); // undefined
// // f(); // error
// if (true){
// function f(){ console.log('i am inside!');}
// f(); // 'i am inside!'
// }
// f(); // 'i am inside!'
</script>
</body>
</html>