2016-01-27 2 views
1

После поиска в течение некоторого времени я до сих пор не нашел то, что искал.Chain custom javascript функции

Существует множество примеров, которые требуют создания нового экземпляра или имеют только функции, которые ничего не возвращают (это означает, что проблема может быть решена с возвратом this).

Я надеюсь, что следующий пример иллюстрирует мою точку хорошо:

// Say I have these functions 
function aNumber(){ 
    var max = 100, min = 0; 
    return (Math.floor(Math.random() * (max - min + 1)) + min); 
} 
function divideBy(_number, _divider){ 
    return (_number/_divider); 
} 
function multiplyBy(_number, _multi){ 
    return (_number * _multi); 
} 
function add(_number, _add){ 
    return (_number + _add); 
} 
function subtract(_number, _sub){ 
    return (_number - _sub); 
} 

// ######################################################### 

// I can do this with them 
var test = aNumber(); 
test = divideBy(aNumber, 2); 
test = add(aNumber, 5); 
test = multiplyBy(aNumber, 3); 
test = subtract(aNumber, 10); 

// I would like to do this however: 
var test = aNumber().divideBy(2).add(5).multiplyBy(3).subtract(10); 

Что будет наиболее эффективным способом, чтобы сделать последнюю работу линии?

Я дезинформировал, что это возможно без создания нового экземпляра чего-то?

+0

Нет ничего плохого в создании новых экземпляров, не знаете, почему вы хотели бы этого избежать? – Bergi

ответ

3

Да, для этого необходимо изменить PrototypeObject. Объектами являются экземпляры. Таким образом, вам нужно создать объект для этого.

function MyNum(value) { 
    this._val = value;  // Having _variable is for denoting it is a private variable. 
} 

объектов Инициализировать с помощью:

var myNum = new MyNum(5); 

А теперь с помощью этого определите следующие:

MyNum.prototype.divideBy = function() {} 
MyNum.prototype.multiplyBy = function() {} 

Не забудьте использовать return _val; внутри этих функций.

+0

Вы, вероятно, имели в виду не забывать 'return this;', для цепочки? – Bergi

+0

@Bergi Да. Это верно. –

0

Да, вам нужно создать экземпляр чего-то. Это может быть простой объектный литерал, конструктор функций и т. Д.

Идея состоит в том, что все ваши методы хранятся на каком-то объекте, не так ли? Единственный способ доступа к этим методам - ​​доступ к ним через этот объект. Имея это в виду, каждая функция должна ВОЗВРАТЬ объект, который содержит все эти методы.

Быстрый пример

var myMethods = { 
    one: function() { 
    console.log('one'); 
    // You can return 'this' or reference the object by name 
    return this; 
    // or 
    // return myMethods; 
    }, 

    two: function() { 
    console.log('two'); 
    return this; 
    } 
}; 

myMethods.one().two().one().two(); 
//=> 'one', 'two', 'one', 'two' 

Смотрите, когда вы ссылаетесь на метод непосредственно, например, так

var someMethod = myMethods.one; 
someMethod() //=> undefined 

Это происходит потому, что «это» теперь ссылается на глобальный объект, который является другая история другой день. Просто следите, если вы ссылаетесь на метод таким образом.

3

Попробуйте, пожалуйста, ниже для создания без экземпляра и ключевого слова прототипа.

Здесь добавлен еще один метод, по умолчанию можно установить число или случайное число. если номер не указан.

