İfadelerde ( ) "virgül operatörü" hakkındaki bu soruyu ,
ve bununla ilgili MDN belgelerini okudum , ancak yararlı olduğu bir senaryo düşünemiyorum.
Peki virgül operatörü ne zaman kullanışlıdır?
İfadelerde ( ) "virgül operatörü" hakkındaki bu soruyu ,
ve bununla ilgili MDN belgelerini okudum , ancak yararlı olduğu bir senaryo düşünemiyorum.
Peki virgül operatörü ne zaman kullanışlıdır?
,
Operatörle bir ilgisi olduğundan emin değilim . Bu satır içinde de geçerlidir C#
, ancak ,
operatör orada mevcut değildir.
,
her zaman ,
operatör değildir (ve hiçbir zaman ,
C # ' da operatör değildir). Bu nedenle C # , sözdiziminin bir parçası olarak ,
özgürce kullanılırken bir işleci ,
olmayabilir.
,
, yaygın olarak kullanılmadığı gerçeğini özetledi (ve a'nın her oluşumu ,
virgül operatörü değildir) . Ancak geçici bir değişken oluşturmadan bir değişken takası satır içi yapmak için onu ve bir Dizi ödünç alabilirsiniz. Eğer değerlerini karşılıklı olarak istediğiniz göz önüne alındığında a
ve b
yapabileceğiniz a = [b][b = a,0]
. Bu, akımı b
Diziye yerleştirir. İkincisi []
, mülkiyet erişim gösterimi. Erişilen endeksidir 0
, ancak atamadan önce a
hiç b
beri artık güvenli olan b
Array tutulur. içindeki ,
çoklu ifadeleri yapmamızı sağlar []
.
Yanıtlar:
Aşağıdakiler muhtemelen kendiniz yazmadığınız için çok kullanışlı değildir, ancak bir minifier virgül operatörünü kullanarak kodu küçültebilir. Örneğin:
if(x){foo();return bar()}else{return 1}
olacaktı:
return x?(foo(),bar()):1
? :
(Bir ölçüde) virgül operatörü iki ifade bir ifadesi olarak yazılmasına izin verir çünkü operatör, şimdi kullanılabilir.
Bu , bazı düzgün sıkıştırmaya izin vermesi açısından yararlıdır (burada 39 -> 24 bayt).
Ben virgülle gerçeğini vurgulamak istiyorum var a, b
olduğunu değil bir dahilinde olmadığından virgül operatörü ifadesi . Virgülün var
ifadelerde özel bir anlamı vardır . a, b
bir ifadede iki değişkene atıfta bulunur ve b
bunun için geçerli değildir var a, b
.
if (condition) var1 = val1, var2 = val2;
Ben şahsen mümkün olduğunda parantezlerden kaçınmanın kodu daha okunaklı hale getirdiğini düşünüyorum.
Virgül operatörü, tek bir ifadenin beklendiği bir yere birden çok ifade koymanıza olanak tanır. Virgülle ayrılmış birden çok ifadenin sonuç değeri, virgülle ayrılmış son ifadenin değeri olacaktır.
Kişisel olarak çok sık kullanmıyorum çünkü birden fazla ifadenin beklendiği pek çok durum yok ve kodu yazmanın virgül operatörünü kullanmaktan daha az kafa karıştırıcı bir yolu yok. for
Birden fazla değişkenin artırılmasını istediğinizde , bir döngünün sonunda ilginç bir olasılık vardır :
// 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
}
Burada i++, j++
, bir ifadeye izin verilen bir yere konulabileceğini görüyorsunuz . Bu özel durumda, çoklu ifadeler yan etkiler için kullanılır, bu nedenle bileşik ifadelerin sonuncunun değerini alması önemli değildir, ancak bunun gerçekten önemli olabileceği başka durumlar da vardır.
Virgül İşleci, Javascript'te işlevsel kod yazarken sıklıkla yararlıdır.
Bir süre önce bir SPA için yazdığım ve aşağıdaki gibi bir şeye sahip olan bu kodu düşünün
const actions = _.chain(options)
.pairs() // 1
.filter(selectActions) // 2
.map(createActionPromise) // 3
.reduce((state, pair) => (state[pair[0]] = pair[1], state), {}) // 4
.value();
Bu oldukça karmaşık ama gerçek dünya senaryosuydu. Ne olduğunu açıklarken yanımda olun ve bu süreçte Virgül Operatörü için durumu açıklayın.
Kullanarak bu işleve geçirilen tüm seçenekleri ayır pairs
dönecek olan { a: 1, b: 2}
içine[['a', 1], ['b', 2]]
Bu özellik çiftleri dizisi, sistemdeki 'eylemler' olarak kabul edilenlere göre filtrelenir.
Ardından, dizideki ikinci dizin, o eylemi temsil eden bir promise döndüren bir işlevle değiştirilir (kullanarak map
)
Son olarak, çağrısı reduce
her "özellik dizisini" ( ['a', 1]
) nihai bir nesneye geri birleştirecektir.
Sonuç, options
argümanın yalnızca uygun anahtarları içeren ve değerleri çağıran işlev tarafından tüketilebilen dönüştürülmüş bir versiyonudur .
Sadece bakıyorum
.reduce((state, pair) => (state[pair[0]] = pair[1], state), {})
Azaltma işlevinin boş bir durum nesnesiyle başladığını state
ve bir anahtar ve değeri temsil eden her çift için işlev state
, anahtar / değer çiftine karşılık gelen nesneye bir özellik ekledikten sonra aynı nesneyi döndürür . ECMAScript 2015'in ok işlevi sözdizimi nedeniyle, işlev gövdesi bir ifadedir ve sonuç olarak Virgül Operatörü kısa ve kullanışlı bir "yineleme" işlevine izin verir .
Kişisel olarak, ECMAScript 2015 + Arrow Functions ile daha işlevsel bir tarzda Javascript yazarken çok sayıda vakayla karşılaştım. Ok işlevleriyle karşılaşmadan önce (örneğin sorunun yazılması sırasında olduğu gibi) virgül operatörünü asla kasıtlı bir şekilde kullanmadım.
reduce
.reduce((state, [key, value]) => (state[key] = value, state), {})
. Ve bunun cevabın amacını bozduğunu, ancak .reduce((state, [key, value]) => Object.assign(state, { [key]: value }), {})
virgül operatörüne olan ihtiyacı tamamen ortadan kaldıracağını anlıyorum .
Virgül operatörünün başka bir kullanımı, yalnızca kolaylık sağlamak amacıyla repl veya konsolda umursamadığınız sonuçları gizlemektir.
Örneğin myVariable = aWholeLotOfText
, repl veya konsolda değerlendirirseniz , az önce atadığınız tüm verileri yazdıracaktır. Bu, sayfalar ve sayfalar olabilir ve görmemeyi tercih ederseniz, bunun yerine değerlendirebilirsiniz myVariable = aWholeLotOfText, 'done'
ve repl / console sadece 'bitti' yazacaktır.
Doğru işaret Oriel † özelleştirilmiş olduğu toString()
veya get()
fonksiyonlar hatta bu yararlı hale getirebileceğini.
Virgül operatörü JavaScript'e özel değildir, C ve C ++ gibi diğer dillerde mevcuttur . Bir ikili operatör olarak bu, genellikle bir ifade olan birinci işlenen, ikinci işlenenin gerektirdiği istenen yan etkiye sahip olduğunda yararlıdır. Wikipedia'dan bir örnek:
i = a += 2, a + b;
Açıkçası iki farklı kod satırı yazabilirsiniz, ancak virgül kullanmak başka bir seçenektir ve bazen daha okunabilirdir.
Flanagan'a katılmıyorum ve virgülün gerçekten yararlı olduğunu ve özellikle ne yaptığınızı bildiğinizde daha okunaklı ve zarif kod yazmanıza izin verdiğini söyleyebilirim:
Virgül kullanımıyla ilgili çok ayrıntılı makale şu şekildedir:
Gösteri kanıtı için oradan birkaç örnek:
function renderCurve() {
for(var a = 1, b = 10; a*b; a++, b--) {
console.log(new Array(a*b).join('*'));
}
}
Bir fibonacci üreteci:
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
JQuery .parent()
fonksiyonunun analog olan birinci ebeveyn öğesini bulun :
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()))
, bu bağlamda gayet iyi olur.
Bunun dışında pratik bir kullanım bulamadım ama işte James Padolsey'in bu tekniği bir süre döngüsünde IE tespiti için güzelce kullandığı bir senaryo :
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;
}());
Bu iki satırın yürütülmesi gerekir:
div.innerHTML = '<!--[if gt IE ' + (++v) + ']><i></i><![endif]-->',
all[0]
Ve virgül operatörünün içinde, her ikisi de değerlendirilir, ancak biri bir şekilde ayrı ifadelerde bulunmuş olabilir.
do
- while
döngü.
JavaScript'te virgül operatörü kullanılarak dolaylı olarak bir işlevi çağırarak yapılabilecek "tuhaf" bir şey vardır.
Burada uzun bir açıklama var: JavaScript'te dolaylı işlev çağrısı
Bu sözdizimini kullanarak:
(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);
}());
Global değişkene erişebilirsiniz çünkü eval
doğrudan çağrıldığında ve dolaylı olarak çağrıldığında farklı çalışır.
Bunun gibi yardımcıları yazarken en kullanışlı virgül operatörünü buldum.
const stopPropagation = event => (event.stopPropagation(), event);
const preventDefault = event => (event.preventDefault(), event);
const both = compose(stopPropagation, preventDefault);
Virgülü bir || ile değiştirebilirsiniz. veya &&, ancak daha sonra işlevin ne döndürdüğünü bilmeniz gerekir.
Bundan daha da önemlisi, virgül ayırıcı amacı iletir - kod , sol işlenenin neyi değerlendirdiğini umursamaz , oysa alternatiflerin orada olmak için başka bir nedeni olabilir. Bu da anlaşılmasını ve yeniden düzenlenmesini kolaylaştırır. İşlev dönüş türü herhangi bir şekilde değişirse, yukarıdaki kod etkilenmeyecektir.
Doğal olarak aynı şeyi başka şekillerde de başarabilirsiniz, ancak bu kadar özlü değil. Eğer || ve && virgül operatörü gibi ortak kullanımda bir yer buldu.
tap
( ramdajs.com/docs/#tap ) ile yaptıklarına benzer . Esasen, bir yan etki yürütüyorsunuz ve ardından başlangıç değerini döndürüyorsunuz; fonksiyonel programlamada çok yararlı :)
Kullanmak zorunda kaldığım tipik bir durum, isteğe bağlı bağımsız değişken ayrıştırması sırasında. Bence onu hem daha okunabilir hem de daha özlü hale getiriyor, böylece ayrıştırma argümanı işlev gövdesine hakim olmaz.
/**
* @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();
// ...
}
Diyelim ki bir diziniz var:
arr = [];
Bu push
diziye girdiğinizde , nadiren push
döndürülen değerle, yani dizinin yeni uzunluğuyla, daha çok dizinin kendisiyle ilgilenirsiniz :
arr.push('foo') // ['foo'] seems more interesting than 1
Virgül operatörünü kullanarak, diziye itebilir, diziyi virgül için son işlenen olarak belirleyebilir ve ardından sonucu (dizinin kendisi) sonraki bir dizi yöntemi çağrısı için, bir tür zincirleme olarak kullanabiliriz:
(arr.push('bar'), arr.push('baz'), arr).sort(); // [ 'bar', 'baz', 'foo' ]
Virgül operatörünün kullanılabileceği başka bir alan da Kod Gizleme'dir .
Bir geliştiricinin şöyle bir kod yazdığını varsayalım:
var foo = 'bar';
Şimdi, kodu gizlemeye karar veriyor. Kullanılan araç kodu şu şekilde değiştirebilir:
var Z0b=(45,87)>(195,3)?'bar':(54,65)>(1,0)?'':'baz';// Z0b == 'bar'
var i, j, k;
vsvar i; var j, var k
?