理解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机制的主要内容,如果未能解决你的问题,请参考以下文章