1. 变量声明提升

先看以下代码:

1)var in_window = "a" in window; console.log(in_window);

2)var in_window = "a" in window; console.log(in_window); if(!("a" in window)) { var a = 1; }

3)var a; var in_window = "a" in window; console.log(in_window); if(!("a" in window)) { a = 1; }

控制台输出的结果分别是:false true true。如何解释? 这是由于在js的变量作用域中有个规则:所有变量声明都在范围作用域的顶部!也就是说,在2)代码中,if语句块内的申明的变量a,会自动提到上面去申明。其等价于3)。

由上述的分析可知,可以理解下面代码的输出结果是undefined。

if(!("a" in window)) { var a = 1; } console.log(a); //undefined  该代码其实相当于:var a; if(!("a" in window")) { a = 1; } console.log(a);

再试一次:

var s = '';

if (false) {

    var a = 1;

}

浏览器中的调试结果如下:

有图有真相。变量a的声明的确提升了。

巩固题:

var s = ''; while(false) { var a = 1; } console.log(a); //undefined

if(!("a" in window)) { a = 1 } console.log(a); //1

console.log(a); //报错,"ReferenceError: a is not defined."

2. 函数声明提升

定义函数有两种方式:一种是函数申明,另一种是函数表达式。函数申明形式:function functionName(arg0, arg1, arg2) { //函数体 },函数表达式形式:var functionName = function(arg0, arg1, arg2) { //函数体 } 。关于函数申明,它有一个重要特征就是函数声明提升,看下面的例子。

sayHi();

function sayHi() {

    console.log("hi");

}

浏览器中的调试结果如下: 发现函数sayHi已经被声明了,并且其值为sayHi函数。第一行代码执行后,输出hi。

若采用函数表式的形式,此时我们能看到变量声明提升的效果。

sayHi();

var sayHi = function() {

    console.log("hi");

}

在浏览中的调试效果如下:发现变量sayHi提升了,它的值是undefined,第一行代码执行的话,会报错:"TypeError:undefined is not a function"。

接下来的例子就很好理解。

if(!("a" in window)) { var a = function() { window.a = 1; } } console.log(a); //undefined 该代码等价于: var a; if(!("a" in window)) { a = function() { window.a = 1; } } console.log(a); 其实无论if语句块中的a被定义成何种类型的值,a的申明都提前了。(变量提升)

将上述代码变形如下:

if(!("a" in window)) { function a() { window.a = 1; }} console.log(a); //function a() { window.a = 1;}(函数申明提升)

由此可以总结出,所有函数声明也在范围作用域的顶部。那么函数声明和变量声明,哪个的优先级高呢?

3. 变量声明 VS 函数声明

如下图对比所示:函数声明会覆盖变量声明。

     VS      VS   

但是如果在变量声明的同时,对变量进行初始化,情况会有所不同。对同一个变量名,声明变量同时初始化变量优先级高于函数声明。

    VS      VS   

再练几题:

function a() { return false; }

var s = '';

if(a()) {

    var a = 1;

}

console.log(a);

上述代码输出的a值为:function a() { return false; }

function a() { return true; }

var s = '';

if(a()) {

    var a = 1;

}

console.log(a);

上述代码输出的a值为:1

function a() { return true; }

var a;

var s = '';

if(a()) {

    a = 1;

}

console.log(a);

上述代码输出的a值为:1

由对上述代码的分析:可以总结出如下规律:

1)变量声明提升变量申明在进入执行上下文就完成了。

只要变量在代码中进行了声明,无论它在哪个位置上进行声明, js引擎都会将它的声明放在范围作用域的顶部;

2)函数声明提升执行代码之前会先读取函数声明,意味着可以把函数申明放在调用它的语句后面。

只要函数在代码中进行了声明,无论它在哪个位置上进行声明, js引擎都会将它的声明放在范围作用域的顶部;

3)变量or函数声明函数声明会覆盖变量声明,但不会覆盖变量赋值。

同一个名称标识a,即有变量声明var a,又有函数声明function a() {},不管二者声明的顺序,函数声明会覆盖变量声明,也就是说,此时a的值是声明的函数function a() {}。注意:如果在变量声明的同时初始化a,或是之后对a进行赋值,此时a的值变量的值。eg: var a; var c = 1; a = 1; function a() { return true; } console.log(a); //1

时间:2014-10-17

地点:合肥

参考:http://www.cnblogs.com/yexiaochai/archive/2013/04/22/3034949.html

