收藏 分享(赏)

详解Javascript上下文与作用域.docx

上传人:scg750829 文档编号:7088052 上传时间:2019-05-05 格式:DOCX 页数:8 大小:359.29KB
下载 相关 举报
详解Javascript上下文与作用域.docx_第1页
第1页 / 共8页
详解Javascript上下文与作用域.docx_第2页
第2页 / 共8页
详解Javascript上下文与作用域.docx_第3页
第3页 / 共8页
详解Javascript上下文与作用域.docx_第4页
第4页 / 共8页
详解Javascript上下文与作用域.docx_第5页
第5页 / 共8页
点击查看更多>>
资源描述

1、图文并茂详解 Javascript 上下文与作用域本文尝试阐述 Javascript 中的上下文与作用域背后的机制,主要涉及到执行上下文(execution context)、作用域链(scope chain)、闭包(closure)、this 等概念。Execution context执行上下文(简称上下文)决定了 Js 执行过程中可以获取哪些变量、函数、数据,一段程序可能被分割成许多不同的上下文,每一个上下文都会绑定一个变 量对象(variable object),它就像一个容器,用来存储当前上下文中所有已定义或可获取的变量、函数等。位于最顶端或最外层的上下文称为全局上下文(global

2、context),全局上下文取决于执行环境,如 Node 中的 global 和Browser 中的 window:需要注意的是,上下文与作用域(scope)是不同的概念。Js 本身是单进程的,每当有 function 被执行时,就会产生一个新的上下文,这一上 下文会被压入Js 的上下文堆栈(context stack)中,function 执行结束后则被弹出,因此Js 解释器总是在栈顶上下文中执行。在生成新的上下文时,首先会绑定该上下文的变量对象,其中 包括 arguments 和该函数中定义的变量;之后会创建属于该上下文的作用域链(scope chain),最后将 this 赋予这一 fu

3、nction 所属的Object,这一过程可以通过下图表示:this上文提到 this 被赋予 function 所属的 Object,具体来说,当 function 是定义在 global 对中时,this 指向 global;当 function 作为 Object 的方法时,this 指向该 Object:1.var x = 1; 2.var f = function() 3. console.log(this.x); 4. 5.f(); / - 1 6. 7.var ff = function() 8. this.x = 2; 9. console.log(this.x); 10. 1

4、1. ff(); / - 2 12. x / - 2 13. 14. var o = x: “os x“, f: f; 15. o.f(); / “os x“ 上文提到,在 function 被执行时生成新的上下文时会先绑定当前上下文的变量对象,再创建作用域链。我们知道 function 的定义是可以嵌套 在其他function 所创建的上下文中,也可以并列地定义在同一个上下文中(如global)。作用域链实际上就是自下而上地将所有嵌套定义的上下文所 绑定的变量对象串接到一起,使嵌套的 function 可以“继承”上层上下文的变量,而并列的 function 之间互不干扰:1.var x =

5、 global; 2.function a() 3. var x = “as x“; 4. function b() 5. var y = “bs y“; 6. console.log(x); 7. ; 8. b(); 9. 10. function c() 11. var x = “cs x“; 12. function d() 13. console.log(y); 14. ; 15. d(); 16. 17. a(); / - “as x“ 18. c(); / - ReferenceError: y is not defined 19. x / - “global“ 20. y / -

6、 ReferenceError: y is not defined Closure如果理解了上文中提到的上下文与作用域链的机制,再来看闭包的概念就很清楚了。每个 function 在调用时会创建新的上下文及作用域链,而作用域 链就是将外层(上层)上下文所绑定的变量对象逐一串连起来,使当前 function 可以获取外层上下文的变量、数据等。如果我们在 function 中定义 新的function,同时将内层 function 作为值返回,那么内层 function 所包含的作用域链将会一起返回,即使内层 function 在其他 上下文中执行,其内部的作用域链仍然保持着原有的数据,而当前的上

