谈javascript变量声明
之前的面试中遇到过一道面试题
var a =10;
(function(){
console.log(a);
var a =20;}
)()
- 短短5行代码log的结果是什么?
- 如果把
var a = 20;和console.log(a)语句顺序对调呢?
这道题目的答案是undefined。不是10。
关键在于javascript的变量声明有一个hoisting机制,变量声明永远都会被提升至作用域的最顶端(注意测试还只是声明,还没有赋值)。其实上面的语句相当于:

var a =10;
(function(){
var a;//在这里对变量hoisting,先声明
console.log(a);
a =20;//再赋值
})()

再精简一点:

bla =2
var bla; // 这是分割线,上下代码的效果其实是一样的 var bla;
bla =2;

也就是先使用,再声明(注意是声明,还没有赋值),这样一来,声明和赋值就被分开来了。所以最佳实践都推荐最好在函数的顶端把需要使用的变量首先声明一遍。
同理,我们可以理解下面的代码也是会报错的
f()//明显这里有错,因为f还没有被赋一个函数
var f =function(){
console.log("Hello");
}
但有一个问题,如果将上例f的函数声明修改一下,还会报错吗
f()//可以运行吗?
function f(){
console.log("Hello");
}
这里我其实想强调的是两种函数声明的var f = function () {}和function f() {}差别。
事实上,javascript中所有的函数声明(function declarations)和变量声明(variable declarations)都会被提升(hoisted)至它们所在作用域的最顶端。需要注意的是函数声明只有一种,也就是function f() {}的形式。而var f = function () {}是什么?你可以理解为它是将一个匿名函数(当然也可以取函数名,下面会解释)赋值给了一个变量。
就哪上面两个例子来说,同样是想实现先使用再定义的效果。只有第二种有用,虽然函数f在使用之后才定义,但是在javascript解释器中,它仍然是先于执行语句被定义的。
而第一个例子,执行的效果是这样的
var f;
f()//没有定义任何函数,当然无法执行
f =function(){
console.log("Hello");
}
这么看来,虽然javascript是允许先执行再声明,但切勿这么做,请遵循先声明再使用的好习惯。
再看看另一种情况,如果我把之前的函数定义
var f =function(){};
- 给右侧的匿名函数增加函数名
- 以右侧函数名来执行函数
- 能成功吗?
var f =function ab(){};
ab();
答案是否定的,因为上面的代码对f函数的定义是以命名函数表达式(Named Function Expressions),而并非真正的函数声明,注意该函数名只在该函数的作用域内有用。下面这段代码充分说明了它的意义:

var f =function foo(){
return typeof foo;
};
typeof foo;// "undefined"
f();// "function"

那么如此声明还有什么意义呢?好吧,就我目前找到的资料而言,这样做的好处就是便于调试。
接下来考虑一些意想不到的边缘,虽然我觉得一个程序员写出下面的代码有点自找苦吃,而且应该是在实战中避免的,但作为考试的题目来说是值得一说的。比如对比下面两段代码:

function value(){
return 1;
}
var value;
alert(typeof value);//"function"
function value(){
return 1;
}
var value =1;
alert(typeof value);//"number"

