小编给大家分享一下JavaScript中的作用域和作用域链是什么,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获、下面让我们一起去了解一下吧!
作用域(范围)
作用域是在运行时代码中的某些特定部分中变量,函数和对象的可访问性。换句话说,作用域决定了代码区块中变量和其他资源的可见性。可能这两句话并不好理解,我们先来看个例子:
函数outFun2 () { var不变=澳诓惚淞?“;; } outFun2();//要先执行这个函数,否则根本不知道里面是啥 console.log(不变);//未捕获ReferenceError:不变不是
从定义上面的例子可以体会到作用域的概念,变量不变在全局作用域没有声明,所以在全局作用域下取值会报的错。我们可以这样理解:<强>作用域就是一个独立的地盘,让变量不会外泄,暴露出去>强。也就是说<强>作用域最大的用处就是隔离变量,不同作用域下同名变量不会有冲突。强>
<强> ES6之前JavaScript没有块级作用域,只有全局作用域和函数作用域强> .ES6的到来,为我们提供了“块级作用域”,可通过新增命令我们和const来体现。
在代码中任何地方都能访问到的对象拥有全局作用域,一般来说以下几种情形拥有全局作用域:
- <李>最外层函数和在最外层函数外面定义的变量拥有全局作用域李>
var outVariable=拔沂亲钔獠惚淞俊?//最外层变量 函数outFun(){//最外层函数 var不变=澳诓惚淞俊? 函数innerFun(){//内层函数 console.log(不变); } innerFun (); } console.log (outVariable);//我是最外层变量 outFun ();//内层变量 console.log(不变);//不变的没有定义 innerFun ();//innerFun没有定义
- <李>所有末定义直接赋值的变量自动声明为拥有全局作用域李>
函数outFun2 () { 变量=拔炊ㄒ逯苯痈持档谋淞俊? var inVariable2=澳诓惚淞?“;; } outFun2();//要先执行这个函数,否则根本不知道里面是啥 console.log(变量);//未定义直接赋值的变量 console.log (inVariable2);//inVariable2没有定义
- <李>所有窗口对象的属性拥有全局作用域李>
一般情况下,窗口对象的内置属性都拥有全局作用域,例如window.name, window.location, window.top等等。
全局作用域有个弊端:如果我们写了很多行JS代码,变量定义都没有用函数包括,那么它们就全部都在全局作用域中。这样就会污染全局命名空间,容易引起命名冲突。
//张三写的代码中 var data=https://www.yisu.com/zixun/{: 100}//李四写的代码中 var data={x:真}
这就是为何jQuery, Zepto等库的源码,所有的代码都会放在<代码>(函数(){....})()代码>中。因为放在里面的所有变量,都不会被外泄和暴露,不会污染到外面,不会对其他的库或者JS脚本造成影响。这是函数作用域的一个体现。
函数作用域,是指声明在函数内部的变量,和全局作用域相反,局部作用域一般只在固定的代码片段内可访问到,最常见的例如函数内部。
函数doSomething () { var blogName=袄死镄兄邸? 函数innerSay () { 警报(blogName); } innerSay (); } 警报(blogName);//脚本错误 innerSay ();//脚本错误
<强>作用域是分层的,内层作用域可以访问外层作用域的变量,反之则不行>强。我们看个例子,用泡泡来比喻作用域可能好理解一点:
最后输出的结果为2、4、12
- <李>泡泡1是全局作用域,有标识符foo;李> <>李泡泡2是作用域foo,有标识符,酒吧,b;李> <>李泡泡3是作用域酒吧,仅有标识符c。李>
值得注意的是:<强>块语句(大括号“{}”中间的语句),如如果和开关条件语句和段时间或循环语句,不像函数,它们不会创建一个新的作用域>强。在块语句中定义的变量将保留在它们已经存在的作用域中。
如果(真){//& # 39;如果# 39;条件语句块不会创建一个新的作用域 var name=& # 39; Hammad& # 39;;//名字依然在全局作用域中 } console.log(名称);//日志& # 39;Hammad& # 39;JavaScript中的作用域和作用域链是什么