Comments 54
А что насчет ленивых вычислений?
Классная статья и хорошие примеры!
Небольшое замечание: вместо того, чтобы добавлять обертку вокруг jQuery.ajax можно было бы сделать аналогичное на базе jQuery.Deferred. Собственно вызов jQuery.ajax и возвращает jQuery.Deferred. Правда тогда бы было труднее показать преимущества map/reduce :)
а чем не угодил такой кусок:
и зачем надо было городить foreach (через численный), который в принципе реализован нативно?
Много просто лишено смысла в реализации: все сводится к тому что «мне красиво и нравится, поэтому функционального программирования тут нет»
for (key in arr){
return arr[key];
}
и зачем надо было городить foreach (через численный), который в принципе реализован нативно?
Много просто лишено смысла в реализации: все сводится к тому что «мне красиво и нравится, поэтому функционального программирования тут нет»
Не универсальное решение.
В чистом JS это сработает, но некоторые фреймворки могут добавить свой функционал в Array.prototype и тогда при итерировании вы этот атрибут тоже обойдете.
В чистом JS это сработает, но некоторые фреймворки могут добавить свой функционал в Array.prototype и тогда при итерировании вы этот атрибут тоже обойдете.
У автора мешанина JQuery и чистого с последующим сравнением того, что сравнивать, по сути, нельзя.
Добавление в Array.prototype атрибутов, которые можно обойти с помощью for(key in arr) — феерический бред, т.к. есть объекты, а есть массивы.
Добавление в Array.prototype атрибутов, которые можно обойти с помощью for(key in arr) — феерический бред, т.к. есть объекты, а есть массивы.
Не понял про бред, поясните.
Выводит
0
1
newprop
Array.prototype.newProp = "newprop"
var b = new Array();
b.push(0);
b.push(1);
for (var i in b) console.log(b[i]);
Выводит
0
1
newprop
Я про то, что надобность данных структур по-моему сильно преувеличена.
Массив данных должен являться массивом данных, а не объектом хранения дополнительных структур, функций и т.д., т.к. для этого есть объекты.
Массив данных должен являться массивом данных, а не объектом хранения дополнительных структур, функций и т.д., т.к. для этого есть объекты.
Если использовать, например, тот же es5-shim, то в старых браузерах код будет работать некорректно
Это в идеале.
А реальности можно словить че нить интересное.
Например в старых версия IE (не знаю как сейчас), у массива не было функции indexOf, и некоторые для исправления этой проблемы поступали очень просто:
А реальности можно словить че нить интересное.
Например в старых версия IE (не знаю как сейчас), у массива не было функции indexOf, и некоторые для исправления этой проблемы поступали очень просто:
if (!Array.prototype.indexOf) {
Array.prototype.indexOf = function(item) {
...
}
}
Вероятно этим и не угодил:
P.S. То есть надо деллать дополнительную проверну на a.hasOwnProperty(i)
P.P.S. Насколько я помню, конструкция с in не гарантирует верную последовательность перебора. Она может быть такой исключительно по совпадению.
var a = [1, 2], i;
Array.prototype.someFunc = function() {};
for (i in a) {
console.log(i, ' > ' , a[i]);
}
P.S. То есть надо деллать дополнительную проверну на a.hasOwnProperty(i)
P.P.S. Насколько я помню, конструкция с in не гарантирует верную последовательность перебора. Она может быть такой исключительно по совпадению.
Спасибо большое за статью!
for(var i =0; l< arr.length; i<l; ++i){ console.log(arr[i]); }
А не так должно быть?
for(var i=0, l = arr.length; i<l; ++i){
console.log(arr[i]);
}
И так в нескольких местах оператору for 4 терма передается.
По поводу ФП на javascript — все хорошо, но количество слов function иногда задалбывает
Лично мне приятнее видеть, когда асинхронные запросы выполняются в виде. Не знаю, как остальным, так скобок нет грядки в конце выражения
Лично мне приятнее видеть, когда асинхронные запросы выполняются в виде. Не знаю, как остальным, так скобок нет грядки в конце выражения
SomeAsyncronousController.SomeMethodAsync(args).then(function(callback) { });
Думаю, стоит упомянуть, что ни map, ни reduce, ни forEach не работают в IE < 9.
Очень интересно, однако я смог осилить ровно половину. Через пол годика приду дочитывать.
В JavaScript для функционального программирования важно понимать несколько ключевых особенностей языка:
1. функции — вызываемые объекты (их можно возвращать и передавать)
2. функция не проверяет тип и кол-во аргументов в нее переданных (имена аргументов формальны)
3. каждая функция образует лексическое замыкание (и это замыкание путешествует с ней)
4. this и прототипы
Дальше все прочее можно написать уже исходя из потребностей. Можно даже таких слов как «Функции высшего порядка» и «Частичное применение функций» не знать :)
1. функции — вызываемые объекты (их можно возвращать и передавать)
2. функция не проверяет тип и кол-во аргументов в нее переданных (имена аргументов формальны)
3. каждая функция образует лексическое замыкание (и это замыкание путешествует с ней)
4. this и прототипы
Дальше все прочее можно написать уже исходя из потребностей. Можно даже таких слов как «Функции высшего порядка» и «Частичное применение функций» не знать :)
Да, эти нюансы очень важны, но их редко где можно встретить описанными вместе. Да еще и в контексте функционального программирования. На ум приходит только Secrets of Javascript Ninja.
По поводу производительности функций:
— Браузеры оптимизируют итераторы (сворачивают функции) так что ваша функция формально может и не вызываться (если вы, конечно, не делаете нечто извращенное и оптимизация не проходит). Так что пишите .map() .forEach() для холодных и теплых циклов — берегите глаза от for ;-)
— Наследование через замыкания дороже прототипного наследования (Scope функции может создаваться каждый раз при вызове функции). Опять же это заметно только в очень горячих функциях.
— Браузеры оптимизируют итераторы (сворачивают функции) так что ваша функция формально может и не вызываться (если вы, конечно, не делаете нечто извращенное и оптимизация не проходит). Так что пишите .map() .forEach() для холодных и теплых циклов — берегите глаза от for ;-)
— Наследование через замыкания дороже прототипного наследования (Scope функции может создаваться каждый раз при вызове функции). Опять же это заметно только в очень горячих функциях.
Что есть наследование через замыкания?
Ох я уж с этим наследованием наговорил чего-попало. Хотел сказать конструкторы через фактори дороже обычных через new (но не фатально).
В общем всякие фактори функций и куча вложенных функций это дороже обычного new и нескольких неизменных функций.
var createSmth = function (myPrivate) {
myPrivate = myPrivate || 0;
return {
setMyPrivate: function (val) {
myPrivate = b;
}
};
};
// или что-то такое
function makeF() {
var x = 11;
var y = 22;
return function (what) {
switch (what) {
case "x": return x;
case "y": return y;
}
}
}
var f = makeF();
f("x");
В общем всякие фактори функций и куча вложенных функций это дороже обычного new и нескольких неизменных функций.
А это:
Разве нельзя заменить на:
var totalLength = buffers.
map(function (buffer) {return buffer.length; }).
reduce(function(sum, curr){return sum+curr;}, 0);
Разве нельзя заменить на:
var totalLength = buffers.
reduce(function(sum, buffer){return sum + buffer.length;}, 0);
?Конечно можно. Но чем проще каждый шаг, тем проще понимать, что происходит. Особенно для тех, кто не сильно знаком с reduce.
Можно ведь и
заменить на
Чтобы совсем функцоинально. Но будет ли понятнее? :)
Можно ведь и
function combine(scripts, callback){
async.map(scripts, ajax, function(contents){
callback(contents.join(""));
});
}
заменить на
function combine(scripts, callback){
async.map(scripts, ajax, function(contents){
callback(contents.reduce(function(result, current) { return result + current},""));
});
}
Чтобы совсем функцоинально. Но будет ли понятнее? :)
Ваш пример вообще не коррелирует с тем, что я предложил.
Вы предлагаете расписать один шаг так, как он там внутри представляется, я же предложил два шага в один записать.
Вы предлагаете расписать один шаг так, как он там внутри представляется, я же предложил два шага в один записать.
Разделение на map и reduce было сделано специально. Давайте представим, что buffer.length не просто buffer.length, а какое-то тяжелое вычисление. Которое надо раскинуть на кластер машин для ускорения.
В случае с явно выделенным map это будет просто и писать и читать. Если же все запихнуть в один reduce- это будет сложнее для восприятия.
Композиция функций поэтому и получилась такой мощной, что сначала мы разделили все на элементарные блоки. Их проще писать, их проще понимать, их проще тестировать.
В случае с явно выделенным map это будет просто и писать и читать. Если же все запихнуть в один reduce- это будет сложнее для восприятия.
Композиция функций поэтому и получилась такой мощной, что сначала мы разделили все на элементарные блоки. Их проще писать, их проще понимать, их проще тестировать.
не туда( написал комент
>>Под циклом будем понимать стандартное лобовое решение. Примерно такое
>>for(var i =0; i
>>for(var i =0; i
Для полного погружения в функциональное программирование на JavaScript:
И еще один интересный пост про оптимизация хвостовой рекурсии: Tail call optimization on it’s way… Who gives a frak?!
- Translation from Haskell to JavaScript of selected portions of the best introduction to monads I’ve ever read
- Monad Syntax for JavaScript
- Understanding Monads With JavaScript
И еще один интересный пост про оптимизация хвостовой рекурсии: Tail call optimization on it’s way… Who gives a frak?!
Спешу заметить, что пост начинается в ошибочного примера (с функцией add). Говорится, что «Можно тот же код записать по-другому.». На самом деле эти формы записи имеют достаточно серьезные отличия, и, вообще говоря, работают по-разному. Объяснение которых уходит корнями спецификацию языка. О этих отличиях, кстати, любят спрашивать на собеседованиях. Кому интересно разобраться в данном вопросе, рекомендую почитать про Function Statement и Function Definition, например у Дмитрия Сошникова: dmitrysoshnikov.com/ecmascript/ru-chapter-5-functions/
> var str = «Mentioned by » + tweeps.map(prop («name»)).join(", ");
Есть очень интересная вещь под названием «вызов по имени» (в RightJS, кстати, используется), позволяет заменить .map(prop(«name»)) на .map(«name»).
Есть очень интересная вещь под названием «вызов по имени» (в RightJS, кстати, используется), позволяет заменить .map(prop(«name»)) на .map(«name»).
Писал библиотеку для glomper.com реализующую функциональный подход при разработке «богатых приложений» на js github.com/freeart/brisk
> С чем тут могут быть проблемы? С областями видимости Javascript. В этом языке область видимость не поблочная, а функциональная. то есть все 3 функции будут видеть одно и то значение переменной i. Поскольку цикл отработает раньше, чем придут ответы от сервера, все три функции будут работать с i == 3;
Просто замените var на let.
Просто замените var на let.
va ul = cull.dom.el("ul", className:"bands"},
cull.dom.el("li", "Tom Waits"));
очепятка, нету {
Статья настолько простая, что уже сложная.
«Порадовала» масса опечаток.
«Порадовала» масса опечаток.
Неплохо бы что-то сделать с ясностью формулировок:
По факту сказано — в JS функция является объектом, (то есть фактически, отдельно от объекта существовать не может), в отличие от Java где отдельно от объекта существовать не может...
Одним из больших плюсов Javascript является то, что функции в нем являются полноценными объектами. Настоящие First Class Citizen.
В отличие, например от Java, где функция отдельно от объекта существовать не может.
По факту сказано — в JS функция является объектом, (то есть фактически, отдельно от объекта существовать не может), в отличие от Java где отдельно от объекта существовать не может...
Хотелось бы обратить внимание, что замена
for (var i =1; l = arr.length; i< l; ++i){
}
на foreach.
далеко не эквивалентна в общем случае. Стандарт языка не гарантирует что порядок вывода будет совпадать в обоих конструкциях, более того в разных реализациях (разных браузерах) присутствуют собственные эффекты.
for (var i =1; l = arr.length; i< l; ++i){
}
на foreach.
далеко не эквивалентна в общем случае. Стандарт языка не гарантирует что порядок вывода будет совпадать в обоих конструкциях, более того в разных реализациях (разных браузерах) присутствуют собственные эффекты.
Sign up to leave a comment.
Функциональное программирование на Javascript