第一段代码想说明的是函数声明会覆盖变量声明,注意是声明,还没有赋值。如代码中,虽然同名变量在函数后再次声明,但是typeof的结果仍然是function
第二段代码想说明的是函数声明不会覆盖变量赋值或者说初始化,如代码所示
Name Resolution Order
为什么会有上面的结果,为什么函数的声明会覆盖变量的声明。就是因为name resolution order。我不知道怎么翻译这个名词,暂且就翻译为名称解析顺序吧。
在javascript中,一个变量名(name)有四种方式进入作用域(scope)中
- 语言内置,所有的作用域中都有
this和arguments关键字 - 形式参数,函数的参数在整个作用域中都是有效的
- 函数声明
- 变量声明
上面列出的四种顺序也正是由高到底的优先级的顺序(关于这点我有所保留,我测试的结果是参数和函数的优先级都会比语言内置的优先级高,你可以把形式参数取名为arguments,或者定义一个函数名为arguments,结果内置的argument说被覆盖了),一旦一个变量名已经声明了,那么它就不可能被其他更低优先级的变量声明形式所覆盖。
谈javascript变量声明的更多相关文章
- 浅谈JavaScript变量声明提升
前段时间阿里实习生内推,一面就被刷了,也是郁闷.今天系统给发通知,大致意思就是内推环节不足以了解彼此,还可以参加笔试,于是赶紧再投一次.官网流程显示笔试时间3月31日,时间快到了,开始刷题.网上搜了一 ...
- 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 变量声明提升
JavaScript 变量声明提升 一.变量提升的部分只是变量的声明,赋值语句和可执行的代码逻辑还保持在原地不动 二.在基本的语句(或者说代码块)中(比如:if语句.for语句.while语句.swi ...
- JavaScript变量声明与变量声明提前
JavaScript变量声明 JavaScript中存储数据的容器称为变量.用关键字和标识符创建新变量的语句,称为变量声明.可以通过关键字var进行变量声明,在ES6中增加了let.const关键字声 ...
- JavaScript变量声明提前
上周四吃完午饭,leader发了一道JavaScript的题目给我们做,我们Team里面有做前端的,有做后台的,也有做mobile web的,所以大家对题目的理解各自都不一样,然后在QQ讨论组里面进行 ...
- JavaScript 变量声明提前
<JavaScript权威指南>中指出:JavaScript变量在声明之前已经可用,JavaScript的这个特性被非正式的称为声明提前(hoisting),即JavaScript函数中声 ...
- JavaScript 变量声明:var、let、const
1. 概述 1.1 说明 在ES5 声明变量的方法:var命令和function命令. 在ES6 声明变量的方法:var命令.function命令.let命令.const命令.import命令.cla ...
随机推荐
- 从 HTTP 到 HTTPS 再到 HSTS
近些年,随着域名劫持.信息泄漏等网络安全事件的频繁发生,网站安全也变得越来越重要,也促成了网络传输协议从 HTTP 到 HTTPS 再到 HSTS 的转变. HTTP HTTP(超文本传输协议) 是一 ...
- 把JavaScript代码改成ES6语法不完全指南
目录 * 核心例子 * 修改成静态变量(const)或块级变量(let) * 开始修改 * 疑问解释(重复定义会发生什么) * 疑问解释(let的块级作用域是怎样的) * 疑问解释(const定义的变 ...
- JavaScript实现隔行换颜色
<!DOCTYPE html><html> <head> <meta charset="UTF-8"> <title>& ...
- ireport导出中英文pdf
准备: 报表开发工具:ireport 5.6.0 报表框架: jasperreport5.6.0 1.中文格式设置pdf fontname.isembedded.pdfencoding pdf fon ...
- 弹性布局flex
前几天写过怪异盒子布局,以前在项目中用到弹性布局flex这个属性,当时没深入研究,这里各种查阅各种测试,把这个属性记录下 以免忘记, 弹性布局:是提供一种更加有效的方式来对一个容器中的条目进行排列.对 ...
- Linux-mknod命令(9)
mknod命令用于创建字符设备文件和块设备文件 (ls /dev -l 结果显示b开头和c开头的,即标识了块设备和字符设备.) 为了管理设备,所以设备中都有两个设备号: 主设备号:为了区分不同类型的 ...
- webpack2学习日志
webpack说容易也容易,说难也难,主要还是看个人,想学到什么样的程度,很多公司可能要求仅仅是会用就行,但是也有一些公司要求比较高,要懂一些底层的原理,所以还是要花一些时间的,看个人需求.这篇仅仅是 ...
- [iOS] file patterns: The `public_header_files` pattern did not match any file.
由于之前集成私有pod,遇到问题, 默认的头文件目录设置为:s.public_header_files = ‘Pod/Classes/**/*.h’:但是如果Classes目录中,你的代码文件夹层次结 ...
- python--用户登录验证
目标要求: 1.最多输入3次用户名密码, 2.如果是被锁用户,则一次即退出程序, 3.如果输入正确的用户名密码,则提示登陆成功,程序结束, 4.3次输入不对,会将用户写入被锁用户列表,当然,该用户名需 ...
- 3rd-Bing Dict使用分析
英语学习APP的案例分析 0x00 写在前面 我们生活中很多时候要和软件打交道,大家上课开小差时候玩的手机游戏,买火车票的网站,互相联系用的微信.QQ,等等都是软件,都很值得分析.你为何成为它们的用户 ...