что используется для вызова функции внутри функции, а не для передачи двух аргументов? [Дубликат]

== выполняет контрольную проверку равенства, ссылаясь на то, что 2 объекта (строки в этом случае) относятся к одному и тому же объекту в памяти.

Метод equals() будет проверять, будет ли содержимое или состояния двух объектов одинаковы.

Очевидно, что == работает быстрее, но во многих случаях может (может) давать ложные результаты, если вы просто хотите сказать, имеет ли 2 String s тот же текст.

Определенно рекомендуется использовать метод equals().

Не беспокойтесь о производительности. Некоторые способы поощрения использования String.equals():

  1. Реализация String.equals() сначала проверяет ссылочное равенство (используя ==), и если две строки одинаковы по ссылке, дальнейший расчет Выполняется!
  2. Если 2 ссылки на строки не совпадают, String.equals() будет проверять длину строк. Это также является быстрой операцией, поскольку класс String хранит длину строки, не нужно считать символы или кодовые точки. Если длины отличаются, дальнейшая проверка не выполняется, мы знаем, что они не могут быть равными.
  3. Только если мы доберемся до этого, будет фактически сопоставлено содержимое двух строк, и это будет короткий сравнение: не все символы будут сравниваться, если мы найдем несоответствующий символ (в том же положении в 2 строках), никакие другие символы не будут проверены.

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

163
задан 17 revs, 7 users 31% 25 October 2017 в 21:02
поделиться

15 ответов

@Hank Gay

В ответ на комментарий EmbiggensTheMind:

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

В JavaScript - и я предполагаю, что большинство других реальных языков (не лямбда-исчисление) - это обычно связано с частичным применением. John Resig объясняет это лучше , но суть в том, что у них есть некоторая логика, которая будет применяться к двум или более аргументам, и вы знаете только значения для некоторых из этих аргументов.

Вы можете использовать частичное приложение / каррирование, чтобы исправить эти известные значения и вернуть функцию, которая принимает только неизвестные, которые будут вызываться позже, когда у вас действительно есть значения, которые вы хотите передать. Это обеспечивает отличный способ избежать повторения себя, когда вы бы снова и снова вводили одни и те же встроенные модули JavaScript со всеми одинаковыми значениями, кроме одного. Чтобы украсть пример Джона:

String.prototype.csv = String.prototype.split.partial(/,\s*/);
var results = "John, Resig, Boston".csv();
alert( (results[1] == "Resig") + " The text values were split properly" );
30
ответ дан Andreas Grech 15 August 2018 в 19:43
поделиться
  • 1
  • 2
    Это действительно плохой ответ. Currying не имеет ничего общего с частичным применением. Currying позволяет выполнять функцию композиции. Состав функции позволяет повторно использовать функцию. Повторное использование функций повышает надежность обслуживания кода. Это так просто! – ftor 24 June 2016 в 21:31
  • 3
    @ftor сэр, вы очень плохой ответ. Очевидно, что каррирование делает работу более вкусной. Вы явно упустили точку. – Callat 19 July 2018 в 20:03

Я знаю его старый поток, но мне нужно будет показать, как это используется в библиотеках javascript:

Я буду использовать библиотеку lodash.js для описания этих понятий конкретно.

Пример:

var fn = function(a,b,c){ 
return a+b+c+(this.greet || ‘'); 
}

Частичное применение:

var partialFnA = _.partial(fn, 1,3);

Currying:

var curriedFn = _.curry(fn);

Связывание:

var boundFn = _.bind(fn,object,1,3 );//object= {greet: ’!'}

использование :

curriedFn(1)(3)(5); // gives 9 
or 
curriedFn(1,3)(5); // gives 9 
or 
curriedFn(1)(_,3)(2); //gives 9


partialFnA(5); //gives 9

boundFn(5); //gives 9!

разница:

после каррирования мы получаем новую функцию без параметров, предварительно связанных.

после частичного приложения мы получаем функцию, которая связана с некоторыми предварительными параметрами.

в привязке мы можем связать контекст, который будет использоваться для замены «this», если не связанный по умолчанию любой функции будет областью окна.

Посоветуйте: Нет необходимости изобретать велосипед. Частичное применение / привязка / каррирование очень связаны. Вы можете видеть разницу выше. Используйте это значение где угодно, и люди узнают, что вы делаете, без проблем в понимании, плюс вам придется использовать меньше кода.

1
ответ дан 2 revs 15 August 2018 в 19:43
поделиться

Функции JavaScript называются lamda на другом функциональном языке. Его можно использовать для создания новой api (более мощной или дополняющей функции) на основе простого ввода другого разработчика. Карри - всего лишь один из методов. Вы можете использовать его для создания упрощенного api для вызова сложного api. Если вы являетесь разработчиком, который использует упрощенную api (например, вы используете jQuery для простого манипулирования), вам не нужно использовать curry. Но если вы хотите создать упрощенную api, карри - ваш друг. Вам нужно написать фреймворк javascript (например, jQuery, mootools) или библиотеку, тогда вы сможете оценить его силу. Я написал расширенную функцию curry, в http://blog.semanticsworks.com/2011/03/enhanced-curry-method.html . Вам не нужно использовать метод curry для currying, он просто помогает делать currying, но вы всегда можете сделать это вручную, написав функцию A () {}, чтобы вернуть другую функцию B () {}. Чтобы сделать его более интересным, используйте функцию B () для возврата другой функции C ().

1
ответ дан 2 revs, 2 users 67% 15 August 2018 в 19:43
поделиться

Еще один удар по нему, от работы с обещаниями.

(Отказ от ответственности: JS noob, исходящий из мира Python. Даже там, currying не используется так много, но может прийти в удобном случае, поэтому я закрепил функцию currying - см. ссылки)

Во-первых, я начинаю с вызова ajax. У меня есть определенная обработка для успеха, но при отказе я просто хочу дать пользователю обратную связь, что вызов чего-то привел к некоторой ошибке . В моем фактическом коде я отображаю обратную связь с ошибками на панели начальной загрузки, но я просто использую запись здесь.

Я изменил свой живой URL-адрес, чтобы сделать это неудачным.

function ajax_batch(e){
    var url = $(e.target).data("url");

    //induce error
    url = "x" + url;

    var promise_details = $.ajax(
        url,
        {
            headers: { Accept : "application/json" },
            // accepts : "application/json",
            beforeSend: function (request) {
                if (!this.crossDomain) {
                    request.setRequestHeader("X-CSRFToken", csrf_token);
                }
        },
        dataType : "json",
        type : "POST"}
    );
    promise_details.then(notify_batch_success, fail_status_specific_to_batch);
}

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

У меня все еще есть информация доступна во время кодирования - в моем случае у меня есть несколько возможных партий, но я не знаю, какая из них была неудачной синтаксический анализ ответа сервера о неудавшемся URL-адресе.

function fail_status_specific_to_batch(d){
    console.log("bad batch run, dude");
    console.log("response.status:" + d.status);
}

Давайте сделаем это. Консольный выход:

console:

bad batch run, dude utility.js (line 109) response.status:404

Теперь, давайте немного изменим ситуацию и воспользуемся многократным обработчиком сбоев, но также и тот, который curried во время выполнения с использованием контекста вызова с известным в коде времени и информации о времени выполнения, доступной из события.

    ... rest is as before...
    var target = $(e.target).text();
    var context = {"user_msg": "bad batch run, dude.  you were calling :" + target};
    var contexted_fail_notification = curry(generic_fail, context); 

    promise_details.then(notify_batch_success, contexted_fail_notification);
}

function generic_fail(context, d){
    console.log(context);
    console.log("response.status:" + d.status);
}

function curry(fn) {
     var slice = Array.prototype.slice,
        stored_args = slice.call(arguments, 1);
     return function () {
        var new_args = slice.call(arguments),
              args = stored_args.concat(new_args);
        return fn.apply(null, args);
     };
}

console:

Object { user_msg="bad batch run, dude. you were calling :Run ACL now"} utility.js (line 117) response.status:404 utility.js (line 118)

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

https: //javascriptweblog.wordpress .com / 2010/04/05 / curry-cooking-up-tastier-functions / http://www.drdobbs.com/open-source/currying-and-partial-functions-in- javasc / 231001821? PGNO = 2

4
ответ дан 3 revs 15 August 2018 в 19:43
поделиться

