以下是我的个人思考
非严格模式下
首先我是看了阮一峰的ES6 标准的一个例子
function f(){ console.log(' I am outside'); }
(function (){
if(false){
//重复声明一次函数f
function f() { console.log('I am inside'); }
}
f();
}());
按照阮一峰的讲解,ES6支持块级作用域,不管会不会进入到if代码,其内部声明的函数皆不会影响到块级作用域的外部,在ES6中输出结果应该为"I am outside"
我在Node.js v7.9.0在非严格模式下运行的时候发生了错误 TypeError: f is not a function。
这说明 f是已经声明了,但它还不是一个函数。我又把代码中false改成了true。
function f(){ console.log(' I am outside'); }
(function (){
if(true){
//重复声明一次函数f
function f() { console.log('I am inside'); }
}
f();
}());
结果控制台输出"I am inside"。 所以我觉得在非严格模式下,不管块会不会被执行,块内定义的函数都会影响块外的作用域,会有类似”变量提升“的效果。 就像下面这段代码那样:
function f(){ console.log(' I am outside'); }
(function (){
var f;
if(false){
//给f赋值
f = function() { console.log('I am inside'); }
}
f();
}());
严格模式下
但是在严格模式下,就不会有影响
'use strict'
(function(){
if(false){
function f(){
console.log("I am inside!");
}
}
console.log(typeof f);
console.log(f.toString());
f();
})();
输出结果:
/*
function
function f(){
console.log("I am outside!");
}
I am outside!
*/
按照阮一峰的说法,严格模式下,函数只能在顶层作用域和函数作用域内声明,其他情况就会报错,可是我在Node.js下用严格模式运行并没有报错。 那我就在想,会不会在严格模式下,在块级作用域内定义的函数根本就声明不了?那也就不存在会不会影响块外作用域的事情了。 我又把代码改了下:
function f(){
console.log("I am outside!");
}
(function(){
if(true){
function f(){
console.log("I am inside!");
}
console.log(typeof f);
console.log(f.toString());
}
console.log(typeof f);
console.log(f.toString());
f();
})();
输出结果:
/*
function
function f(){
console.log("I am inside!");
}
function
function f(){
console.log("I am outside!");
}
I am outside!
*/
好复杂呀,但我觉得没必要搞清楚那么复杂的问题。其实,在嵌套的函数中,最好别使用这种语法,而是使用
let f = function() {};
来自酷炫的 CNodeMD
@zhanzhenzhen 能不能再讲清楚一点?😝
来自酷炫的 CNodeMD
根据Douglas Crockford的《JavaScript精粹》一书,函数最好都不要使用function f()
这种形式,而应该使用f=function()
这种形式(原因我忘了)。似乎很多“函数式语言”,例如F#,就是只支持后者的形式。该书作者是JSON的设计者。
我猜想原因可能就是容易搞清楚前后顺序吧。所以我从很多年前开始,就使用这种方式了。而且这种方式和ES2015箭头函数的区别也小。比较“兼容”。
@zhanzhenzhen 正好最近阅读日买了这本书,回头去看看,谢谢啦
来自酷炫的 CNodeMD