我是靠谱客的博主 称心白云,最近开发中收集的这篇文章主要介绍JavaScript:遍历原型链,调用栈,作用域链(转)JavaScript:遍历原型链,调用栈,作用域链,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

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

 

在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

转载于:https://www.cnblogs.com/sandianbaozi/archive/2012/12/03/2799529.html

最后

以上就是称心白云为你收集整理的JavaScript:遍历原型链,调用栈,作用域链(转)JavaScript:遍历原型链,调用栈,作用域链的全部内容,希望文章能够帮你解决JavaScript:遍历原型链,调用栈,作用域链(转)JavaScript:遍历原型链,调用栈,作用域链所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(34)

评论列表共有 0 条评论

立即
投稿
返回
顶部