WebKit中自定义JavaScript类型对instanceof语句的处理

来源:互联网 发布:白人警察枪杀黑人知乎 编辑:程序博客网 时间:2024/05/21 07:06

WebKit中,自行扩展的JavaScript类型需要定义下面的结构体

/*!@struct JSClassDefinition@abstract This structure contains properties and callbacks that define a type of object. All fields other than the version field are optional. Any pointer may be NULL.@field version The version number of this structure. The current version is 0.@field attributes A logically ORed set of JSClassAttributes to give to the class.@field className A null-terminated UTF8 string containing the class's name.@field parentClass A JSClass to set as the class's parent class. Pass NULL use the default object class.@field staticValues A JSStaticValue array containing the class's statically declared value properties. Pass NULL to specify no statically declared value properties. The array must be terminated by a JSStaticValue whose name field is NULL.@field staticFunctions A JSStaticFunction array containing the class's statically declared function properties. Pass NULL to specify no statically declared function properties. The array must be terminated by a JSStaticFunction whose name field is NULL.@field initialize The callback invoked when an object is first created. Use this callback to initialize the object.@field finalize The callback invoked when an object is finalized (prepared for garbage collection). Use this callback to release resources allocated for the object, and perform other cleanup.@field hasProperty The callback invoked when determining whether an object has a property. If this field is NULL, getProperty is called instead. The hasProperty callback enables optimization in cases where only a property's existence needs to be known, not its value, and computing its value is expensive. @field getProperty The callback invoked when getting a property's value.@field setProperty The callback invoked when setting a property's value.@field deleteProperty The callback invoked when deleting a property.@field getPropertyNames The callback invoked when collecting the names of an object's properties.@field callAsFunction The callback invoked when an object is called as a function.@field hasInstance The callback invoked when an object is used as the target of an 'instanceof' expression.@field callAsConstructor The callback invoked when an object is used as a constructor in a 'new' expression.@field convertToType The callback invoked when converting an object to a particular JavaScript type.@discussion The staticValues and staticFunctions arrays are the simplest and most efficient means for vending custom properties. Statically declared properties autmatically service requests like getProperty, setProperty, and getPropertyNames. Property access callbacks are required only to implement unusual properties, like array indexes, whose names are not known at compile-time.If you named your getter function "GetX" and your setter function "SetX", you would declare a JSStaticValue array containing "X" like this:JSStaticValue StaticValueArray[] = {    { "X", GetX, SetX, kJSPropertyAttributeNone },    { 0, 0, 0, 0 }};Standard JavaScript practice calls for storing function objects in prototypes, so they can be shared. The default JSClass created by JSClassCreate follows this idiom, instantiating objects with a shared, automatically generating prototype containing the class's function objects. The kJSClassAttributeNoAutomaticPrototype attribute specifies that a JSClass should not automatically generate such a prototype. The resulting JSClass instantiates objects with the default object prototype, and gives each instance object its own copy of the class's function objects.A NULL callback specifies that the default object callback should substitute, except in the case of hasProperty, where it specifies that getProperty should substitute.*/typedef struct {    int                                 version; /* current (and only) version is 0 */    JSClassAttributes                   attributes;    const char*                         className;    JSClassRef                          parentClass;            const JSStaticValue*                staticValues;    const JSStaticFunction*             staticFunctions;        JSObjectInitializeCallback          initialize;    JSObjectFinalizeCallback            finalize;    JSObjectHasPropertyCallback         hasProperty;    JSObjectGetPropertyCallback         getProperty;    JSObjectSetPropertyCallback         setProperty;    JSObjectDeletePropertyCallback      deleteProperty;    JSObjectGetPropertyNamesCallback    getPropertyNames;    JSObjectCallAsFunctionCallback      callAsFunction;    JSObjectCallAsConstructorCallback   callAsConstructor;    JSObjectHasInstanceCallback         hasInstance;    JSObjectConvertToTypeCallback       convertToType;} JSClassDefinition;


假设MyObject是我们在C中自定义JavaScript类型的一个对象,并挂载到全局对象下。在网页中遇到下面的代码

myObject instanceof MyObject


如果这里MyObject是个普通对象,即,是以下面的方式定义

JSObjectRef myObject = JSObjectMake(context, MyObject_class(context), NULL);JSStringRef myObjectIString = JSStringCreateWithUTF8CString("MyObject");JSObjectSetProperty(context, globalObject, myObjectIString, myObject, kJSPropertyAttributeNone, NULL);JSStringRelease(myObjectIString);


那么上面的JavaScript语句,执行时将会调用到JSClassDefinition中定义的JSObjectHasInstanceCallback来判断是否成立;如果JSObjectHasInstanceCallback没有设置,直接返回false,WebKit不会自行判断。

如果MyObject是个构造器,即,是以下面的方式定义

JSStringRef myConstructorIString = JSStringCreateWithUTF8CString("MyObject");JSObjectRef myConstructor = JSObjectMakeConstructor(context, MyObject_class(context), callAsConstructor); //这里的callAsConstructor与JSClassDefinition中的JSObjectCallAsConstructorCallback属性功能类似JSObjectSetProperty(context, globalObject, myConstructorIString, myConstructor, kJSPropertyAttributeNone, NULL);JSStringRelease(myConstructorIString);


那么WebKit在遇到instanceof语句时,会自动判断myObject的类属性。如果myObject是在JavaScript中用下面的语句创建

var myObject = new MyObject();


或者在C中,通过下面的语句创建

JSObjectRef myObject = JSObjectMake(context, MyObject_class(context), NULL);


则判断为真。(在C中可以通过JavaScriptCore API中的JSValueIsInstanceOfConstructor()获得同样的结果)

总结:

  • 如果自定义的JavaScript类型,在构造方面没有什么特殊之处,正常返回此自定义类型的对象(通过JSObjectMake创建),则不需要实现JSClassDefinition结构中的JSObjectCallAsConstructorCallback和JSObjectHasInstanceCallback属性。最方便的办法是挂载一个自定义类型的构造器到全局对象下。
  • 如果希望自定义的JavaScript类型有一个对象能挂载到全局对象下,同时这个对象还能起到构造器的作用,请同时实现JSClassDefinition结构中的JSObjectCallAsConstructorCallback和JSObjectHasInstanceCallback属性(通常这意味着JSObjectCallAsConstructorCallback返回的不是简单的用自定义类型构造出来的对象,通过系统默认的判断方式无法准确判断)。
原创粉丝点击