создать новый экземпляр объекта bind - PullRequest
1 голос
/ 25 марта 2012

Я создаю новый класс на основе класса Base, связанного с внешними методами из ext 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, так что я просто боюсь, что жестко закодированный здесь метод связывания не сработает: (

Можно ли этого достичь?

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

1 Ответ

2 голосов
/ 26 марта 2012

Боюсь, возникло недоразумение о том, как работает 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'});

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

...