热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

JavaScript:遍历原型链,调用栈,作用域链

在JavaScript中,有三种常见的链式结构:原型链(PrototypeChain),调用栈(CallStack),作用域链(ScopeChain).本文并不准备讲这些概念的基础知识,而是

在Javascript中,有三种常见的链式结构:原型链(Prototype Chain),调用栈(Call Stack),作用域链(Scope Chain).本文并不准备讲这些概念的基础知识,而是要给出如何遍历这三种链结构的方法,从而加深理解.

遍历原型链

在Javascript中,任何对象都有自己的原型链.原型链是由一系列对象加上最后的null组成的.如果还没掌握相关基础知识,可以看看我在MDN上翻译的继承与原型链一文.遍历函数如下:

function getPrototypeChain(obj) {
    var protoChain = [];
    while (obj = Object.getPrototypeOf(obj)) {
        protoChain.push(obj);
    }
    protoChain.push(null);
    return protoChain;
}

尝试执行一下

>getPrototypeChain(new String(""))
[String, Object, null]                     //依次是String.prototype,Object.prototype,null
  
>getPrototypeChain(function(){})
[function Empty() {}, Object, null]        //依次是Function.prototype,Object.prototype,null

这个函数是在我以前写的一篇文章Javascript:我对原型链的理解中给出的.

遍历调用栈

在Javascript中,调用栈就是一系列的函数,表明当前函数是由哪些上层函数调用的.遍历函数如下:

function getCallStack() {
    var stack = [];
    var fun = getCallStack;
    while (fun = fun.caller) {
        stack.push(fun)
    }
    return stack
}

该函数用到了非标准的caller属性,不过主流浏览器都支持它.尝试执行一下:

function a() {
    b()
}

function b() {
    c()
}

function c() {
    alert(getCallStack().map(function (fun) {
        return fun.name  //使用了非标准的name属性
    }))  
}

a()  //弹出c,b,a
b()  //弹出c,b

在调试工具中,我们可以直接使用console.trace()来打印出调用栈.在递归调用中,如果调用栈的长度过长,引擎就会抛出异常"too much recursion".到底多长是上限,不同的引擎不同的操作系统环境这个值是不同的.可以使用下面这个函数表达式获取到这个上限值:

> (function(i){try{(function m(){++i&&m()}())}catch(e){return i}})(0)
50761

遍历作用域链

作用域链是由一系列执行上下文(Execution context)中的活动对象(Activation object)加最后的全局对象组成的.活动对象是一个抽象实体(Abstract Entity),它是由引擎内部来管理的,并不能通过Javascript来访问.看不到,摸不着,所以这些知识就很难理解.

不过在Mozilla的引擎中,有一个魔法属性__parent__可以获取到函数执行时的活动对象.只是在SpiderMonkey中,该属性已经被删除了(Firefox 4开始).不过在Mozilla的另外一个Javascript引擎Rhino(Java编写)上,还可以使用这个特殊属性.遍历代码如下:

function getScopeChain(fun) {
    var scopeChain = [];
    while (fun = fun.__parent__) {
        scopeChain.push(fun);
}
return scopeChain;
}

尝试执行一下:

var a = 0;
(function fun1() {
    var a = 1;
    (function fun2() {
        var a = 2;
        (function fun3() {
            var a = 3;
            getScopeChain(function () {}).map(function (obj) {
                print("-----------------------------")
                for(var i in obj){
                    print(i + ":" + (obj[i].name?obj[i].name:obj[i]))
                }
            })
        })()
    })()
})()

-----------------------------           //函数fun3
arguments:[object Arguments]        
a:3
fun3:fun3
-----------------------------           //函数fun2
arguments:[object Arguments]
a:2
fun2:fun2
-----------------------------           //函数fun1
arguments:[object Arguments]
a:1
fun1:fun1
-----------------------------           //全局上下文
a:0
getScopeChain:getScopeChain

另外,如果是在Firefox的特权代码中(chrome上下文),还可以使用Debugger API来获取到各种引擎内部隐藏着的数据,Firebug中的以及Firefox自带的调试器,都是用这些API来实现的.


