banner.gif adie's blog
主页 博客 胭脂泪,相留醉,几时重,自是人生长恨水长东
统计
日志总数: 127
评论总数: 123
日志分类
日志归档
最近日志
最近评论
订阅
rss2.gif

atom.gif

google_rss
zt.gif 【技术资料】 阅读 5465 次

javascript hacking guide part 6

2007-03-26 12:49:20
[摘自] sunshineormer.javaeye.com

书接上回,我们说到global对象的初始创建已经完成了。那,你肯定会问了,为什么说是初始创建,而不是完整的创建呢?要回答这个问题,还要从ECMA262说起:

 

在ECMA262,强调了Global这个全局函数的很多信息,比如说,这个内置对象是先于Context就存在了的。比方说,在默认的情况下,我们调用的方法,其实都是Global这个对象的方法。比方说 :

var obj = new Object();

其实也就等于

var obj = new this.Object();

像parseInt这样的方法,其实也都是挂在Global名下的。Global对象下,有若干属性,包括Object,Array,Boolean,String…. 这么说你肯定就明白了。其他的内置对象,都是Global的一个属性值。其实,不光内置对象,所有的新定义的function ,也都会在定义后(即通过function关键字)在Global的属性列表中增加一个指向自己的属性。

那么,我们可以想一下,Global和Object之间的关系,真的是很微妙啊。Global.prototype和Object.prototype会是什么样的关系呢?

如果你是一个心急的人,一点会说:“写一段代码不就知道了吗?”。你的程序是不是这样写的?

document.writeln(global.prototype = = …

sorry,忘了告诉你了,global对象是不能这么访问的。你在程序中写:

document.writeln(global);

将会打出undefined.不过,这个Global对象又缺省存在,我们应该怎么去访问它呢?请让我先卖一个关子吧。

 

有了Global的这个概念以后,我们继续来分析源代码。从part4-part5,我们基本上只在围绕着一个函数做文章,

glob = JS_NewObject(cx, &global_class, NULL, NULL);

这个函数的调用关系讲完之后,我们就要看下面的代码段了。

JS_InitStandardClasses(cx, glob)

JS_DefineFunctions(cx, glob, shell_functions)

从名字上看,我们是要在glob这个对象下,创建并挂接系统内置的对象了(事实也果真如此)。

 

JS_InitStandardClasses这个函数定义在jsapi.c 这个文件中,我们可以很容易的找到其中的重要部分:

/* Define a top-level property 'undefined' with the undefined value. */

    atom = cx->runtime->atomState.typeAtoms[JSTYPE_VOID];

    if (!OBJ_DEFINE_PROPERTY(cx, obj, ATOM_TO_JSID(atom), JSVAL_VOID,

                             NULL, NULL, JSPROP_PERMANENT, NULL)) {

        return JS_FALSE;

    }

 

    /* Function and Object require cooperative bootstrapping magic. */

    if (!js_InitFunctionAndObjectClasses(cx, obj))

        return JS_FALSE;

 

    /* Initialize the rest of the standard objects and functions. */

    return js_InitArrayClass(cx, obj) &&

           js_InitBlockClass(cx, obj) &&

           js_InitBooleanClass(cx, obj) &&

           js_InitCallClass(cx, obj) &&

           js_InitExceptionClasses(cx, obj) &&

           js_InitMathClass(cx, obj) &&

                     。。。。

我在这段代码中,找到的几个处比较重要的函数调用,用红颜色圈了出来。

第一个部分是一个宏:OBJ_DEFINE_PROPERTY,这个宏的主要作用是调用函数指针,来给glob对象创建一个新的属性,属性的类型是JSVAL_VOID,这说明,ECMA262中要求的,Undefined属性是Global的一个属性,已经得到了实现。

第二部分,是我们的主角,弄懂了这个函数,基本上就可以初步理解ECMAScript的对象模型了。而且,它的注释也很有意思,使用了cooperative bootstrapping magic这样的字眼。好的,那就让我们跑到后台去,看看魔术师的鬼把戏是怎么出来的吧。

 

js_InitFunctionAndObjectClasses仍然在同文件中,所以不用调转就可以找到。

/* If cx has no global object, use obj so prototypes can be found. */

    if (!cx->globalObject)

        JS_SetGlobalObject(cx, obj);

 

    /* Record Function and Object in cx->resolvingTable, if we are resolving. */

。。。。

/* Initialize the function class first so constructors can be made. */

    fun_proto = js_InitFunctionClass(cx, obj);

    if (!fun_proto)

        goto out;

 

    /* Initialize the object class next so Object.prototype works. */

    obj_proto = js_InitObjectClass(cx, obj);

    if (!obj_proto) {

        fun_proto = NULL;

        goto out;

    }

 

    /* Function.prototype and the global object delegate to Object.prototype. */

    OBJ_SET_PROTO(cx, fun_proto, obj_proto);

    if (!OBJ_GET_PROTO(cx, obj))

        OBJ_SET_PROTO(cx, obj, obj_proto);

这个程序的开头两大段,做的工作,我猜想我们可以跳过,不知道正不正确,我更想从js_InitFunctionClass(cx, obj)开始(标红的部分)。我们可以看到,我们还是把global当成参数传到了这个函数体中,这样,我们得到的的返回值,就是Function.prototype;同样,如果我们继续向下看,就会看到js_InitObjectClass(cx, obj)这个函数,从返回值、注释加上对函数名的推测,我们会看到,函数运行后返回了Object.prototype。

然后呢,我们留意一下注释,哦,我的老天啊。我的猜测是没有错的Function.prototype和Global对象的prototype被委托给了Object.prototype.这还不够让我们兴奋的吗?

 

允许兴奋,可不要兴奋大发劲了啊。我们还有正事没有做呢。js_InitFunctionClass还在等着我们去解密呢。

这个函数在jsfun.c中有定义,麻烦你动手先将它找出来。

 

JSObject *

js_InitFunctionClass(JSContext *cx, JSObject *obj)

{

    JSObject *proto;

    JSAtom *atom;

    JSFunction *fun;

 

    proto = JS_InitClass(cx, obj, NULL, &js_FunctionClass, Function, 1,

                         function_props, function_methods, NULL, NULL);

    if (!proto)

        return NULL;

    atom = js_Atomize(cx, js_FunctionClass.name, strlen(js_FunctionClass.name),

                      0);

    if (!atom)

        goto bad;

    fun = js_NewFunction(cx, proto, NULL, 0, 0, obj, NULL);

    if (!fun)

        goto bad;

    fun->u.i.script = js_NewScript(cx, 1, 0, 0);

    if (!fun->u.i.script)

        goto bad;

    fun->u.i.script->code[0] = JSOP_STOP;

    fun->flags |= JSFUN_INTERPRETED;

return proto;

 

为了简单起见,我将这个函数的调用图先列出来:

js_InitFunctionClass

       JS_InitClass

              js_Atomize

              js_NewObject

                     js_NewGCThing

       js_Atomize

       js_NewFunction

              js_NewGCThing

 

那么,我们可以从这个调用图中推导出什么来呢?咱们下回书接着说。

▲评论

X 正在回复:
姓 名: 留下更多信息
性 别:
邮 件:
主 页:
Q Q:
来 自:
职 业:
评 论:
验 证:


Valid HTML 4.01 Strict Valid CSS!
Copyleft.A!die Software Studio.ADSS
Power by webmaster@adintr.com