Вот интересное и практическое использование currying в JavaScript, которое использует замыкания :

function converter(toUnit, factor, offset, input) {
    offset = offset || 0;
    return [((offset + input) * factor).toFixed(2), toUnit].join(" ");
}

var milesToKm = converter.curry('km', 1.60936, undefined);
var poundsToKg = converter.curry('kg', 0.45460, undefined);
var farenheitToCelsius = converter.curry('degrees C', 0.5556, -32);

milesToKm(10);            // returns "16.09 km"
poundsToKg(2.5);          // returns "1.14 kg"
farenheitToCelsius(98);   // returns "36.67 degrees C"

Это зависит от расширения curry Function, хотя, как вы видите, он использует только apply (ничего необычного):

Function.prototype.curry = function() {
    if (arguments.length < 1) {
        return this; //nothing to curry with - return function
    }
    var __method = this;
    var args = toArray(arguments);
    return function() {
        return __method.apply(this, args.concat([].slice.apply(null, arguments)));
    }
}
108
ответ дан 5 revs, 4 users 54% 15 August 2018 в 19:43
поделиться
  • 1
    Отлично! Я вижу, что он похож на букву lisp, которая гласит: «Lisp - программируемый язык программирования». – santiagobasulto 6 September 2011 в 20:48
  • 2
    Интересно, но этот пример не работает. offset+input будет undefined + 1.60936 в вашем примере milesToKm; что приводит к NaN. – Nathan Long 12 October 2011 в 20:35
  • 3
    @Nathan - смещение не может быть неопределенным - по умолчанию 0 – AngusC 10 November 2011 в 19:44
  • 4
    Из того, что я прочитал (сейчас), «curry» обычно не входит в сумку трюков Function, если вы не используете библиотеку Prototype или не добавляете ее самостоятельно. Очень здорово. – Roboprog 8 March 2012 в 05:06
  • 5
    То же самое можно получить с помощью метода ES5 bind (). Bind создает новую функцию, которая при вызове вызывает исходную функцию с контекстом ее первого аргумента и с последующей последовательностью аргументов (предшествующей любой переданной новой функции). Итак, вы можете ... var milesToKm = converter.bind (это, 'km', 1.60936); или var farenheitToCelsius = converter.bind (это «градусы C», 0,5556, -32); Первый аргумент, контекст, это, не имеет значения здесь, чтобы вы могли просто пройти неопределенный. Конечно, вам нужно будет увеличить базовый прототип функции с помощью собственного метода привязки для резервного резерва ES5 – hacklikecrack 22 September 2012 в 13:30

Я нашел функции, похожие на functools.partial python более полезными в JavaScript:

function partial(fn) {
  return partialWithScope.apply(this,
    Array.prototype.concat.apply([fn, this],
      Array.prototype.slice.call(arguments, 1)));
}

function partialWithScope(fn, scope) {
  var args = Array.prototype.slice.call(arguments, 2);
  return function() {
    return fn.apply(scope, Array.prototype.concat.apply(args, arguments));
  };
}

Почему вы хотите его использовать? Обычная ситуация, когда вы хотите использовать это, - это когда вы хотите привязать this к функции к значению:

var callback = partialWithScope(Object.function, obj);

Теперь, когда вызывается обратный вызов, this указывает на obj. Это полезно в ситуациях событий или для сохранения некоторого пространства, потому что оно обычно делает код короче.

Currying похожа на частичную с той разницей, что функция, возвращаемая currying, принимает только один аргумент (насколько я понимаю, ).

5
ответ дан Armin Ronacher 15 August 2018 в 19:43
поделиться

Я просто написал пример jPaq, который показывает некоторые интересные приложения функции curry. Проверьте это здесь: Выполнение строковых функций

0
ответ дан Chris West 15 August 2018 в 19:43
поделиться

