Я прочитал этот вопрос об «операторе запятой» в выражениях ( ,
) и документах MDN об этом, но я не могу придумать сценарий, в котором это было бы полезно.
Итак, когда полезен оператор запятой?
Я прочитал этот вопрос об «операторе запятой» в выражениях ( ,
) и документах MDN об этом, но я не могу придумать сценарий, в котором это было бы полезно.
Итак, когда полезен оператор запятой?
,
оператором. Эта строка также действительна C#
, но ,
оператора там нет.
,
не всегда является ,
оператором (и никогда не является ,
оператором в C #). Таким образом, в C # может отсутствовать ,
оператор, при этом он может свободно использоваться ,
как часть синтаксиса.
,
широко не используется (и не каждое вхождение a ,
является оператором запятой) . Но вы можете позаимствовать его и массив, чтобы выполнить замену переменных на месте без создания временной переменной. Учитывая, что вы хотите поменять местами значения a
и b
, вы можете это сделать a = [b][b = a,0]
. Это помещает ток b
в массив. Второй []
- это обозначение доступа к свойствам. Индекс доступа является 0
, но не перед назначением a
на b
, который теперь безопасно , так как b
сохраняются в массиве. ,
позволяет нам сделать несколько выражений в []
.
Ответы:
Следующее, вероятно, не очень полезно, поскольку вы не пишете его самостоятельно, но минификатор может сжимать код с помощью оператора запятой. Например:
if(x){foo();return bar()}else{return 1}
станет:
return x?(foo(),bar()):1
? :
Оператор теперь можно использовать, так как оператор запятая (в определенной степени) позволяет два заявления должны быть записаны как одно заявление.
Это является полезным в том , что она позволяет некоторым аккуратным сжатия (39 -> 24 байт здесь).
Я хотел бы подчеркнуть тот факт , что запятая в var a, b
это не оператор запятой , потому что не существует в пределах выражения . Запятая имеет особое значение в var
отчетности . a, b
в выражении будет ссылаться на две переменные и оценивать b
, что не относится к var a, b
.
if (condition) var1 = val1, var2 = val2;
я лично считаю, что избегание скобок там, где это возможно, делает код более читабельным.
Оператор запятая позволяет помещать несколько выражений в место, где ожидается одно выражение. Результирующее значение нескольких выражений, разделенных запятой, будет значением последнего выражения, разделенного запятыми.
Я лично не использую его очень часто, потому что не так много ситуаций, когда ожидается более одного выражения, и нет менее запутанного способа написания кода, чем использование оператора запятой. Одна интересная возможность - это конец for
цикла, когда вы хотите увеличить более одной переменной:
// j is initialized to some other value
// as the for loop executes both i and j are incremented
// because the comma operator allows two statements to be put in place of one
for (var i = 0; i < items.len; i++, j++) {
// loop code here that operates on items[i]
// and sometimes uses j to access a different array
}
Здесь вы видите, что i++, j++
это можно поместить в место, где разрешено одно выражение. В этом конкретном случае несколько выражений используются для побочных эффектов, поэтому не имеет значения, что составные выражения принимают значение последнего, но есть и другие случаи, когда это действительно может иметь значение.
Оператор запятая часто бывает полезен при написании функционального кода на Javascript.
Рассмотрим этот код, который я написал некоторое время назад для SPA, в котором было что-то вроде следующего
const actions = _.chain(options)
.pairs() // 1
.filter(selectActions) // 2
.map(createActionPromise) // 3
.reduce((state, pair) => (state[pair[0]] = pair[1], state), {}) // 4
.value();
Это был довольно сложный, но реальный сценарий. Потерпите меня, пока я объясню, что происходит, и в процессе изложу аргументы в пользу оператора запятой.
Разберите все параметры, переданные в эту функцию, используя pairs
которые превратятся { a: 1, b: 2}
в[['a', 1], ['b', 2]]
Этот массив пар свойств фильтруется по тому, какие из них считаются «действиями» в системе.
Затем второй индекс в массиве заменяется функцией, которая возвращает обещание, представляющее это действие (используя map
)
Наконец, вызов reduce
объединит каждый «массив свойств» ( ['a', 1]
) обратно в конечный объект.
Конечным результатом является преобразованная версия options
аргумента, которая содержит только соответствующие ключи и значения которых потребляются вызывающей функцией.
Глядя только на
.reduce((state, pair) => (state[pair[0]] = pair[1], state), {})
Вы можете видеть, что функция сокращения начинается с пустого объекта состояния state
, и для каждой пары, представляющей ключ и значение, функция возвращает тот же state
объект после добавления свойства к объекту, соответствующему паре ключ / значение. Из-за синтаксиса стрелочной функции ECMAScript 2015 тело функции является выражением, и в результате оператор запятая позволяет использовать краткую и полезную функцию «итерация» .
Лично я сталкивался с многочисленными случаями, когда писал Javascript в более функциональном стиле с помощью ECMAScript 2015 + Arrow Functions. Сказав это, до того, как столкнуться с функциями стрелок (например, во время написания вопроса), я никогда не использовал оператор запятой намеренно.
reduce
.reduce((state, [key, value]) => (state[key] = value, state), {})
. И я понимаю, что это противоречит цели ответа, но .reduce((state, [key, value]) => Object.assign(state, { [key]: value }), {})
полностью устраняет необходимость в операторе запятой.
Другой вариант использования оператора запятой - скрытие результатов, которые вам не нужны, в реплике или консоли исключительно для удобства.
Например, если вы выполняете оценку myVariable = aWholeLotOfText
в repl или console, он распечатает все данные, которые вы только что назначили. Это могут быть страницы и страницы, и если вы не хотите их видеть, вы можете вместо этого оценить myVariable = aWholeLotOfText, 'done'
, и repl / console просто напечатает «готово».
Ориэл правильно отмечает †, что индивидуальные настройки toString()
или get()
функции могут даже сделать это полезным.
Оператор запятая не является специфическим для JavaScript, он доступен на других языках, таких как C и C ++ . Как бинарный оператор это полезно, когда первый операнд, который обычно является выражением, имеет желаемый побочный эффект, требуемый вторым операндом. Один пример из Википедии:
i = a += 2, a + b;
Очевидно, вы можете написать две разные строки кода, но использование запятой - еще один вариант, который иногда более удобочитаем.
Я бы не согласился с Фланаганом и сказал, что запятая действительно полезна и позволяет писать более читаемый и элегантный код, особенно когда вы знаете, что делаете:
Вот очень подробная статья об использовании запятых:
Несколько примеров оттуда для доказательства демонстрации:
function renderCurve() {
for(var a = 1, b = 10; a*b; a++, b--) {
console.log(new Array(a*b).join('*'));
}
}
Генератор Фибоначчи:
for (
var i=2, r=[0,1];
i<15;
r.push(r[i-1] + r[i-2]), i++
);
// 0,1,1,2,3,5,8,13,21,34,55,89,144,233,377
Найдите первый родительский элемент, аналог .parent()
функции jQuery :
function firstAncestor(el, tagName) {
while(el = el.parentNode, el && (el.tagName != tagName.toUpperCase()));
return el;
}
//element in http://ecma262-5.com/ELS5_HTML.htm
var a = $('Section_15.1.1.2');
firstAncestor(a, 'div'); //<div class="page">
while ((el = el.parentNode) && (el.tagName != tagName.toUpperCase()))
в этом контексте было бы хорошо.
Я не нашел практического применения, кроме этого, но вот один сценарий, в котором Джеймс Падолси прекрасно использует эту технику для обнаружения IE в цикле while:
var ie = (function(){
var undef,
v = 3,
div = document.createElement('div'),
all = div.getElementsByTagName('i');
while ( // <-- notice no while body here
div.innerHTML = '<!--[if gt IE ' + (++v) + ']><i></i><![endif]-->',
all[0]
);
return v > 4 ? v : undef;
}());
Эти две строки должны выполняться:
div.innerHTML = '<!--[if gt IE ' + (++v) + ']><i></i><![endif]-->',
all[0]
И внутри оператора запятой оба оцениваются, хотя можно было как-то сделать их отдельными операторами.
do
- while
петля.
Есть кое-что «странное», что можно сделать в JavaScript, вызвав функцию косвенно с помощью оператора запятой.
Здесь есть подробное описание: Косвенный вызов функции в JavaScript
Используя этот синтаксис:
(function() {
"use strict";
var global = (function () { return this || (1,eval)("this"); })();
console.log('Global === window should be true: ', global === window);
var not_global = (function () { return this })();
console.log('not_global === window should be false: ', not_global === window);
}());
Вы можете получить доступ к глобальной переменной, потому что eval
при прямом вызове работает иначе, а при косвенном вызове.
Я считаю, что оператор запятой наиболее полезен при написании таких помощников.
const stopPropagation = event => (event.stopPropagation(), event);
const preventDefault = event => (event.preventDefault(), event);
const both = compose(stopPropagation, preventDefault);
Вы можете заменить запятую на || или &&, но тогда вам нужно знать, что возвращает функция.
Более важно то, что разделитель запятой сообщает о намерении - код не заботится о том, что оценивает левый операнд, тогда как альтернативы могут иметь другую причину для присутствия. Это, в свою очередь, упрощает понимание и рефакторинг. Если тип возвращаемого значения функции когда-либо изменится, это не повлияет на приведенный выше код.
Естественно, вы можете добиться того же другими способами, но не так кратко. Если || и && нашли место в общем использовании, как и оператор запятой.
tap
( ramdajs.com/docs/#tap ). По сути, вы выполняете побочный эффект, а затем возвращаете начальное значение; очень полезен в функциональном программировании :)
Типичный случай, когда я в конечном итоге использую его, - это анализ необязательных аргументов. Я думаю, что это делает его более читабельным и лаконичным, так что синтаксический анализ аргументов не доминирует над телом функции.
/**
* @param {string} [str]
* @param {object} [obj]
* @param {Date} [date]
*/
function f(str, obj, date) {
// handle optional arguments
if (typeof str !== "string") date = obj, obj = str, str = "default";
if (obj instanceof Date) date = obj, obj = {};
if (!(date instanceof Date)) date = new Date();
// ...
}
Допустим, у вас есть массив:
arr = [];
Когда вы push
заходите в этот массив, вас редко интересует push
возвращаемое значение, а именно новая длина массива, а скорее сам массив:
arr.push('foo') // ['foo'] seems more interesting than 1
Используя оператор запятой, мы можем нажать на массив, указать массив в качестве последнего операнда запятой, а затем использовать результат - сам массив - для последующего вызова метода массива, своего рода цепочки:
(arr.push('bar'), arr.push('baz'), arr).sort(); // [ 'bar', 'baz', 'foo' ]
Еще одна область, в которой можно использовать оператор запятой, - это обфускация кода. .
Допустим, разработчик пишет такой код:
var foo = 'bar';
Теперь она решает скрыть код. Используемый инструмент может изменить код следующим образом:
var Z0b=(45,87)>(195,3)?'bar':(54,65)>(1,0)?'':'baz';// Z0b == 'bar'
var i, j, k;
противvar i; var j, var k
?