javascript变量声明提升(hoisting)
javascript的变量声明具有hoisting机制,JavaScript引擎在执行的时候,会把所有变量的声明都提升到当前作用域的最前面。
先看一段代码
|
1
2
3
4
5
|
var v = "hello";(function(){ console.log(v); var v = "world";})(); |
这段代码运行的结果是什么呢?
答案是:undefined
这段代码说明了两个问题,
第一,function作用域里的变量v遮盖了上层作用域变量v。代码做少些变动
|
1
2
3
4
5
|
var v = "hello";if(true){ console.log(v); var v = "world";} |
输出结果为”hello”,说明javascript是没有块级作用域的。函数是JavaScript中唯一拥有自身作用域的结构。
第二,在function作用域内,变量v的声明被提升了。所以最初的代码相当于:
|
1
2
3
4
5
6
|
var v = "hello";(function(){ var v; //declaration hoisting console.log(v); v = "world";})(); |
声明、定义与初始化
声明宣称一个名字的存在,定义则为这个名字分配存储空间,而初始化则是为名字分配的存储空间赋初值。
用C++来表述这三个概念
|
1
2
3
|
extern int i;//这是声明,表明名字i在某处已经存在了int i;//这是声明并定义名字i,为i分配存储空间i = 0;//这是初始化名字i,为其赋初值为0 |
javascript中则是这样
|
1
2
|
var v;//声明变量vv = "hello";//(定义并)初始化变量v |
因为javascript为动态语言,其变量并没有固定的类型,其存储空间大小会随初始化与赋值而变化,所以其变量的“定义”就不像传统的静态语言一样了,其定义显得无关紧要。
声明提升
当前作用域内的声明都会提升到作用域的最前面,包括变量和函数的声明
|
1
2
3
4
5
6
|
(function(){ var a = "1"; var f = function(){}; var b = "2"; var c = "3";})(); |
变量a,f,b,c的声明会被提升到函数作用域的最前面,类似如下:
|
1
2
3
4
5
6
7
|
(function(){ var a,f,b,c; a = "1"; f = function(){}; b = "2"; c = "3";})(); |
请注意函数表达式并没有被提升,这也是函数表达式与函数声明的区别。进一步看二者的区别:
|
1
2
3
4
5
6
7
8
9
|
(function(){ //var f1,function f2(){}; //hoisting,被隐式提升的声明 f1(); //ReferenceError: f1 is not defined f2(); var f1 = function(){}; function f2(){}})(); |
上面代码中函数声明f2被提升,所以在前面调用f2是没问题的。虽然变量f1也被提升,但f1提升后的值为undefined,其真正的初始值是在执行到函数表达式处被赋予的。所以只有声明是被提升的。
名字解析顺序
javascript中一个名字(name)以四种方式进入作用域(scope),其优先级顺序如下:
1、语言内置:所有的作用域中都有 this 和 arguments 关键字
2、形式参数:函数的参数在函数作用域中都是有效的
3、函数声明:形如function foo() {}
4、变量声明:形如var bar;
名字声明的优先级如上所示,也就是说如果一个变量的名字与函数的名字相同,那么函数的名字会覆盖变量的名字,无论其在代码中的顺序如何。但名字的初始化却是按其在代码中书写的顺序进行的,不受以上优先级的影响。看代码:
|
1
2
3
4
5
6
7
8
9
|
(function(){ var foo; console.log(typeof foo); //function function foo(){} foo = "foo"; console.log(typeof foo); //string})(); |
如果形式参数中有多个同名变量,那么最后一个同名参数会覆盖其他同名参数,即使最后一个同名参数并没有定义。
以上的名字解析优先级存在例外,比如可以覆盖语言内置的名字arguments。
命名函数表达式
可以像函数声明一样为函数表达式指定一个名字,但这并不会使函数表达式成为函数声明。命名函数表达式的名字不会进入名字空间,也不会被提升。
|
1
2
3
4
5
|
f();//TypeError: f is not a functionfoo();//ReferenceError: foo is not definedvar f = function foo(){console.log(typeof foo);};f();//functionfoo();//ReferenceError: foo is not defined |
命名函数表达式的名字只在该函数的作用域内部有效。
From:http://openwares.net/js/javascript_declaration_hoisting.html
javascript变量声明提升(hoisting)的更多相关文章
- JavaScript 变量声明提升
JavaScript 变量声明提升 一.变量提升的部分只是变量的声明,赋值语句和可执行的代码逻辑还保持在原地不动 二.在基本的语句(或者说代码块)中(比如:if语句.for语句.while语句.swi ...
- 浅谈JavaScript变量声明提升
前段时间阿里实习生内推,一面就被刷了,也是郁闷.今天系统给发通知,大致意思就是内推环节不足以了解彼此,还可以参加笔试,于是赶紧再投一次.官网流程显示笔试时间3月31日,时间快到了,开始刷题.网上搜了一 ...
- javascript变量声明提升和函数声明提升
在ES6之前,JavaScript没有块级作用域(一对花括号{}即为一个块级作用域),只有全局作用域和函数作用域.变量提升即将变量声明提升到它所在作用域的最开始的部分. JS的解析过程分为两个阶段:预 ...
- JavaScript变量声明提升
JavaScript代码在被解析引擎执行前,会被“编译”把变量声明等放在合适的作用域中,如果不了解这一点,会让人产生很多疑惑. 文章:详解js变量声明提升
- javascript变量声明 及作用域
javascript变量声明提升(hoisting) http://openwares.net/js/javascript_declaration_hoisting.html 可能要FQ一下 java ...
- 【转】javascript变量声明 及作用域
javascript变量声明提升(hoisting) javascript的变量声明具有hoisting机制,JavaScript引擎在执行的时候,会把所有变量的声明都提升到当前作用域的最前面. 先看 ...
- javascript变量声明及作用域总结
javascript变量声明及作用域总结 一.总结 一句话总结:还是得好好看书,光看视频是不得行的,浅学无用,要相互印证,要真正理解才有用,比如<Javascript权威指南> 书 1.j ...
- 解读JavaScript中的Hoisting机制(js变量声明提升机制)
hoisting机制:javascript的变量声明具有hoisting机制,JavaScript引擎在执行的时候,会把所有变量的声明都提升到当前作用域的最前面. 知识点一:javascript是没有 ...
- 深入理解javascript作用域系列第三篇——声明提升(hoisting)
× 目录 [1]变量 [2]函数 [3]优先 前面的话 一般认为,javascript代码在执行时是由上到下一行一行执行的.但实际上这并不完全正确,主要是因为声明提升的存在.本文是深入理解javasc ...
随机推荐
- Python爬虫之编写一个可复用的下载模块
看用python写网络爬虫第一课之编写可复用的下载模块的视频,发现和<用Python写网络爬虫>一书很像,写了点笔记: #-*-coding:utf-8-*- import urllib2 ...
- 基于vue的滚动条组件之--element隐藏组件滚动条scrollbar使用
在项目中,总是需要用到滚动条,但windows浏览器默认的滚动条是很丑的,为了页面美观,可以考虑优化滚动条样式. vue Element UI官方文档上并没有放出滚动条相关的示例说明,但是实际上是有 ...
- Codeforces Round #286 (Div. 2)A. Mr. Kitayuta's Gift(暴力,string的应用)
由于字符串的长度很短,所以就暴力枚举每一个空每一个字母,出现行的就输出.这么简单的思路我居然没想到,临场想了很多,以为有什么技巧,越想越迷...是思维方式有问题,遇到问题先分析最简单粗暴的办法,然后一 ...
- How to install php 7.x on CentOS 7
Step 1: Setup the Webtatic YUM repo Precompiled PHP 7.x binaries are available for CentOS 7 from the ...
- 浅学soap--------3
//person.wsdl 标签 <?xml version="1.0" ?> <definitions name="person" targ ...
- 使用Visio画UML模型
Microsoft Office Visio“UML 模型图” 模板为创建复杂软件系统的面向对象的模型 (模型:建模系统的一种抽象表示,它从特定的视角并在某一抽象级别上指定建模系统.) 提供全面的支持 ...
- GC(Garbage Collection)垃圾回收机制
1.在垃圾回收器中,程序员没有执行权,只有通知它的权利. 2.程序员可以通过System.gc().通知GC运行,但是Java规范并不能保证立刻运行. 3.finalize()方法,是java提供给程 ...
- eShopOnWeb
eShopOnWeb https://www.cnblogs.com/sheng-jie/p/9616675.html 构建现代Web应用 1.引言 eShopOnWeb是基于ASP.NET Core ...
- LeetCode Beautiful Arrangement
原题链接在这里:https://leetcode.com/problems/beautiful-arrangement/description/ 题目: Suppose you have N inte ...
- list_for_each_entry
内核里面用list_for_each_entry实在太多了,定义在linux-3.10/include/linux/list.h: /** * list_for_each_entry - iterat ...