代码片段:

var a = 1;

function foo() {
console.log(a); //输出为undefined
if (!a) {
var a = 2;
}
alert(a);
}; foo();

以上代码执行的结果为:2

一、声明与定义

1、声明:是指声称某样东西的存在,比如:一个变量或一个函数;

var a; //声明变量

2、定义:是指某样东西的具体实现,比如:一个变量的值是多少,一个函数的函数体是什么;

var a = 1; //定义变量

即:

var a;     //声明变量
a = 1; //定义变量(赋值)
var a = 1; //合二为一,声明变量并复制给它
//当你认为你只做了一件事的时候(var a = 1;),
//实际上解释器把这件事情分解成了两个步骤:一个是声明(var a;),另一个是定义(a = 1;)

回到最开始的代码片段:

var a = 1;

function foo() {
var a; //变量提升至顶部
if (!a) {
a = 2;
}
alert(a); //此时的a并不是函数体外的全局变量
}; foo();

如代码所示,当进入函数体内时,又定义了新的变量a,当时其值为undefined,故if判断条件为真,接着为新的变量a赋值2,输出结果为2。

二、作用域

1、为什么不是在if语句内声明新变量a?

答:因为javascript没有块级作用域,只有函数作用域,并不是代表遇见{ }就产生新的作用域。

当解析器读到if语句时,发现其声明了新的变量a,解析器会将声明提升至作用域顶部(这是默认行为,并且无法改变),这一过程就是变量提升。

如果就是要输出结果为1,那就要在函数体内部创建新的作用域,如:

var a =1;
function foo(){
if(!a){
(function(){ //会创建一个新的函数作用域,该作用域在函数体内部,故alert
var a = 2;//不过根据“闭包”,这个作用域可以访问上层作用域
})();
}
alert(a);
} foo();

“请始终保持作用域内所有的变量声明都放置在作用域顶部。”

2、在javascript中,有四种方式可以让命名进入到作用域中(按优先级排序):

(1)语言定义的命名:如this 或 arguments,他们在所有作用域内都有效,并且优先级最高;

(2)形式参数:函数定义时声明的形参会作为变量被提升至函数的作用域内,所以,形参是本地的,不是外部的或全局的,也可在执行函数时把外部变量传进来,传进来之后就变成本地的;

(3)函数声明:函数体内部也还可以声明函数;

(4)变量声明:即函数作用域内声明的变量会提升至作用域顶部。

三、函数声明和函数表达式的差别

1、当函数或变量提升时,只提升了声明,没有提升定义;

2、比如:

function test(){
foo();
function foo(){
alert("我是会出现的哦");
}
} test();
function test(){
foo();
var foo = function (){
alert("我是不会出现的哦");
}
} test();

具体来讲:

栗子一:函数foo 是一个声明,既然是声明,就会被提升,这就是函数声明的提升,函数声明和函数体都将被提升至作用域顶部;

栗子二:被提升的仅仅是函数名foo ,函数定义还停留在原处,因此在执行foo() 时,作用域只知道函数foo 的存在,不知道它是干嘛的,故执行会报错(undefined is not a function),这就是函数表达式,只有函数命名会提升,函数体还停留在原地。

原文链接:https://segmentfault.com/a/1190000000348228

