习惯于OOP语言编程后,会发现Javascript世界有很多匪夷所思的奇奇怪怪的现象(比如闭包),我花了大量的精力研究这些奇怪现象的根源,最后发现:源自于javascript的作用域不是块级作用域,同时它有一套基于作用域链的标识查找机制。本文大部分内容来自互联网,经过整理、改进而成。
Javascript引擎和DOM采用的垃圾回收算法:引用计数
javascript和DOM有各自的垃圾回收器,单独运作良好,合作时一不小心会出问题。引用计数这个算法的缺陷就是:Javascript 对象和DOM对象彼此循环引用,造成彼此的引用计数永远不能为0,垃圾回收器无法正确回收这些参与循环引用的对象,最终造成内存泄漏(Memory Leak)。闭包是循环引用“大户”。如果对垃圾回收感兴趣,可以看看 垃圾收集趣史
词法作用域(lexical scope,一般简称作用域)、with/eval
简单来说javascript的作用域是由function划分的。读完这篇文章你会了解词法作用域 Javascript运行机制浅探,with/eval这 两个特例会扰乱作用域,即所谓动态作用域(dynamic scope)
作用域链(Scope Chain) 和 标识查找机制
作用域链是一个链表(数据结构),它是Javascript的灵魂,只有理解了它才能理解Javascript世界奇奇怪怪的现象。作用域链由活动对象链成。
标识查找机制稍后结合函数执行的原理加以说明。
活动对象(call object)
国内很多人称之为调用对象(call object),本文用英文call obejct(但我私下认为翻译为"活动对象"更好,不至于和this所指的对象混淆。)
非常特殊的javascript引擎内的对象,ECMAScript规范术语称之为activation object(活动对象)。多个call object和全局对象组成作用域链(scope chain )
函数的本质(有名函数、匿名函数)、函数的[[scope]]属性 函数在javascript里面是一个特殊的引用类型 ,它继承于位于javascript世界最顶端的object,类型是Function,是其他常见引用类型的构造函数的所属类型。
在定义函数的时候,Javascript引擎会为function对象的一个私有[[scope]]属性赋值,理论上只有js引擎自己才能访问(也即:一般情况下无法通过语法来访问,但Firefox下有一个__parent___可以访问到)。匿名函数的[[scope]]属性指向匿名函数定义时的上下文对象;有名函数除了和匿名函数一样,还会在[[scope]]属性的顶端再指向一个Javascript对象(继承自obejct.prototype),这个对象被链接到函数定义时的Scope Chain,他本身带有一个属性就是函数的名字,这确保函数内部的代码可以无误地访问到自己的函数名以便进行递归。
当定义函数的时候,javascript解析器会将函数的作用域链(scope chain)设置为定义函数时函数所在的“环境”,如果函数是一个全局函数,则scope chain中只有window对象。
当执行函数时的微观世界,请看稍后的说明。
闭包(closure)
javascript所有的函数都是闭包,但是只有嵌套形式的闭包(也是我们经常讨论的形式)才能体现这个javascript 特性的强大。推荐阅读这篇文章: 深入理解JavaScript闭包(closure)
函数执行时的作用域链和活动对象是如何形成的及与闭包的关系
1、javascript解析器启动时就会初始化建立一个全局对象global object,这个全局对象就 拥有了一些预定义的全局变量和全局方法,如Infinity, parseInt, Math,所有程序中定义的全局变量都是这个全局对象的属性。在客户端javascript中,Window就是这个javascript的全局对象。
2、当javascript执行一个function时,会生成一个对象,称之为call object,function中的局部变量和function的参数都成为这个call object的属性,以免覆写同名的全局变量。
3、javascript解析器每次执行function时,都会为此function创建一个execution context执行环境,在此function执行环境中最重要的一点就是function的作用域链scope chain,这是一个对象链,由全局对象和活动对象构成,对象链具体构成过程见下面说明。
4、标识的查找机制:当javascript查询变量x的值时,就会检查此作用域链中第一个对象,可能是function的call object或全局对象(比如window),如果对象中有定义此x属性,则返回值,不然检查作用域链中的下一个对象是否定义x属性,在作用域链中没有找到,最后返回undefined。
5、当javascript执行一个function时,它会先将此function定义时的作用域作为其作用域链,然后创建一个活动对象(call object),置于作用域链的顶部,function的参数及内部var声明的所有局部变量都会成为此调用对象的属性。
6、this关键词指向方法的调用者,而不是以调用对象的属性存在,同一个方法中的this在不同的function调用中,可能指向不同的对象。
7、The Call Object as a Namespace。将活动对象当作命名空间使用,避免命名污染。
(function() {
// 在方法体内用var声明的所有局部变量,都是以方法调用时创建的活对象的属性形式 存在。
// 这样就避免与全局变量发生命名冲突。
})();
8、javascript中所有的function都是一个闭包,但只有当一个嵌套函数被导出到它所定义的作用域外时,这种闭包才强大。如果理解了闭包,就会理解function执行时的作用域链和活动对象,才能真正掌握javascript。
9、嵌套闭包的微观世界:在嵌套闭包时,当内部函数的引用被保存到嵌套闭包之外一个全局变量或者一个对象的属性时,在这种情况下,此内部函数有一个外部引用,并且在其外围调用函数的活动对象中有一个属性指向此内部函数。因为有其他对象引用此内部函数,所以在外围函数被调用一次后,其创建的活动对象会继续存在,并不会被垃圾回收器回收(因为引用计数不为0),内部函数的参数和局部变量都会在这个活动对象中得以维持,javascript代码任何形式都不能直接访问此活动对象,但是此活动对象是内部函数被调用时创建的作用域链的一部分,可以被内部函数访问并修改。
最后介绍一个奇怪现象:下面的代码,为什么鼠标移动到li上,title总是6,而不是我们所预想的数字呢?看你能不能根据以上的知识,解释这种现象的原因。提示:变量查找机制
分享到:
相关推荐
虽然它对初学者来说学习起来很容易,但 JavaScript 也可用于构建需要许多高级编程概念的复杂应用程序和系统。 在这篇文章中,我将解释一些最高级的 JavaScript 概念,每个有经验的软件开发人员都应该知道这些概念。...
测试JS 深入研究核心和高级Javascript概念。 包含简单的异步测试套件,以及各种测试,它们证明了我在探究John Resig和Bear Bibeault撰写的“ JavaScript忍者秘诀”时偶然发现的每个概念。
javascript 演示描述基本到高级 JavaScript 概念1.Basic 2.cookies 3.dom 4. 事件 5. 例外。 6. 渐进增强 7. 原型 8. 高级,哎呀 9. 模式 10. 正则表达式。
javascript-例子
JavaScript 遇到“行尸走肉” 使用电视剧《行尸走肉》中的示例的高级 javascript 概念示例。 在命令行上通过节点使用。 设置 使用 nodejs 进行简单的命令行日志记录以理解概念,例如。 $ node prototypes
#JavaScript 研究 在这里,您可以找到我针对高级 JavaScript 概念的各种练习的解决方案; 回调、闭包、高阶函数。
Java脚本 JavaScript概念(新手入门)
本书在上一版基础上进行了大幅度更新和修订,融入了近几年来javascript应用发展的最新成果,几乎涵盖了所有需要理解的重要概念和最新的javascript应用成果。从颇具深度的javascript语言基础到作用域(链),从引用类型...
Vue.js入门指南:从基础到进阶,掌握现代JavaScript框架的核心概念与高级特性(2W字小白教程)
本书在上一版基础上进行了大幅度更新和修订,融入了近几年来javascript应用发展的最新成果,几乎涵盖了所有需要理解的重要概念和最新的javascript应用成果。从颇具深度的javascript语言基础到作用域(链),从引用类型...
这个 Javascript 纸牌游戏将作为学习高级 Javascript 概念的教程。 话题 面向对象 设计模式 观察员 迭代器 单身人士 Cucumber和小Cucumber的 BDD 带摩卡的 TDD 咕噜出版 LESS 和 CSS,响应式设计 带有 Travis CI ...
很好的JavaScript入门教材,概念讲解清晰,准确,扎实。
节点JS:高级概念 udemy.com在线课程 特征 事件循环 簇 ab(基准测试) 网络工作者 Redis
JS-高级概念
第一页 Javascript高级教程 第二页 本教程的课程计划 第三页 一个if-then-else的快捷方式 第四页 什么是变量 第五页 变量的使用方法 第2课 第一页 Javascript高级教程-第2日 第二页 神奇的字符串处理 第三...
高级JavaScript概念 这些是我有关高级JS主题(例如“ this”,原型,闭包等)的注释。 关键字this this取决于函数的调用方式(“执行上下文”)。 什么this是指可以使用4条规则进行评估(全球,对象/隐性,显性,新...
一、了解脚本的概念,掌握:JavaScrip语言基本语法、HTML语言和JavaScrip如何嵌入到HTML语言中 。 二、了解JavaScrip的各种数据类型,掌握各种运算符,表达式...三、了解各种对象的的概念,掌握各种对象的属性和方法。
Javascript:中级到高级这是针对新手和初级前端开发人员的一些中级到高级Javascript概念的简短指南。 我们的目标不是全面覆盖。 但请专注于我们认为将帮助开发人员提高技能,加深他们对该语言的理解并最终编写更好的...
node.js是一套用来编写高性能网络服务器的JavaScript工具包,全书涉及安装配置、基本概念、核心模块基础等
本书在上一版基础上进行了大幅度更新和修订,融入了近几年来javascript应用发展的最新成果,几乎涵盖了所有需要理解的重要概念和最新的javascript应用成果。从颇具深度的javascript语言基础到作用域(链),从引用类型...