var Calculator = { 
 

 
setNumber: function(givenNumber) { 
 
    var max = 100, 
 
     min = 0; 
 

 
    this.number = (givenNumber) ? givenNumber : (Math.floor(Math.random() * (max - min + 1)) + min); 
 
    return this; 
 
}, 
 

 
divideBy: function(_divider) { 
 
    this.number = (this.number/_divider); 
 
    return this; 
 
}, 
 

 
multiplyBy: function(_multi) { 
 
    this.number = (this.number * _multi); 
 
    return this; 
 
}, 
 

 
add: function(_add) { 
 
    this.number = (this.number + _add); 
 
    return this; 
 
}, 
 

 
subtract: function(_sub) { 
 
    this.number = (this.number - _sub); 
 
    return this; 
 
}, 
 

 
result: function() { 
 
    return this.number; 
 
} 
 
    } 
 

 
    document.write('<pre>'); 
 
    document.writeln(Calculator.setNumber(2).divideBy(2).add(5).multiplyBy(3).subtract(10).result()); 
 
    document.writeln(Calculator.setNumber(4).divideBy(2).add(5).multiplyBy(3).subtract(10).number); 
 
    document.writeln(Calculator.setNumber().divideBy(2).add(5).multiplyBy(3).subtract(10).result()); 
 
    document.write('</pre>');

+0

Я бы использовал '.result()' вместо '.number' –

+1

добро пожаловать, проверьте обновленный ответ! –

+0

Этот вид одноэлементного дизайна не допускает нескольких параллельных вычислений. – Bergi

0

Хотя, как правило, не рекомендуется добавлять функции в прототипе примитивов JavaScript, вы можете делать то, что вы ищете, делая так.

function aNumber(){ 
 
    var max = 100, min = 0; 
 
    return (Math.floor(Math.random() * (max - min + 1)) + min); 
 
} 
 

 
function divideBy(_number, _divider){ 
 
    return (_number/_divider); 
 
} 
 
function multiplyBy(_number, _multi){ 
 
    return (_number * _multi); 
 
} 
 
function add(_number, _add){ 
 
    return (_number + _add); 
 
} 
 
function subtract(_number, _sub){ 
 
    return (_number - _sub); 
 
} 
 

 
Number.prototype.divideBy = function(_divider){ 
 
\t return divideBy(this, _divider); 
 
}; 
 

 
Number.prototype.multiplyBy = function(_multi){ 
 
\t return multiplyBy(this, _multi); 
 
}; 
 

 
Number.prototype.add = function(_add){ 
 
\t return add(this, _add); 
 
}; 
 

 
Number.prototype.subtract = function(_sub){ 
 
\t return subtract(this, _sub); 
 
}; 
 

 
var test = aNumber().divideBy(2).add(5).multiplyBy(3).subtract(10);

+0

Эти дополнительные функции выглядят как много шаблонов. Почему бы просто не поместить логику в методы? – Bergi

+1

Вы могли бы, но мое намерение состояло в том, чтобы показать способ, который будет работать в обоих методах, перечисленных в списке. Вы увидите, что я начал с того, что было в исходном сообщении, а затем просто добавил функции к примитивному типу. Если вы хотите использовать функцию более чем одним способом, более DRY имеет одну ссылку на функцию, которая выполняет эту работу. –

0

Как Praveen и Venkatraman сказали, я нашел следующие сообщения об цепочке, но все должен объявить новый instanse перед обращением любых метод для изменения method-chaining-in-javascript и beautiful-javascript-easily-create-chainable-cascading-methods-for-expressiveness

или вы можете использовать эту реализацию https://jsfiddle.net/ayinloya/zkys5dk6/

function aNumber() { 
 
    var max = 100; 
 
    var min = 0; 
 
    this._number = (Math.floor(Math.random() * (max - min + 1)) + min); 
 
    console.log("a init", this._number) 
 
} 
 

 
aNumber.prototype.divideBy = function(_divider) { 
 
    this._number = (this._number/_divider) 
 
    return this; 
 
} 
 

 
aNumber.prototype.multiplyBy = function(_multi) { 
 
    this._number = (this._number * _multi); 
 
    return this; 
 
} 
 

 
aNumber.prototype.add = function(_add) { 
 
    this._number = (this._number + _add); 
 
    return this; 
 
} 
 

 
aNumber.prototype.subtract = function(_sub) { 
 
    this._number = (this._number - _sub); 
 
    return this; 
 
} 
 
aNumber.prototype.ans = function() { 
 
    return this._number; 
 
} 
 

 
var a = new aNumber() 
 

 
alert(a.add(2).subtract(1).ans())