javaScript函数提升及作用域的更多相关文章

  1. 【译】学习JavaScript中提升、作用域、闭包的终极指南

    这似乎令人惊讶,但在我看来,理解JavaScript语言最重要和最基本的概念是理解执行上下文.通过正确学习它,你将很好地学习更多高级主题,如提升,作用域链和闭包.考虑到这一点,究竟什么是"执 ...

  2. JavaScript变量提升及作用域

    今天在知乎看前端面试题的时候,看到这样的问题,发现自己懂的真的是太少了,看了给的例子,所以写一下自己的理解. 首先放一段代码: var v= “hello JavaScript”; alert(v); ...

  3. 浅谈JavaScript 函数作用域当中的“提升”现象

    在JavaScript当中,定义变量通过var操作符+变量名.但是不加 var 操作符,直接赋值也是可以的. 例如 : message = "hello JavaScript ! " ...

  4. JavaScript 函数作用域的“提升”现象

    在JavaScript当中,定义变量通过var操作符+变量名.但是不加 var 操作符,直接赋值也是可以的.例如 : message = "hello JavaScript ! " ...

  5. 深入理解javascript函数定义与函数作用域

    最近在学习javascript的函数,函数是javascript的一等对象,想要学好javascript,就必须深刻理解函数.本人把思路整理成文章,一是为了加深自己函数的理解,二是给读者提供学习的途径 ...

  6. javascript中的变量作用域以及变量提升

    在javascript中, 理解变量的作用域以及变量提升是非常有必要的.这个看起来是否很简单,但其实并不是你想的那样,还要一些重要的细节你需要理解. 变量作用域 “一个变量的作用域表示这个变量存在的上 ...

  7. JavaScript系列文章:变量提升和函数提升

    第一篇文章中提到了变量的提升,所以今天就来介绍一下变量提升和函数提升.这个知识点可谓是老生常谈了,不过其中有些细节方面博主很想借此机会,好好总结一下. 今天主要介绍以下几点: 1. 变量提升 2. 函 ...

  8. javascript中的变量作用域以及变量提升详细介绍

    在javascript中, 理解变量的作用域以及变量提升是非常有必要的.这个看起来是否很简单,但其实并不是你想的那样,还要一些重要的细节你需要理解变量作用域 “一个变量的作用域表示这个变量存在的上下文 ...

  9. js:函数与变量作用域的提升

    一.要彻底理解JS的作用域和Hoisting,只要记住以下三点即可:      1.所有申明都会被提升到作用域的最顶上      2.同一个变量申明只进行一次,并且因此其他申明都会被忽略      3 ...

随机推荐

  1. cannot be cast to javax.servlet.Servlet

    在第一次开发Maven项目时,maven环境和仓库以及eclipse都和讲师讲解的一样,可是却遇到下面这个问题: java.lang.ClassCastException: servlet.UserS ...

  2. sql2008 发送邮件

    --"管理"-"数据库邮件"-右键"配置数据库右键" Exec msdb.dbo.sp_send_dbmail @profile_name= ...

  3. 重学C语言---04字符串和格式化输入/输出

    1.程序示例 //talkback.c一个能为你提供一些信息的对话框 #include <stdio.h> #include <string.h> //提供strlen函数原型 ...

  4. 我的第一个python web开发框架(8)——项目结构与RESTful接口风格说明

    PS:再次说明一下,原本不想写的太啰嗦的,可之前那个系列发布后发现,好多朋友都想马上拿到代码立即能上手开发自己的项目,对代码结构.基础常识.分类目录与文件功能结构.常用函数......等等什么都不懂, ...

  5. 再识QT(1)

    2015年的时候开始接触QT,自学了1个月,由于没有项目驱动,也没人指导,最终还是撇下了,水平也仅限于拖拖控件,做一些简单的界面,对QT的内部机制完全是懵逼的.时隔两年,最近由于公司项目需要使用QT, ...

  6. 游标的小知识(借鉴and整理)

    一.游标(用来存储多条查询数据的一种数据结构(结果集),它有一个指针,用来从上往下移动,从而达到遍历每条记录的作用) 游标也可以理解为逐行返回SQL语句的结果集 如何编写一个游标? 1.声明游标 de ...

  7. Python之qq邮件

    用python发送电子邮件验证这个功能,可以说花费了我很久时间,这也是为什么我重头敲了之前的两遍代码.不要说我傻,仅仅是笨了一点而已 ^.- . 之前我所参考是如何发送 GMail. 但是我并不想这么 ...

  8. django-rest-framework之序列化

    前言:昨天学习了rest-framework序列化方面的知识,故写了博客记录一下.官网:http://www.django-rest-framework.org/tutorial/1-serializ ...

  9. jQuery源码的一个坑

    纯吐槽 大半夜也真是够了,想学着jQ造个小轮子巩固下js,结果一开始就卡住了. 虽然之前也看过源码,但是主要是研究方法实现什么的,对于框架主函数和入口结构不怎么熟悉,于是想着一步一步调试看看. $(' ...

  10. 两个HTML地址栏传中文参数乱码

    这个不叫乱码,我非专业.这个是url编码,js本身就是读取url编码的.对于js获取url的中文你可以尝试用escape() encodeURI() encodeURIComponent() deco ...