全面了解函数声明与函数表达式、变量提升

 更新时间:2016年08月09日 10:39:18   投稿:jingxian  
下面小编就为大家带来一篇全面了解函数声明与函数表达式、变量提升。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧

函数的声明方式

在定义一个函数的时候通常有两种声明方式:

foo(){};   // 函数声明
var foo = function(){};  // 函数表达式

不同之处

1、函数表达式后面加括号可以直接执行
2、函数声明会提前预解析

预解析

让我们先看一个例子:

foo();     // 函数声明
foo_later();   // foo_later is not a function

function foo(){ console.log('函数声明'); }
var foo_later = function(){ console.log('函数表达式'); }

可以看到,函数声明foo被预解析了,它可以在其自身代码之前执行;而函数表达式foo_later则不能。要解决这个问题,我们先要弄清楚JavaScript解析器的工作机制。

变量提升(hoist)

JavaScript解析器会在自身作用域内将变量和函数声明提前(hoist),也就是说,上面的例子其实被解析器理解解析成了以下形式:

function foo(){ console.log('函数声明'); }  // 函数声明全部被提前
var foo_later;   // 函数表达式(变量声明)仅将变量提前,赋值操作没有被提前

foo();       
foo_later();   


foo_later = function(){ console.log('函数表达式'); }

这样也就可以解释,为什么在函数表达式之前调用函数,会返回错误了,因为它还没有被赋值,只是一个未定义变量,当然无法被执行。

同样的,我们也可以试着猜测下面这段代码的输出结果:

console.log(declaredLater);  

var declaredLater = "Now it's defined!";

console.log(declaredLater);  

该段代码可以被解析成一下形式:

 

var declaredLater;     

console.log(declaredLater);  // undefined

declaredLater = "Now it's defined!";

console.log(declaredLater);  // Now it's defined!

 变量声明被提到最前(所以不会报出变量不存在的错误),但赋值没有被提前,所以第一次的输出结果是undefined。

需要注意的是

由于函数声明会被预解析,所以不要使用此种方法来声明不同函数。尝试猜想下面例子的输出结果:

if(true){
 function aaa(){
  alert('1');
 } 
}
else{
 function aaa(){
  alert('2');
 }
}

aaa();

与我们预想的不同,该段代码弹出的是“2”.这是因为两个函数声明在if语句被执行之前就被预解析了,所以if语句根本没有用,调用aaa()的时候直接执行了下面的函数。

总结

通过上面的讲解可以总结如下:

•变量的声明被提前到作用域顶部,赋值保留在原地

•函数声明整个“被提前”

•函数作为值赋给变量时只有变量“被提前”了,函数没有“被提前”

通过练习上面的实例自己多感受一下。另外,作为最佳实践:变量声明一定要放在作用域/函数的最上方(JavaScript 只有函数作用域!)。

以上这篇全面了解函数声明与函数表达式、变量提升就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • JS实现点击登录弹出窗口同时背景色渐变动画效果

    JS实现点击登录弹出窗口同时背景色渐变动画效果

    这篇文章主要介绍了JS实现点击登录弹出窗口同时背景色渐变动画效果,涉及JavaScript基于鼠标事件及时间函数定时触发形成渐变动画的相关技巧,需要的朋友可以参考下
    2016-03-03
  • 用file标签实现多图文件上传预览

    用file标签实现多图文件上传预览

    本文介绍了用file标签实现多图文件上传预览的方法。具有很好的参考价值,下面跟着小编一起来看下吧
    2017-02-02
  • JS弹出层遮罩,隐藏背景页面滚动条细节优化分析

    JS弹出层遮罩,隐藏背景页面滚动条细节优化分析

    下面小编就为大家带来一篇JS弹出层遮罩,隐藏背景页面滚动条细节优化分析。小编觉得挺不错的,现在分享给大家,也给大家做个参考
    2016-04-04
  • typescript在node.js下使用别名(paths)无效的问题详解

    typescript在node.js下使用别名(paths)无效的问题详解

    这篇文章主要给大家介绍了关于typescript在node.js下使用别名(paths)无效问题的相关资料,文中通过图文以及示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2022-07-07
  • javascript模拟git diff命令实现文本文件差异比较

    javascript模拟git diff命令实现文本文件差异比较

    这篇文章主要为大家详细介绍了javascript如何模拟git diff命令实现文本文件差异比较效果,文中的示例代码讲解详细,感兴趣的小伙伴可以参考下
    2023-12-12
  • JS不完全国际化&本地化手册 之 理论篇

    JS不完全国际化&本地化手册 之 理论篇

    最近加入到新项目组负责前端技术预研和选型,其中涉及到一个熟悉又陌生的需求——国际化&本地化。熟悉的是之前的项目也玩过,陌生的是之前的实现仅仅停留在"有"的阶段而已。趁着这个机会好好学习整理一下,为后面的技术选型做准备
    2016-09-09
  • javascript 中事件冒泡和事件捕获机制的详解

    javascript 中事件冒泡和事件捕获机制的详解

    这篇文章主要介绍了javascript 中事件冒泡和事件捕获机制的详解的相关资料,网上的相关资料有很多,但是讲的不是多清楚,通过本文希望能让大家理解掌握,需要的朋友可以参考下
    2017-09-09
  • JavaScript绘制游戏地图并且操控人物移动

    JavaScript绘制游戏地图并且操控人物移动

    JavaScript开发小游戏,目标是使用JavaScript绘制简单的二维地图,采用二维数组存储地图信息,使用表格绘制地图,每个td单元格存储数据,使用JavaScript keyPress键盘事件监听WASD键,按键触发时人物做出相应操作,人物下一步碰撞到障碍物,终止人物运动
    2023-10-10
  • js使用栈来实现10进制转8进制与取除数及余数

    js使用栈来实现10进制转8进制与取除数及余数

    这篇文章主要介绍了js使用栈来实现10进制转8进制、js取除数、余数,需要的朋友可以参考下
    2014-06-06
  • 如何基于JS截获动态代码

    如何基于JS截获动态代码

    这篇文章主要介绍了JS注入eval, Function系统函数并截获动态代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-12-12

最新评论