ES6之块级作用域与函数声明--读书笔记
2017-06-26 17:02
381 查看
函数能不能在块级作用域之中声明?
ES5 规定,函数只能在顶层作用域和函数作用域之中声明,不能在块级作用域声明。
// 情况一 if (true) { function f() {} } // 情况二 try { function f() {} } catch(e) { // ... }
上面两种函数声明,据 ES5 的规定都是非法的。
但是,浏览器没有遵守这个规定,为了兼容以前的旧代码,还是支持在块级作用域之中声明函数,因此上面两种情况实际都能运行,不会报错。
再来看一下ES6:
ES6 引入了块级作用域,明确允许在块级作用域之中声明函数。ES6 规定,块级作用域之中,函数声明语句的行为类似于let,在块级作用域之外不可引用。
下面看一段代码:
function f() { console.log('I am outside!'); } (function () { if (false) { // 重复声明一次函数f function f() { console.log('I am inside!'); } } f(); }());
ES6 理论上会得到“I am outside!”。因为块级作用域内声明的函数类似于let,对作用域之外没有影响。但是,如果你真的在 ES6 浏览器中运行一下上面的代码,是会报错的,这是为什么呢?
原因是若改变了块级作用域内声明的函数的处理规则,显然会对老代码产生很大影响。为了减轻因此产生的不兼容问题,ES6规定,浏览器的实现可以不遵守上面的规定,允许有自己的行为方式。
允许在块级作用域内声明函数。函数声明类似于var,即会提升到全局作用域或函数作用域的头部。
同时,函数声明还会提升到所在的块级作用域的头部。
注意,上面三条规则只对 ES6 的浏览器实现有效,其他环境的实现不用遵守,还是将块级作用域的函数声明当作let处理。
根据这三条规则,在浏览器的 ES6 环境中,块级作用域内声明的函数,行为类似于var声明的变量。
// 浏览器的 ES6 环境 function f() { console.log('I am outside!'); } (function () { if (false) { // 重复声明一次函数f function f() { console.log('I am inside!'); } } f(); }()); // Uncaught TypeError: f is not a function
上面的代码在符合 ES6 的浏览器中,都会报错,因为实际运行的是下面的代码。
// 浏览器的 ES6 环境 function f() { console.log('I am outside!'); } (function () { var f = undefined; if (false) { function f() { console.log('I am inside!'); } } f(); }()); // Uncaught TypeError: f is not a function
考虑到环境导致的行为差异太大,应该避免在块级作用域内声明函数。
//函数声明语句 { let a = 'hello'; function f() { return a; } //f(); //hello } //f(); //hello
建议:若需要,应写成函数表达式,而不是函数声明语句。如下
// 函数表达式 { let a = 'hello'; let f = function () { return a; }; } //
还需注意:ES6 的块级作用域允许声明函数的规则,只在使用大括号的情况下成立,如果没有使用大括号,就会报错。
// 报错 'use strict'; if (true) function f() {}
// 不报错 'use strict'; if (true) { function f() {} }
补充一下:
function f() { console.log('I am outside!'); } (function () { if (false) { // 重复声明一次函数f function f() { console.log('I am inside!'); } } f(); }());
ES5 中运行,会得到“I am inside!”,因为在if内声明的函数f会被提升到函数头部,实际运行的代码如下。
// ES5 环境 function f() { console.log('I am outside!'); } (function () { function f() { console.log('I am inside!'); } if (false) { } f(); }());
相关文章推荐
- es6学习第1天,箭头函数 块级作用域
- ES6的块级作用域--读书笔记
- javascript中不存在块级作用域,所以要小心使用在块级作用域中的函数声明所带来的作用域混乱.
- 【读书笔记】【深入理解ES6】#1-块级作用域绑定
- javascript的函数作用域及声明提前
- 一个题目引发的闭包、函数声明以及作用域的简单思考
- 【1练习】Objective-C 类的声明、函数消息的定义方法、字段作用域
- JS作用域为“函数级作用域”,记住最简明的一句“函数中声明的所有变量,无论是在哪里声明的,在整个函数中它们都是有定义的。”QQ253079952
- ES6-let带来了更简单的块级作用域
- ES6箭头函数和它的作用域
- 16_函数(【七】垃圾收集和块级作用域的概念)
- 函数声明与定义,作用域,函数声明与表达式的区别
- javascript中变量没有块级作用域---函数内申明的变量在整个函数中都有效!
- 127 函数作用域 块级作用域
- js中变量的函数作用域和声明提前
- 函数作用域和块级作用域?
- 标识符的作用域--程序级>文件级>类级>函数级>块级
- JS之 函数模仿块级作用域,私有变量,模块模式
- JavaScript中的作用域与函数和变量声明的提升
- 函数作用域和声明提前