forked from BonsaiDen/JavaScript-Garden
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathindex.html
More file actions
1995 lines (1507 loc) · 86.3 KB
/
index.html
File metadata and controls
1995 lines (1507 loc) · 86.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<!DOCTYPE html><html lang="tr"><head><title>JavaScript Garden</title><meta charset="utf-8"><meta name="description" content="JavaScript'in Acayiplikleri ve Kusurları için bir Rehber."><link rel="stylesheet" href="../style/garden.css" media="all"><link rel="stylesheet" href="../style/print.css" media="print"><!--[if lt IE 9]>
<script src="javascript/html5.js"></script>
<![endif]-->
</head><body><!-- Navigation--><nav id="nav_main"><div><ul><li><a href="/JavaScript-Garden/pl" title="JavaScript Garden - ogród JavaScript po polsku">pl</a></li><li><a href="/JavaScript-Garden/" title="JavaScript Garden in English">en</a></li><li><a href="/JavaScript-Garden/ru" title="JavaScript Гарден по-русски">ru</a></li><li><a href="/JavaScript-Garden/zh" title="JavaScript Garden 中文翻译">zh</a></li><li class="active"><a href="/JavaScript-Garden/tr" title="JavaScript Garden Türkçe">tr</a></li><li><a href="/JavaScript-Garden/es" title="JavaScript Garden es Español">es</a></li><li><a href="/JavaScript-Garden/ja" title="JavaScript Garden in Japanese">ja</a></li><li><a href="/JavaScript-Garden/ko" title="JavaScript Garden">ko</a></li><li><a href="/JavaScript-Garden/fi" title="JavaScript-puutarha suomeksi">fi</a></li></ul><a id="top" href="#intro" title="Back to top">#top</a><a id="hide_menu" class="tablet">Hide Menu</a></div><ul><li class="nav_intro"><h1><a href="#intro">Giriş</a></h1><ul></ul></li><li class="nav_object"><h1><a href="#object">Nesneler</a></h1><ul><li><a href="#object.general">Nesne Kullanımı ve Özellikleri</a></li><li><a href="#object.prototype">Prototip</a></li><li><a href="#object.hasownproperty"><code>hasOwnProperty</code></a></li><li><a href="#object.forinloop"><code>for in</code> Döngüsü</a></li></ul></li><li class="nav_function"><h1><a href="#function">Fonksiyonlar</a></h1><ul><li><a href="#function.general">Fonksiyon Tanımlaması ve Fonksiyon İfadesi</a></li><li><a href="#function.this"><code>this</code> Nasıl Çalışır</a></li><li><a href="#function.closures">Closure ve Referanslar</a></li><li><a href="#function.arguments"><code>arguments</code> Nesnesi</a></li><li><a href="#function.constructors">Nesne Oluşturucular</a></li><li><a href="#function.scopes">Kapsamlar ve İsim Uzayları</a></li></ul></li><li class="nav_array"><h1><a href="#array">Diziler</a></h1><ul><li><a href="#array.general">Dizi İterasyonu ve Özellikleri</a></li><li><a href="#array.constructor"><code>Array</code> Oluşturucusu</a></li></ul></li><li class="nav_types"><h1><a href="#types">Nesne Tipleri</a></h1><ul><li><a href="#types.equality">Eşitlik ve Karşılaştırmalar</a></li><li><a href="#types.typeof"><code>typeof</code> Operatörü</a></li><li><a href="#types.instanceof"><code>instanceof</code> Operatörü</a></li><li><a href="#types.casting">Tip Dönüşümleri</a></li></ul></li><li class="nav_core"><h1><a href="#core">Temel</a></h1><ul><li><a href="#core.eval">Neden <code>eval</code> Kullanılmamalı</a></li><li><a href="#core.undefined"><code>undefined</code> ve <code>null</code></a></li><li><a href="#core.semicolon">Otomatik Noktalı Virgül İlavesi</a></li><li><a href="#core.delete"><code>delete</code> Operatörü</a></li></ul></li><li class="nav_other"><h1><a href="#other">Diğer</a></h1><ul><li><a href="#other.timeouts"><code>setTimeout</code> ve <code>setInterval</code></a></li></ul></li></ul></nav><!-- Mobile navigation--><nav id="nav_mobile"><a id="nav_prev_section" href="#">prev section<span class="nav_section_name">section name</span></a><a id="nav_next_section" href="#">next section<span class="nav_section_name">section name</span></a><a id="show_menu">show menu</a></nav><!-- Sections--><section id="intro"><!-- Introduction--><header id="intro.intro"><h1>Giriş</h1><div><p><strong>JavaScript Garden</strong> JavaScript programlama dilinin acayiplikleri üzerine
derlenmiş bir döküman koleksiyonudur. Henüz ustalaşmamış JavaScript
programcılarının sıkça yaptığı yanlışlar, dile has incelikler ve performans
sorunlarına karşı tavsiyeler içerir.</p>
<p>JavaScript Garden'ın amacı size JavaScript öğretmek <strong>değildir</strong>. Bu rehberde
anlatılan konuları anlamak için JavaScript dilini önceden biliyor olmanız
gerekir. Eğer JavaScript dilinin temellerini öğrenmek istiyorsanız, lütfen
Mozilla Programcı Ağı'nda bulunan mükemmel <a href="https://developer.mozilla.org/en/JavaScript/Guide">rehbere</a> başvurun.</p>
<h2>Yazarlar</h2>
<p>Bu rehber, sevimli birer <a href="http://stackoverflow.com/">Stack Overflow</a> kullanıcısı olan <a href="http://stackoverflow.com/users/170224/ivo-wetzel">Ivo Wetzel</a> (Yazım)
ve <a href="http://stackoverflow.com/users/313758/yi-jiang">Zhang Yi Jiang</a> (Tasarım) tarafından hazırlanmıştır.</p>
<h2>Katkıda Bulunanlar</h2>
<ul>
<li><a href="https://github.com/caio">Caio Romão</a> (Yazım düzeltmeleri)</li>
<li><a href="https://github.com/blixt">Andreas Blixt</a> (Dil düzeltmeleri)</li>
</ul>
<h2>Sunum</h2>
<p>JavaScript Garden GitHub üzerinden, ve ayrıca <a href="http://cramerdev.com/">Cramer Development</a>
tarafından desteklenen <a href="http://javascriptgarden.info/">JavaScriptGarden.info</a> adresinden sunulmaktadır.</p>
<h2>Lisans</h2>
<p>JavaScript Garden <a href="https://github.com/BonsaiDen/JavaScript-Garden/blob/next/LICENSE">MIT lisansı</a> altında yayınlanmıştır ve <a href="https://github.com/BonsaiDen/JavaScript-Garden">GitHub</a>
üzerinde bulunmaktadır. Eğer rehberde yanlışlıklar veya yazım hatalarına
rastlarsanız lütfen <a href="https://github.com/BonsaiDen/JavaScript-Garden/issues">sorunu bize bildirin</a> veya bir <code>pull request</code> gönderin.
Bizi ayrıca Stack Overflow'da <a href="http://chat.stackoverflow.com/rooms/17/javascript">JavaScript sohbet odasında</a> da
bulabilirsiniz.</p></div></header><!-- Articles--></section><section id="object"><!-- Introduction--><header id="object.intro"><h1>Nesneler</h1></header><!-- Articles--><article id="object.general"><h2>Nesne Kullanımı ve Özellikleri</h2><div><p>JavaScript'te iki istisna dışında her şey bir nesne olarak davranır;
bu istisnalar da <a href="#core.undefined"><code>null</code></a> ve <a href="#core.undefined"><code>undefined</code></a>
'dır.</p>
<pre><code>false.toString() // 'false'
[1, 2, 3].toString(); // '1,2,3'
function Foo(){}
Foo.bar = 1;
Foo.bar; // 1
</code></pre>
<p>Sık düşülen bir yanılgı sayı sabitlerinin nesne olarak kullanılamayacağıdır. Bu
yanılgının sebebi de JavaScript çözümleyicisinin <em>nokta notasyonu</em> ile girilen
sayıları bir reel sayı olarak algılama hatasıdır.</p>
<pre><code>2.toString(); // SyntaxError hatası verir
</code></pre>
<p>Bu hatayı aşıp sayı sabitlerinin de nesne olarak davranmasını sağlamak için
uygulanabilecek bazı çözümler vardır. </p>
<pre><code>2..toString(); // ikinci nokta doğru şekilde algılanır
2 .toString(); // noktanın solundaki boşluğa dikkat edin
(2).toString(); // ilk önce 2 değerlendirilir
</code></pre>
</div><div><h3>Bir veri türü olarak nesneler</h3>
<p>JavaScript nesneleri aynı zamanda bir <a href="http://en.wikipedia.org/wiki/Hashmap"><em>Hashmap</em></a> olarak da kullanılabilir,
nesneler temelde isimli özellikler ve bunlara karşılık gelen değerlerden
ibarettir.</p>
<p>Nesne sabiti (<code>{}</code> notasyonu) ile düz bir nesne yaratmak mümkündür. Bu yeni
nesne <a href="#object.prototype">kalıtım</a> ile <code>Object.prototype</code> 'dan türüyecektir ve
hiçbir <a href="#object.hasownproperty">baz özelliğe</a> sahip olmayacaktır.</p>
<pre><code>var foo = {}; // yeni bir boş nesne
// adı 'test' ve değeri 12 olan bir özelliği sahip yeni bir nesne
var bar = {test: 12};
</code></pre>
</div><div><h3>Özelliklere erişmek</h3>
<p>Bir nesnenin özelliklerine iki yolla erişilebilir, ya nokta notasyonu ile veya
köşeli parantez notasyonu ile.</p>
<pre><code>var foo = {name: 'Kitten'}
foo.name; // kitten
foo['name']; // kitten
var get = 'name';
foo[get]; // kitten
foo.1234; // SyntaxError
foo['1234']; // çalışır
</code></pre>
<p>Her iki notasyon da aynı şekilde çalışır, tek fark köşeli parantez notasyonunun
özelliklerin dinamik olarak oluşturulmasına ve normalde bir yazım hatasına yol
açabilecek özellik isimlerinin kullanılmasına izin vermesidir.</p>
</div><div><h3>Özellikleri silmek</h3>
<p>Bir nesnenin özelliklerinden birini silmenin tek yolu <code>delete</code> operatörünü
kullanmaktır; özelliğe <code>undefined</code> veya <code>null</code> değerlerini atamak sadece
özelliğin <em>değerini</em> kaldırır, <em>anahtarı</em> değil.</p>
<pre><code>var obj = {
bar: 1,
foo: 2,
baz: 3
};
obj.bar = undefined;
obj.foo = null;
delete obj.baz;
for(var i in obj) {
if (obj.hasOwnProperty(i)) {
console.log(i, '' + obj[i]);
}
}
</code></pre>
<p>Yukarıdaki örnek sonuç olarak hem <code>bar undefined</code> hem de <code>foo null</code> yazacaktır.
Sadece <code>baz</code> özelliği kaldırılmış olacak ve çıktıda görünmeyecektir.</p>
</div><div><h3>Anahtar notasyonu</h3>
<pre><code>var test = {
'case': 'anahtar kelime olduğu için katar olarak girildi',
delete: 'yine bir anahtar kelime' // SyntaxError hatası
};
</code></pre>
<p>Nesne özellikleri düz karakterler olarak da katar notasyonu ile de
tanımlanabilir. Fakat JavaScript çözümleyicisinin bir başka tasarım hatası
yüzünden, yukarıdaki örnek ECMAScript 5 öncesinde bir <code>SyntaxError</code> hatası
verecektir.</p>
<p>Bu hata <code>delete</code> 'in bir <em>anahtar kelime</em> olmasından kaynaklanır, bu nedenle
eski JavaScript motorlarının bu örneği doğru algılaması için <em>karakter katarı</em>
notasyonu ile girilmelidir.</p></div></article><article id="object.prototype"><h2>Prototip</h2><div><p>JavaScript klasik bir kalıtım modeli değil <em>prototip</em> modeli kullanır.</p>
<p>Çoğu zaman bu modelin JavaScript'in zayıf yönlerinden biri olduğu söylense de,
aslında prototip model klasik modelden daha güçlüdür. Mesela prototip model
temel alınarak klasik kalıtım modeli oluşturulabilir, fakat bunun tersini yapmak
çok daha zordur.</p>
<p>Prototip kalıtım modeli kullanan tek popüler dil JavaScript olduğu için iki
model arasındaki farklılıklara alışmak biraz zaman alır.</p>
<p>İlk büyük farklılık JavaScript'te kalıtımın <em>prototip zincirleri</em> ile
yapılmasıdır.</p>
<aside>
<p><strong>Not:</strong> <code>Bar.prototype = Foo.prototype</code> gibi basit bir atama yapmak her iki
nesnenin de <strong>aynı</strong> prototipe sahip olmasına neden olacaktır. Bu yüzden bir
nesnenin prototipinde yapılacak değişiklikler diğer nesnenin prototipini de
etkileyecektir, ki çoğu zaman istenen etki bu değildir.</p>
</aside>
<pre><code>function Foo() {
this.value = 42;
}
Foo.prototype = {
method: function() {}
};
function Bar() {}
// Bar nesnesinin prototipi olarak yeni bir Foo nesnesini ata
Bar.prototype = new Foo();
Bar.prototype.foo = 'Hello World';
// Nesne oluşturucusunun Bar olmasını sağla
Bar.prototype.constructor = Bar;
var test = new Bar() // yeni bir Bar oluştur
// Sonuçta ortaya çıkan prototip zinciri
test [bir Bar sınıfı nesnesi]
Bar.prototype [bir Foo sınıfı nesnesi]
{ foo: 'Hello World' }
Foo.prototype
{ method: ... }
Object.prototype
{ toString: ... /* vs. */ }
</code></pre>
<p>Yukarıda, <code>test</code> nesnesi hem <code>Bar.prototype</code> hem de <code>Foo.prototype</code> 'dan
türeyecektir; bu nedenle <code>Foo</code> 'da tanımlanmış olan <code>method</code> fonksiyonuna
da erişebilir. Ayrıca, prototipi olan <strong>tek</strong> <code>Foo</code> nesnesinin <code>value</code>
özelliğine de erişebilir. Dikkat edilmesi gereken bir nokta, <code>new Bar()</code>
ifadesinin yeni bir <code>Foo</code> nesnesi <strong>yaratmayıp</strong>, prototipine atanmış olan
nesneyi kullanmasıdır; bu nedenle, tüm <code>Bar</code> nesneleri <strong>aynı</strong> <code>value</code>
özelliğine sahip olacaktır.</p>
<aside>
<p><strong>Not:</strong> <code>Bar.prototype = Foo</code> gibi bir ifade <strong>kullanmayın</strong>, çünkü <code>Foo</code>
'nun prototipine değil fonksiyon nesnesine işaret edecektir. Yani
prototip zinciri <code>Foo.prototype</code> değil <code>Function.prototype</code> üzerinden
gidecektir; ve bu yüzden, <code>method</code> prototip zincirinde bulunmayacaktır.</p>
</aside>
</div><div><h3>Özelliklere bulmak</h3>
<p>Bir nesnenin özelliklerine erişildiğinde, JavaScript, istenen isimdeki özelliği
bulana kadar prototip zincirinde <strong>yukarı</strong> doğru dolaşır.</p>
<p>Zincirin en üstüne ulaştığında (yani <code>Object.protype</code>) ve hala istenen özelliği
bulamamışsa sonuç olarak <a href="#core.undefined"><code>undefined</code></a> verecektir.</p>
</div><div><h3>prototype özelliği</h3>
<p><code>prototype</code> özelliği dil tarafından prototip zincirleri oluşturmak için
kullanılsa da, bu özelliğe <strong>herhangi</strong> bir değer atamak mümkündür. Fakat
prototip olarak atanan ilkel nesne türleri göz ardı edilecektir.</p>
<pre><code>function Foo() {}
Foo.prototype = 1; // hiç bir etkisi olmaz
</code></pre>
<p>Bir önceki örnekte gösterildiği gibi, prototip olarak nesneler atanabilir, bu da
prototip zincirlerinin dinamik olarak oluşturulabilmesini sağlar.</p>
</div><div><h3>Performans</h3>
<p>Prototip zincirinin yukarısındaki özellikleri aramanın performansı kritik olan
programlarda olumsuz etkileri olabilir. Ek olarak, mevcut olmayan özelliklere
erişmeye çalışmak da tüm prototip zincirinin baştan sona taranmasına neden
olacaktır.</p>
<p>Ayrıca, bir nesnenin özellikleri üzerinde <a href="#object.forinloop">iterasyon</a>
yapıldığında da prototip zinciri üzerindeki <strong>tüm</strong> özelliklere bakılacaktır.</p>
</div><div><h3>Temel prototiplerin genişletilmesi</h3>
<p>Sıklıkla yapılan bir hata <code>Object.protype</code> 'ı veya diğer baz prototipleri
genişletmektir.</p>
<p>Bu tekniğe <a href="http://en.wikipedia.org/wiki/Monkey_patch"><em>monkey patching</em></a> denir ve <em>kapsüllemeyi</em> bozar. Bu teknik
<a href="http://prototypejs.org/">Prototype</a> gibi bazı popüler sistemlerde kullanılsa bile, temel nesne
türlerine <em>standart olmayan</em> özellikler eklenmesinin geçerli iyi bir nedeni
yoktur.</p>
<p>Temel prototipleri genişletmenin <strong>tek bir</strong> geçerli nedeni vardır, o da daha
yeni JavaScript motorlarında bulunan özelliklerin eski motorlara getirilmesidir;
mesela <a href="https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/forEach"><code>Array.forEach</code></a>.</p>
</div><div><h3>Sonuç</h3>
<p>Prototip kalıtım modeli kullanan karmaşık programlar yazmadan önce bu modelin
tamamen anlaşılması <strong>şarttır</strong>. Ayrıca, prototip zincirinin uzunluğuna dikkat
edilmeli ve çok uzaması durumunda performans sorunları yaşamamak için parçalara
bölünmelidir. Bundan başka, temel prototipler yeni JavaScript motorları ile
uyumluluk sağlamak dışında bir nedenle <strong>asla</strong> genişletilmemelidir.</p></div></article><article id="object.hasownproperty"><h2><code>hasOwnProperty</code></h2><div><p>Bir özelliğin nesnenin <a href="#object.prototype">prototip zinciri</a> üzerinde bir yerde
<strong>değil</strong>, <em>kendisi</em> üzerinde tanımlandığını belirlemek için, <code>Object.prototype</code>
kalıtımı ile tüm nesnelerin sahip olduğu <code>hasOwnProperty</code> metodunun kullanılması
gerekir.</p>
<aside>
<p><strong>Not:</strong> Bir özelliğin <code>undefined</code> olduğunu kontrol etmek yeterli <strong>değildir</strong>.
Bir özelliğin değeri <code>undefined</code> olarak atandığı halde özelliğin kendisi
pekala mevcut olabilir.</p>
</aside>
<p><code>hasOwnProperty</code> JavaScript'te nesne özellikleri üzerinde çalışıp prototip
zincirinin tümünü <strong>dolaşmayan</strong> tek şeydir.</p>
<pre><code>// Object.prototype'a bar özelliğini ekle
Object.prototype.bar = 1;
var foo = {goo: undefined};
foo.bar; // 1
'bar' in foo; // true
foo.hasOwnProperty('bar'); // false
foo.hasOwnProperty('goo'); // true
</code></pre>
<p>Sadece <code>hasOwnProperty</code> beklenen doğru sonucu verecektir, nesne özellikleri
üzerinde iterasyon yaparken bu çok önemlidir. Bir nesnenin <em>kendisi</em> üzerinde
değil de protip zinciri üzerinde bir yerde tanımlanmış olan özelliklerini
çıkarmanın başka hiçbir yolu <strong>yoktur</strong>.</p>
</div><div><h3><code>hasOwnProperty</code> özelliği</h3>
<p>JavaScript <code>hasOwnProperty</code> adının bir özellik olarak kullanılmasını engellemez;
bu nedenle bir nesnenin bu isimde bir özelliğe sahip olması ihtimali varsa,
doğru sonuç alabilmek için <code>hasOwnProperty</code><em>haricen</em> kullanılmalıdır.</p>
<pre><code>var foo = {
hasOwnProperty: function() {
return false;
},
bar: 'Here be dragons'
};
foo.hasOwnProperty('bar'); // her zaman false verir
// hasOwnProperty başka bir nesne üzerinde
// kullanıldığında 'this' foo olur
({}).hasOwnProperty.call(foo, 'bar'); // true
</code></pre>
</div><div><h3>Sonuç</h3>
<p>Bir nesnenin bir özelliği sahip olup olmadığını kontrol etmek için
kullanılabilecek <strong>tek</strong> yöntem <code>hasOwnProperty</code> 'dir. Aynı zamanda, nesne
<a href="#object.prototype">prototiplerinin</a> genişletilmesinden kaynaklanabilecek
hataların önüne geçmek için, <strong>tüm</strong> <a href="#object.forinloop"><code>for in</code> döngüleri</a> ile
<code>hasOwnProperty</code> kullanılması tavsiye olunur.</p></div></article><article id="object.forinloop"><h2><code>for in</code> Döngüsü</h2><div><p>Tıpkı <code>in</code> operatörü gibi <code>for in</code> döngüsü de bir nesnenin özellikleri üzerinde
iterasyon yaparken prototip zincirini dolaşır.</p>
<aside>
<p><strong>Not:</strong> <code>for in</code> döngüsü iterasyon yaparken <code>enumerable</code> niteliği <code>false</code>
olan özelliklere uğramaz; mesela, bir dizinin <code>length</code> özelliğini atlar.</p>
</aside>
<pre><code>// Object.prototype'a bar özelliğini ekle
Object.prototype.bar = 1;
var foo = {moo: 2};
for(var i in foo) {
console.log(i); // hem bar hem de moo yazar
}
</code></pre>
<p><code>for in</code> döngüsünün davranışını değiştirmek mümkün olmadığı için, istenmeyen
özelliklerin döngünün içinde filtrelenmesi gerekir, bu da <code>Object.prototype</code>
nesnesinin <a href="#object.hasownproperty"><code>hasOwnProperty</code></a> metodu ile yapılır.</p>
<aside>
<p><strong>Not:</strong> <code>for in</code> döngüsü tüm prototip zincirini dolaştığı için bir nesneye
eklenen her yeni kalıtım katmanı döngüyü biraz daha yavaşlatacaktır.</p>
</aside>
</div><div><h3><code>hasOwnProperty</code> kullanarak filtrelemek</h3>
<pre><code>// yukarıdaki örnekteki foo nesnesi
for(var i in foo) {
if (foo.hasOwnProperty(i)) {
console.log(i);
}
}
</code></pre>
<p>Doğru kullanım bu yeni versiyonda gösterildiği gibidir. <code>hasOwnProperty</code> kontrol
edildiği için <strong>sadece</strong> <code>moo</code> yazacaktır. <code>hasOwnProperty</code> kullanılmaz ise ve
<code>Object.protype</code> 'ın baz özellikleri değiştirilmişse, program bazı hatalara
yatkın olabilir.</p>
<p>Bunu yapan ve yaygın olarak kullanılan bir JavaScript sistemi <a href="http://www.prototypejs.org/">Prototype</a>
'dır. Bu sistemde <code>hasOwnProperty</code> kullanmayan <code>for in</code> döngüleri kesinlikle
hatalı sonuç verecektir.</p>
</div><div><h3>Sonuç</h3>
<p><code>hasOwnProperty</code> <strong>her zaman</strong> kontrol edilmelidir. Programın içinde çalıştığı
ortam için, nesnelerin baz özelliklerinin değiştirilip değiştirilmediğine dair
hiçbir kabul yapılmamalıdır.</p></div></article></section><section id="function"><!-- Introduction--><header id="function.intro"><h1>Fonksiyonlar</h1></header><!-- Articles--><article id="function.general"><h2>Fonksiyon Tanımlaması ve Fonksiyon İfadesi</h2><div><p>Fonksiyonlar JavaScript'te birinci sınıf nesnelerdir, yani sıradan bir değer
gibi kullanılabilirler. Bu özellik sıklıkla bir <em>isimsiz fonksiyonu</em> başka bir
fonksiyona - ki bu muhtemelen asenkron bir fonksiyondur - <code>callback</code> olarak
geçirmekte kullanılır.</p>
</div><div><h3><code>function</code> tanımlaması</h3>
<pre><code>function foo() {}
</code></pre>
<p>Yukarıdaki fonksiyon tanımlaması program çalışmadan önce
<a href="#function.scopes">yukarı taşınır</a> ve böylece <em>tanımlandığı</em> kapsam içinde
<em>her yerde</em> (hatta tanımlanmadan önce bile) kullanılabilir.</p>
<pre><code>foo(); // foo bu satır çalışmadan önce oluşturuldu
function foo() {}
</code></pre>
</div><div><h3><code>function</code> ifadesi</h3>
<pre><code>var foo = function() {};
</code></pre>
<p>Bu örnekte <em>isimsiz fonksiyon</em> <code>foo</code> değişkenine atanır.</p>
<pre><code>foo; // 'undefined'
foo(); // Bu satır bir TypeError hatasına neden olur
var foo = function() {};
</code></pre>
<p>Yukarıdaki <code>var</code> anahtar kelimesi bir bildirim olduğu için <code>foo</code> değişkeni
program çalışmadan önce yukarı alınır, program çalıştığında <code>foo</code> tanımlanmştır.</p>
<p>Fakat değer atamaları sadece program çalışırken gerçekleşeceği için, ilgili
satır çalıştığında, <code>foo</code> değişkeninin değeri varsayılan olarak
<a href="#core.undefined">undefined</a> olacaktır.</p>
</div><div><h3>İsimli fonksiyon ifadesi</h3>
<p>Bir başka özel durum isimli fonksiyon ifadesidir.</p>
<pre><code>var foo = function bar() {
bar(); // Çalışır
}
bar(); // ReferenceError hatası verir
</code></pre>
<p>Burada <code>bar</code> fonksiyonuna dış kapsamdan ulaşılamaz, çünkü sadece <code>foo</code>
değişkenine atanmıştır; fakat iç kapsamda <code>bar</code> fonksiyonuna erişilebilir.
Bunun nedeni JavaScript'te <a href="#function.scopes">isim çözümlemenin</a> çalışma
şeklidir, fonksiyonun adına fonksiyonun içinden <em>her zaman</em> erişilebilir.</p></div></article><article id="function.this"><h2><code>this</code> Nasıl Çalışır</h2><div><p>JavaScript'te <code>this</code> özel kelimesinin anlamı diğer programlama dillerinden
farklıdır. <code>this</code> kelimesinin birbirinden farklı anlamlar yüklendiği tam
<strong>beş</strong> durum vardır.</p>
</div><div><h3>Genel kapsam</h3>
<pre><code>this;
</code></pre>
<p><code>this</code> kelimesi genel kapsamda kullanıldığında <em>global</em> nesneye işaret eder.</p>
</div><div><h3>Bir fonksiyon çağırma</h3>
<pre><code>foo();
</code></pre>
<p>Burada <code>this</code> yine <em>global</em> nesneye işaret eder.</p>
<aside class="es5"><p><strong>ES5 Notu:</strong> Mutlak modda bu davranış <strong>kaldırılmıştır</strong>. Bu durumda <code>this</code>
kelimesinin değeri <code>undefined</code> olacaktır.</p>
</aside>
</div><div><h3>Bir metod çağırma</h3>
<pre><code>test.foo();
</code></pre>
<p>Bu örnekte <code>this</code> kelimesi <code>test</code> 'e işaret edecektir.</p>
</div><div><h3>Bir nesne oluşturucu çağırma</h3>
<pre><code>new foo();
</code></pre>
<p>Bir fonksiyon başında <code>new</code> anahtar kelimesi ile birlikte çağrılırsa bir
<a href="#function.constructors">nesne oluşturucu</a> olarak davranır. Bu fonksiyonun
içinde <code>this</code> kelimesi <em>yeni oluşturulan</em> <code>Object</code> 'e işaret eder.</p>
</div><div><h3><code>this</code> kelimesinin atanması</h3>
<pre><code>function foo(a, b, c) {}
var bar = {};
foo.apply(bar, [1, 2, 3]); // dizi aşağıdaki gibi açılır
foo.call(bar, 1, 2, 3); // sonuç: a = 1, b = 2, c = 3
</code></pre>
<p><code>Function.prototype</code> 'ın <code>call</code> veya <code>apply</code> metodları kullanıldığında, çağrılan
fonksiyonun içinde <code>this</code> 'in değeri ilk argümanın değeri olarak <strong>atanır</strong>.</p>
<p>Sonuç olarak, yukarıdaki örnekte <em>metod çağırma</em> durumu geçerli <strong>olmayacak</strong>,
bunun yerine <code>foo</code> fonksiyonu içinde <code>this</code> 'in değeri <code>bar</code> olacaktır.</p>
<aside>
<p><strong>Not:</strong> <code>this</code> kelimesi bir <code>Object</code> sabiti içinde nesnenin kendisine
işaret etmek için <strong>kullanılamaz</strong>. Yani <code>var obj = {me: this}</code> gibi bir
ifadede <code>me</code>, <code>obj</code> nesnesine işaret <strong>etmeyecektir</strong>, <code>this</code> sadece yukarıda
açıklanan beş durumdan biri ile kullanılabilir.</p>
</aside>
</div><div><h3>Sık düşülen yanılgılar</h3>
<p>Yukarıdaki durumların çoğu mantıklı görünse bile, ilk durum dilin tasarım
hatalarından biri olarak değerlendirilmelidir çünkü <strong>hiçbir</strong> pratik
kullanılımı yoktur.</p>
<pre><code>Foo.method = function() {
function test() {
// this genel nesneye işaret eder
}
test();
}
</code></pre>
<p>Bir başka yanılgı <code>test</code> fonksiyonunun içinde <code>this</code> 'in <code>Foo</code> 'ya işaret
edeceğinin sanılmasıdır, ama bu <strong>doğru değildir</strong>.</p>
<p><code>test</code> fonksiyonu içinden <code>Foo</code> 'ya erişmenin yolu <code>method</code> içinde bir lokal
değişken oluşturmaktır.</p>
<pre><code>Foo.method = function() {
var that = this;
function test() {
// Burada this yerine that kullanın
}
test();
}
</code></pre>
<p><code>that</code> kelimesinin dilde özel bir anlamı yoktur, ama sıklıkla dış kapsamdaki
<code>this</code> 'e işaret etmek için kullanılır. Bu yöntem <a href="#function.closures"><code>closure</code></a>
kavramı ile birlikte kullanıldığında <code>this</code> değerini program içinde taşımaya da
yarar.</p>
</div><div><h3>Metodları değişkenlere atamak</h3>
<p>JavaScript'te mevcut <strong>olmayan</strong> bir başka özellik de fonksiyon isimlendirmedir,
başka bir deyişle bir metodu bir değişkene <strong>atamak</strong>.</p>
<pre><code>var test = someObject.methodTest;
test();
</code></pre>
<p>İlk durum nedeniyle <code>test</code> artık sıradan bir fonksiyon olarak davranacaktır; bu
nedenle <code>test</code> fonksiyonu içinde <code>this</code> artık <code>someObject</code> 'e işaret
etmeyecektir.</p>
<p><code>this</code> kelimesinin geç bağlanması ilk bakışta yanlış görünse de, aslında
<a href="#object.prototype">prototipsel kalıtımı</a> mümkün kılan şey budur.</p>
<pre><code>function Foo() {}
Foo.prototype.method = function() {};
function Bar() {}
Bar.prototype = Foo.prototype;
new Bar().method();
</code></pre>
<p>Yukarıda <code>Bar</code> sınıfına ait bir nesnenin <code>method</code> 'u çağrıldığında <code>this</code> bu
nesneye işaret edecektir.</p></div></article><article id="function.closures"><h2>Closure ve Referanslar</h2><div><p>JavaScript'in en güçlü özelliklerinden biri de <code>closure</code> 'lara sahip olmasıdır.
Bunun anlamı her hangi bir kapsamın <strong>her zaman</strong> kendisini içeren kapsama
erişebilmesidir. JavaScript'te tek kapsam <a href="#function.scopes">fonksiyon kapsamı</a>
olduğu için temelde tüm fonksiyonlar <code>closure</code> 'durlar.</p>
</div><div><h3>Private değişkenler</h3>
<pre><code>function Counter(start) {
var count = start;
return {
increment: function() {
count++;
},
get: function() {
return count;
}
}
}
var foo = Counter(4);
foo.increment();
foo.get(); // 5
</code></pre>
<p>Burada, <code>Counter</code> <strong>iki</strong> <code>closure</code> verir: <code>increment</code> fonksiyonu ve <code>get</code>
fonksiyonu. Bu iki fonksiyon da <code>Counter</code> fonksiyonun kapsamına ait bir
<strong>referans</strong> 'a sahiptir, ve bu nedenle söz konusu kapsamda tanımlanmış olan
<code>count</code> değişkenine erişebilirler.</p>
</div><div><h3>Private değişkenler nasıl işler</h3>
<p>JavaScript'te kapsam referanslarına erişmek yada atama yapmak mümkün olmadığı
için, dış kapsamdan <code>count</code> değişkenine ulaşmak <strong>mümkün değildir</strong>. Bu
değişkene ulaşmanın tek yolu yukarıdaki iki <code>closure</code> 'dur.</p>
<pre><code>var foo = new Counter(4);
foo.hack = function() {
count = 1337;
};
</code></pre>
<p>Bu program parçası <code>Counter</code> fonksiyonun kapsamındaki <code>count</code> değişkeninin
değerini <strong>değiştirmez</strong>, çünkü <code>foo.hack</code> <strong>bu kapsamda</strong> tanımlanmamıştır.
Bunun yerine <em>global</em> kapsamda yeni bir değişen oluşturur (yada mevcut bir
değişkeni değiştirir).</p>
</div><div><h3>Döngü içinde closure</h3>
<p>Sık yapılan bir hata, döngü içinde closure kullanıp döngünün indeks değişkeninin
değerinin kopyalanacağını varsaymaktır.</p>
<pre><code>for(var i = 0; i < 10; i++) {
setTimeout(function() {
console.log(i);
}, 1000);
}
</code></pre>
<p>Yukarıdaki örnek çıktı olarak <code>0</code> - <code>9</code> arası sayıları vermek yerine, <code>10</code>
sayısını on kez yazacaktır.</p>
<p>İçteki <em>isimsiz</em> fonksiyon <code>i</code> değişkeninin değerine değil referansına sahiptir
ve <code>console.log</code> çağrıldığında, <code>for</code> döngüsü çoktan tamamlanmış ve <code>i</code>
değişkeninin değeri <code>10</code> olmuştur.</p>
<p>İstenen davranışı elde etmek için <code>i</code> değişkeninin değerinin <strong>kopyalanması</strong>
gerekir.</p>
</div><div><h3>Referans probleminin çözümü</h3>
<p>Döngünün indeks değişkeninin değerini kopyalamanın en iyi yolu bir
<a href="#function.scopes">isimsiz fonksiyon</a> kullanmaktır.</p>
<pre><code>for(var i = 0; i < 10; i++) {
(function(e) {
setTimeout(function() {
console.log(e);
}, 1000);
})(i);
}
</code></pre>
<p>Dıştaki isimsiz fonksiyon her adımda çağrılacak ve <code>e</code> parametresi olarak
<code>i</code> 'nin <strong>değerinin</strong> bir kopyası verilecektir.</p>
<p><code>setTimeOut</code> fonksiyonuna verilen isimsiz fonksiyon artık <code>e</code> 'ye ait bir
referansa sahip olacaktır, ve referansın değeri döngü tarafından
<strong>değiştirilmeyecektir</strong>.</p>
<p>Bu davranışı başka bir yolla da elde etmek mümkündür; isimsiz fonksiyondan başka
bir fonksiyon döndürmek. Bu durumda yukarıdaki ile aynı davranış elde
edilecektir.</p>
<pre><code>for(var i = 0; i < 10; i++) {
setTimeout((function(e) {
return function() {
console.log(e);
}
})(i), 1000)
}
</code></pre></div></article><article id="function.arguments"><h2><code>arguments</code> Nesnesi</h2><div><p>JavaScript'te her fonksiyon kapsamında <code>arguments</code> adlı özel bir nesne
tanımlıdır. Bu nesne fonksiyon çağrılırken verilen argümanların listesini
içerir.</p>
<aside>
<p><strong>Not:</strong> Eğer <code>arguments</code> adında bir değişken fonksiyon kapsamında bir <code>var</code>
ifadesi ile veya tanımlı parametre olarak zaten mevcutsa, <code>arguments</code> nesnesi
oluşturulmaz.</p>
</aside>
<p><code>arguments</code> nesnesi bir <code>Array</code> <em>değildir</em>. Bir dizinin özelliklerinin bir
kısmına sahip olsa da (<code>length</code> özelliği) <code>Array.prototype</code> sınıfından
türetilmemiştir, aslında bir <code>Object</code> bile değildir.</p>
<p>Bu nedenle, <code>arguments</code> nesnesi üzerinde <code>push</code>, <code>pop</code> ve <code>slice</code> gibi standart
dizi metotlarını kullanmak mümkün <strong>değildir</strong>. Klasik <code>for</code> döngüsü <code>arguments</code>
nesnesi ile kullanılabilir, ancak standart dizi metotlarını kullanmak için
gerçek bir diziye dönüştürmek gerekir.</p>
</div><div><h3>Diziye dönüştürmek</h3>
<p>Aşağıdaki program parçası <code>arguments</code> nesnesinin tüm elemanlarına sahip yeni bir
dizi verecektir.</p>
<pre><code>Array.prototype.slice.call(arguments);
</code></pre>
<p>Bu dönüşüm <strong>yavaştır</strong>, ve performansın belirleyici olduğu durumlarda
kullanılması <strong>tavsiye olunmaz</strong>.</p>
</div><div><h3>Argümanların geçirilmesi</h3>
<p>Aşağıdaki örnekte, argümanların bir fonksiyondan diğerine geçirilmesi
için önerilen yöntem gösterilmiştir.</p>
<pre><code>function foo() {
bar.apply(null, arguments);
}
function bar(a, b, c) {
// do stuff here
}
</code></pre>
<p>Bir başka püf noktası da <code>call</code> ve <code>apply</code> 'ı birlikte kullanarak hızlı,
ilişkisiz fonksiyonlar yaratmaktır.</p>
<pre><code>function Foo() {}
Foo.prototype.method = function(a, b, c) {
console.log(this, a, b, c);
};
// "method" 'un ilişkisiz bir versiyonunu yarat
// Aldığı parametreler: this, arg1, arg2...argN
Foo.method = function() {
// Sonuç: Foo.prototype.method.call(this, arg1, arg2... argN)
Function.call.apply(Foo.prototype.method, arguments);
};
</code></pre>
</div><div><h3>Tanımlı parametreler ve argüman indisleri</h3>
<p><code>arguments</code> nesnesi her iki özelliği ve fonksiyonun tanımlı parametreleri için
<em>getter</em> ve <em>setter</em> fonksiyonlar oluşturur.</p>
<p>Sonuç olarak, bir tanımlı parametrenin değerini değiştirmek <code>arguments</code>
nesnesindeki karşılık gelen özelliğin değerini de değiştirecektir.</p>
<pre><code>function foo(a, b, c) {
arguments[0] = 2;
a; // 2
b = 4;
arguments[1]; // 4
var d = c;
d = 9;
c; // 3
}
foo(1, 2, 3);
</code></pre>
</div><div><h3>Performans mitleri ve gerçekler</h3>
<p><code>arguments</code> nesnesi fonksiyon kapsamında bir değişken veya tanımlı parametre
olarak kullanılmış olması durumları dışında her zaman oluşturulur. Kullanılıp
kullanılmaması fark etmez.</p>
<p><em>getter</em> ve <em>setter</em> fonksiyonlar <strong>her zaman</strong> oluşturulur; dolayısıyla
<code>arguments</code> nesnesini kullanmanın performans üzerinde olumsuz bir etkisi yoktur,
özellikle de sadece <code>arguments</code> nesnesinin özelliklerine erişmekten ibaret
olmayan <em>gerçek</em> programlarda.</p>
<aside class="es5"><p><strong>ES5 Notu:</strong> Söz konusu <em>getter</em> ve <em>setter</em> fonksiyonlar mutlak modda
oluşturulmaz.</p>
</aside>
<p>Fakat, modern JavaScript motorlarının performansını ciddi bir şekilde etkileyen
bir durum vardır. Bu durum <code>arguments.callee</code> nesnesinin kullanılmasıdır.</p>
<pre><code>function foo() {
arguments.callee; // içinde olduğumuz fonksiyon nesnesi
arguments.callee.caller; // ve çağıran fonksiyon nesnesi
}
function bigLoop() {
for(var i = 0; i < 100000; i++) {
foo(); // Normalde inline edilirdi...
}
}
</code></pre>
<p>Yukarıdaki program parçasında, <code>foo</code> fonksiyonuna <a href="http://en.wikipedia.org/wiki/Inlining">inlining</a> uygulanması
mümkün değildir çünkü fonksiyonun hem kendisini ve kendisini çağıran fonksiyonu
bilmesi gerekmektedir. Bu yüzden hem inlining yapılamadığı için bir performans
artışı sağlanamamış hem de kapsüllenme bozulmuş olmaktadır, çünkü fonksiyon
artık kendisini çağıran kapsama bağımlı hale gelmiş olabilir.</p>
<p><code>arguments.callee</code> ve özelliklerinin <strong>asla</strong> kullanılmaması
<strong>şiddetle tavsiye olunur</strong>.</p>
<aside class="es5"><p><strong>ES5 Notu:</strong> Mutlak modda <code>arguments.callee</code> kullanımı kaldırılmıştır ve
kullanılması durumunda bir <code>TypeError</code> hatası oluşacaktır.</p>
</aside></div></article><article id="function.constructors"><h2>Nesne Oluşturucular</h2><div><p>JavaScript'te oluşturucular diğer dillerden farklıdır. Başında <code>new</code> bulunan
her fonksiyon çağrısı bir oluşturucudur.</p>
<p>Oluşturucunun (çağrılan fonksiyonun) içinde <code>this</code> 'in değeri yeni yaratılan
<code>Object</code> 'dir. Bu <strong>yeni</strong> nesnenin <a href="#object.prototype"><code>prototipi</code></a> oluşturucu
olarak çağrılan fonksiyon nesnesinin prototipidir.</p>
<p>Çağrılan fonksiyonda bir <code>return</code> ifadesi yoksa, <code>this</code> (yani yeni nesneyi)
döndürür.</p>
<pre><code>function Foo() {
this.bla = 1;
}
Foo.prototype.test = function() {
console.log(this.bla);
};
var test = new Foo();
</code></pre>
<p>Yukarıdaki program <code>Foo</code> oluşturucusunu çağırır ve yeni yaratılan nesnenin
<code>prototipini</code> <code>Foo.prototype</code> olarak belirler.</p>
<p>Oluşturucunun içinde bir <code>return</code> ifadesi bulunması durumunda, <strong>ve sadece</strong>
bu değer bir <code>Object</code> ise oluşturucu fonksiyon verilen değeri döndürür.</p>
<pre><code>function Bar() {
return 2;
}
new Bar(); // yeni bir Bar nesnesi
function Test() {
this.value = 2;
return {
foo: 1
};
}
new Test(); // döndürülen nesne
</code></pre>
<p><code>new</code> anahtar kelimesi ihmal edilirse, fonksiyon yeni bir nesne <strong>döndürmez</strong>.</p>
<pre><code>function Foo() {
this.bla = 1; // global nesnenin özelliğini değiştirir
}
Foo(); // undefined
</code></pre>
<p>Yukarıdaki örnek bazı durumlarda doğru çalışıyor gibi görünebilir, ama
JavaScript'te <a href="#function.this"><code>this</code></a> 'in çalışma şeklinden dolayı <code>this</code>
'in değeri <em>global nesne</em> olacaktır.</p>
</div><div><h3>Nesne fabrikaları</h3>
<p><code>new</code> anahtar kelimesini ihmal edebilmek için oluşturucu fonksiyonun bir değer
döndürmesi gerekir.</p>
<pre><code>function Bar() {
var value = 1;
return {
method: function() {
return value;
}
}
}
Bar.prototype = {
foo: function() {}
};
new Bar();
Bar();
</code></pre>
<p>Yukarıda <code>Bar</code> fonksiyonunu çağıran her iki ifade de aynı şeyi döndürecektir:
<code>method</code> adında bir <a href="#function.closures"><code>closure</code></a> özelliği olan yeni yaratılmış
bir nesne.</p>
<p>Başka bir nokta da <code>new Bar()</code> fonksiyonunun döndürülen nesnenin prototipini
<strong>etkilememesidir</strong>. Yeni nesnenin prototipi oluşturulacaktır ancak <code>Bar</code> bu
nesneyi döndürmez.</p>
<p>Yukarıdaki örnekte <code>new</code> anahtar kelimesini kullanmakla kullanmamak arasında
hiçbir bir fark yoktur.</p>
</div><div><h3>Fabrikalar ile yeni nesneler oluşturmak</h3>
<p><code>new</code> anahtar kelimesinin <strong>kullanılmaması</strong> tavsiye edilir, çünkü unutulması
durumu hatalara sebep olabilir.</p>
<p>Bunun yerine yeni bir nesne oluşturmak için bir fabrika kullanılmalıdır.</p>
<pre><code>function Foo() {
var obj = {};
obj.value = 'blub';
var private = 2;
obj.someMethod = function(value) {
this.value = value;
}
obj.getPrivate = function() {
return private;
}
return obj;
}
</code></pre>
<p>Yukarıdaki örnek hem <code>new</code> anahtar kelimesinin unutulmasından etkilenmez hem de
<a href="#function.closures">private değikenlerin</a> kullanılmasını kolaylaştırır, ama
bazı dezavantajları da vardır.</p>
<ol>
<li>Oluşturulan nesneler bir prototip üzerinde metotlarını <strong>paylaşmadıkları</strong>
için daha fazla hafıza kullanılır.</li>
<li>Başka bir sınıf türetmek için fabrikanın tüm metotları başka bir nesneden
kopyalaması veya bu nesneyi yeni nesnenin prototipine yerleştirmesi gerekir.</li>
<li>Sadece <code>new</code> anahtar kelimesinin ihmal edilmesinden kaynaklanacak sorunları
gidermek için prototip zincirinden vazgeçmek dilin ruhuna aykırıdır.</li>
</ol>
</div><div><h3>Sonuç</h3>
<p><code>new</code> anahtar kelimesini ihmal etmek hatalara neden olabilir, fakat bu
kesinlikle prototip zincirinden vazgeçmek için bir neden <strong>olamaz</strong>. Hangi
çözümün belirli bir programa uygun olduğu kararını verirken, en önemli nokta
nesne oluşturmak için belirli bir yöntemi seçip bu çözüme <strong>bağlı kalmaktır</strong>.</p></div></article><article id="function.scopes"><h2>Kapsamlar ve İsim Uzayları</h2><div><p>JavaScript'te birbiri ile eşleşen ayraçlar kullanılmasına karşın blok
kapsamı <strong>bulunmaz</strong>; bu nedenle, dilde sadece <em>fonksiyon kapsamı</em> mevcuttur.</p>
<pre><code>function test() { // fonksiyon kapsamı
for(var i = 0; i < 10; i++) { // kapsam değil
// sayaç
}
console.log(i); // 10
}
</code></pre>
<aside>
<p><strong>Not:</strong> Bir değer atama, <code>return</code> ifadesi veya fonksiyon argümanı olarak
kullanıldığında <code>{...}</code> notasyonu bir nesne değişmezi olarak <strong>değil</strong>
blok ifade olarak değerlendirilir. Bu özellik
<a href="#core.semicolon">otomatik noktalı virgül ilavesi</a> ile birleştiğinde fark
edilmesi zor hatalara neden olabilir.</p>
</aside>
<p>JavaScript'te isim uzayları kavramı da bulunmaz, tanımlanan herşey
<em>genel olarak paylaşılmış</em> tek bir isim uzayının içindedir.</p>
<p>Bir değişkene erişildiğinde, JavaScript değişkenin tanımını bulana dek yukarıya
doğru tüm kapsamlara bakar. Genel kapsama ulaşıldığı halde hala değişkenin
tanımı bulanamamışsa bir <code>ReferenceError</code> hatası oluşur.</p>
</div><div><h3>Genel değişkenler felaketi</h3>
<pre><code>// A programı
foo = '42';
// B programı
var foo = '42'
</code></pre>
<p>Yukarıdaki iki program birbirinden <strong>farklıdır</strong>. A programında <em>genel</em> kapsamda
bir <code>foo</code> değişkeni tanımlanmıştır, B programındaki <code>foo</code> değişkeni ise <em>mevcut</em>
kapsamda tanımlanmıştır.</p>
<p>Bu iki tanımlamanın birbirinden <strong>farklı</strong> <em>etkileri</em> olacaktır, <code>var</code> anahtar
kelimesini kullanmamanın önemli sonuçları olabilir.</p>
<pre><code>// genel kapsam
var foo = 42;
function test() {
// lokal kapsam
foo = 21;
}
test();
foo; // 21
</code></pre>
<p><code>test</code> fonksiyonun içinde <code>var</code> anahtar kelimesinin atlanması genel kapsamdaki
<code>foo</code> değişkeninin değerini değiştirecektir. İlk bakışta bu önemsiz gibi görünse
de, binlerce satırlık bir programda <code>var</code> kullanılmaması korkunç ve takibi güç
hatalara neden olacaktır.</p>
<pre><code>// genel kapsam
var items = [/* bir dizi */];
for(var i = 0; i < 10; i++) {
subLoop();
}
function subLoop() {
// subLoop fonksiyonun kapsamı
for(i = 0; i < 10; i++) { // var kullanılmamış
// do amazing stuff!
}
}
</code></pre>
<p>Dışarıdaki döngüden <code>subLoop</code> fonksiyonu bir kez çağrıldıktan sonra çıkılacaktır,
çünkü <code>subLoop</code> <code>i</code> değişkeninin dış kapsamdaki değerini değiştirir. İkinci
<code>for</code> döngüsünde de <code>var</code> kullanılması bu hatayı kolayca engelleyecektir.
<em>Bilinçli olarak</em> dış kapsama erişilmek istenmiyorsa <code>var</code> ifadesi <strong>asla</strong>
atlanmamalıdır.</p>
</div><div><h3>Lokal değişkenler</h3>
<p>JavaScript'te lokal değişkenler sadece <a href="#function.general">fonksiyon</a>
parametreleri ve <code>var</code> ifadesi ile tanımlanan değişkenlerdir.</p>
<pre><code>// genel kapsam
var foo = 1;
var bar = 2;
var i = 2;
function test(i) {
// test fonksiyonunun lokal kapsamı
i = 5;
var foo = 3;
bar = 4;
}
test(10);
</code></pre>
<p><code>test</code> fonksiyonun içinde <code>foo</code> ve <code>i</code> lokal değişkenlerdir, <code>bar</code> değişkenine
değer atanması ise genel kapsamdaki aynı isimdeki değişkenin değerini
değiştirecektir.</p>
</div><div><h3>Yukarı taşıma</h3>
<p>JavaScript'te tanımlamalar <strong>yukarı taşınır</strong>. Yani hem <code>var</code> ifadesi hem de
<code>function</code> bildirimleri içindeki bulundukları kapsamın en üstüne taşınırlar.</p>
<pre><code>bar();
var bar = function() {};
var someValue = 42;
test();
function test(data) {
if (false) {
goo = 1;
} else {
var goo = 2;
}
for(var i = 0; i < 100; i++) {
var e = data[i];