推荐阅读
  • 在对WordPress Duplicator插件0.4.4版本的安全评估中,发现其存在跨站脚本(XSS)攻击漏洞。此漏洞可能被利用进行恶意操作,建议用户及时更新至最新版本以确保系统安全。测试方法仅限于安全研究和教学目的,使用时需自行承担风险。漏洞编号:HTB23162。 ... [详细]
  • 本文介绍了如何利用Struts1框架构建一个简易的四则运算计算器。通过采用DispatchAction来处理不同类型的计算请求,并使用动态Form来优化开发流程,确保代码的简洁性和可维护性。同时,系统提供了用户友好的错误提示,以增强用户体验。 ... [详细]
  • HTML5 Web存储技术是许多开发者青睐本地应用程序的重要原因之一,因为它能够实现在客户端本地存储数据。HTML5通过引入Web Storage API,使得Web应用程序能够在浏览器中高效地存储数据,从而提升了应用的性能和用户体验。相较于传统的Cookie机制,Web Storage不仅提供了更大的存储容量,还简化了数据管理和访问的方式。本文将从基础概念、关键技术到实际应用,全面解析HTML5 Web存储技术,帮助读者深入了解其工作原理和应用场景。 ... [详细]
  • 【问题】在Android开发中,当为EditText添加TextWatcher并实现onTextChanged方法时,会遇到一个问题:即使只对EditText进行一次修改(例如使用删除键删除一个字符),该方法也会被频繁触发。这不仅影响性能,还可能导致逻辑错误。本文将探讨这一问题的原因,并提供有效的解决方案,包括使用Handler或计时器来限制方法的调用频率,以及通过自定义TextWatcher来优化事件处理,从而提高应用的稳定性和用户体验。 ... [详细]
  • 深入剖析Java中SimpleDateFormat在多线程环境下的潜在风险与解决方案
    深入剖析Java中SimpleDateFormat在多线程环境下的潜在风险与解决方案 ... [详细]
  • 使用 ListView 浏览安卓系统中的回收站文件 ... [详细]
  • Python 伦理黑客技术:深入探讨后门攻击(第三部分)
    在《Python 伦理黑客技术:深入探讨后门攻击(第三部分)》中,作者详细分析了后门攻击中的Socket问题。由于TCP协议基于流,难以确定消息批次的结束点,这给后门攻击的实现带来了挑战。为了解决这一问题,文章提出了一系列有效的技术方案,包括使用特定的分隔符和长度前缀,以确保数据包的准确传输和解析。这些方法不仅提高了攻击的隐蔽性和可靠性,还为安全研究人员提供了宝贵的参考。 ... [详细]
  • 在处理 XML 数据时,如果需要解析 `` 标签的内容,可以采用 Pull 解析方法。Pull 解析是一种高效的 XML 解析方式,适用于流式数据处理。具体实现中,可以通过 Java 的 `XmlPullParser` 或其他类似的库来逐步读取和解析 XML 文档中的 `` 元素。这样不仅能够提高解析效率,还能减少内存占用。本文将详细介绍如何使用 Pull 解析方法来提取 `` 标签的内容,并提供一个示例代码,帮助开发者快速解决问题。 ... [详细]
  • 开发工具WebDeveloper1.1.8https:addons.mozilla.orgen-USfirefoxaddon60以工具栏的形式对网页的(X)HTML、脚本、多媒体、 ... [详细]
  • 【转】JS键盘按钮keyCode及示例大全(JS前端)
    文章目录以功能区分布以keycode编号顺序分布简记表使用示例:组合键获取用户按下的键javascript判断是否按回车键屏蔽按键组合健获取键和相应值的js回目录 ... [详细]
  • 如何使网页自适应电脑屏幕分辨率?
    在1024*768或者800*600的分辨率下可以自动调整成适用于该客户端分辨率的大小。  第一种方法:做一个网页解决问题(长了点)  如果只是因为浏览者改变了浏览器的设置,或者因为浏览器不兼容,使自 ... [详细]
  • 本文介绍了一种自定义的Android圆形进度条视图,支持在进度条上显示数字,并在圆心位置展示文字内容。通过自定义绘图和组件组合的方式实现,详细展示了自定义View的开发流程和关键技术点。示例代码和效果展示将在文章末尾提供。 ... [详细]
  • 提升视觉效果:Unity3D中的HDR与Bloom技术(高动态范围成像与光线散射)
    提升视觉效果:Unity3D中的HDR与Bloom技术(高动态范围成像与光线散射) ... [详细]
  • 本文深入解析了WCF Binding模型中的绑定元素,详细介绍了信道、信道管理器、信道监听器和信道工厂的概念与作用。从对象创建的角度来看,信道管理器负责信道的生成。具体而言,客户端的信道通过信道工厂进行实例化,而服务端则通过信道监听器来接收请求。文章还探讨了这些组件之间的交互机制及其在WCF通信中的重要性。 ... [详细]
  • 在本文中,我们将详细介绍如何构建一个用于自动回复消息的XML类。当微信服务器接收到用户消息时,该类将生成相应的自动回复消息。以下是具体的代码实现:```phpclass We_Xml { // 代码内容}```通过这个类,开发者可以轻松地处理各种消息类型,并实现高效的自动回复功能。我们将深入探讨类的各个方法和属性,帮助读者更好地理解和应用这一技术。 ... [详细]
author-avatar
aaaaaaaaaaa的美丽人生_556
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有