详解js变量声明提高

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

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

一开始我以为输出的是undefined。可是真正的结果是hello world。带着疑问再看另一段代码:java

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

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

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

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

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

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

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

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

根据javascript的运行机制和javascript没有块做用域这个特色,能够得出,变量name会声明提高移至做用域 scope (全局域或者当前函数做用域) 顶部的。因此上述代码就至关于:ip

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那样会被查找到,提早声明,而是运行到了该代码才会被声明执行。下面例子很好说明这个问题:it

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

clipboard.png

谢谢你们观看,你们有什么好见解能够提出来讨论讨论。io

相关文章
相关标签/搜索