Я согласен, что порой вы хотели бы получить мяч, создавая псевдофункцию, которая всегда будет иметь значение первого аргумента. К счастью, я столкнулся с совершенно новой библиотекой JavaScript под названием jPaq (h ttp: //jpaq.org/ ), который обеспечивает эту функциональность. Самое лучшее в библиотеке - это то, что вы можете загрузить свою собственную сборку, которая содержит только тот код, который вам понадобится.

0
ответ дан Clarence Fredericks 15 August 2018 в 19:43
поделиться

Вы можете использовать встроенное связывание для быстрого однолинейного решения

function clampAngle(min, max, angle) {
    var result, delta;
    delta = max - min;
    result = (angle - min) % delta;
    if (result < 0) {
        result += delta;
    }
    return min + result;
};

var clamp0To360 = clampAngle.bind(null, 0, 360);

console.log(clamp0To360(405)) // 45

0
ответ дан cstuncsik 15 August 2018 в 19:43
поделиться

Я бы сказал, что, скорее всего, вся анимационная библиотека в JS использует currying. Вместо того, чтобы передавать каждому вызову набор влияющих элементов и функцию, описывая, как должен себя вести элемент, функции более высокого порядка, которая будет обеспечивать все временные элементы, как правило, легче для клиента выпустить, так как открытый API функция «slideUp», «fadeIn», которая принимает только элементы в качестве аргументов, и это всего лишь какая-то функция в карри, возвращающая функцию высокого порядка с встроенной функцией «анимация» по умолчанию.

1
ответ дан gizmo 15 August 2018 в 19:43
поделиться
  • 1
    Почему лучше работать с функцией повышения, а не просто называть ее по умолчанию? – Dave Nolan 22 September 2008 в 09:39
  • 2
    Поскольку он является более модульным, чтобы иметь возможность выполнять «doMathOperation», с добавлением / умножением / квадратом / модулем / другой-калибровкой по желанию, чем представить все "по умолчанию" что высшая функция может поддерживать. – gizmo 22 September 2008 в 11:52

Что касается библиотек, использующих его, всегда есть Functional .

Когда это полезно в JS? Вероятно, в то же время он полезен и на других современных языках, но единственный раз, когда я могу его использовать, связан с частичным применением.

1
ответ дан Hank Gay 15 August 2018 в 19:43
поделиться
  • 1
    Спасибо Хэнк - пожалуйста, можете ли вы расширить его, когда он будет полезен вообще? – Dave Nolan 22 September 2008 в 10:17

Это не волшебство или что-то еще ... просто приятная стенография анонимных функций.

partial(alert, "FOO!") эквивалентно function(){alert("FOO!");}

partial(Math.max, 0) соответствует function(x){return Math.max(0, x);}

Призывы к частичной ( MochiKit терминологии. Я думаю, что некоторые другие библиотеки дают функции, которые способствуют тому или иному), выглядят немного лучше и менее шумно, чем анонимные функции.

2
ответ дан Liam 15 August 2018 в 19:43
поделиться

Просто хотел добавить некоторые ресурсы для Functional.js:

Лекция / конференция, объясняющая некоторые приложения http://www.youtube.com/watch?v=HAcN3JyQoyY

Обновлена ​​библиотека Functional.js: https://github.com/loop-recur/FunctionalJS Некоторые приятные помощники (извините, новый здесь, без репутации: p): / loop-recur / PreludeJS

Я недавно использовал эту библиотеку, чтобы уменьшить повторение в библиотеке помощников js IRC-клиентов. Это замечательный материал - действительно помогает очистить и упростить код.

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

0
ответ дан megawac 15 August 2018 в 19:43
поделиться

Вот пример.

Я использую кучу полей с JQuery, чтобы я мог видеть, что делают пользователи. Код выглядит так:

$('#foo').focus(trackActivity);
$('#foo').blur(trackActivity);
$('#bar').focus(trackActivity);
$('#bar').blur(trackActivity);

(Для пользователей, не являющихся JQuery, я говорю, что в любое время, когда несколько полей получают или теряют фокус, мне нужна функция trackActivity (). Я мог бы также использовать анонимную функцию, но мне пришлось бы ее дублировать 4 раза, поэтому я вытащил ее и назвал ее.)

Теперь выясняется, что одно из этих полей нужно обрабатывать по-разному , Я хотел бы иметь возможность передать параметр в одном из этих вызовов, которые будут переданы нашей инфраструктуре отслеживания. С каррированием я могу.

2
ответ дан William Pietri 15 August 2018 в 19:43
поделиться
4
ответ дан 3 revs 5 September 2018 в 18:57
поделиться
Другие вопросы по тегам:

Похожие вопросы: