前面的话

  一般认为,javascript代码在执行时是由上到下一行一行执行的。但实际上这并不完全正确,主要是因为声明提升的存在。本文是深入理解javascript作用域系列第三篇——声明提升(hoisting)

变量声明提升

a = 2 ;
var a;
console.log( a );

  直觉上,会认为是undefined,因为var a声明在a = 2;之后,可能变量被重新赋值了,因为会被赋予默认值undefined。但是,真正的输出结果是2

console.log( a ) ;
var a  =  2 ;

  鉴于上面的特点,可能会认为这个代码片段也会同样输出2。但,真正的输出结果是undefined

  所有这些和观感相违背的原因是在于编译器的编译过程

  第一篇介绍过作用域的内部原理。引擎会在解释javascript代码之前首先对其进行编译。编译阶段中的一部分工作就是找到所有的声明,并用合适的作用域将它们关联起来

  包括变量和函数在内的所有声明都会在任何代码被执行前首先被处理

var a = 2 ;

  这个代码片段实际上包括两个操作:var a 和 a = 2

  第一个定义声明是在编译阶段由编译器进行的。第二个赋值操作会被留在原地等待引擎在执行阶段执行

//对变量a的声明提升到最上面后,再执行代码时,控制台输出2
var a;
a = 2 ;
console.log(a);

  声明从它们在代码中出现的位置被“移动”到了最上面,这个过程就叫作提升(hoisting)

  [注意]每个作用域都会进行提升操作

console.log(a);
var a = 0;
function fn(){console.log(b);var b = 1;function test(){console.log(c);var c = 2;}test();
}
fn();

//变量声明提升后,变成下面这样
var a ;
console.log(a);
a = 0;
function fn(){var b;console.log(b);b = 1;function test(){var c ;console.log(c);c = 2;}test();
}
fn();

函数声明提升

  声明包括两种:变量声明和函数声明。不仅变量声明可以提升,函数声明也有提升操作

foo();
function foo(){console.log(1);//1
}

  上面这个代码片段之所以能够在控制台输出1,就是因为foo()函数声明进行了提升,如下所示:

function foo(){console.log(1);
}
foo();

  函数声明会提升,但函数表达式却不会提升

foo();
var foo = function(){console.log(1);//TypeError: foo is not a function
}

  上面这段程序中的变量标识符foo被提升并分配给全局作用域,因此foo()不会导致ReferenceError。但是foo此时并没有赋值,foo()由于对undefined值进行函数调用而导致非法操作,因此会抛出TypeError异常

//变量提升后,代码如下所示:
var foo;
foo();
foo = function(){console.log(1);
}

  即使是具名的函数表达式也无法被提升

foo();//TypeError: foo is not a function
var foo = function bar(){console.log(1);
};

//声明提升后,代码变为:
var foo;
foo();//TypeError: foo is not a function
foo = function bar(){console.log(1);
};

  [注意]函数表达式的名称只能在函数体内部使用,而不能在函数体外部使用

var bar;
var foo = function bar(){console.log(1);
};
bar();//TypeError: bar is not a function

函数覆盖

  函数声明和变量声明都会被提升。但是,函数声明会覆盖变量声明

var a;
function a(){}
console.log(a);//'function a(){}'

  但是,如果变量存在赋值操作,则最终的值为变量的值

var a=1;
function a(){}
console.log(a);//1

var a;
function a(){};
console.log(a);//'function a(){}'
a = 1;
console.log(a);//1

  [注意]变量的重复声明是无用的,但函数的重复声明会覆盖前面的声明(无论是变量还是函数声明)

  【1】变量的重复声明无用

var a = 1;
var a;
console.log(a);//1

  【2】由于函数声明提升优先于变量声明提升,所以变量的声明无作用

var a;
function a(){console.log(1);
}
a();//1

  【3】后面的函数声明会覆盖前面的函数声明

a();//2
function a(){console.log(1);
}
function a(){console.log(2);
}

  所以,应该避免在同一作用域中重复声明

转载于:https://www.cnblogs.com/yujihaia/p/7417354.html

