objective-c 对象可以用作 Javascript 对象的原型吗?

Can an objective-c object be used as a prototype of Javascript object?

让我们假设在 iOS:

@implementation SomeClass
- (void)sayHello {
    NSLog(@"Hello, World!");
}
@end

...

context[@"NativeObject"] = [SomeClass new];

然后在 Javascript:

var test = {};
test.__proto__ = NativeObject;

为什么我检查的时候:

!!NativeObject; //returns true
test.__proto__ === NativeObject; //returns false
test.__proto__ === undefined; //returns true
"sayHello" in test; //returns true
Object.getOwnPropertyNames(test).indexOf("sayHello") == -1; //returns true

既然最后2次测试都暗示有原型,为什么第2次和第3次测试说没有? Javascript核心是否损坏,或者我是否遗漏了有关其实施方式的一些关键信息?

是的,可以。答案来自JSExport documentation:

In JavaScript, inheritance is supported via a chain of prototype objects. For each Objective-C class you export, JavaScriptCore creates a prototype within the enclosing JavaScript context (a JSContext object). For the NSObject class, the prototype object is the JavaScript context's Object prototype. For all other Objective-C classes, JavaScriptCore creates a prototype object whose internal [Prototype] property points to the prototype property created for the Objective-C class's superclass. As such, the prototype chain for a JavaScript wrapper object reflects the wrapped Objective-C type's inheritance hierarchy.

In addition to the prototype object, JavaScriptCore produces a JavaScript constructor object for each Objective-C class.

我放了一个 OS X test project on github 来演示它产生以下输出:

!!NativeObject EQUALS true
test.__proto__ === NativeObject EQUALS true
test.__proto__ === undefined EQUALS false
"sayHello" in test EQUALS true
Object.getOwnPropertyNames(test).indexOf("sayHello") == -1 EQUALS true

几点观察:

  1. test.__proto__ === NativeObject 总是 returned true 而你看到它 return false.
  2. test.__proto__ === undefined 总是 return 编辑 false 而你看到它 return true

我还 运行 一个测试,我在其中注释掉了 JSExport 协议,它具有从原型链中删除 SomeClass 的效果,但原型链仍然存在,根据我假设的文档NSObject 的原型:

!!NativeObject EQUALS true
test.__proto__ === NativeObject EQUALS true
test.__proto__ === undefined EQUALS false
"sayHello" in test EQUALS false
Object.getOwnPropertyNames(test).indexOf("sayHello") == -1 EQUALS true