[转载]向高级Javascript程序员阵营迈进:Javascript一些概念研究总结

简介:


习惯于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,而不是我们所预想的数字呢?看你能不能根据以上的知识,解释这种现象的原因。提示:变量查找机制。

< html >  
< head >  
< title > 循环内的闭包 应该谨慎 </ title >  
</ head >  
< body >  
< ul  id ="list" >  
< li > 第1条记录 </ li >  
< li > 第2条记录 </ li >  
< li > 第3条记录 </ li >  
< li > 第4条记录 </ li >  
< li > 第5条记录 </ li >  
< li > 第6条记录 </ li >  
</ ul >  
< script  type ="text/javascript" >
var  list_obj  =  document.getElementById( " list " ).getElementsByTagName( " li " );  // 获取list下面的所有li的对象数组
for  ( var  i  =  0 ; i  <=  list_obj.length; i ++ ) {
list_obj[i].onmousemove 
=  function () {
this .style.backgroundColor  =  " #eee " ;
document.title
= i
};
list_obj[i].onmouseout 
=  function () {
this .style.backgroundColor  =  " #fff " ;
}
}
</ script >  
</ body >  
</ html >

为什么上面的代码改成下面的就好了呢?

< html >  
< head >  
< title > 循环内的闭包 应该谨慎 </ title >  
</ head >  
< body >  
< ul  id ="list" >  
< li > 第1条记录 </ li >  
< li > 第2条记录 </ li >  
< li > 第3条记录 </ li >  
< li > 第4条记录 </ li >  
< li > 第5条记录 </ li >  
< li > 第6条记录 </ li >  
</ ul >  
< script  type ="text/javascript" >
var  list_obj  =  document.getElementById( " list " ).getElementsByTagName( " li " );  // 获取list下面的所有li的对象数组
for  ( var  i  =   0 ; i  <=  list_obj.length; i ++ ) {
(
function (i){
list_obj[i].onmousemove 
=   function () {
this .style.backgroundColor  =   " #eee " ;
document.title
= i
};
list_obj[i].onmouseout 
=   function () {
this .style.backgroundColor  =   " #fff " ;
}
})(i);
}
</ script >  
</ body >  
</ html >

 

 文章转载自:http://www.cnblogs.com/kaima/archive/2009/03/07/advanced_javascript_concept.html

 

本文转自 酷小孩 博客园博客,原文链接: http://www.cnblogs.com/babycool/archive/2012/03/25/2416460.html ,如需转载请自行联系原作者

