The differences between Pure JS and JS-Binding objects

Cocos Creator Engine uses V8 to export CPP classes to Javascript, we call it JS-Binding. There're some differences between Pure JS and JS-Binding objects. If your application needs to run on all platforms, especially on native platforms, it's better not to use some APIs that behave differently between Web and Native platforms. If you have to use them, you need to write some platform specified code like if (NATIVE) {...} else {...} .

Properties

The properties of pure JS objects are assigned to instance, but they're assigned to prototype for JS-Binding objects.

Pure JS objects

class MyClass {
  constructor() {
    this.a = 'a';
    this.b = false;
    this.c = 100;
  }
};

const myobj = new MyClass();
const ownA = myobj.hasOwnProperty('a');
console.log(`ownA: ${ownA}`); // ownA: true

JS-Binding objects

// C++ class
class MyClass {
public:
  std::string a;
  bool b;
  int32_t c;
};

// The snippet of JS-Binding glue code.
bool js_register_cc_MyClass(se::Object* obj) {
    auto* cls = se::Class::create("MyClass", obj, nullptr, _SE(js_new_cc_MyClass)); 
    cls->defineStaticProperty("__isJSB", se::Value(true), se::PropertyAttribute::READ_ONLY | se::PropertyAttribute::DONT_ENUM | se::PropertyAttribute::DONT_DELETE);

    cls->defineProperty("a", _SE(js_cc_MyClass_a_get), _SE(js_cc_MyClass_a_set)); 
    cls->defineProperty("b", _SE(js_cc_MyClass_b_get), _SE(js_cc_MyClass_b_set)); 
    cls->defineProperty("c", _SE(js_cc_MyClass_c_get), _SE(js_cc_MyClass_c_set)); 

    cls->defineFinalizeFunction(_SE(js_delete_cc_MyClass));
    cls->install();
    JSBClassType::registerClass<cc::MyClass>(cls);

    __jsb_cc_MyClass_proto = cls->getProto();
    __jsb_cc_MyClass_class = cls;
    se::ScriptEngine::getInstance()->clearException();
    return true;
}
//
const myobj = new jsb.MyClass();
const ownA = myobj.hasOwnProperty('a');
console.log(`ownA: ${ownA}`); // ownA: false
const protoOwnA = myobj.__proto__.hasOwnProperty('a');
console.log(`protoOwnA: ${protoOwnA}`); // protoOwnA: true

So if you have written some JS code depends on hasOwnProperty, you need to keep in mind of the above difference since it may cause your application to work correctly on Web platform, but be broken on Native platform.

Possible Solution

If the application needs to run on Native platform, while checking whether a property exists on a JS-Binding object, you need to check its __proto__ either. For example:

function doSomething(v) {
  // ......
}

function foo() {
  for (const key in myObj) {
    if (myObj.hasOwnProperty('a')) {
      doSomething(myObj['a']);
    } else if (NATIVE) {
      if (myObj.__proto__.hasOwnProperty('a')) {
        doSomething(myObj['a']);
      }
    }
  }
}

results matching ""

    No results matching ""