习惯于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-examples"项目是为了演示和教育开发者如何在实践中应用高级JavaScript概念。这个压缩包中的"javascript-examples-master"包含了丰富的实例,旨在帮助学习者深入理解并掌握JavaScript的高级特性。 1. **...
测试JS 深入研究核心和高级Javascript概念。 包含简单的异步测试套件,以及各种测试,它们证明了我在探究John Resig和Bear Bibeault撰写的“ JavaScript忍者秘诀”时偶然发现的每个概念。
JavaScript,作为一种广泛应用于...压缩包中的资源可能包括教程、示例代码、实践项目、在线课程链接等,可以帮助开发者深入理解并熟练运用这些高级JavaScript概念。学习和掌握这些知识,将使你在Web开发领域更加专业。
javascript 演示描述基本到高级 JavaScript 概念1.Basic 2.cookies 3.dom 4. 事件 5. 例外。 6. 渐进增强 7. 原型 8. 高级,哎呀 9. 模式 10. 正则表达式。
JavaScript 遇到“行尸走肉” 使用电视剧《行尸走肉》中的示例的高级 javascript 概念示例。 在命令行上通过节点使用。 设置 使用 nodejs 进行简单的命令行日志记录以理解概念,例如。 $ node prototypes
"JavaScript高级编程"这本书深入探讨了这门语言的高级特性和最佳实践,旨在帮助开发者提升技能水平,实现更高效、更可靠的代码编写。以下是该书可能涵盖的一些关键知识点: 1. **基础语法**:包括变量、数据类型...
黑马前端学习JS高级系列教程是一个专门针对JavaScript高级特性和实践的资源集合,旨在帮助开发者深入理解和掌握JavaScript的核心概念,提高编程技能。本复习资料以Markdown(md)格式呈现,便于阅读和整理学习笔记。...
"js高级教你学好前端"这一主题旨在深入探讨JavaScript的高级特性,帮助开发者提升技能,打造更加高效、交互性更强的Web应用。 JavaScript的核心概念包括变量、数据类型、操作符、流程控制(如条件语句和循环)、...
这本书分为三章,涵盖了Ext JS的关键概念和技术,旨在帮助开发者充分利用这个强大的JavaScript库来构建功能丰富的Web应用程序。 第一章可能涉及了Ext JS的基础和核心概念,包括MVC(Model-View-Controller)架构的...
在这个过程中,读者将学会如何设计模块化的应用,并理解高级JavaScript概念在实际开发中的应用。 Node.js与传统后端技术的主要区别在于其基于事件和非阻塞I/O模型的编程范式。在Node.js中,服务器对客户端请求的...
此外,书中还深入讲解了函数、作用域、闭包等关键概念,这些都是JavaScript独特特性和强大功能的核心所在。特别是闭包,它是理解和掌握JavaScript高级特性的重要一步,能帮助开发者实现数据封装和模块化编程。 ...
接下来,我们将详述一些基本和高级的JavaScript概念: ### 基础概念 1. **变量(Variables)**:使用`var`, `let` 或 `const` 关键字声明,其中`let` 和 `const` 是ES6新增的特性,提供更安全的变量管理。 2. **...
这篇《JavaScript高级教程》全面深入地探讨了这门语言的核心概念和技术,旨在帮助开发者从初级水平跃升至高级阶段。 首先,JavaScript的基础部分涵盖了变量、数据类型(包括基本类型和引用类型)、操作符、流程控制...
这本书并不是简单的“Hello World”教程,而是深入探讨了高级JavaScript概念,特别是与Node.js相关的特性。 Node.js 的核心优势在于其单线程事件驱动模型,结合高性能的V8引擎,使其成为构建高吞吐量网络服务的理想...
JavaScript,也被称为JS,是一种广泛应用于网页和网络应用的编程语言,尤其在客户端脚本方面具有重要地位。作为"Web的三大核心技术"之一,JavaScript与HTML和CSS共同构建了现代互联网体验的基础。"JavaScript高级...
4. **高级JavaScript概念**:在开发过程中,深入讲解JavaScript的一些高级概念及其在Node.js中的应用。 #### 四、JavaScript与Node.js的特性对比 - **服务器端JavaScript**:Node.js提供了服务器端的JavaScript...
6. **模块系统(ES6模块和CommonJS)**:JavaScript提供了模块化代码的方法,ES6的`import`和`export`关键字用于模块导入导出,而CommonJS(如Node.js中)则使用`require`和`module.exports`。 7. **高阶函数...
本资源聚焦于JavaScript的高级概念,特别是回调函数、闭包和高阶函数这三个核心主题。下面将详细阐述这些概念。 ### 回调函数 回调函数是JavaScript中处理异步操作的一种常见方式。在JavaScript中,由于其单线程...
JavaScript高级编程是面向C#程序员的一种技术,旨在简化代码并实现更高效的效果。JavaScript作为一种功能强大的脚本语言,它的灵活性允许开发者在对象创建后动态定义其属性,这在早期的JavaScript开发中尤其常见。...