ÃoÄu operatörü okuldan hatırlarsınız. Toplama +, çarpma *, çıkarma - vs.
Bu bölümde okulda görmediÄiniz aritmetiÄi iÅleyeceÄiz.
Tanımlamalar: âunaryâ, âbinaryâ, âoperandâ
BaÅlamadan önce terminolojiyi öÄrenmekte fayda var.
-
Operand operatörlerin uygulandıÄı(+,-,* vs.) deÄerlerdir. ÃrneÄin çarpma iÅlemi için
5*2örneÄinden gidersek. İki tane operand vardır. Bunlardan solda olan5ve saÄ operand2. Bunlara argüman da denebilir. -
EÄer tek operanddan oluÅursa bu operatör unary olarak adlandırılır. ÃrneÄin,
"-"sayının iÅaretini deÄiÅtirir:let x = 1; x = -x; alert( x ); // -1, unary iÅlemi gerçekleÅti -
EÄer operatörün iki tane operandâı var ise buna binary operand denir. ÃrneÄin çıkarma iÅlemi aÅaÄıda bu formda bulunur.
let x = 1, y = 3; alert( y - x ); // 2, iki sayının çıkarılması binary operand iÅlemidir.Åeklen, iki operatörden konuÅuyoruz.
unaryçıkarma ( tek operand iÅareti deÄiÅtirir) ve binary çıkarma ( iki operatör çıkarma )
Karakter dizisi birleÅtirme, binary +
JavaScriptâte operatörlerin özel durumlarından birisi karakter dizilerinin + iÅareti ile birleÅtirilebilmesidir.
Böylece + iÅaretinin amacının ötesinde bir iÅlem yapabildiÄinin farkına varmıŠolmalısınız.
Normalde + iki sayıyı toplamaya yaparken eÄer bir taraf karakter dizisi ise bu durumda birleÅtirmeye yarar.
let s = "my" + "string";
alert(s); // mystring
Dikkat edin eÄer iki operandâdan birisi karakter dizisi ise diÄeri ne olursan olsun karakter dizisine çevrilir.
ÃrneÄin:
alert( '1' + 2 ); // "12"
alert( 2 + '1' ); // "21"
GördüÄünüz gibi, ilk operand veya ikinci operandın karakter dizisi olması bir Åeyi deÄiÅtirmiyor. Kural basit, her iki taraftan birisi karakter dizisi ise diÄerini de karakter dizisine çevir ve birleÅtir.
Yani "+" iÅlemi hem birleÅtirme hem de tip deÄiÅtirme yapmaktadır. Bu sadece "+" operatörüne has bir olaydır.
ÃrneÄin çıkarma ve çarpmanın davranıÅı farklıdır:
alert( 2 - '1' ); // 1
alert( '6' / '2' ); // 3
Sayısal deÄer dönüÅtürme, unary +
+ iki formda bulunur. Yukarıda kullandıÄımız binary form(iki tane operand olma olayı) veya unary form(tek operand olması).
EÄer unary + veya tek bir deÄerle kullanılan + iÅareti sayılar ile bir Åey yapmaz. Fakat eÄer bu bir sayı deÄilse sayıya çevrilir.
ÃrneÄin:
// Sayılara bir etkisi yoktur
let x = 1;
alert( +x ); // 1
let y = -2;
alert( +y ); // -2
// Sayı olmayan deÄerleri çevirir
alert( +true ); // 1
alert( +"" ); // 0
Aslında Number(...) iÅlemini yapar. Fakat daha kısa biçimyle.
Karakter dizilerini sayılara çevirme gerekliliÄi sıklıkla önünüze gelir. ÃrneÄin HTML form deÄerlerini alırken sadece karakter dizisi kullanır. Fakat ya siz bunları toplamak istiyorsanız ?
BildiÄiniz gibi iki karakter dizisini + iÅareti ile toplarsanız birleÅtirme iÅlemi yapar:
let elma = "2";
let portakal = "3";
alert( elma + portakal ); // "23", binary toplama iki karakter dizisini birleÅtiriyor
EÄer sayı olarak kullanmak istiyorsanız, önce dönüÅtürme iÅlemini yapıp sonra toplayabilirsiniz.
let elma = "2";
let portakal = "3";
// her iki deÄer de binary toplama iÅleminden önce sayıya çevrilmiÅlerdi
alert( +elma + +portakal ); // 5
// Daha uzun bi Åekilde bu iÅlemi yapmak istiyorsanız
// alert( Number(apples) + Number(oranges) ); // 5
// Åeklinde yapabilirsiniz.
Olaya bir matematikçi gözünden bakarsanız + kullanımı garip gelebilir. Fakat bir programcının gözünden özel bir olay yok aslında: operandâı bir tane olan(unary) toplama iÅlemi önce uygulanıyor ve karakter dizisini sayıya çeviriyor. Daha sonra iki tane operandâlı ( binary) toplama iÅlemi bunları topluyor.
Neden önce âunaryâ iÅlemi gerçekleÅiyor da âbinaryâ iÅlemi gerçekleÅmiyor? Buna yüksek öncelik diyebiliriz.
Operatör Ãncelikleri
EÄer bir ifade birden fazla operatör içeriyorsa. Bu ifade çalıÅtırılırken tanımlı önceliklere göre çalıÅtırılır, bir baÅka ifade ile öncelik sırasına göre çalıÅtırılır.
Okuldan hepinizin hatırlayacaÄı gibi çarpma iÅlemi toplamadan önce yapılır 1 + 2 * 2. Aslında öncelik tam olarakta budur. Ãarpma iÅlemi toplama iÅleminden daha yüksek önceliÄe sahiptir.
Parantez, bu öncelikleri çiÄner ve eÄer bu önceliklerden memnun deÄilseniz bunları tekrar tanımlamanıza olanak verir. ÃrneÄin (1 + 2 ) * 2
JavaScript dilinde birçok operatör vardır. Her operatörün de bir önceliÄi. Yüksek öncelik sayısına sahip operatör önce çalıÅır. EÄer öncelik deÄerleri eÅit ise soldan saÄa doÄru çalıÅır.
öncelik tablosu ( Ezberlemenize gerek yok sadece unary operatörlerin binary olanlara göre daha üstün olduÄunu hatırlayın yeter). Yani +elma + +portakal iÅleminde önce unary ile elmaânın deÄerini sayı yapar sonra portakalâın deÄerini sayı yapar ve en sonunda toplar.
| Ãncelik | Adı | İÅareti |
|---|---|---|
| ⦠| ⦠| ⦠|
| 16 | unary toplama | + |
| 16 | unary çıkarma | - |
| 14 | çarpma | * |
| 14 | bölme | / |
| 13 | toplama | + |
| 13 | çıkarma | - |
| ⦠| ⦠| ⦠|
| 3 | atama | = |
| ⦠| ⦠| ⦠|
GörüleceÄi üzere âunary toplamaâ 16 ile normal toplama iÅlemi(binary toplama) 13 ün öncesindedir.
Atama
Atama operatörü = dir. Ãncelik sırasında en altlarda yer almaktadır. Böylece x = 2 * 2 + 1 ifadesi çalıÅtıÄında önce tüm iÅlemler yapılır ardından â=â çalıÅtırılarak sonuç x içerisinde tutulur.
let x = 2 * 2 + 1;
alert( x ); // 5
Zincirleme atama yapmak Åu Åekilde mümkündür:
let a, b, c;
a = b = c = 2 + 2;
alert( a ); // 4
alert( b ); // 4
alert( c ); // 4
Zincirleme atama saÄdan sola doÄru olur. Ãnce en saÄdaki deÄiÅkene deÄer atanır. 2+2 deÄeri önce câye ardından b ve son olarak da aâya atanır. En sonunda tüm deÄiÅkenler tek bir deÄeri alırlar.
"=" operatörü deÄer döndürürOperatör her zaman deÄer döndürür. Toplama + veya çarpma için * bu çok açıktır. Fakat ya atama ? Atama operatörü de aslında deÄer döndürür.
AÅaÄıdaki gibi bir iÅlem yaptıÄınızda value xâin içine yazılır ve sonra döndürülür.
Daha karmaÅık bir örnek Åu Åekilde yapılabilir:
let a = 1;
let b = 2;
let c = 3 - (a = b + 1);
alert( a ); // 3
alert( c ); // 0
Yukarıdaki örnekte, (a = b+1) in sonucu a ya atandıktan sonra(3) 3âden çıkarmak için kullanılıyor.
Komik bi kod deÄil mi? Nasıl çalıÅtıÄını anlamanız lazım, bazen baÅka kütüphaneler kullandıÄınızda böyle Åeyleri sizin yazmanız beklenmez. Böyle olaylar aslında kodun okunaklılıÄını azaltır.
Kalan: %
Kalan % operatörü yüzde ile alakası olmayan bir operatördür.
a % b aânın bâye bölümünden kalan deÄeri verir.
ÃrneÄin:
alert( 5 % 2 ); // 5'in 2 ile bölümünden kalan 1'dir.
alert( 8 % 3 ); // 8'in 3 ile bölümünden kalan 2'dir.
alert( 6 % 3 ); // 6'nın 3 ile bölümünden kalan 0'dır.
Ãs alma **
Ãs alma operatörü JavaScript diline sonradan eklenen bir operatördür.
DoÄal sayı olan b deÄeri için a ** b aânın b defa kendisiyle çarpılması demektir.
ÃrneÄin:
alert( 2 ** 2 ); // 4 (2 * 2)
alert( 2 ** 3 ); // 8 (2 * 2 * 2)
alert( 2 ** 4 ); // 16 (2 * 2 * 2 * 2)
Integer olmayan deÄerler için de aynı iÅlemi yapmak mümkün örneÄin:
alert( 4 ** (1/2) ); // 2 ( 1/2 üstü karekökü anlamına da gelir.)
alert( 8 ** (1/3) ); // 2 (1/3 üstü ise küp kök anlamına gelir. )
Artırma/Azaltma
Bir sayıyı artırmak veya azlatmak sayısal operasyonlarda önemli sayılabilecek bir düzeydedir.
Bunun için özel bir operatör yapılmıÅtır:
-
Artırma
++deÄiÅkenin deÄerini 1 artırır:let sayac = 2; sayac++; // sayac = sayac + 1 ile aynı, fakat daha kısa alert( sayac ); // 3 -
Azaltma
--deÄiÅkenin deÄerini bir azaltır:let sayac = 2; sayac--; // sayac = sayac - 1 ile aynı, fakat daha kısa alert( sayac ); // 1
Artırma/Azaltma sadece deÄiÅkenlere uygulanabilirler. 5++ gibi bir kullanım hata verecektir.
++ ve -- operatörleri deÄiÅkenden önce veya sonra kullanılabilirler.
- Operatör deÄiÅkenden sonra geliyorsa ona âpostfix formâ deriz:
counter++. - âprefix formâ ise opeatörün deÄiÅkenden önce geldiÄi durumdur:
++counter.
Bu iki durumda da aynı iÅlem yapılır: counter deÄiÅkeni 1 arttırılır.
Peki bir farkları var mı? Evet, fakat bunu ++/-- iÅleminden dönen deÄerleri kullanırsak görebiliriz.
Åöyle açıklayabiliriz. BildiÄimiz üzere tüm operatörler bir deÄer döndürür. arttırma/azaltma opeatörleri buna bir istisna deÄildir. Prefix formu oluÅan yeni deÄeri döndürürken, postfix formu eski deÄeri(arttırma/azaltma iÅlemi yapılmadan önceki) döndürür.
Farkı görebilmemiz için örneÄi inceleyelim:
let counter = 1;
let a = ++counter; // (*)
alert(a); // 2
(*) satırında prefix formundaki ++counter counter deÄiÅkenini arttırır ve yeni deÄer olan 2 yi döndürür. Yani alert bize 2 deÄerini gösterecektir.
Åimdi de postfix kullanıma bakalım:
let counter = 1;
let a = counter++; // (*) changed ++counter to counter++
alert(a); // 1
(*) satırında postfix formundaki ++counter de aynı Åekilde counter deÄiÅkenini arttırır fakat bu sefer deÄiÅkenin eski deÄerini(arttırma iÅlemi yapılmadan önceki) deÄerini döndürür. Yani alert bize 1 deÄerini gösterecektir.
Ãzetle:
-
EÄer arttırma/azaltma iÅleminin sonucunu kullanmıyorsak hangi formu kullandıÄımızın bir farkı olmaz:
let counter = 0; counter++; ++counter; alert( counter ); // 2, iki satır da aynı iÅlemi yaptı. -
EÄer bir deÄeri arttıracak ve onu aynı anda(o iÅlem sırasında) kullanacaksak, prefix formunu kullanmamız gerekir:
let counter = 0; alert( ++counter ); // 1 -
EÄer arttırma yapacak fakat arttırma yapmadan yapmadan önceki deÄeri kullanacaksak, postfix formunu kullanmamız gerekir:
let counter = 0; alert( counter++ ); // 0
++/-- operatörleri ayrıca bir ifadenin içinde kullanılabilirler. Ãncelikleri diÄer tüm operatörlerden daha yüksektir.
ÃrneÄin:
let counter = 1;
alert( 2 * ++counter ); // 4
alttaki örnek ile karÅılaÅtıralım:
let counter = 1;
alert( 2 * counter++ ); // 2, çünkü counter++ "eski" deÄeri döndürecektir
Teknik olarak doÄru olmakla birlikte bu tür kullanımlar kodu daha az okunur kılar. Bir satırında birden çok iÅlem yapılması çok iyi deÄildir.
Kod okurken hızlı bir göz taraması sırasında counter++ ifadesini gözden kaçırmamız oldukça olasıdır. DeÄiÅkenin arttırıldıÄı açıkça gözükmeyebilir.
âBir satır â bir iÅlemâ stili önerilir:
let counter = 1;
alert( 2 * counter );
counter++;
Bitsel(Bitwise) Operatörler
Bitsel operatörler argümanlara 32-bitlik doÄal sayı gibi davranır ve ikili gösterimleri düzeyinde çalıÅır.
Bu operatörler JavaScriptâe özgü deÄildir. ÃoÄu programlama dilinde bulunurlar.
Operatörlerin listesi:
- AND â VE (
&) - OR â VEYA (
|) - XOR â ÃZEL VEYA (
^) - NOT â DEÄİL (
~) - LEFT SHIFT â SOLA KAYDIRMA (
<<) - RIGHT SHIFT â SAÄ KAYDIRMA (
>>) - ZERO-FILL RIGHT SHIFT â SIFIR DOLDURARAK SAÄ KAYDIRMA (
>>>)
Bu oparatörler çok nadir kullanılır. Onları anlamak için düÅük seviyeli sayı temsiline girmemiz gerekiyor ve özellikle de yakın zamanda onlara ihtiyaç duymayacaÄımızdan Åu anda bunu yapmak uygun olmayacaktır. Merak ediyorsanız, MDN ile ilgili Bitwise Operators makalesini okuyabilirsiniz. Gerçekten ihtiyacınız olduÄunda bunu yapmak daha doÄru olacaktır.
Modify-in-place (Yerinde DeÄiÅtir)
Bazen bir deÄiÅken üzerinde bir operatör iÅlemi yaparız ve yeni oluÅacak deÄerini aynı deÄiÅkende tutmak isteriz.
ÃrneÄin:
let n = 2;
n = n + 5;
n = n * 2;
Bu iÅlemler += ve *= kullanılarak kısaltılabilir:
let n = 2;
n += 5; // Åu an n = 7 (n = n + 5 ile aynı)
n *= 2; // Åu an n = 14 (n = n * 2 ile aynı)
alert( n ); // 14
Kısa olan âmodify-and-assignâ operatörleri tüm aritmetik ve bitsel operatörler için mevcuttur: /=, -=, vb.
Bu tür operatörler normal bir atama(assignment) ile aynı önceliÄe sahiptir, bu yüzden diÄer birçok hesaplamalardan sonra çalıÅırlar.
let n = 2;
n *= 3 + 5;
alert( n ); // 16 (önce saÄ kısımda iÅlem yapıldı, n *= 8 gibi)
Virgül
Virgül operatörü , nadir ve en alıÅılmadık operatörlerden birisidir. Bazen daha kısa kodlar yazmak için kullanılır. Bu yüzden neler olduÄunu anlamak için bu operatörü de bilmemiz gerekiyor.
Virgül operatörü birden fazla ifadeyi virgül , ile ayırarak hesaplamamıza olanak saÄlar. Her bir ifade iÅleme alınır fakat bu ifadelerden sadece sonuncusu döndürülür.
ÃrneÄin:
let a = (1 + 2, 3 + 4);
alert( a ); // 7 (3 + 4 iÅleminin sonucu)
Burada, ilk ifade olan 1 + 2 iÅleme giriyor fakat sonucu çöpe atılıyor. Sonrasında gelen 3 + 4 iÅleme giriyor ve sonuç olarak geri döndürülüyor.
Unutmamak gerekir ki; virgül operatörü çok düÅük bir önceliÄe sahiptir, önceliÄi ='den bile daha düÅüktür. Bu yüzden yukarıdaki örnekte gördüÄümüz gibi parantezler çok önemlidir.
Parantezler olmadan: a = 1 + 2, 3 + 4 ifadesinde önce + iÅleme alınır, deÄerler toplanarak a = 3, 7 ifadesine çevirilir, ondan sonra atama operatörü = ile a = 7 ataması yapılır, ve sonuç olarak virgülden önceki sayı olan 3 iÅlenmeyerek yok sayılır.
Peki neden son kısım hariç her Åeyi yok sayan bir operatöre ihtiyacımız var?
Bazen bizler; bir satırda birkaç iÅlem yapılan karmaÅık yapılarda bu operatörü kullanırız.
ÃrneÄin:
// Bir satırda 3 farklı iÅlem
for (a = 1, b = 3, c = a * b; a < 10; a++) {
...
}
Bu tarz numaralar birçok JavaScript frameworklerinde kullanılır. Bu yüzden bunlardan bahsettik. Ama genelde bunlar kodun okunabilirliÄini azaltıyorlar. Bu yüzden kullanmadan önce iyi düÅünmek gerekir.
Yorumlar
<code>kullanınız, birkaç satır eklemek için ise<pre>kullanın. EÄer 10 satırdan fazla kod ekleyecekseniz plnkr kullanabilirsiniz)