2012-03-25 2 views
1

Я создаю новый класс на основе класса Base, связанного с внешними методами от ext obj.создать новый экземпляр сгенерированного связывания obj

function Base(info) { 
    var self = this; 
    self.name = info.name; 
    self.createNewInstance = function (data) { 
     //I would like to identify the parent constructor 
     // in this case, the obj containing `filter` and `find` methods 
     // and use that to generate a new instance 
     return new self.constructor(data); 
    }; 
    return self; 
} 

var ext = { 
     filter: function() {/*...*/}, 
     find: function() {/*...*/} 
    }, 
    FinalClass = Base.bind(ext), 
    instance1 = FinalClass({name: 'John'}), 
    instance2 = instance1.createNewInstance({name: 'Mark'}); 

console.log(instance1); 
//--> {name: 'John', filter: [Function], find: [Function], createNewInstance: [Function]} 
console.log(instance2); 
//--> {name: 'Mark'} 

Но как вы можете видеть, что я хотел бы создать новый экземпляр внутри FinalClass класса, который будет иметь возможность использовать привязываться методы, а не только те, класса Base. Таким образом, instance2 также будет иметь filter, find и createNewInstance методов.

Я бы использовать различные типы классов, которые наследуют же Base класс, так что просто жёстко метод связывания там не будет работать, я боюсь :(

Возможно ли это достичь?

заранее спасибо

ответ

2

Я боюсь, что некоторые недоразумения о том, как работает Javascript проанализируем код:.

var ext = { 
     filter: function() {/*...*/}, 
     find: function() {/*...*/} 
    }, 
    FinalClass = Base.bind(ext), 

Итак, здесь у вас есть функция Base, связанная с ext. Это означает, что каждый раз, когда вы звоните FinalClass, this будет ext.

instance1 = FinalClass({name: 'John'}), 

Здесь вы звоните FinalClass передавая объект с name равным «Джон». Потому что в Base у вас есть:

function Base(info) { 
    var self = this; 
    self.name = info.name; 
    // ... 
    return self; 
} 

И this является экземпляром ext в FinalClass, это означает, что вы добавить новое свойствоname для ext объекта. И я думаю, ты этого не хочешь. Затем вы возвращаете self, это означает, что вы снова возвращаете ext.

После этого у вас есть:

instance2 = instance1.createNewInstance({name: 'Mark'}); 

Давайте посмотрим на этот метод:

self.createNewInstance = function (data) { 
    return new self.constructor(data); 
}; 

Поскольку instance1 это не создают с помощью new оператора, и это ext сама, это означает, его конструктор Object, а не FinalClass, как вы, вероятно, ожидали.

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

function Base(info) { 
    this.name = info.name; 

    this.createNewInstance = function (data) { 
     return new this.constructor(data); 
    }; 

    return this; 
} 

var ext = { 
     filter: function() {/*...*/}, 
     find: function() {/*...*/} 
    }; 

function FinalClass(info) { 
    var object = Object.create(ext); 
    object.constructor = FinalClass; 

    return Base.call(object, info); 
} 

var instance1 = FinalClass({name: 'John'}), 
    instance2 = instance1.createNewInstance({name: 'Mark'}); 

console.log(instance1); 
console.log(instance2); 
// notice that `filter` and `find` won't probably be listed because are not "own properties", but the objects have them: 
console.log(instance1.filter); 
console.log(instance2.filter); 

Вы также можете написать метод полезности в Base, обобщающий немного, что работа, так что ваш код будет выглядит следующим образом:

function Base(info) { 
    this.name = info.name; 

    this.createNewInstance = function (data) { 
     return new this.constructor(data); 
    }; 

    return this; 
} 

Base.create = function(extension) { 
    return function Extendend() { 
     var object = Object.create(extension); 
     object.constructor = Extendend; 

     return Base.apply(object, arguments); 
    } 
} 

var ext = { 
     filter: function() {/*...*/}, 
     find: function() {/*...*/} 
    }; 

var FinalClass = Base.create(ext); 

var instance1 = FinalClass({name: 'John'}), 
    instance2 = instance1.createNewInstance({name: 'Mark'}); 

Надеюсь, что это поможет, если у вас есть сомнения или я неправильно понял ваш вопрос, просто дайте мне знать!

+0

wow Большое спасибо ZER0, это было именно то, что я искал, спасибо, что поставил этот отличный ответ вместе – zanona

Смежные вопросы