JS 存在变量提升,这个的设计其实是低劣的,或者是语言实现时的一个副作用。它允许变量不声明就可以访问,或声明在后使用在前。新手对于此则很迷惑,甚至许多使用JS多年老手也比较迷惑。但在 ES6 加入 let/const 后,变量Hoisting 就不存在了。
一、 变量未声明,直接使用
function test() { alert(notDefined); } test(); // "text-align: center">二. 变量声明在末尾
function test() { alert(declaredButNotAssigned); // undefined var declaredButNotAssigned; } test();输出 undefined, 结果比上例有所改善,没有报错,代码可以运行,但变量值可能不是程序员所期望的。
三、 变量声明在末尾,同时给变量赋值
function test() { alert(declaredAndAssigned); // undefined var declaredAndAssigned = 1; } test();结果和 二 相同, 很明显,并不会因为赋值了就输出 1。
二、三 都发生了变量提升(Hoisting),简单定义
变量提升: 在指定作用域里,从代码顺序上看是变量先使用后声明,但运行时变量的 “可访问性” 提升到当前作用域的顶部,其值为 undefined ,没有 “可用性”。
这里强调 “代码顺序” 和 “运行顺序”,是因为多数时候我们写的代码都是顺序执行的,即 “代码顺序” 和 “运行顺序” 是一致的。这也符合人的大脑的思维过程。比如有过 C语言 经验的程序员
#include <stdio.h> int main() { int x = 1; printf("%d, ", x); // 1 }两句代码,先声明整数型 x, 再输出。代码顺序和运行顺序是一致的,即正常运行。
如果顺序反过来
#include <stdio.h> int main() { printf("%d, ", x); // error int x = 1; }此时,编译都不能通过了。但JS里可以反过来写,见二、三。
因此,有类 C语言 经验的程序员,都很清楚变量需要 先声明后使用,不然会报错。而到了JS里,有 变量提升 现象,可以 先使用后声明,C 的经验用到 JS 里迷惑便出现了。
四、 函数表达式也存在变量提升
function test() { alert(func); // undefined var func = function() {}; } test();但如果想使用这个 func,则无可能
function test() { alert(func); // undefined func(); // 报异常 var func = function() {}; } test();结果func 是 undefined,调用 func 则会报异常。 在上面的定义中提到了 可访问性 和 可用性 对应如下语句。
可访问性:alert(func),输出 undefined,可以运行,可以访问 func。
可用性: func(), 报异常,不能正常调用 func,表示无可用性。
二、三、四 都是使用 var 声明的变量,JS 里函数声明也会存在提升,只是这个 “变量” 比较特殊,它是一个 function 类型(可以作为函数、方法或构造器)。它的名字(标识符)也会提升到当前作用域的顶部。
五、函数声明的名也会提升到当前作用域顶部
function test() { alert(f1); // function f1(); // "called" function f1() { alert('called'); } } test();我们看到,声明 f1 在代码最末,f1 使用在前,alert(f1) 和 f1() 都正常执行,表示 可访问性 和 可用性 都有了。
前面说了,变量提升(Hoisting)没什么用,属于语言的低劣设计,好的习惯还是 “先声明后使用”。这个特性也会出现在不少大公司面试题里
题1:
// 写出以下代码的运行结果 var a = 1; function fn() { if (!a) { var a = 2; } alert(a); // "htmlcode">// 写出以下代码的运行结果 var a = 1; function fn() { a = 2; return; function a() {} } fn(); alert(a); // "htmlcode">function test() { alert(declaredButNotAssigned1); // 报异常 alert(declaredButNotAssigned2); // 报异常 alert(func); // 报异常 let declaredButNotAssigned1; let declaredButNotAssigned2 = true; let func = function() {}; } test();这强制程序员养成好的习惯,变量需要“先声明再使用”,否则报错。
以下摘自MDN的关于let不在发生变量提升的描述
复制代码 代码如下:
In ECMAScript 6, let does not hoist the variable to the top of the block. If you reference a variable in a block before the let declaration for that variable is encountered, this results in a ReferenceError, because the variable is in a "temporal dead zone" from the start of the block until the declaration is processed.
用 let 声明变量后,typeof 也不再安全
if (condition) { alert(typeof num); // Error! let num = 100; }以前可以用 typeof == 'undefined',来判断是否引入了某lib,比如jQuery
// 判断jQuery是否引入了 if (typeof $ !== 'undefined') { // do something }...jQuery没有引入,$ 没有声明,这句也不会报错而影响到下面的代码执行,但如果是 let 声明的就会报错了。
以上所述就是本文的全部内容了,希望大家能够喜欢。
标签:JavaScript,标识符提升
无为清净楼资源网 Design By www.qnjia.com
免责声明:本站文章均来自网站采集或用户投稿,网站不提供任何软件下载或自行开发的软件! 如有用户或公司发现本站内容信息存在侵权行为,请邮件告知! 858582#qq.com
更新日志
- 柏菲·珞叔作品集《金色大厅2》限量开盘母带ORMCD[低速原抓WAV+CUE]
- Gareth.T《sad songs(Explicit)》[320K/MP3][29.03MB]
- Gareth.T《sad songs(Explicit)》[FLAC/分轨][152.85MB]
- 证声音乐图书馆《海风摇曳·盛夏爵士曲》[320K/MP3][63.06MB]
- 龚玥《金装龚玥HQCD》头版限量[WAV分轨]
- 李小春《吻别》萨克斯演奏经典[原抓WAV+CUE]
- 齐秦《辉煌30年24K珍藏版》2CD[WAV+CUE]
- 证声音乐图书馆《海风摇曳·盛夏爵士曲》[FLAC/分轨][321.47MB]
- 群星 《世界经典汽车音乐》 [WAV分轨][1G]
- 冷漠.2011 《冷漠的爱DSD》[WAV+CUE][1.2G]
- 陈明《流金岁月精逊【中唱】【WAV+CUE】
- 群星《Jazz-Ladies1-2爵士女伶1-2》HQCD/2CD[原抓WAV+CUE]
- 群星《美女私房歌》(黑胶)[WAV分轨]
- 郑源.2009《试音天碟》24BIT-96KHZ[WAV+CUE][1.2G]
- 飞利浦试音碟 《环球群星监听录》SACD香港版[WAV+CUE][1.1G]