版权
作者: 酷小孩 
相关文章
|
3月前
|
存储 监控 JavaScript
基于布隆过滤器的 Node.js 算法在局域网电脑桌面监控设备快速校验中的应用研究
本文探讨了布隆过滤器在局域网电脑桌面监控中的应用,分析其高效空间利用率、快速查询性能及动态扩容优势,并设计了基于MAC地址的校验模型,提供Node.js实现代码,适用于设备准入控制与重复数据过滤场景。
188 0
|
2月前
|
运维 监控 JavaScript
基于 Node.js 图结构的局域网设备拓扑分析算法在局域网内监控软件中的应用研究
本文探讨图结构在局域网监控系统中的应用,通过Node.js实现设备拓扑建模、路径分析与故障定位,提升网络可视化、可追溯性与运维效率,结合模拟实验验证其高效性与准确性。
229 3
|
Web App开发 JavaScript 前端开发
Node.js 是一种基于 Chrome V8 引擎的后端开发技术,以其高效、灵活著称。本文将介绍 Node.js 的基础概念
Node.js 是一种基于 Chrome V8 引擎的后端开发技术,以其高效、灵活著称。本文将介绍 Node.js 的基础概念,包括事件驱动、单线程模型和模块系统;探讨其安装配置、核心模块使用、实战应用如搭建 Web 服务器、文件操作及实时通信;分析项目结构与开发流程,讨论其优势与挑战,并通过案例展示 Node.js 在实际项目中的应用,旨在帮助开发者更好地掌握这一强大工具。
379 1
|
6月前
|
监控 算法 JavaScript
基于 JavaScript 图算法的局域网网络访问控制模型构建及局域网禁止上网软件的技术实现路径研究
本文探讨局域网网络访问控制软件的技术框架,将其核心功能映射为图论模型,通过节点与边表示终端设备及访问关系。以JavaScript实现DFS算法,模拟访问权限判断,优化动态策略更新与多层级访问控制。结合流量监控数据,提升网络安全响应能力,为企业自主研发提供理论支持,推动智能化演进,助力数字化管理。
180 4
|
6月前
|
监控 算法 JavaScript
公司局域网管理视域下 Node.js 图算法的深度应用研究:拓扑结构建模与流量优化策略探析
本文探讨了图论算法在公司局域网管理中的应用,针对设备互联复杂、流量调度低效及安全监控困难等问题,提出基于图论的解决方案。通过节点与边建模局域网拓扑结构,利用DFS/BFS实现设备快速发现,Dijkstra算法优化流量路径,社区检测算法识别安全风险。结合WorkWin软件实例,展示了算法在设备管理、流量调度与安全监控中的价值,为智能化局域网管理提供了理论与实践指导。
179 3
|
8月前
|
存储 算法 JavaScript
基于 Node.js 深度优先搜索算法的上网监管软件研究
在数字化时代,网络环境呈现出高度的复杂性与动态性,上网监管软件在维护网络秩序与安全方面的重要性与日俱增。此类软件依托各类数据结构与算法,实现对网络活动的精准监测与高效管理。本文将深度聚焦于深度优先搜索(DFS)算法,并结合 Node.js 编程语言,深入剖析其在上网监管软件中的应用机制与效能。
119 6
|
10月前
|
JavaScript 前端开发 容器
this、self、window、top 在 JavaScript 中的区别深入研究
在 JavaScript 开发中,`this`、`self`、`window` 和 `top` 是四个常用的概念。`this` 指向当前执行上下文的对象,其值取决于函数调用方式;`self` 在全局作用域中等同于 `window`,常用于 Web Workers;`window` 代表浏览器窗口,是全局变量的容器;`top` 指向最顶层窗口,用于判断是否在框架中。理解这些概念有助于编写健壮的代码。
328 1
this、self、window、top 在 JavaScript 中的区别深入研究
|
机器学习/深度学习 自然语言处理 JavaScript
信息论、机器学习的核心概念:熵、KL散度、JS散度和Renyi散度的深度解析及应用
在信息论、机器学习和统计学领域中,KL散度(Kullback-Leibler散度)是量化概率分布差异的关键概念。本文深入探讨了KL散度及其相关概念,包括Jensen-Shannon散度和Renyi散度。KL散度用于衡量两个概率分布之间的差异,而Jensen-Shannon散度则提供了一种对称的度量方式。Renyi散度通过可调参数α,提供了更灵活的散度度量。这些概念不仅在理论研究中至关重要,在实际应用中也广泛用于数据压缩、变分自编码器、强化学习等领域。通过分析电子商务中的数据漂移实例,展示了这些散度指标在捕捉数据分布变化方面的独特优势,为企业提供了数据驱动的决策支持。
1494 2
信息论、机器学习的核心概念:熵、KL散度、JS散度和Renyi散度的深度解析及应用
|
缓存 前端开发 JavaScript
JavaScript前端路由的实现原理及其在单页应用中的重要性,涵盖前端路由概念、基本原理、常见实现方式
本文深入解析了JavaScript前端路由的实现原理及其在单页应用中的重要性,涵盖前端路由概念、基本原理、常见实现方式(Hash路由和History路由)、优点及挑战,并通过实际案例分析,帮助开发者更好地理解和应用这一关键技术,提升用户体验。
467 1
|
存储 JavaScript 前端开发
JavaScript 对象的概念
JavaScript 对象的概念
127 4

热门文章

最新文章