关于作用域、防止作用域污染、作用域链和闭包的理解
参考博客:https://www.geek-share.com/detail/2704474670.html
作用域
变量的作用域无非就是两种:全局作用域和局部作用域。
全局作用域:
最外层函数定义的变量拥有全局作用域,即对任何内部函数来说,都是可以访问的:
[code] <script> var outerVar = "outer"; function fn(){ console.log(outerVar); } fn();//result:outer </script>
局部作用域:
和全局作用域相反,局部作用域一般只在固定的代码片段内可访问到,而对于函数外部是无法访问的,最常见的例如函数内部
[code]<script> function fn(){ var innerVar = "inner"; } fn(); console.log(innerVar);// ReferenceError: innerVar is not defined </script>
需要注意的是,函数内部声明变量的时候,一定要使用var命令。如果不用的话,实际上声明了一个全局变量!
以下是一个重要的特性!!
只要函数内定义了一个局部变量,函数在解析的时候都会将这个变量“提前声明”,举例:
[code] <script> var scope = "global"; function fn(){ console.log(scope);//result:undefined var scope = "local"; console.log(scope);//result:local; } fn(); </script>
第一个输出居然是undefined,原本以为它会访问外部的全局变量(scope=”global”),但是并没有。这可以算是javascript的一个特点,只要函数内定义了一个局部变量,函数在解析的时候都会将这个变量“提前声明”。
[code] <script> var scope = "global"; function fn(){ var scope;//提前声明了局部变量 console.log(scope);//result:undefined scope = "local"; console.log(scope);//result:local; } fn(); </script>
但是javascript不同,并没有所谓的块级作用域,javascript的作用域是相对函数而言的,可以称为函数作用域:
[code] <script> for(var i = 1; i < 10; i++){ //coding } console.log(i); //10 </script>
防止作用域污染
在多人协作时,如果定义过多的全局变量 有可能造成全局变量冲突,也就是全局变量污染问题, 尽量避免全局变量。
可采取两种措施:
一是定义全局变量命名空间,只创建一个全局变量,并定义该变量为当前应用容器,把其他全局变量追加在该命名空间下
[code]var MY={}; my.name={ big_name:"zhangsan", small_name:"lisi" }; my.work={ school_work:"study", family_work:"we are" };
二 是利用匿名函数将脚本包裹起来
[code](function(){ var exp={}; var name="aa"; exp.method=function(){ return name; }; window.ex=exp; })();
作用域链(Scope Chain)
那什么是作用域链?
我的理解就是,根据在内部函数可以访问外部函数变量的这种机制,用链式查找决定哪些数据能被内部函数访问。
想要知道js怎么链式查找,就得先了解js的执行环境
执行环境(execution context)
js为每一个执行环境关联了一个变量对象。环境中定义的所有变量和函数都保存在这个对象中。
js的执行顺序是根据函数的调用来决定的,当一个函数被调用时,该函数环境的变量对象就被压入一个环境栈中。而在函数执行之后,栈将该函数的变量对象弹出,把控制权交给之前的执行环境变量对象。
[code] <script> var scope = "global"; function fn1(){ return scope; } function fn2(){ return scope; } fn1(); fn2(); </script>
上面代码执行情况演示:
闭包
其实闭包也就是指有权访问另一个函数作用域的函数而已。常用的创建闭包的方法就是在函数内部创建另一个函数。
闭包有两个作用:
第一个就是可以读取自身函数外部的变量(沿着作用域链寻找)
第二个就是让这些外部变量始终保存在内存中 (容易导致内存泄漏)
关于this对象
关于闭包经常会看到这么一道题:
[code] var name = "The Window"; var object = { name : "My Object", getNameFunc : function(){ return function(){ return this.name; }; } }; alert(object.getNameFunc()());//result:The Window
《javascript高级程序设计》一书给出的解释是:
this对象是在运行时基于函数的执行环境绑定的:在全局函数中,this等于window,而当函数被作为某个对象调用时,this等于那个对象。不过,匿名函数具有全局性,因此this对象同常指向window。
阅读更多
- JavaScript关于作用域、作用域链和闭包的理解
- JavaScript关于作用域、作用域链和闭包的理解
- 深入理解javascript原型和闭包(18)——补充:上下文环境和作用域的关系
- 关于JS变量的作用域,作用域链与闭包
- 关于“javascript变量的作用域”的理解
- JavaScript this的作用域、匿名函数、闭包 的理解
- 深入理解JavaScript作用域和作用域链
- 深入理解JavaScript作用域、变量对象、闭包
- 关于闭包,前后文,作用域链
- 关于JS闭包的理解
- 深入理解JavaScript作用域和作用域链
- 深度理解作用域链和闭包
- 深入理解javascript原型和闭包(18)——补充:上下文环境和作用域的关系
- 【转】深入理解JavaScript作用域和作用域链
- 关于js闭包的研究和理解
- 4000 关于闭包的理解
- 关于闭包和javascript函数表达式的一点理解
- 关于lua的闭包自我理解
- 关于闭包,巧妙地抽象理解
- 关于Javascript 闭包的理解