Как исправить это определение класса в JavaScript для поддержки оператора instanceof - PullRequest
2 голосов
/ 14 февраля 2012

У меня есть метод определения класса для создания класса в JavaScript:

var Class = function() {
    var clazz = null,
    pros = {};
    for (var i = 0; i < arguments.length; i++) {
        var arg = arguments[i];
        if (typeof arg == "function") arg = arg.prototype;
        else {
            arg.init && (clazz = arg.init, delete arg.init)
        }
        for (var p in arg) pros[p] = arg[p];
    }
    clazz.prototype = pros;
    return clazz;
};

var Person = Class({
    init: function(name) {
        this.name = name;
    },
    say:function(){
        console.info(this.name);
    }
});

var Man = Class(Person, {
    init: function(name) {
        Person.apply(this, arguments);
        this.gender = 'man'
    }
});

var m = new Man('kk');
console.info(m instanceof Man);
console.info(m instanceof Person);

Однако он не поддерживает оператор instanceof.

Есть идеи, чтобы это исправить?

1 Ответ

3 голосов
/ 14 февраля 2012

Вы должны отслеживать цепочку прототипов, чтобы заставить instanceof работать. В настоящее время вы просто копируете свойства в один объект и используете его как прототип возвращаемой функции. В результате информация о том, что Parent является родителем Man, теряется.

Вам нужно установить прототип вместо копирования. Так как вам нужно изменить существующий объект, чтобы установить базовый прототип, устаревшее свойство __proto__ является обязательным. Object.create здесь нельзя использовать, потому что это возвращает новый объект.

Редактировать: Это возможно без __proto__, но вам понадобится трюк function F: http://jsfiddle.net/p9pvQ/.

var clazz = null,
    pros = Object.prototype; // root of chain

for (var i = 0; i < arguments.length; i++) {
    var arg = arguments[i];

    if (typeof arg === "function") {
        arg = arg.prototype;
    } else {
        if(arg.init) {
            clazz = arg.init;
            delete arg.init;
        }
        var o = arg;
        arg = (function() { function F() {}; F.prototype = pros; return new F; })();
        for(var key in o) arg[key] = o[key];
    }

    pros = arg;
}

m будет иметь цепочку прототипов следующим образом:

Class.init // m
  gender: "man"
  name: "kk"
  __proto__: F // Man
    __proto__: F // Person
      say: function (){
      __proto__: Object // Object.prototype
        __defineGetter__: function __defineGetter__() { [native code] }
        __defineSetter__: function __defineSetter__() { [native code] }
        ... (Object.prototype functions)
...