变量声明提升 Vs. 函数声明提升的更多相关文章

  1. 原型模式故事链(4)--JS执行上下文、变量提升、函数声明

    上一章:JS的数据类型 传送门:https://segmentfault.com/a/11... 好!话不多少,我们就开始吧.对变量提升和函数声明的理解,能让你更清楚容易的理解,为什么你的程序报错了~ ...

  2. JS 函数提升&变量提升以及函数声明&函数表达式的区别

    感谢原文作者:迟早会有猫 原文链接:https://www.cnblogs.com/SidselLoong/p/10515809.html 今天看js的变量提升问题,里面提到了函数提升.然后发现自己之 ...

  3. 【JS】函数提升变量提升以及函数声明和函数表达式的区别

    今天看js的变量提升问题,里面提到了函数提升.然后发现自己之前一直把函数声明和函数表达式弄错,导致函数提升出错 一.变量提升 console.log(a) var a=100 //undefined ...

  4. 【JS点滴】声明提前,变量声明提前,函数声明提前,声明提前的先后顺序

    声明提前,函数声明提前,好吧,老生常谈的问题了.正好,前些天在掘金看到一道关于声明提前的笔试题,那么这里就以这道题来作为本文的引子吧,代码如下: console.log(a)//? a();//? ; ...

  5. js变量的作用域、变量的提升、函数的提升

    变量的作用域在函数之外声明的变量,叫做全局变量,因为它可被当前文档中的任何其他代码所访问.在函数内部声明的变量,叫做局部变量,因为它只能在当前函数的内部访问. ECMAScript 6 之前的 Jav ...

  6. Js 变量声明提升和函数声明提升

    Js代码分为两个阶段:编译阶段和执行阶段 Js代码的编译阶段会找到所有的声明,并用合适的作用域将它们关联起来,这是词法作用域的核心内容 包括变量声明(var a)和函数声明(function a(){ ...

  7. js中变量提升(一个是变量,一个是函数表达式都会存在变量提升,函数声明不存在)

    一.变量提升 在ES6之前,JavaScript没有块级作用域(一对花括号{}即为一个块级作用域),只有全局作用域和函数作用域.变量提升即将变量声明提升到它所在作用域的最开始的部分.上个简历的例子如: ...

  8. javascript变量声明提升和函数声明提升

    在ES6之前,JavaScript没有块级作用域(一对花括号{}即为一个块级作用域),只有全局作用域和函数作用域.变量提升即将变量声明提升到它所在作用域的最开始的部分. JS的解析过程分为两个阶段:预 ...

  9. JavaScript变量提升和函数声明预解析

    1.首先理解函数作用域 在JavaScript中,变量的定义并不是以代码块作为作用域的,而是以函数作用作用域的.也就是说,如果变量是在某个函数中定义的,那么它在函数以外的地方是不可见的.而如果该变量是 ...

随机推荐

  1. Jenkins TcpSlaveAgentListener Config

    http://wenku.baidu.com/link?url=wDbeRoqh8ERRvBKXsKVi7biWe8e369iZmYTfEFDz0aI1Sj5YjXq_AN1gFjFjiS0yBw0W ...

  2. 【svn】一个设置,少写几个字

    以下场景仅适用于修改bug的时候,在提交代码的时候少写几个字,嘿嘿: 1.打开[SVN 属性],在代码目录右键 2.打开BUG跟踪设置窗口 3.输入BUG的URL前缀以及%BUGID%,如 复选框,建 ...

  3. 监控web服务方法

    本地监控:端口  netstat -anltup | grep 80  nmap ip -p 80 telnet ip:80 lsof -i :80|wc -l 进程 ps -ef| grep ngi ...

  4. C#随学随记

    1.Microsoft.NET是基于Windows平台的一种技术(简称.NET),它包含了能在.NET Framework平台运行的所有语言..NET Framework是微软为开发应用程序创建的一个 ...

  5. 解读HTML 5新语法 提高语义价值

    HTML 5的新标记 设计者们需要完成的任务是要给HTML 5开发一个更丰富的和更有含义的语义,当然可以想象这种新方案将会是很灵活和很高效的,同时与所有的现代互联网标准相适应.下面就是一些将要在HTM ...

  6. python(三)set集合

    set集合的特点是无序.不重复序列 创建集合: 1 2 3 4 5 6 7 8 9 10 11 12 13 a.s1 = {11,22} b.s2 = set() c.s3 = set([11,22, ...

  7. TCP/IP协议(二)

    2014-09-04 11:03:27   注:关于seq 和 ack 的理解,seq为发送的字节的第一个序号,一直累加,ack接收字节的最后一个序号+1,建立连接和结束连接时的SYN.FIN标志位占 ...

  8. Fiddler—PC上实现手机的抓包

    PC上安装Fiddler之后,可以抓取各种浏览器的请求,通过一些设置可以获取iPhone.安卓手机.windows phone的请求.具体的工作原理我也不多说(哼,绝对不是因为我不懂XD),主要说下如 ...

  9. tar等

    tar格式,会打包成一个文件,可以对多个目录,或者多个文件进行打包tar命令只是打包,不会压缩,打包前后大小是一样的 tar命令 -c //打包-x //解压-f //指定文件-t //查看 tar ...

  10. Hibernate <查询缓存>

    查询缓存: 定义:查询缓存它是基于二级缓存的,可以保存普通属性查询的结果,查询对象实体时,他会保存id作为键,查询结果作为值,下个对象访问时,可以直接查到 查询缓存查询实体对象时,显著的特点是,会执行 ...