理解javascript作用域及hosting机制

Posted 灰锅

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了理解javascript作用域及hosting机制相关的知识,希望对你有一定的参考价值。

 

javascript中, 理解变量的作用域以及变量提升是非常有必要的,特别是对于初学者,很容易莫名地就掉坑里。

一、javaScript作用域

在C语言中,一对花括号{}代表一个独立的作用域,我们称之为块级作用域。一个块级作用域中,只作用于该块的变量可以被声明,只会影响快内而不会影响块外面的作用域。javaScript没有块级作用域,只有全局作用域和函数作用域。

全局作用域其实是全局对象的作用域,任意地方都可以访问到。函数对象作用域跟C的局部变量作用域是不同的,它的作用域是整个函数范围,在函数内声明的所有变量在函数体内始终是可见的。

下面我们吃些栗子来加深理解:

栗子代码1:

var x=‘我是只锅‘;//声明一个全局变量x
console.log(x);//‘我是只锅’
if(1){
  var x=‘我是只灰色的锅‘;
  console.log(x);//‘我是只灰色的锅’
}
console.log(x);//‘我是只灰色的锅’

 

在if语句里面改变了变量x的值,全局变量x也就改变了,说明{}没有建立新的作用域,而是处于全局作用域中的,由此可见javascript跟        C的作用域是不一样的。对于全局作用域的变量,无论是在if语句内还是函数内都可以访问到;

栗子代码2:

 

function a(){
    var arg=‘我是只锅‘;
}
console.log(arg);//浏览器报错:arg is not defined

 

arg变量是在函数a内声明的,函数外没有声明,无法获取到arg变量,所以浏览器报错。说明函数对象作用域,只有在函数体内才可以访问,而函数体外是不能访问。

栗子代码3:

 

var arg=‘我是只锅‘;
function a(){
    console.log(arg);//undefined
    var arg=‘我是只灰色的锅‘;
    console.log(arg);//‘我是只灰色的锅’
}
a();

 

         这里应该很多童靴可能会认为第三行会输出“我是只锅”,因为代码还没有执行到var语句声明arg的地方。然而并非如此,这到底是为什么呢?这里就引申出javascript作用域的一个特性:hosting机制。

二、hosting机制

所谓的hoisting,也就是变量提升的概念。变量提升即将变量声明提升到它所在作用域的最开始的部分。在javaScript中,变量和函数的声明会提升到最顶部执行。

由于函数作用域的特性,局部变量在整个函数体内始终是有定义的。因此在上面的栗子3中,函数体内局部变量arg遮盖了同名全局变量arg。不过,只是声明提前了,赋值执行是没有被提前的,所以第三行会输出undefined。由此,上面的过程相当于这样:

 

var arg=‘我是只锅‘;
function a(){
    var arg;
    console.log(arg);//undefined
    arg=‘我是只灰色的锅‘;
    console.log(arg);//‘我是只灰色的锅’
}
a();

 

下面我们接着吃些栗子来深剖一下hosting的特点:

(1)函数声明提升高于变量声明

栗子代码1:

console.log(typeof a);//function
var a;
function a(){
    ...
}

 

栗子代码2:

console.log(typeof a);//function
function a(){
    ...
}
var a;

 

同时定义变量a和函数a,无论是先定义函数还是后定义函数,最后a显示的都是函数,证明function的优先级高于var。

(2)匿名函数不会向上提升

栗子代码:

 

console.log(typeof a);//undefined
var a=function (){
    ...
}

 

匿名函数这种形式其实就是var变量的声明定义,因此第一行输出结果为undefined,应该是可以理解的。

(3)不同代码块中的函数互不影响

          栗子代码:

 

<script>//代码块1
    console.log(typeof a);//undefined
    var a=function (){
        ...
    }
</script>

<script>//代码块2
    function a(){
        ...
    }
</script>

 

代码块1中的a,输出的是undefined,说明代码块2的函数a没有被提前到代码块1之前,由此可见不同代码块之间函数是互不影响的。

以上是关于理解javascript作用域及hosting机制的主要内容,如果未能解决你的问题,请参考以下文章

JS 函数作用域及变量提升那些事!

关于Javascript作用域及作用域链的总结

javascript函数作用域及this指向详解

javascript函数作用域及this指向详解

JavaScript作用域及作用域链详解声明提升

第一百零六节,JavaScript变量作用域及内存