Нативный способ добавления пользовательских функций JavaScript в цепочку вызовов методов
Я хотел бы знать, есть ли способ для этого:
Object.prototype.chain = function(f) { return f.call(this) }
function fun1() {
doSomethingWithObject(this)
return this
}
function fun2() {
doSomethingElse(this)
return this
}
someObject
.method1('something')
.method2()
.chain(checkSomething() ? fun1 : fun2)
.method3()
Но мне не хочется менять прототип Object
. Есть ли способ сделать это без изменения прототипа Objects
или других конструкторов, которые я использую (и я не разработчик)
Редактирование:
Я чувствую, что не очень хорошо объясняю, поэтому давайте добавим некоторые детали:
Что я хотел бы сделать, так это использовать некоторые API, которые я не определяю. someObject
определяется следующим образом: с цепными методами:
var someObject = {
method1: function(val) {
// do something
return this
},
method2: function() {
// do something
return this
},
method3: function() {
// do something
return this
}
}
Теперь представьте, что я не могу изменить этот код, потому что этот объект из библиотеки, и поэтому я не хочу этого делать. Затем представьте, что я хотел бы связать методы и некоторые пользовательские функции (см. Мой первый фрагмент) для многих других объектов. Самое простое - подключить метод chain
к Object.prototype
.
Но я думаю, что это может привести к конфликтам в будущем. Я ищу способ сделать то же самое, не касаясь прототипа.
Ответы
Ответ 1
Обертка - это то, что обернет любой объект, чтобы сделать его совместимым с "цепочкой", и добавит еще один цепной метод, который позволит вам подключать внешние функции и по-прежнему получать цепочку.
Проверьте этот пример:
function myObj() {
this.state = {
a: 1
};
this.method1 = function () {
console.log("1");
}
this.method2 = function () {
console.log("2");
}
this.method3 = function () {
console.log("3");
}
this.method4 = function () {
console.log(this.state);
}
}
function objectChainWrapper(obj) {
this.chain = function (fn) {
fn.call(obj);
return this;
}
for (var prop in obj) {
if (obj.hasOwnProperty(prop) && typeof obj[prop] == 'function') {
this[prop] = (function (methodName) {
return function () {
obj[methodName].call(obj);
return this;
}
}(prop))
}
}
}
var obj = new myObj();
var wrapper = new objectChainWrapper(obj);
var chainMethod = function(){ console.log('chain') };
var chainMethodState = function(){ console.log(this.state) };
wrapper.method1().method2().chain(chainMethodState).method3().chain(chainMethod).method4();
JSFIDDLE.
Ответ 2
Я удивлен, что нет никаких ответов на это, если честно.
Существует множество способов изначально ввести цепочку. Мне нравится использовать раскрытие шаблона модуля.
Итак, я создаю базовую модель (иди и запусти ее в хром консоли firefox)
var Dog = function(name) {
var self = this;
this.name = name;
var core = {
getName:function(){
return self.name;
}
};
this.movement = function(){ //this function will be exposed including its returned functions for chaining
console.log(self.name + " is getting restless... ");
var jump = function(){
console.log(self.name + " jumps around ");
return this //returns the movement scope
};
var run = function(){
console.log(self.name + " has decided to run");
return this //returns the movement scope
};
return {
jump:jump,
run:run
};
}
console.log("A Pup has been born, we shall call him... " + name);
return{
movement:self.movement //only .movement is exposed to the outside world
};
}
Теперь создайте новую собаку, используя var p = new Dog("doggyName");
теперь вы можете цеплять функции. Попробуйте:
p.movement().jump().run().jump().run();
Вы должны получить текст, записанный в консоли, который соответствует каждой функции.
Возвращая объем этой функции после выполнения вашей функции перемещения, вы обнаружите дополнительные функции, которые возвращаются в этой области (см. комментарии в коде). Затем они могут быть привязаны к концу вашей текущей функции при условии, что они находятся в одном и том же объеме. Это позволяет вам обладать определенными частями вашего кода. Например, с этой собакой все движения ограничены до self.movement
, вы можете иметь все, что есть, до self.eat
и т.д.
Прочитайте раскрывающийся шаблон модуля. Хотя это не единственный способ сделать это.