专栏首页前端一会灵活使用JS函数声明与函数表达式要弄清哪两点?

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

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

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

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

 1console.log(fn());
 2function fn(){
 3    return 'helloNitx';
 4}
 5//打印:helloNitx
 6
 7console.log(fn());
 8var fn = function(){
 9    return 'helloNitx';
10}
11//输出:TypeError: fn is not a function

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

 1//错误示例:不要把函数声明放在条件语句中,有的浏览器会把fn声明为返回1的函数,有的浏览器把fn声明为返回2的函数
 2if(true){
 3    function fn(){
 4        console.log('1');
 5    }
 6}else {
 7    function fn(){
 8        console.log('2');
 9    }
10}
11fn();   
12
13//伪正确示例:
14var foo = null;
15if(true){
16    foo = function(){
17        console.log('3');
18    }
19}else {
20    foo = function(){
21        console.log('4');
22    }
23}
24foo();

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

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

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

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

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

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

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

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

本文分享自微信公众号 - 前端小二(frontendxiao2)

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2018-12-11

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • MessagePack Java Jackson 序列化和反序列化 POJO 为 MessagePack 的数组类型用来与 msgpack-java:0.6 保持兼容性

    在 msgpack-java 0.6 或者早期的版本中,POJO 在 MessagePack 中被序列化和反序列化为数组变量。

    HoneyMoose
  • 关于爱情!诗人有情诗, 程序员有情码。

    注释:「你说他很好,要和他一起生活。我转过身没舍得告诉你,我看到的未来不能同时容下他和你,但愿是我记不起,我原来从来没有见过你」

    用户5997198
  • thinkphp的 getField用法总结

    getField方法是ThinkPHP中用来获取字段值的方法,区别于select和find方法,通常仅用于获取个别字段的值。但是事实上并没有那么简单,该方法的用...

    公众号php_pachong
  • 【Flutter 专题】48 图解 Android 原生集成 Flutter Module

    和尚接触了 Flutter 一段时间,但与原生交互方面还未曾接触,今天根据 官方文档 学习一下 Android 原生如何集成最基本的 Flutter...

    阿策
  • 【Flutter 专题】49 图解 Flutter 与 Android 原生交互

    和尚上一篇简单学习了一下 Android 原生接入 Flutter Module,现在学习一下两者之间的数据交互;

    阿策
  • PHP简单实现“相关文章”功能的方法

    通常在做内容网站的时候,需要在每一篇文章中出现与该文章相关的文章列表。对于大多数人来说,使用的方法通常是:建立一个关键词列表,判断每篇文章包含有那些关键词,最后...

    公众号php_pachong
  • Android 极光推送与 WebView 日常问题小结

    极光推送在日常的应用中应用广泛,集成简单送达率较高,和尚刚开始集成时很方便,但是随着项目的逐渐变大,分包和组件化等应用比较多,此时单独出 push ...

    阿策
  • PHP similar_text() 函数

    注释:levenshtein() 函数比 similar_text() 函数更快。不过,similar_text() 函数通过更少的必需修改次数提供更精确的结果...

    公众号php_pachong
  • 项目中常常出现的问题,答案在这里!

    >如果是技术问题,接下去第二问,这个问题能解决吗?是否需要大牛一起来看一下。如果回答需要帮助,直接找技术一起看。

    公众号php_pachong
  • 学习路线

    我们可以通过今年最新的TIOBE编程语言排行榜看到,JAVA在“昨天”、和“今天”都强势霸据榜单第一名,哇哦,看起来好像很厉害,那么为我们又为什么要学习Java...

    BWH_Steven

扫码关注云+社区

领取腾讯云代金券