7、下文可能无法获取原先外层function 中的数据,使得 function 内部的作用域 链被保护起来,从而形成“闭包”。看下面的例子:1.var x = 100; 2.var inc = function() 3. var x = 0; 4. return function() 5. console.log(x+); 6. ; 7.; 8. 9.var inc1 = inc(); 10. var inc2 = inc(); 11. 12. inc1(); / - 0 13. inc1(); / - 1 14. inc2(); / - 0 15. inc1(); / - 2 16. inc2(

8、); / - 1 17. x; / - 100 执行过程如下图所示,inc 内部返回的匿名 function 在创建时生成的作用域链包括了 inc 中的 x,即使后来赋值给 inc1 和 inc2 之后,直接在 global context 下调用,它们的作用域链仍然是由定义中所处的上下文环境决定,而且由于 x 是在 function inc 中定义的,无法被外层的 global context 所改变,从而实现了闭包的效果:this in closure我们已经反复提到执行上下文和作用域实际上是通过 function 创建、分割的,而 function 中的 this 与作用域链不同,它是由

9、*执行该 function 时*当前所处的 Object 环境所决定的,这也是 this 最容易被混淆用错的一点。一般情况下的例子如下:1.var name = “global“; 2.var o = 3. name: “o“, 4. getName: function() 5. return this.name 6. 7.; 8.o.getName(); / - “o“ 由于执行 o.getName()时 getName 所绑定的 this 是调用它的 o,所以此时 this = o;更容易搞混的是在 closure 条件下:1.var name = “global“; 2.var oo =

10、 3. name: “oo“, 4. getNameFunc: function() 5. return function() 6. return this.name; 7. ; 8. 9. 10. oo.getNameFunc()(); / - “global“ 此时闭包函数被 return 后调用相当于:1.getName = oo.getNameFunc(); 2.getName(); / - “global“ 换一个更明显的例子:1.var ooo = 2. name: “ooo“, 3. getName: oo.getNameFunc() / 此时闭包函数的 this 被绑定到新的

11、Object 4.; 5.ooo.getName(); / - “ooo“ 当然,有时候为了避免闭包中的 this 在执行时被替换,可以采取下面的方法:1.var name = “global“; 2.var oooo = 3. name: “ox4“, 4. getNameFunc: function() 5. var self = this; 6. return function() 7. return self.name; 8. ; 9. 10. ; 11. oooo.getNameFunc()(); / - “ox4“ 或者是在调用时强行定义执行的 Object:1.var name

12、= “global“; 2.var oo = 3. name: “oo“, 4. getNameFunc: function() 5. return function() 6. return this.name; 7. ; 8. 9. 10. oo.getNameFunc()(); / - “global“ 11. oo.getNameFunc().bind(oo)(); / - “oo“ 总结Js 是一门很有趣的语言,由于它的很多特性是针对 HTML 中 DOM 的操作,因而显得随意而略失严谨,但随着前端的不断繁荣发展和 Node 的兴 起,Js 已经不再是“toy language”或是

13、jQuery 时代的“CSS 扩展”,本文提到的这些概念无论是对新手还是从传统 Web 开发中过度过来的 Js 开发人员来说,都很容易 被混淆或误解,希望本文可以有所帮助。写这篇总结的原因是我在 Github 上分享的 Learn javascript in one picture,刚开始有人质疑这只能算是一张语法表(syntax cheat sheet),根本不会涉及更深层的闭包、作用域等内容,但是出乎意料的是这个项目竟然获得 3000 多个 star,所以不能虎头蛇尾,以上。【编辑推荐】1. JavaScript 写一个小乌龟推箱子游戏 2. JavaScript 在移动端中胜出是有原因的 3. 初探 JavaScriptJS 另类的作用域和声明提前 4. 如何在 JavaScript 对象中嵌入私有成员

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 企业管理 > 管理学资料

本站链接:文库   一言   我酷   合作


客服QQ:2549714901微博号:道客多多官方知乎号:道客多多

经营许可证编号: 粤ICP备2021046453号世界地图

道客多多©版权所有2020-2025营业执照举报