资讯专栏INFORMATION COLUMN

详解js变量声明提升

NSFish / 1272人阅读

摘要:换句话说,在代码执行之前,会对作用域链中所有变量和函数声明先处理完先。总结一句话就是只有声明被提升,而赋值或其他运算会留在原地。为其声明变量隐性劫持到所在区域中。

之前一直觉会认为javascript代码执行是由上到下一行行执行的。自从看了《你不知道的JS》后发现这个观点并不完全正确。先来给大家举一个书本上的的例子:

  var a="hello world";
  var a;
  console.log(a); 
 
 

一开始我觉得输出的是undefined。但是真正的结果是hello world。带着疑问再看另外一段代码:

console.log(a);
var a="hello world";

借鉴与上面的例子会认为会输出一个hello world,或者是抛出一个没有声明的异常错误,然而发现这两种想法也是错误。输出的结果是‘undefined’。这书非常人性化的总结出了结论是:

引擎解释javascript代码的之前会对其进行编译。在编译过程中会查找所有声明,并用合适作用域将他们关联起来。换句话说,在代码执行之前,会对作用域链中所有变量和函数声明先处理完先。所以,当遇到var a="hello world"中是 var a是先在编译阶段执行,然后在执行a="hello world"。所以,第一段代码实质上是:

var a;
a="hello world";
console.log(a);

所以输出的就就是helloworld。总结一句话就是:只有声明被提升,而赋值或其他运算会留在原地。所以第二段代码实际上就是:

var a;
console.log(a);
a="hello world";

介绍完这两个经典例子是时候来看看一下这个例子了:

var name = "world";
(function () {
if (typeof name == "undefined") {
var name = "yang";
console.log("Hello " + name)
} else {
console.log("Hello " + name)
}
})()
  

根据javascript的运行机制和javascript没有块作用域这个特点,可以得出,变量name会声明提升移至作用域 scope (全局域或者当前函数作用域) 顶部的。所以上述代码就相当于:

var name = "world";
(function () {
var name;
if (typeof name == "undefined") {
var name = "yang";
console.log("Hello " + name)
} else {
console.log("Hello " + name)
}
})()

因此,if判断的时候typeof name == "undefined"是true。所以会执行条件为true里面的代码。输出就是Hello yang。
那么如果想实现上面的函数,我们该如何实现?答案非常简单那就创建块作用域了。如何最简单的创建块作用域呢?那当然是采用es6的新特性let关键字。let关键字可以将变量绑定到所在的任意区域中通常在{...}中。换句话说。let为其声明变量隐性劫持到所在区域中。下列例子中:let就绑定到if (typeof name == "undefined") {...}中。所以name不会被提升,所以判断就为假,于是就可以输出我们期待已久的‘helloworld’。

var name = "world";
(function () {
if (typeof name == "undefined") {
let name = "yang";

console.log("Hello " + name)
} else {
console.log("Hello " + name)
}
})()

注意点:let所在的块级作用域,在声明代码被运行前,是不会像var那样会被查找到,提前声明,而是运行到了该代码才会被声明执行。下面例子很好说明这个问题:

(function (){
    console.log(b);
    let b=2;
})()

谢谢大家观看,大家有什么好看法可以提出来讨论讨论。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/87981.html

相关文章

  • ES6 变量作用域与提升变量的生命周期详解

    摘要:不同的是函数体并不会再被提升至函数作用域头部,而仅会被提升到块级作用域头部避免全局变量在计算机编程中,全局变量指的是在所有作用域中都能访问的变量。 ES6 变量作用域与提升:变量的生命周期详解从属于笔者的现代 JavaScript 开发:语法基础与实践技巧系列文章。本文详细讨论了 JavaScript 中作用域、执行上下文、不同作用域下变量提升与函数提升的表现、顶层对象以及如何避免创建...

    lmxdawn 评论0 收藏0
  • 详解函数与变量声明提升

    摘要:注意是前面,而不是最前面,因为变量声明提升的优先级别要低于函数声明提升。分解后是这样从以下代码可以看出这也印证了变量声明提升与变量定义分两步走的结论。 函数声明 定义函数有两种方式: 一种是函数声明,另一种是函数表达式。函数声明语法如下: function functionName(arg0, arg1, arg2) { // 函数体 } 函数声明提升 所谓的函数声明提升,是指...

    马忠志 评论0 收藏0
  • 深入理解 js 声明提升( 尾部有总结 和 面试题解析 )

    摘要:要理解函数的提升行为,让我们先解析什么是的提升。也就是说声明提升了,赋值还留着原地,等待执行。声明被提升,而包括函数表达式的赋值在内的赋值操作并不会提升,而是留在原地等待执行。 javaScript自上而下执行的顺序受到很多新手和部分老手的共识,但是这其实并不完全正确,这涉及到js的编译过程,这方面我们稍后会聊到,先考虑下面代码: window.onload = function(){...

    curlyCheng 评论0 收藏0
  • 详解JavaScript函数模式

    摘要:函数表达式又名匿名函数为变量赋的值是函数定义本身。在语言里任何匿名函数都是属于对象。这种情况下,就叫做回调函数。如上面代码示例展示了文档单击事件时以冒泡模式传递给回调函数的特别适用于事件驱动编程,因为回调模式支持程序以异步方式运行。 JavaScript设计模式的作用是提高代码的重用性,可读性,使代码更容易的维护和扩展 在javascript中,函数是一类对象,这表示他可以作为参数传递...

    wwolf 评论0 收藏0
  • JavaScript声明变量详解

    摘要:命令用于规定模块的对外接口,命令用于输入其他模块提供的功能所以在一定程度上来说,也具有声明变量的功能。当没有声明,直接给变量赋值时,会隐式地给变量声明,此时这个变量作为全局变量存在。 前言 如果文章中有出现纰漏、错误之处,还请看到的小伙伴多多指教,先行谢过 在ES5阶段,JavaScript 使用 var 和 function 来声明变量, ES6 中又添加了let、const、imp...

    paulquei 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<