深入理解javascript作用域系列第三篇相关推荐

  1. 深入理解javascript作用域系列第四篇——块作用域

    前面的话 尽管函数作用域是最常见的作用域单元,也是现行大多数javascript最普遍的设计方法,但其他类型的作用域单元也是存在的,并且通过使用其他类型的作用域单元甚至可以实现维护起来更加优秀.简洁的 ...

  2. javascript面向对象系列第三篇——实现继承的3种形式

    前面的话 学习如何创建对象是理解面向对象编程的第一步,第二步是理解继承.开宗明义,继承是指在原有对象的基础上,略作修改,得到一个新的对象.javascript主要包括类式继承.原型继承和拷贝继承这三种 ...

  3. 深入理解this机制系列第三篇——箭头函数

    前面的话 this机制与函数调用有关,而作用域则与函数定义有关.有没有什么是可以将this机制和作用域联系起来的呢?本文将介绍ES6新增的内容--箭头函数 痛点 对于闭包的痛点在于,闭包的this默认 ...

  4. 深入理解javascript函数系列第二篇——函数参数

    前面的话 javascript函数的参数与大多数其他语言的函数的参数有所不同.函数不介意传递进来多少个参数,也不在乎传进来的参数是什么数据类型,甚至可以不传参数.本文是深入理解javascript函数 ...

  5. JavaScript 开发进阶:理解 JavaScript 作用域和作用域链(上)

    作用域是JavaScript最重要的概念之一,想要学好JavaScript就需要理解JavaScript作用域和作用域链的工作原理.今天这篇文章对JavaScript作用域和作用域链作简单的介绍,希望 ...

  6. JavaScript 开发进阶:理解 JavaScript 作用域和作用域链

    作用域是JavaScript最重要的概念之一,想要学好JavaScript就需要理解JavaScript作用域和作用域链的工作原理.今天这篇文章对JavaScript作用域和作用域链作简单的介绍,希望 ...

  7. [未完整]JavaScript 开发进阶:理解 JavaScript 作用域和作用域链

    转载:http://www.cnblogs.com/lhb25/archive/2011/09/06/javascript-scope-chain.html 作用域是JavaScript最重要的概念之 ...

  8. [深度][PyTorch] DDP系列第三篇:实战与技巧

    [深度][PyTorch] DDP系列第三篇:实战与技巧 转自:https://zhuanlan.zhihu.com/p/250471767 零. 概览 想要让你的PyTorch神经网络在多卡环境上跑 ...

  9. 【JavaScript 教程系列第 10 篇】判断一个数是整数还是小数

    这是[JavaScript 教程系列第 10 篇],如果觉得有用的话,欢迎关注专栏. 思路 如果一个数是整数,那么 parseInt() 函数和 parseFloat() 函数的返回值是相同的,反之返 ...

最新文章

  1. php判断值是否为空
  2. 去除浮动列表的右边距 利用负边距
  3. AOJ 558 Cheese(bfs)
  4. python中easygui和tkinter_python easygui Tkinter
  5. 计算机软件编程英语词汇集锦
  6. java 球弹跳的高度_关于皮球弹跳高度的几个问题
  7. Flash CS6 专业版破解教程、Flash CS6 激活序列号、破解补丁
  8. 微型计算机8088拆字实验编程,LGN-01B型 PLC可编程控制器及单片机开发系统综合实验台...
  9. 山东科技大学计算机学院陈卓艳,转发教务部表彰大学生学习竞赛获奖单位和个人通知...
  10. The PostScript backend does not support transparency; partially transparent artists will be rendered
  11. PowerBI帮助提示工具
  12. python 正则表达式 断言 不定长表达式_【教程】详解Python正则表达式之: (?!…) negative lookahead assertion 前向否定匹配 /前向否定断言...
  13. pytorch训练FER2013模型
  14. QT 图片浏览器(一)
  15. HAFederation
  16. 2015 去哪儿 面试以及霸面之旅 虽然没过。。
  17. PMP备考指南之第二章:项目运作环境
  18. 云服务器如何配置比较好
  19. 2022年电工(初级)考试题及电工(初级)考试试卷
  20. UVA 10935 卡片游戏

热门文章

  1. Java成神之路——String长度限制
  2. 微型计算机接口技术2018真题,2018年微机原理及接口技术复习题.doc
  3. 创建型模式、结构型模式和行为型模式_设计模式之创建型模式
  4. 寻找素数分配线程算法
  5. linux5.5 里dns,linux red hat 5.5 dns 问题求解
  6. 【Flink】Flink 反压机制 导致checkpoint 失败
  7. 【Elasticsearch】Elasticsearch 5.1.2滚动升级至 5.6.4
  8. 【Flink】数据传输 挖个坑 把自己埋了 ClassCastException String cannot be cast to [LJava.lang.String
  9. Spring 容器简介
  10. mac安装cmake