灵活使用JS函数声明与函数表达式要弄清哪两点?

函数声明和函数表达式到底有什么区别?

要弄清函数声明和函数表达式的区别,首先要明白在JS中声明和表达式的行为存在十分微妙而又十分重要的差别。

首先,函数声明会在任何表达式被解析和求值之前先行被解析和求值。即使声明位于源代码中的最后一行,它也会先于同一作用域中位于最前面的表达式被求值。其实原理就是靠的作用域与变量提升机制,这块先不细说,后面单独写篇文章吧。

console.log(fn());
function fn(){
    return 'helloNitx';
}
//打印:helloNitx

console.log(fn());
var fn = function(){
    return 'helloNitx';
}
//输出:TypeError: fn is not a function

这里要补充个重要的知识点:由于通过条件语句控制函数声明的行为并未标准化,因此在不同环境下可能会得到不同的结果。所以不要在条件语句中使用函数声明,而可以使用函数表达式。

//错误示例:不要把函数声明放在条件语句中,有的浏览器会把fn声明为返回1的函数,有的浏览器把fn声明为返回2的函数
if(true){
    function fn(){
        console.log('1');
    }
}else {
    function fn(){
        console.log('2');
    }
}
fn();   

//伪正确示例:
var foo = null;
if(true){
    foo = function(){
        console.log('3');
    }
}else {
    foo = function(){
        console.log('4');
    }
}
foo();

注意,这里第二个示例为什么我注释为伪正确示例?看下面这段关于函数声明规则官方摘录:

函数声明只能出现在程度或函数体内。从句法上讲,它们不能出现在中,比如不能出现在if、while或for语句。因为块只能包含语句,而不能包含函数声明这样的源元素。而唯一可能让表达式出现在块中的情形,就是让它作为表达式语句的一部分。但是规范也明确规定表达式语句不能以function开头。而这实际上就是说,函数表达式同样也不能出现在语句或块中。由于存在上述限制,只要函数出现在块中,实际上就可以看作是一个语法错误,而不用管什么函数声明或表达式。

所以较佳实践应是,不要把函数写在语句或块中,不管是声明函数还是表达式函数。

表达式函数里有匿名表达式函数和命名表达式函数。

所谓的命名函数表达式,指的是有名字的函数表达式,这个名字技术上称为标识符。var bar = function foo(){};实际上就是一个命名函数表达式,这里有个细节需要注意:即这个名字(标识符)只在新定义的函数的作用域中有效,规范要求标识符不能在外围的作用域中有效。

var f = function foo(){
    return typeof foo;      //foo只在内部作用域中有效
}
console.log(typeof foo);    //undefined
console.log(typeof f);      //function

这个名字(标识符)的作用在于调试方便,其他与匿名函数表达式如var bar = function(){};没有区别。另外浏览器的调试器通常功能较简,遇到复杂的程序时,效果不大。

在实际开发中,函数声明和函数表达式可以灵活选择,只是需要理清两点:变量和作用域的提升问题,在函数表达式中注意匿名函数表达式和命名函数表达式的区别。

喜欢本文请扫下方二维码,关注微信公众号: 前端小二,查看更多我写的文章哦,多谢支持。
在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值