Я прочитав це запитання про "оператор кома" у виразах ( ,
) та документації 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++
їх можна поставити там, де дозволено один вираз. У цьому конкретному випадку множинні вирази використовуються для побічних ефектів, тому не має значення, що складені вирази набувають значення останнього, але є й інші випадки, коли це насправді може мати значення.
Comma Operator часто корисний під час написання функціонального коду в 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
)
Нарешті, виклик to reduce
об'єднає кожен "масив властивостей" ( ['a', 1]
) назад у кінцевий об'єкт.
Кінцевим результатом є трансформована версія options
аргументу, яка містить лише відповідні ключі і значення яких споживає виклична функція.
Дивлячись просто
.reduce((state, pair) => (state[pair[0]] = pair[1], state), {})
Ви можете бачити, що функція зменшення починається з порожнього об'єкта стану state
, і для кожної пари, що представляє ключ і значення, функція повертає той самий state
об'єкт після додавання властивості до об'єкта, що відповідає парі ключ / значення. Через синтаксис функції стрілки ECMAScript 2015 тіло функції є виразом, і в результаті оператор Comma дозволяє короткий та корисний "ітератор" .
Особисто я стикався з численними випадками, коли писав Javascript у більш функціональному стилі за допомогою ECMAScript 2015 + Arrow Functions. Сказавши це, до того, як я зіткнувся з функціями стрілок (наприклад, під час написання запитання), я ніколи не використовував оператор-кома будь-яким свідомим способом.
reduce
.reduce((state, [key, value]) => (state[key] = value, state), {})
. І я усвідомлюю, що це .reduce((state, [key, value]) => Object.assign(state, { [key]: value }), {})
перешкоджає меті відповіді, але повністю виключає потребу в операторі коми.
Ще одне використання оператора коми - приховування результатів, які вас не турбують, у repl чи консолі, лише для зручності.
Наприклад, якщо ви оцінюєте myVariable = aWholeLotOfText
в repl або консолі, він надрукує всі дані, які ви щойно призначили. Це можуть бути сторінки та сторінки, і якщо ви бажаєте не бачити їх, ви можете замість цього оцінитиmyVariable = aWholeLotOfText, 'done'
, і repl / консоль просто надрукує "готово".
Oriel правильно зазначає †, що персоналізовані функції 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' ]
Ще однією областю, де можна використовувати оператор коми, є Obfuscation Code .
Скажімо, розробник пише такий код:
var foo = 'bar';
Тепер вона вирішує заплутати код. Використовуваний інструмент може змінити код таким чином:
var Z0b=(45,87)>(195,3)?'bar':(54,65)>(1,0)?'':'baz';// Z0b == 'bar'
Демонстрація: http://jsfiddle.net/uvDuE/
var i, j, k;
протиvar i; var j, var k
?