From 9f506be95f7f5fb9160daca3caccec4a83e708e8 Mon Sep 17 00:00:00 2001 From: Dmitry Scriptin Date: Sun, 27 Mar 2011 00:37:00 +0300 Subject: [PATCH 001/463] added empty article about delete operator (EN) --- doc/en/core/delete.md | 0 doc/en/index.json | 3 ++- 2 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 doc/en/core/delete.md diff --git a/doc/en/core/delete.md b/doc/en/core/delete.md new file mode 100644 index 00000000..e69de29b diff --git a/doc/en/index.json b/doc/en/index.json index d4e52883..0c078397 100644 --- a/doc/en/index.json +++ b/doc/en/index.json @@ -59,7 +59,8 @@ "articles": [ "eval", "undefined", - "semicolon" + "semicolon", + "delete" ] }, { From bd0f12a7e39d45d314454e3fcbb23213b09c0735 Mon Sep 17 00:00:00 2001 From: Dmitry Scriptin Date: Sun, 27 Mar 2011 03:02:29 +0400 Subject: [PATCH 002/463] added content to operator article --- doc/en/core/delete.md | 87 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 87 insertions(+) diff --git a/doc/en/core/delete.md b/doc/en/core/delete.md index e69de29b..37a12816 100644 --- a/doc/en/core/delete.md +++ b/doc/en/core/delete.md @@ -0,0 +1,87 @@ +## The `delete` Operator + +In short, it's *impossible* to delete global variables, functions and some other +stuff in JavaScript which have a `DontDelete` attribute set. + +### Global code and Function code + +When a variable or a function is defined in a global +or a [function scope](#function.scopes) it is a property of either +Activation object or Global object. Such properties have a set of attributes, +one of these is `DontDelete`. Variable and function declarations in global +and function code always create properties with `DontDelete`, therefore +cannot be deleted. + + // global variable: + var a = 1; // DontDelete is set + delete a; // false + a; // 1 + + // normal function: + function f() {} // DontDelete is set + delete f; // false + typeof f; // "function" + + // reassigning doesn't help: + f = 1; + delete f; // false + f; // 1 + +### Explicit properties + +There are things which can be deleted normally: these are explicitly set +properties. + + // explicitly set property: + var obj = {x: 1}; + obj.y = 2; + delete obj.x; // true + delete obj.y; // true + obj.x; // undefined + obj.y; // undefined + +In the example above `obj.x` and `obj.y` can be deleted because they have no +`DontDelete` atribute. That's why an example below works too. + + // this works fine, except for IE: + var GLOBAL_OBJECT = this; + GLOBAL_OBJECT.a = 1; + a === GLOBAL_OBJECT.a; // true - just a global var + delete GLOBAL_OBJECT.a; // true + GLOBAL_OBJECT.a; // undefined + +Here we use a trick to delete `a`. [`this`](#function.this) here refers +to the Global object and we explicitly declare variable `a` as it's property +which allows us to delete it. + +IE (at least 6-8) has some bugs, so code above doesn't work. + +### Function arguments and built-ins + +Functions' normal arguments, [`arguments` object](#function.arguments) +and built-in properties also have `DontDelete` set. + + // function arguments and properties: + (function (x) { + + delete arguments; // false + typeof arguments; // "object" + + delete x; // false + x; // 1 + + function f(){} + delete f.length; // false + typeof f.length; // "number" + + })(1); + +### Host objects + +Behaviour of `delete` operator can be unpredictable for hosted objects. Due to +specification, host objects are allowed to implement any kind of behavior. + +### In conclusion + +`delete` operator often has an unexpected behaviour and can be safely used +only for dealing with explicitly set properties on normal objects. From b089bc821bf7ce94e3b5a6435028d2c30a50ec0d Mon Sep 17 00:00:00 2001 From: oozcitak Date: Tue, 26 Apr 2011 01:11:24 +0300 Subject: [PATCH 003/463] Merged intro. --- doc/tr/index.json | 6 +----- doc/tr/intro/index.md | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 5 deletions(-) diff --git a/doc/tr/index.json b/doc/tr/index.json index 36a94b8d..e6654186 100644 --- a/doc/tr/index.json +++ b/doc/tr/index.json @@ -6,11 +6,7 @@ { "title": "Giriş", "dir": "intro", - "articles": [ - "authors", - "contributors", - "license" - ] + "articles": [] }, { "title": "Nesneler", diff --git a/doc/tr/intro/index.md b/doc/tr/intro/index.md index 303ef891..f747fd0f 100644 --- a/doc/tr/intro/index.md +++ b/doc/tr/intro/index.md @@ -11,5 +11,38 @@ anlatılan konuları anlamak için JavaScript dilini önceden biliyor olmanız istiyorsanız, lütfen Mozilla Programcı Ağı'nda bulunan mükemmel [rehbere][1] başvurun. +## Yazarlar + +Bu rehber, sevimli birer [Stack Overflow][2] kullanıcısı olan [Ivo Wetzel][3] (Yazım) +ve [Zhang Yi Jiang][4] (Tasarım) tarafından hazırlanmıştır. + +## Katkıda Bulunanlar + + - [Caio Romão][5] (Yazım düzeltmeleri) + - [Andreas Blixt][6] (Dil düzeltmeleri) + +## Hosting +JavaScript Garden'a GitHub üzerinden, ve ayrıca [Cramer Development][7] +tarafından desteklenen [JavaScriptGarden.info][8] adresinden ulaşılabilir. + +## Lisans + +JavaScript Garden [MIT lisansı][9] altında yayınlanmıştır ve [GitHub][10] +üzerinde bulunmaktadır. Eğer rehberde yanlışlıklar veya yazım hatalarına +rastlarsanız lütfen [sorunu bize bildirin][11] veya bir `pull request` gönderin. +Bizi ayrıca Stack Overflow'da [JavaScript sohbet odasında][12] da +bulabilirsiniz. + [1]: https://developer.mozilla.org/en/JavaScript/Guide +[2]: http://stackoverflow.com/ +[3]: http://stackoverflow.com/users/170224/ivo-wetzel +[4]: http://stackoverflow.com/users/313758/yi-jiang +[5]: https://github.com/caio +[6]: https://github.com/blixt +[7]: http://cramerdev.com/ +[8]: http://javascriptgarden.info/ +[9]: https://github.com/BonsaiDen/JavaScript-Garden/blob/next/LICENSE +[10]: https://github.com/BonsaiDen/JavaScript-Garden +[11]: https://github.com/BonsaiDen/JavaScript-Garden/issues +[12]: http://chat.stackoverflow.com/rooms/17/javascript From 95397b5e192643d6971b7e8fe0e8bef312b9d31a Mon Sep 17 00:00:00 2001 From: oozcitak Date: Tue, 26 Apr 2011 01:11:32 +0300 Subject: [PATCH 004/463] Merged intro. --- doc/tr/intro/authors.md | 8 -------- doc/tr/intro/contributors.md | 8 -------- doc/tr/intro/license.md | 13 ------------- 3 files changed, 29 deletions(-) delete mode 100644 doc/tr/intro/authors.md delete mode 100644 doc/tr/intro/contributors.md delete mode 100644 doc/tr/intro/license.md diff --git a/doc/tr/intro/authors.md b/doc/tr/intro/authors.md deleted file mode 100644 index 6e53d523..00000000 --- a/doc/tr/intro/authors.md +++ /dev/null @@ -1,8 +0,0 @@ -## Yazarlar - -Bu rehber, sevimli birer Stack Overflow kullanıcısı olan [Ivo Wetzel][1] (Yazım) -ve [Zhang Yi Jiang][2] (Tasarım) tarafından hazırlanmıştır. - -[1]: http://stackoverflow.com/users/170224/ivo-wetzel -[2]: http://stackoverflow.com/users/313758/yi-jiang - diff --git a/doc/tr/intro/contributors.md b/doc/tr/intro/contributors.md deleted file mode 100644 index ba517abc..00000000 --- a/doc/tr/intro/contributors.md +++ /dev/null @@ -1,8 +0,0 @@ -## Katkıda Bulunanlar - - - [Caio Romão][1] (Yazım düzeltmeleri) - - [Andreas Blixt][2] (Dil düzeltmeleri) - -[1]: https://github.com/caio -[2]: https://github.com/blixt - diff --git a/doc/tr/intro/license.md b/doc/tr/intro/license.md deleted file mode 100644 index a0484d74..00000000 --- a/doc/tr/intro/license.md +++ /dev/null @@ -1,13 +0,0 @@ -## Lisans - -JavaScript Garden [MIT lisansı][1] altında yayınlanmıştır ve [GitHub][2] -üzerinde bulunmaktadır. Eğer rehberde yanlışlıklar veya yazım hatalarına -rastlarsanız lütfen [sorunu bildirin][3] veya bir `pull request` gönderin. -Bizi ayrıca Stack Overflow'da [JavaScript sohbet kanalında][4] da -bulabilirsiniz. - -[1]: https://github.com/BonsaiDen/JavaScript-Garden/blob/next/LICENSE -[2]: https://github.com/BonsaiDen/JavaScript-Garden -[3]: https://github.com/BonsaiDen/JavaScript-Garden/issues -[4]: http://chat.stackoverflow.com/rooms/17/javascript - From 69ab28a6fe8542bdca48c6d5fb113b3154749998 Mon Sep 17 00:00:00 2001 From: oozcitak Date: Tue, 26 Apr 2011 01:16:24 +0300 Subject: [PATCH 005/463] Fixes #56 in Turkish translation. --- doc/tr/object/hasownproperty.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/doc/tr/object/hasownproperty.md b/doc/tr/object/hasownproperty.md index e5eb5df0..634b3695 100644 --- a/doc/tr/object/hasownproperty.md +++ b/doc/tr/object/hasownproperty.md @@ -42,8 +42,9 @@ doğru sonuç alabilmek için `hasOwnProperty `*haricen* kullanılmalıdır. foo.hasOwnProperty('bar'); // her zaman false verir - // hasOwnProperty haricen kullanıldığında 'this' foo olur - {}.hasOwnProperty.call(foo, 'bar'); // true + // hasOwnProperty başka bir nesne üzerinde + // kullanıldığında 'this' foo olur + ({}).hasOwnProperty.call(foo, 'bar'); // true ### Sonuç From 806c9a6ffe8b45e587fea2bce9e34ed9a1b69c56 Mon Sep 17 00:00:00 2001 From: oozcitak Date: Tue, 26 Apr 2011 01:21:29 +0300 Subject: [PATCH 006/463] Same as BonsaiDen/JavaScript-Garden@c9e3df32127b663bcbacb9b8cf1eda2d4aa791e5 for Turkish translation. --- doc/tr/function/general.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/tr/function/general.md b/doc/tr/function/general.md index e45949c1..84d54801 100644 --- a/doc/tr/function/general.md +++ b/doc/tr/function/general.md @@ -29,8 +29,8 @@ Bu örnekte *isimsiz fonksiyon* `foo` değişkenine atanır. Yukarıdaki `var` anahtar kelimesi bir bildirim olduğu için `foo` değişkeni program çalışmadan önce yukarı alınır, program çalıştığında `foo` tanımlanmştır. -Fakat değer ataması program çalışırken gerçekleşeceği için, ilgili satır -çalıştığında, `foo` değişkeninin değeri varsayılan olarak +Fakat değer atamaları sadece program çalışırken gerçekleşeceği için, ilgili +satır çalıştığında, `foo` değişkeninin değeri varsayılan olarak [undefined](#core.undefined) olacaktır. ### İsimli fonksiyon ifadesi From 2c35f13507c92a6365dedb0bed273d4a4ff95206 Mon Sep 17 00:00:00 2001 From: oozcitak Date: Tue, 26 Apr 2011 01:23:36 +0300 Subject: [PATCH 007/463] Same as BonsaiDen/JavaScript-Garden@07f23c9de9a6245dd3d2986bf285d00a7072fdc8 for Turkish translation. --- doc/tr/object/general.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/tr/object/general.md b/doc/tr/object/general.md index b112a582..7cc81d7c 100644 --- a/doc/tr/object/general.md +++ b/doc/tr/object/general.md @@ -61,8 +61,8 @@ açabilecek özellik isimlerinin kullanılmasına izin vermesidir. ### Özellikleri silmek Bir nesnenin özelliklerinden birini silmenin tek yolu `delete` operatörünü -kullanmaktır; özelliğe `undefined` veya `null` değerlerini atamak **sadece** -özelliğin değerini kaldırır, anahtarı değil. +kullanmaktır; özelliğe `undefined` veya `null` değerlerini atamak sadece +özelliğin *değerini* kaldırır, *anahtarı* değil. var obj = { bar: 1, From cc5b30f9251e52c80a69667840f14dbacf886e50 Mon Sep 17 00:00:00 2001 From: oozcitak Date: Tue, 26 Apr 2011 01:28:45 +0300 Subject: [PATCH 008/463] Same as BonsaiDen/JavaScript-Garden@1b3a48104122202bb02ca451b83c2e3abd8aeaf2 for Turkish translation. --- doc/tr/other/timeouts.md | 7 +++---- doc/tr/types/equality.md | 6 +++--- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/doc/tr/other/timeouts.md b/doc/tr/other/timeouts.md index 594ba83c..5454b8e8 100644 --- a/doc/tr/other/timeouts.md +++ b/doc/tr/other/timeouts.md @@ -111,8 +111,8 @@ olarak `eval` kullanılır. > **Not:** Zamanlama fonksiyonları ECMAScript Standartında bulunmadığı için, > bir katar argümanı almaları durumundaki çalışma şekilleri JavaScript motorları -> arasında farklılık gösterebilir. Gerçekten de, Microsoft'un JScript motoru -> `eval` yerine `Function` oluşturucusunu kullanır. +> arasında farklılık gösterebilir. Mesela, Microsoft'un JScript motoru `eval` +> yerine `Function` oluşturucusunu kullanır. function foo() { // setTimeOut ile bu fonksiyon çağrılacaktır @@ -157,5 +157,4 @@ bulunduran bir *isimsiz fonksiyon* kullanılmalıdır. Ayrıca, `setInterval` fonksiyonu çalışan JavaScript programı tarafından bloke olmadığı için tercih edilmemelidir. -[1]: http://en.wikipedia.org/wiki/Document_Object_Model - +[1]: http://en.wikipedia.org/wiki/Document_Object_Model "Document Object Model" diff --git a/doc/tr/types/equality.md b/doc/tr/types/equality.md index a0d5d296..3240a54e 100644 --- a/doc/tr/types/equality.md +++ b/doc/tr/types/equality.md @@ -3,11 +3,11 @@ JavaScript'de nesnelerin değerlerinin eşitliğini kontrol etmenin iki farklı yolu vardır. -### Eşittir operatörü +### Eşitlik operatörü -Eşittir operatörü iki adet eşittir işaretinden oluşur: `==` +Eşitlik operatörü iki adet eşittir işaretinden oluşur: `==` -JavaScript *weakly typed* bir dildir, bu nedenle, eşittir operatörü ile +JavaScript *weakly typed* bir dildir. Bu nedenle, eşitlik operatörü ile değişkenleri karşılaştırırken **tip dönüşümü** yapar. "" == "0" // false From 192a1df798d436ec5a7b245f410d14941ec5c73a Mon Sep 17 00:00:00 2001 From: oozcitak Date: Tue, 26 Apr 2011 02:07:00 +0300 Subject: [PATCH 009/463] Translated hosting subsection. --- doc/tr/intro/index.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/doc/tr/intro/index.md b/doc/tr/intro/index.md index f747fd0f..e6f1fce6 100644 --- a/doc/tr/intro/index.md +++ b/doc/tr/intro/index.md @@ -21,9 +21,10 @@ ve [Zhang Yi Jiang][4] (Tasarım) tarafından hazırlanmıştır. - [Caio Romão][5] (Yazım düzeltmeleri) - [Andreas Blixt][6] (Dil düzeltmeleri) -## Hosting -JavaScript Garden'a GitHub üzerinden, ve ayrıca [Cramer Development][7] -tarafından desteklenen [JavaScriptGarden.info][8] adresinden ulaşılabilir. +## Sunum + +JavaScript Garden GitHub üzerinden, ve ayrıca [Cramer Development][7] +tarafından desteklenen [JavaScriptGarden.info][8] adresinden sunulmaktadır. ## Lisans From 53decceb1391f2e68b38a95aaf144a5d6f7c1dba Mon Sep 17 00:00:00 2001 From: MONTILLET Xavier Date: Tue, 26 Apr 2011 11:33:00 -0700 Subject: [PATCH 010/463] Added another way to clear "all" timeouts and replaced the "is is" by "it is". --- doc/en/other/timeouts.md | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/doc/en/other/timeouts.md b/doc/en/other/timeouts.md index d196a3b7..02d39ea6 100644 --- a/doc/en/other/timeouts.md +++ b/doc/en/other/timeouts.md @@ -94,8 +94,14 @@ it is necessary to use brute force in order to achieve this functionality. clearTimeout(i); } -There might still be timeouts that are unaffected by this arbitrary number; -therefore, is is instead recommended to keep track of all the timeout IDs, so +But there might still be timeouts that are unaffected by this arbitrary number. Another way of doing this is to consider that the ID given to a timeout is incremented by one everytime you call `setTimeout`. + + // clear "all" timeouts + for(var i = 1; i <= window.setTimeout(function(){}, 1); i++) { + clearTimeout(i); + } + +But even though this works on all main browsers nowadays, it isn't specified that the IDs should be ordered that way and it may change. Therefore, it is instead recommended to keep track of all the timeout IDs, so they can be cleared specifically. ### Hidden use of `eval` From 0a894c199ac7e9f77e6f3fb8463b9b2d5cd111b4 Mon Sep 17 00:00:00 2001 From: MONTILLET Xavier Date: Tue, 26 Apr 2011 14:12:47 -0700 Subject: [PATCH 011/463] Stored the biggest timeout ID to avoid infinite loop. --- doc/en/other/timeouts.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/doc/en/other/timeouts.md b/doc/en/other/timeouts.md index 02d39ea6..655fcc35 100644 --- a/doc/en/other/timeouts.md +++ b/doc/en/other/timeouts.md @@ -97,7 +97,9 @@ it is necessary to use brute force in order to achieve this functionality. But there might still be timeouts that are unaffected by this arbitrary number. Another way of doing this is to consider that the ID given to a timeout is incremented by one everytime you call `setTimeout`. // clear "all" timeouts - for(var i = 1; i <= window.setTimeout(function(){}, 1); i++) { + var biggestTimeoutId = window.setTimeout(function(){}, 1), + i; + for(i = 1; i <= biggestTimeoutId; i++) { clearTimeout(i); } From e531742c68b989e31fbe7f31ffd313c387c212d1 Mon Sep 17 00:00:00 2001 From: Adeel Ahmad Khan Date: Thu, 5 May 2011 18:59:41 -0700 Subject: [PATCH 012/463] minor --- doc/ru/intro/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/ru/intro/index.md b/doc/ru/intro/index.md index fa7c6636..9debe341 100644 --- a/doc/ru/intro/index.md +++ b/doc/ru/intro/index.md @@ -1,6 +1,6 @@ ## Вступление -**JavaScript Гарден** это постоянно обновляющаяся и растущая документация по самым заковыристым темам языка JavaScript. В ней вы найдёте советы о том, как избежать распространённых ошибок и предсказать появление тех или иных багов. В документации подробно освещены проблемы оптимизации и нерекомендуемые практики с которыми, продираясь к глубинам языка, могут столкнуться даже просвещённые JavaScript-программисты. +**JavaScript Гарден** — это постоянно обновляющаяся и растущая документация по самым заковыристым темам языка JavaScript. В ней вы найдёте советы о том, как избежать распространённых ошибок и предсказать появление тех или иных багов. В документации подробно освещены проблемы оптимизации и нерекомендуемые практики с которыми, продираясь к глубинам языка, могут столкнуться даже просвещённые JavaScript-программисты. JavaScript Гарден **не** имеет цели научить вас языку JavaScript. Вам понадобится реальный опыт работы с языком чтобы понимать темы, рассматриваемые в этом руководстве. Если вам требуется изучить основы языка, пожалуйста внимательно ознакомьтесь с замечательным [руководством][1] на сайте Mozilla Developer Network. From 5ef7ea516b63e405895f45f2e97f101a3a200901 Mon Sep 17 00:00:00 2001 From: oozcitak Date: Tue, 17 May 2011 01:17:16 +0300 Subject: [PATCH 013/463] Fixed a little typo. --- doc/tr/intro/index.md | 7 +++---- doc/tr/object/general.md | 2 +- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/doc/tr/intro/index.md b/doc/tr/intro/index.md index e6f1fce6..5c39210a 100644 --- a/doc/tr/intro/index.md +++ b/doc/tr/intro/index.md @@ -2,14 +2,13 @@ **JavaScript Garden** 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 ince hatalar ve performans +programcılarının sıkça yaptığı yanlışlar, dile has incelikler ve performans sorunlarına karşı tavsiyeler içerir. JavaScript Garden'ın amacı size JavaScript öğretmek **değildir**. Bu rehberde anlatılan konuları anlamak için JavaScript dilini önceden biliyor olmanız -şiddetle tavsiye edilir. Eğer JavaScript dilinin temellerini öğrenmek -istiyorsanız, lütfen Mozilla Programcı Ağı'nda bulunan mükemmel [rehbere][1] -başvurun. +gerekir. Eğer JavaScript dilinin temellerini öğrenmek istiyorsanız, lütfen +Mozilla Programcı Ağı'nda bulunan mükemmel [rehbere][1] başvurun. ## Yazarlar diff --git a/doc/tr/object/general.md b/doc/tr/object/general.md index 7cc81d7c..6107ca66 100644 --- a/doc/tr/object/general.md +++ b/doc/tr/object/general.md @@ -21,7 +21,7 @@ Bu hatayı aşıp sayı sabitlerinin de nesne olarak davranmasını sağlamak i uygulanabilecek bazı çözümler vardır. 2..toString(); // ikinci nokta doğru şekilde algılanır - 2 .toString(); // noktanın solundki boşluğa dikkat edin + 2 .toString(); // noktanın solundaki boşluğa dikkat edin (2).toString(); // ilk önce 2 değerlendirilir ### Bir veri türü olarak nesneler From 9d166aa72e08dc1cdeba8f5866c61ca976652597 Mon Sep 17 00:00:00 2001 From: Satoru HIRAKI Date: Sat, 2 Jul 2011 21:49:10 +0900 Subject: [PATCH 014/463] cp en --- doc/ja/array/constructor.md | 35 +++++ doc/ja/array/general.md | 58 ++++++++ doc/ja/core/eval.md | 48 +++++++ doc/ja/core/semicolon.md | 114 ++++++++++++++++ doc/ja/core/undefined.md | 72 ++++++++++ doc/ja/function/arguments.md | 119 ++++++++++++++++ doc/ja/function/closures.md | 98 ++++++++++++++ doc/ja/function/constructors.md | 128 ++++++++++++++++++ doc/ja/function/general.md | 48 +++++++ doc/ja/function/scopes.md | 231 ++++++++++++++++++++++++++++++++ doc/ja/function/this.md | 111 +++++++++++++++ doc/ja/index.json | 68 ++++++++++ doc/ja/intro/index.md | 47 +++++++ doc/ja/object/forinloop.md | 51 +++++++ doc/ja/object/general.md | 99 ++++++++++++++ doc/ja/object/hasownproperty.md | 53 ++++++++ doc/ja/object/prototype.md | 116 ++++++++++++++++ doc/ja/other/timeouts.md | 155 +++++++++++++++++++++ doc/ja/types/casting.md | 70 ++++++++++ doc/ja/types/equality.md | 71 ++++++++++ doc/ja/types/instanceof.md | 38 ++++++ doc/ja/types/typeof.md | 87 ++++++++++++ 22 files changed, 1917 insertions(+) create mode 100644 doc/ja/array/constructor.md create mode 100644 doc/ja/array/general.md create mode 100644 doc/ja/core/eval.md create mode 100644 doc/ja/core/semicolon.md create mode 100644 doc/ja/core/undefined.md create mode 100644 doc/ja/function/arguments.md create mode 100644 doc/ja/function/closures.md create mode 100644 doc/ja/function/constructors.md create mode 100644 doc/ja/function/general.md create mode 100644 doc/ja/function/scopes.md create mode 100644 doc/ja/function/this.md create mode 100644 doc/ja/index.json create mode 100644 doc/ja/intro/index.md create mode 100644 doc/ja/object/forinloop.md create mode 100644 doc/ja/object/general.md create mode 100644 doc/ja/object/hasownproperty.md create mode 100644 doc/ja/object/prototype.md create mode 100644 doc/ja/other/timeouts.md create mode 100644 doc/ja/types/casting.md create mode 100644 doc/ja/types/equality.md create mode 100644 doc/ja/types/instanceof.md create mode 100644 doc/ja/types/typeof.md diff --git a/doc/ja/array/constructor.md b/doc/ja/array/constructor.md new file mode 100644 index 00000000..763f55fb --- /dev/null +++ b/doc/ja/array/constructor.md @@ -0,0 +1,35 @@ +## The `Array` Constructor + +Since the `Array` constructor is ambiguous in how it deals with its parameters, +it is highly recommended to always use the array literals - `[]` notation - +when creating new arrays. + + [1, 2, 3]; // Result: [1, 2, 3] + new Array(1, 2, 3); // Result: [1, 2, 3] + + [3]; // Result: [3] + new Array(3); // Result: [] + new Array('3') // Result: ['3'] + +In cases when there is only one argument passed to the `Array` constructor, +and that argument is a `Number`, the constructor will return a new *sparse* +array with the `length` property set to the value of the argument. It should be +noted that **only** the `length` property of the new array will be set this way, +the actual indexes of the array will not be initialized. + + var arr = new Array(3); + arr[1]; // undefined + 1 in arr; // false, the index was not set + +The behavior of being able to set the length of the array upfront only comes in +handy in a few cases, like repeating a string, in which it avoids the use of a +`for loop` code. + + new Array(count + 1).join(stringToRepeat); + +### In Conclusion + +The use of the `Array` constructor should be avoided as much as possible. +Literals are definitely preferred. They are shorter and have a clearer syntax; +therefore, they also increase the readability of the code. + diff --git a/doc/ja/array/general.md b/doc/ja/array/general.md new file mode 100644 index 00000000..7c8f07ab --- /dev/null +++ b/doc/ja/array/general.md @@ -0,0 +1,58 @@ +## Array Iteration and Properties + +Although arrays in JavaScript are objects, there are no good reasons to use +the [`for in loop`](#object.forinloop) in for iteration on them. In fact there +are a number of good reasons **against** the use of `for in` on arrays. + +> **Note:** JavaScript arrays are **not** *associative arrays*. JavaScript only +> has [objects](#object.general) for mapping keys to values. And while associative +> arrays **preserve** order, objects **do not**. + +Since the `for in` loop enumerates all the properties that are on the prototype +chain and the only way to exclude those properties is to use +[`hasOwnProperty`](#object.hasownproperty), it is already up to **twenty times** +slower than a normal `for` loop. + +### Iteration + +In order to achieve the best performance when iterating over arrays, it is best +to use the classic `for` loop. + + var list = [1, 2, 3, 4, 5, ...... 100000000]; + for(var i = 0, l = list.length; i < l; i++) { + console.log(list[i]); + } + +There is one extra catch in the above example, that is the caching of the +length of the array via `l = list.length`. + +Although the `length` property is defined on the array itself, there is still an +overhead for doing the lookup on each iteration of the loop. And while recent +JavaScript engines **may** apply optimization in this case, there is no way of +telling whether the code will run on one of these newer engines or not. + +In fact, leaving out the caching may result in the loop being only **half as +fast** as with the cached length. + +### The `length` Property + +While the *getter* of the `length` property simply returns the number of +elements that are contained in the array, the *setter* can be used to +**truncate** the array. + + var foo = [1, 2, 3, 4, 5, 6]; + foo.length = 3; + foo; // [1, 2, 3] + + foo.length = 6; + foo; // [1, 2, 3] + +Assigning a smaller length does truncate the array, but increasing the length +does not have any effect on the array. + +### In Conclusion + +For the best performance it is recommended to always use the plain `for` loop +and cache the `length` property. The use of `for in` on an array is a sign of +badly written code that is prone to bugs and bad performance. + diff --git a/doc/ja/core/eval.md b/doc/ja/core/eval.md new file mode 100644 index 00000000..ecf7ba90 --- /dev/null +++ b/doc/ja/core/eval.md @@ -0,0 +1,48 @@ +## Why Not to Use `eval` + +The `eval` function will execute a string of JavaScript code in the local scope. + + var foo = 1; + function test() { + var foo = 2; + eval('foo = 3'); + return foo; + } + test(); // 3 + foo; // 1 + +But `eval` only executes in local scope when it is being called **directly** *and* +the name of the called function is actually `eval`. + + var foo = 1; + function test() { + var foo = 2; + var bar = eval; + bar('foo = 3'); + return foo; + } + test(); // 2 + foo; // 3 + +The use of `eval` should be avoided at **all costs**. 99.9% of its "uses" can be +achieved **without** it. + +### `eval` in Disguise + +The [timeout functions](#other.timeouts) `setTimeout` and `setInterval` can both +take a string as their first argument. This string will **always** get executed +in the global scope since `eval` is not being called directly in that case. + +### Security Issues + +`eval` also is a security problem as it executes **any** code given to it, +it should **never** be used with strings of unknown or untrusted origins. + +### In Conclusion + +`eval` should never be used, any code that makes use of it is to be questioned in +its workings, performance and security. In case something requires `eval` in +order to work, its design is to be questioned and should **not** be used in the +first place, a *better design* should be used, that does not require the use of +`eval`. + diff --git a/doc/ja/core/semicolon.md b/doc/ja/core/semicolon.md new file mode 100644 index 00000000..61d74fd9 --- /dev/null +++ b/doc/ja/core/semicolon.md @@ -0,0 +1,114 @@ +## Automatic Semicolon Insertion + +Although JavaScript has C style syntax, it does **not** enforce the use of +semicolons in the source code, it is possible to omit them. + +But JavaScript is not a semicolon-less language, it in fact needs the +semicolons in order to understand the source code. Therefore the JavaScript +parser **automatically** inserts them whenever it encounters a parse +error due to a missing semicolon. + + var foo = function() { + } // parse error, semicolon expected + test() + +Insertion happens, and the parser tries again. + + var foo = function() { + }; // no error, parser continues + test() + +The automatic insertion of semicolon is considered to be one of **biggest** +design flaws in the language, as it *can* change the behavior of code. + +### How it Works + +The code below has no semicolons in it, so it is up to the parser to decide where +to insert them. + + (function(window, undefined) { + function test(options) { + log('testing!') + + (options.list || []).forEach(function(i) { + + }) + + options.value.test( + 'long string to pass here', + 'and another long string to pass' + ) + + return + { + foo: function() {} + } + } + window.test = test + + })(window) + + (function(window) { + window.someLibrary = {} + + })(window) + +Below is the result of the parser's "guessing" game. + + (function(window, undefined) { + function test(options) { + + // Not inserted, lines got merged + log('testing!')(options.list || []).forEach(function(i) { + + }); // <- inserted + + options.value.test( + 'long string to pass here', + 'and another long string to pass' + ); // <- inserted + + return; // <- inserted, breaks the return statement + { // treated as a block + + // a label and a single expression statement + foo: function() {} + }; // <- inserted + } + window.test = test; // <- inserted + + // The lines got merged again + })(window)(function(window) { + window.someLibrary = {}; // <- inserted + + })(window); //<- inserted + +> **Note:** The JavaScript parser does not "correctly" handle return statements +> which are followed by a new line, while this is not neccessarily the fault of +> the automatic semicolon insertion, it can still be an unwanted side-effect. + +The parser drastically changed the behavior of the code above, in certain cases +it does the **wrong thing**. + +### Leading Parenthesis + +In case of a leading parenthesis, the parser will **not** insert a semicolon. + + log('testing!') + (options.list || []).forEach(function(i) {}) + +This code gets transformed into one line. + + log('testing!')(options.list || []).forEach(function(i) {}) + +Chances are **very** high that `log` does **not** return a function; therefore, +the above will yield a `TypeError` stating that `undefined is not a function`. + +### In Conclusion + +It is highly recommended to **never** omit semicolons, it is also advocated to +keep braces on the same line with their corresponding statements and to never omit +them for one single-line `if` / `else` statements. Both of these measures will +not only improve the consistency of the code, they will also prevent the +JavaScript parser from changing its behavior. + diff --git a/doc/ja/core/undefined.md b/doc/ja/core/undefined.md new file mode 100644 index 00000000..b29da3b4 --- /dev/null +++ b/doc/ja/core/undefined.md @@ -0,0 +1,72 @@ +## `undefined` and `null` + +JavaScript has two distinct values for `nothing`, the more useful of these two +being `undefined`. + +### The Value `undefined` + +`undefined` is a type with exactly one value: `undefined`. + +The language also defines a global variable that has the value of `undefined`, +this variable is also called `undefined`. But this variable is **not** a constant, +nor is it a keyword of the language. This means that its *value* can be easily +overwritten. + +> **ES5 Note:** `undefined` in ECMAScript 5 is **no longer** *writable* in strict +> mode, but its name can still be shadowed by for example a function with the name +> `undefined`. + +Some examples for when the value `undefined` is returned: + + - Accessing the (unmodified) global variable `undefined`. + - Implicit returns of functions due to missing `return` statements. + - `return` statements which do not explicitly return anything. + - Lookups of non-existent properties. + - Function parameters which do not had any explicit value passed. + - Anything that has been set to the value of `undefined`. + +### Handling Changes to the Value of `undefined` + +Since the global variable `undefined` only holds a copy of the actual *value* of +`undefined`, assigning a new value to it does **not** change the value of the +*type* `undefined`. + +Still, in order to compare something against the value of `undefined` it is +necessary to retrieve the value of `undefined` first. + +In order to protect code against a possible overwritten `undefined` variable, a +common technique used is to add an additional parameter to an +[anonymous wrapper](#function.scopes), that gets no argument passed to it. + + var undefined = 123; + (function(something, foo, undefined) { + // undefined in the local scope does + // now again refer to the value + + })('Hello World', 42); + +Another way to achieve the same effect would be to use a declaration inside the +wrapper. + + var undefined = 123; + (function(something, foo) { + var undefined; + ... + + })('Hello World', 42); + +The only difference being here, that this version results in 4 more bytes being +used in case it is minified and there is no other `var` statement inside the +anonymous wrapper. + +### Uses of `null` + +While `undefined` in the context of the JavaScript language is mostly used in +the sense of a traditional *null*, the actual `null` (both a literal and a type) +is more or less just another data type. + +It is used in some JavaScript internals (like declaring the end of the +prototype chain by setting `Foo.prototype = null`), but in almost all cases it +can be replaced by `undefined`. + + diff --git a/doc/ja/function/arguments.md b/doc/ja/function/arguments.md new file mode 100644 index 00000000..3d551ad5 --- /dev/null +++ b/doc/ja/function/arguments.md @@ -0,0 +1,119 @@ +## The `arguments` Object + +Every function scope in JavaScript can access the special variable `arguments`. +This variable holds a list of all the arguments that were passed to the function. + +> **Note:** In case `arguments` has already been defined inside the function's +> scope either via a `var` statement or being the name of a formal parameter, +> the `arguments` object will not be created. + +The `arguments` object is **not** an `Array`. While it has some of the +semantics of an array - namely the `length` property - it does not inherit from +`Array.prototype` and is in fact an `Object`. + +Due to this, it is **not** possible to use standard array methods like `push`, +`pop` or `slice` on `arguments`. While iteration with a plain `for` loop works +just fine, it is necessary to convert it to a real `Array` in order to use the +standard `Array` methods on it. + +### Converting to an Array + +The code below will return a new `Array` containing all the elements of the +`arguments` object. + + Array.prototype.slice.call(arguments); + +This conversion is **slow**, it is **not recommended** to use it in performance +critical sections of code. + +### Passing Arguments + +The following is the recommended way of passing arguments from one function to +another. + + function foo() { + bar.apply(null, arguments); + } + function bar(a, b, c) { + // do stuff here + } + +Another trick is to use both `call` and `apply` together to create fast, unbound +wrappers. + + function Foo() {} + + Foo.prototype.method = function(a, b, c) { + console.log(this, a, b, c); + }; + + // Create an unbound version of "method" + // It takes the parameters: this, arg1, arg2...argN + Foo.method = function() { + + // Result: Foo.prototype.method.call(this, arg1, arg2... argN) + Function.call.apply(Foo.prototype.method, arguments); + }; + + +### Formal Parameters and Arguments Indices + +The `arguments` object creates *getter* and *setter* functions for both its +properties as well as the function's formal parameters. + +As a result, changing the value of a formal parameter will also change the value +of the corresponding property on the `arguments` object, and the other way around. + + 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); + +### Performance Myths and Truths + +The `arguments` object is always created with the only two exceptions being the +cases where it is declared as a name inside of a function or one of its formal +parameters. It does not matter whether it is used or not. + +Both *getters* and *setters* are **always** created; thus, using it has nearly +no performance impact at all, especially not in real world code where there is +more than a simple access to the `arguments` object's properties. + +> **ES5 Note:** These *getters* and *setters* are not created in strict mode. + +However, there is one case which will drastically reduce the performance in +modern JavaScript engines. That case is the use of `arguments.callee`. + + function foo() { + arguments.callee; // do something with this function object + arguments.callee.caller; // and the calling function object + } + + function bigLoop() { + for(var i = 0; i < 100000; i++) { + foo(); // Would normally be inlined... + } + } + +In the above code, `foo` can no longer be a subject to [inlining][1] since it +needs to know about both itself and its caller. This not only defeats possible +performance gains that would arise from inlining, it also breaks encapsulation +since the function may now be dependent on a specific calling context. + +It is **highly recommended** to **never** make use of `arguments.callee` or any of +its properties. + +> **ES5 Note:** In strict mode, `arguments.callee` will throw a `TypeError` since +> its use has been deprecated. + +[1]: http://en.wikipedia.org/wiki/Inlining + + diff --git a/doc/ja/function/closures.md b/doc/ja/function/closures.md new file mode 100644 index 00000000..17554dcb --- /dev/null +++ b/doc/ja/function/closures.md @@ -0,0 +1,98 @@ +## Closures and References + +One of JavaScript's most powerful features is the availability of *closures*, +this means that scopes **always** keep access to the outer scope they were +defined in. Since the only scoping that JavaScript has is +[function scope](#function.scopes), all functions, by default, act as closures. + +### Emulating private variables + + function Counter(start) { + var count = start; + return { + increment: function() { + count++; + }, + + get: function() { + return count; + } + } + } + + var foo = Counter(4); + foo.increment(); + foo.get(); // 5 + +Here, `Counter` returns **two** closures. The function `increment` as well as +the function `get`. Both of these functions keep a **reference** to the scope of +`Counter` and, therefore, always keep access to the `count` variable that was +defined in that very scope. + +### Why Private Variables Work + +Since it is not possible to reference or assign scopes in JavaScript, there is +**no** way of accessing the variable `count` from the outside. The only way to +interact with it is via the two closures. + + var foo = new Counter(4); + foo.hack = function() { + count = 1337; + }; + +The above code will **not** change the variable `count` in the scope of `Counter`, +since `foo.hack` was not defined in **that** scope. It will instead create - or +override - the *global* variable `count`. + +### Closures Inside Loops + +One often made mistake is to use closures inside of loops, as if they were +copying the value of the loops index variable. + + for(var i = 0; i < 10; i++) { + setTimeout(function() { + console.log(i); + }, 1000); + } + +The above will **not** output the numbers `0` through `9`, but will simply print +the number `10` ten times. + +The *anonymous* function keeps a **reference** to `i` and at the time +`console.log` gets called, the `for loop` has already finished and the value of +`i` as been set to `10`. + +In order to get the desired behavior, it is necessary to create a **copy** of +the value of `i`. + +### Avoiding the Reference Problem + +In order to copy the value of the loop's index variable, it is best to use an +[anonymous wrapper](#function.scopes). + + for(var i = 0; i < 10; i++) { + (function(e) { + setTimeout(function() { + console.log(e); + }, 1000); + })(i); + } + +The anonymous outer function gets called immediately with `i` as its first +argument and will receive a copy of the **value** of `i` as its parameter `e`. + +The anonymous function that gets passed to `setTimeout` now has a reference to +`e`, whose value does **not** get changed by the loop. + +There is another possible way of achieving this; that is to return a function +from the anonymous wrapper, that will then have the same behavior as the code +above. + + for(var i = 0; i < 10; i++) { + setTimeout((function(e) { + return function() { + console.log(e); + } + })(i), 1000) + } + diff --git a/doc/ja/function/constructors.md b/doc/ja/function/constructors.md new file mode 100644 index 00000000..ad90b028 --- /dev/null +++ b/doc/ja/function/constructors.md @@ -0,0 +1,128 @@ +## Constructors + +Constructors in JavaScript are yet again different from many other languages. Any +function call that is preceded by the `new` keyword acts as a constructor. + +Inside the constructor - the called function - the value of `this` refers to a +newly created `Object`. The [`prototype`](#object.prototype) of this **new** +object is set to the `prototype` of the function object that was invoked as the +constructor. + +If the function that was called has no explicit `return` statement, then it +implicitly returns the value of `this` - the new object. + + function Foo() { + this.bla = 1; + } + + Foo.prototype.test = function() { + console.log(this.bla); + }; + + var test = new Foo(); + +The above calls `Foo` as constructor and sets the `prototype` of the newly +created object to `Foo.prototype`. + +In case of an explicit `return` statement the function returns the value +specified that statement, **but only** if the return value is an `Object`. + + function Bar() { + return 2; + } + new Bar(); // a new object + + function Test() { + this.value = 2; + + return { + foo: 1 + }; + } + new Test(); // the returned object + +When the `new` keyword is omitted, the function will **not** return a new object. + + function Foo() { + this.bla = 1; // gets set on the global object + } + Foo(); // undefined + +While the above example might still appear to work in some cases, due to the +workings of [`this`](#function.this) in JavaScript, it will use the +*global object* as the value of `this`. + +### Factories + +In order to be able to omit the `new` keyword, the constructor function has to +explicitly return a value. + + function Bar() { + var value = 1; + return { + method: function() { + return value; + } + } + } + Bar.prototype = { + foo: function() {} + }; + + new Bar(); + Bar(); + +Both calls to `Bar` return the exact same thing, a newly create object which +has a property called `method` on it, that is a +[Closure](#function.closures). + +It is also to note that the call `new Bar()` does **not** affect the prototype +of the returned object. While the prototype will be set on the newly created +object, `Bar` never returns that new object. + +In the above example, there is no functional difference between using and +not using the `new` keyword. + + +### Creating New Objects via Factories + +An often made recommendation is to **not** use `new` since forgetting its use +may lead to bugs. + +In order to create new object, one should rather use a factory and construct a +new object inside of that factory. + + function Foo() { + var obj = {}; + obj.value = 'blub'; + + var private = 2; + obj.someMethod = function(value) { + this.value = value; + } + + obj.getPrivate = function() { + return private; + } + return obj; + } + +While the above is robust against a missing `new` keyword and certainly makes +the use of [private variables](#function.closures) easier, it comes with some +downsides. + + 1. It uses more memory since the created objects do **not** share the methods + on a prototype. + 2. In order to inherit the factory needs to copy all the methods from another + object or put that object on the prototype of the new object. + 3. Dropping the prototype chain just because of a left out `new` keyword + somehow goes against the spirit of the language. + +### In Conclusion + +While omitting the `new` keyword might lead to bugs, it is certainly **not** a +reason to drop the use of prototypes altogether. In the end it comes down to +which solution is better suited for the needs of the application, it is +especially important to choose a specific style of object creation **and stick** +with it. + diff --git a/doc/ja/function/general.md b/doc/ja/function/general.md new file mode 100644 index 00000000..64c9e0c9 --- /dev/null +++ b/doc/ja/function/general.md @@ -0,0 +1,48 @@ +## Function Declarations and Expressions + +Functions in JavaScript are first class objects. That means they can be +passed around like any other value. One common use of this feature is to pass +an *anonymous function* as a callback to another, possibly asynchronous function. + +### The `function` Declaration + + function foo() {} + +The above function gets [hoisted](#function.scopes) before the execution of the +program starts; thus, it is available *everywhere* in the scope it was *defined* +in, even if called before the actual definition in the source. + + foo(); // Works because foo was created before this code runs + function foo() {} + +### The `function` Expression + + var foo = function() {}; + +This example assigns the unnamed and *anonymous* function to the variable `foo`. + + foo; // 'undefined' + foo(); // this raises a TypeError + var foo = function() {}; + +Due to the fact that `var` is a declaration, that hoists the variable name `foo` +before the actual execution of the code starts, `foo` is already defined when +the script gets executed. + +But since assignments only happen at runtime, the value of `foo` will default +to [undefined](#core.undefined) before the corresponding code is executed. + +### Named Function Expression + +Another special case is the assignment of named functions. + + var foo = function bar() { + bar(); // Works + } + bar(); // ReferenceError + +Here `bar` is not available in the outer scope, since the function only gets +assigned to `foo`; however, inside of `bar` it is available. This is due to +how [name resolution](#function.scopes) in JavaScript works, the name of the +function is *always* made available in the local scope of the function itself. + diff --git a/doc/ja/function/scopes.md b/doc/ja/function/scopes.md new file mode 100644 index 00000000..7ae5e4f5 --- /dev/null +++ b/doc/ja/function/scopes.md @@ -0,0 +1,231 @@ +## Scopes and Namespaces + +Although JavaScript deals fine with the syntax of two matching curly +braces for blocks, it does **not** support block scope; hence, all that is left +is in the language is *function scope*. + + function test() { // a scope + for(var i = 0; i < 10; i++) { // not a scope + // count + } + console.log(i); // 10 + } + +> **Note:** When not used in an assignment, return statement or as a function +> argument, the `{...}` notation will get interpreted as a block statement and +> **not** as an object literal. This, in conjunction with +> [automatic insertion of semicolons](#core.semicolon), can lead to subtle errors. + +There are also no distinct namespaces in JavaScript, that means that everything +gets defined in one *globally shared* namespace. + +Each time a variable is referenced, JavaScript will traverse upwards through all +the scopes until it finds it. In the case that it reaches the global scope and +still has not found the requested name, it will raise a `ReferenceError`. + +### The Bane of Global Variables + + // script A + foo = '42'; + + // script B + var foo = '42' + +The above two scripts do **not** have the same effect. Script A defines a +variable called `foo` in the *global* scope and script B defines a `foo` in the +*current* scope. + +Again, that is **not** at all the *same effect*, not using `var` can have major +implications. + + // global scope + var foo = 42; + function test() { + // local scope + foo = 21; + } + test(); + foo; // 21 + +Leaving out the `var` statement inside the function `test` will override the +value of `foo`. While this might not seem like a big deal at first, having +thousands of lines of JavaScript and not using `var` will introduce horrible and +hard to track down bugs. + + // global scope + var items = [/* some list */]; + for(var i = 0; i < 10; i++) { + subLoop(); + } + + function subLoop() { + // scope of subLoop + for(i = 0; i < 10; i++) { // missing var statement + // do amazing stuff! + } + } + +The outer loop will terminate after the first call to `subLoop`, since `subLoop` +overwrites the global value of `i`. Using a `var` for the second `for` loop would +have easily avoided this error. The `var` statement should **never** be left out +unless the *desired effect* is to affect the outer scope. + +### Local Variables + +The only source for local variables in JavaScript are +[function](#function.general) parameters and variables that were declared via the +`var` statement. + + // global scope + var foo = 1; + var bar = 2; + var i = 2; + + function test(i) { + // local scope of the function test + i = 5; + + var foo = 3; + bar = 4; + } + test(10); + +While `foo` and `i` are local variables inside the scope of the function `test`, +the assignment of `bar` will override the global variable with the same name. + +### Hoisting + +JavaScript **hoists** declarations. This means that both `var` statements and +`function` declarations will be moved to the top of their enclosing scope. + + 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]; + } + } + +The above code gets transformed before any execution is started. JavaScript moves +the `var` statements as well as the `function` declarations to the top of the +nearest surrounding scope. + + // var statements got moved here + var bar, someValue; // default to 'undefined' + + // the function declartion got moved up too + function test(data) { + var goo, i, e; // missing block scope moves these here + if (false) { + goo = 1; + + } else { + goo = 2; + } + for(i = 0; i < 100; i++) { + e = data[i]; + } + } + + bar(); // fails with a TypeError since bar is still 'undefined' + someValue = 42; // assignments are not affected by hoisting + bar = function() {}; + + test(); + +Missing block scoping will not only move `var` statements out of loops and +their bodies, it will also make the results of certain `if` constructs +non-intuitive. + +In the original code the `if` statement seemed to modify the *global +variable* `goo`, while actually it modifies the *local variable* - after hoisting +has been applied. + +Without the knowledge about *hoisting*, below code might seem to raise a +`ReferenceError`. + + // check whether SomeImportantThing has been initiliazed + if (!SomeImportantThing) { + var SomeImportantThing = {}; + } + +But of course, the above works due to the fact that the `var` statement is being +moved to the top of the *global scope*. + + var SomeImportantThing; + + // other code might initiliaze SomeImportantThing here, or not + + // make sure it's there + if (!SomeImportantThing) { + SomeImportantThing = {}; + } + +### Name Resolution Order + +All scopes in JavaScript, including the *global scope*, have the special name +[`this`](#function.this) defined in them, which refers to the *current object*. + +Function scopes also have the name [`arguments`](#function.arguments) defined in +them which contains the arguments that were passed to a function. + +For example, when trying to access a variable named `foo` inside the scope of a +function, JavaScript will lookup the name in the following order: + + 1. In case there is a `var foo` statement in the current scope use that. + 2. If one of the function parameters is named `foo` use that. + 3. If the function itself is called `foo` use that. + 4. Go to the next outer scope and start with **#1** again. + +> **Note:** Having a parameter called `arguments` will **prevent** the creation +> of the default `arguments` object. + +### Namespaces + +A common problem of having only one global namespace is the likeliness of running +into problems where variable names clash. In JavaScript, this problem can +easily be avoided with the help of *anonymous wrappers*. + + (function() { + // a self contained "namespace" + + window.foo = function() { + // an exposed closure + }; + + })(); // execute the function immediately + + +Unnamed functions are considered [expressions](#function.general); so in order to +being callable, they must first be evaluated. + + ( // evaluate the function inside the paranthesis + function() {} + ) // and return the function object + () // call the result of the evaluation + +There are other ways for evaluating and calling the function expression; which, +while different in syntax, do behave the exact same way. + + // Two other ways + +function(){}(); + (function(){}()); + +### In Conclusion + +It is recommended to always use an *anonymous wrapper* for encapsulating code in +its own namespace. This does not only protect code against name clashes, it +also allows for better modularization of programs. + +Additionally, the use of global variables is considered **bad practice**. **Any** +use of them indicates badly written code that is prone to errors and hard to maintain. + diff --git a/doc/ja/function/this.md b/doc/ja/function/this.md new file mode 100644 index 00000000..85b11f0f --- /dev/null +++ b/doc/ja/function/this.md @@ -0,0 +1,111 @@ +## How `this` Works + +JavaScript has a different concept of what the special name `this` refers to +than most other programming languages do. There are exactly **five** different +ways in which the value of `this` can be bound in the language. + +### The Global Scope + + this; + +When using `this` in global scope, it will simply refer to the *global* object. + + +### Calling a Function + + foo(); + +Here `this` will again refer to the *global* object. + +> **ES5 Note:** In strict mode, the global case **no longer** exists. +> `this` will instead have the value of `undefined` in that case. + +### Calling a Method + + test.foo(); + +In this example `this` will refer to `test`. + +### Calling a Constructor + + new foo(); + +A function call that is preceded by the `new` keyword acts as +a [constructor](#function.constructors). Inside the function `this` will refer +to a *newly created* `Object`. + +### Explicit Setting of `this` + + function foo(a, b, c) {} + + var bar = {}; + foo.apply(bar, [1, 2, 3]); // array will expand to the below + foo.call(bar, 1, 2, 3); // results in a = 1, b = 2, c = 3 + +When using the `call` or `apply` methods of `Function.prototype`, the value of +`this` inside the called function gets **explicitly set** to the first argument +of the corresponding function call. + +As a result, the above example the *method case* does **not** apply, and `this` +inside of `foo` will be set to `bar`. + +> **Note:** `this` **cannot** be used to refer to the object inside of an `Object` +> literal. So `var obj = {me: this}` will **not** result in `me` referring to +> `obj`, since `this` only gets bound by one of the five listed cases. + +### Common Pitfalls + +While most of these cases make sense, the first one is to be considered another +mis-design of the language, as it **never** has any practical use. + + Foo.method = function() { + function test() { + // this is set to the global object + } + test(); + } + +A common misconception is that `this` inside of `test` refers to `Foo`, while in +fact it **does not**. + +In order to gain access to `Foo` from within `test` it is necessary to create a +local variable inside of `method` which refers to `Foo`. + + Foo.method = function() { + var that = this; + function test() { + // Use that instead of this here + } + test(); + } + +`that` is just a normal variable name, but it is commonly used for the reference to an +outer `this`. In combination with [closures](#function.closures), it can also +be used to pass `this` values around. + +### Assigning Methods + +Another thing that does **not** work in JavaScript is function aliasing, that is, +**assigning** a method to a variable. + + var test = someObject.methodTest; + test(); + +Due to the first case `test` now acts like a plain function call; therefore, +`this` inside it will no longer refer to `someObject`. + +While the late binding of `this` might seem like a bad idea at first, it is in +fact what makes [prototypal inheritance](#object.prototype) work. + + function Foo() {} + Foo.prototype.method = function() {}; + + function Bar() {} + Bar.prototype = Foo.prototype; + + new Bar().method(); + +When `method` gets called on a instance of `Bar`, `this` will now refer to that +very instance. + + diff --git a/doc/ja/index.json b/doc/ja/index.json new file mode 100644 index 00000000..d4012ed9 --- /dev/null +++ b/doc/ja/index.json @@ -0,0 +1,68 @@ +{ + "title": "JavaScript Garden", + "langTitle": "JavaScript Garden in English", + "description": "A Guide to JavaScript's Quirks and Flaws.", + "sections": [ + { + "title": "Intro", + "dir": "intro", + "articles": [] + }, + { + "title": "Objects", + "dir": "object", + "articles": [ + "general", + "prototype", + "hasownproperty", + "forinloop" + ] + }, + { + "title": "Functions", + "dir": "function", + "articles": [ + "general", + "this", + "closures", + "arguments", + "constructors", + "scopes" + ] + }, + { + "title": "Arrays", + "dir": "array", + "articles": [ + "general", + "constructor" + ] + }, + { + "title": "Types", + "dir": "types", + "articles": [ + "equality", + "typeof", + "instanceof", + "casting" + ] + }, + { + "title": "Core", + "dir": "core", + "articles": [ + "eval", + "undefined", + "semicolon" + ] + }, + { + "title": "Other", + "dir": "other", + "articles": [ + "timeouts" + ] + } + ] +} diff --git a/doc/ja/intro/index.md b/doc/ja/intro/index.md new file mode 100644 index 00000000..6ddd7c71 --- /dev/null +++ b/doc/ja/intro/index.md @@ -0,0 +1,47 @@ +## Intro + +**JavaScript Garden** is a growing collection of documentation about the most +quirky parts of the JavaScript programming language. It gives advice to +avoid common mistakes, subtle bugs, as well as performance issues and bad +practices that non-expert JavaScript programmers may encounter on their +endeavours into the depths of the language. + +JavaScript Garden does **not** aim to teach you JavaScript. Former knowledge +of the language is strongly recommended in order to understand the topics covered +in this guide. In order to learn the basics of the language, please head over to +the excellent [guide][1] on the Mozilla Developer Network. + +## The Authors + +This guide is the work of two lovely [Stack Overflow][2] users, [Ivo Wetzel][3] +(Writing) and [Zhang Yi Jiang][4] (Design). + +## Contributors + + - [Caio Romão][5] (Spelling corrections) + - [Andreas Blixt][6] (Language corrections) + +## Hosting + +JavaScript Garden is hosted on GitHub, but [Cramer Development][7] supports us +with a mirror at [JavaScriptGarden.info][8]. + +## License + +JavaScript Garden is published under the [MIT license][9] and hosted on +[GitHub][10]. If you find errors or typos please [file an issue][11] or a pull +request on the repository. You can also find us in the [JavaScript room][12] on +Stack Overflow chat. + +[1]: https://developer.mozilla.org/en/JavaScript/Guide +[2]: http://stackoverflow.com/ +[3]: http://stackoverflow.com/users/170224/ivo-wetzel +[4]: http://stackoverflow.com/users/313758/yi-jiang +[5]: https://github.com/caio +[6]: https://github.com/blixt +[7]: http://cramerdev.com/ +[8]: http://javascriptgarden.info/ +[9]: https://github.com/BonsaiDen/JavaScript-Garden/blob/next/LICENSE +[10]: https://github.com/BonsaiDen/JavaScript-Garden +[11]: https://github.com/BonsaiDen/JavaScript-Garden/issues +[12]: http://chat.stackoverflow.com/rooms/17/javascript diff --git a/doc/ja/object/forinloop.md b/doc/ja/object/forinloop.md new file mode 100644 index 00000000..30751ed9 --- /dev/null +++ b/doc/ja/object/forinloop.md @@ -0,0 +1,51 @@ +## The `for in` Loop + +Just like the `in` operator, the `for in` loop also traverses the prototype +chain when iterating over the properties of an object. + +> **Note:** The `for in` loop will **not** iterate over any properties that +> have their `enumerable` attribute set to `false`; for example, the `length` +> property of an array. + + // Poisoning Object.prototype + Object.prototype.bar = 1; + + var foo = {moo: 2}; + for(var i in foo) { + console.log(i); // prints both bar and moo + } + +Since it is not possible to change the behavior of the `for in` loop itself, it +is necessary to filter out the unwanted properties inside the loop body , +this is done by using the [`hasOwnProperty`](#object.hasownproperty) method of +`Object.prototype`. + +> **Note:** Since the `for in` always traverses the complete prototype chain, it +> will get slower with each additional layer of inheritance added to an object. + +### Using `hasOwnProperty` for Filtering + + // still the foo from above + for(var i in foo) { + if (foo.hasOwnProperty(i)) { + console.log(i); + } + } + +This version is the only correct one to use. Due to the use of `hasOwnProperty` it +will **only** print out `moo`. When `hasOwnProperty` is left out, the code is +prone to errors in cases where the native prototypes - e.g. `Object.prototype` - +have been extended. + +One widely used framework which does this is [Prototype][1]. When this +framework is included, `for in` loops that do not use `hasOwnProperty` are +guaranteed to break. + +### In Conclusion + +It is recommended to **always** use `hasOwnProperty`. Never should any +assumptions be made about the environment the code is running in, or whether the +native prototypes have been extended or not. + +[1]: http://www.prototypejs.org/ + diff --git a/doc/ja/object/general.md b/doc/ja/object/general.md new file mode 100644 index 00000000..cbad5f11 --- /dev/null +++ b/doc/ja/object/general.md @@ -0,0 +1,99 @@ +## Object Usage and Properties + +Everything in JavaScript acts like an object, with the only two exceptions being +[`null`](#core.undefined) and [`undefined`](#core.undefined). + + false.toString() // 'false' + [1, 2, 3].toString(); // '1,2,3' + + function Foo(){} + Foo.bar = 1; + Foo.bar; // 1 + +A common misconception is that number literals cannot be used as +objects. That is because a flaw in JavaScript's parser tries to parse the *dot +notation* on a number as a floating point literal. + + 2.toString(); // raises SyntaxError + +There are a couple of workarounds which can be used in order make number +literals act as objects too. + + 2..toString(); // the second point is correctly recognized + 2 .toString(); // note the space left to the dot + (2).toString(); // 2 is evaluated first + +### Objects as a Data Type + +Objects in JavaScript can also be used as a [*Hashmap*][1], they mainly consist +of named properties mapping to values. + +Using a object literal - `{}` notation - it is possible to create a +plain object. This new object [inherits](#object.prototype) from `Object.prototype` and +has no [own properties](#object.hasownproperty) defined on it. + + var foo = {}; // a new empty object + + // a new object with a property called 'test' with value 12 + var bar = {test: 12}; + +### Accessing Properties + +The properties of an object can be accessed in two ways, via either the dot +notation, or the square bracket notation. + + var foo = {name: 'Kitten'} + foo.name; // kitten + foo['name']; // kitten + + var get = 'name'; + foo[get]; // kitten + + foo.1234; // SyntaxError + foo['1234']; // works + +Both notations are identical in their workings, with the only difference being that +the square bracket notation allows for dynamic setting of properties, as well as +the use of property names that would otherwise lead to a syntax error. + +### Deleting Properties + +The only way to actually remove a property from an object is to use the `delete` +operator; setting the property to `undefined` or `null` only remove the +*value* associated with the property, but not the *key*. + + 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]); + } + } + +The above outputs both `bar undefined` and `foo null` - only `baz` was +removed and is therefore missing from the output. + +### Notation of Keys + + var test = { + 'case': 'I am a keyword so I must be notated as a string', + delete: 'I am a keyword too so me' // raises SyntaxError + }; + +Object properties can be both notated as plain characters and as strings. Due to +another mis-design in JavaScript's parser, the above will throw +a `SyntaxError` prior to ECMAScript 5. + +This error arises from the fact that `delete` is a *keyword*; therefore, it must be +notated as a *string literal* to ensure that it will be correctly interpreted by +older JavaScript engines. + +[1]: http://en.wikipedia.org/wiki/Hashmap + diff --git a/doc/ja/object/hasownproperty.md b/doc/ja/object/hasownproperty.md new file mode 100644 index 00000000..319a8801 --- /dev/null +++ b/doc/ja/object/hasownproperty.md @@ -0,0 +1,53 @@ +## `hasOwnProperty` + +In order to check whether a object has a property defined on *itself* and **not** +somewhere on its [prototype chain](#object.prototype), it is necessary to use the +`hasOwnProperty` method which all objects inherit from `Object.prototype`. + +> **Note:** It is **not** enough to check whether a property is `undefined`. The +> property might very well exist, but its value just happens to be set to +> `undefined`. + +`hasOwnProperty` is the only thing in JavaScript which deals with properties and +does **not** traverse the prototype chain. + + // Poisoning Object.prototype + Object.prototype.bar = 1; + var foo = {goo: undefined}; + + foo.bar; // 1 + 'bar' in foo; // true + + foo.hasOwnProperty('bar'); // false + foo.hasOwnProperty('goo'); // true + +Only `hasOwnProperty` will give the correct and expected result, this is +essential when iterating over the properties of any object. There is **no** other +way to exclude properties that are not defined on the object *itself*, but +somewhere on its prototype chain. + +### `hasOwnProperty` as a Property + +JavaScript does **not** protect the property name `hasOwnProperty`; thus, if the +possibility exists that an object might have a property with this name, it is +necessary to use an *external* `hasOwnProperty` in order to get correct results. + + var foo = { + hasOwnProperty: function() { + return false; + }, + bar: 'Here be dragons' + }; + + foo.hasOwnProperty('bar'); // always returns false + + // Use another Object's hasOwnProperty and call it with 'this' set to foo + ({}).hasOwnProperty.call(foo, 'bar'); // true + +### In Conclusion + +When checking for the existence of a property on a object, `hasOwnProperty` is +the **only** method of doing so. It is also recommended to make `hasOwnProperty` +part of **every** [`for in` loop](#object.forinloop), this will avoid errors from +extended native [prototypes](#object.prototype). + diff --git a/doc/ja/object/prototype.md b/doc/ja/object/prototype.md new file mode 100644 index 00000000..f780eba2 --- /dev/null +++ b/doc/ja/object/prototype.md @@ -0,0 +1,116 @@ +## The Prototype + +JavaScript does not feature a classical inheritance model, instead it uses a +*prototypal* one. + +While this is often considered to be one of JavaScript's weaknesses, the +prototypal inheritance model is in fact more powerful than the classic model. +It is for example fairly trivial to build a classic model on top of it, while the +other way around is a far more difficult task. + +Due to the fact that JavaScript is basically the only widely used language that +features prototypal inheritance, it takes some time to adjust to the +differences between the two models. + +The first major difference is that inheritance in JavaScript is done by using so +called *prototype chains*. + +> **Note:** Simply using `Bar.prototype = Foo.prototype` will result in both objects +> sharing the **same** prototype. Therefore, changes to either object's prototype +> will affect the prototype of the other as well, which in most cases is not the +> desired effect. + + function Foo() { + this.value = 42; + } + Foo.prototype = { + method: function() {} + }; + + function Bar() {} + + // Set Bar's prototype to a new instance of Foo + Bar.prototype = new Foo(); + Bar.prototype.foo = 'Hello World'; + + // Make sure to list Bar as the actual constructor + Bar.prototype.constructor = Bar; + + var test = new Bar() // create a new bar instance + + // The resulting prototype chain + test [instance of Bar] + Bar.prototype [instance of Foo] + { foo: 'Hello World' } + Foo.prototype + { method: ... } + Object.prototype + { toString: ... /* etc. */ } + +In the above, the object `test` will inherit from both `Bar.prototype` and +`Foo.prototype`; hence, it will have access to the function `method` that was +defined on `Foo`. It will also have access to the property `value` of the +**one** `Foo` instance that is its prototype. It is important to note that `new +Bar()` does **not** create a new `Foo` instance, but reuses the one assigned to +its prototype; thus, all `Bar` instances will share the **same** `value` property. + +> **Note:** Do **not** use `Bar.prototype = Foo`, since it will not point to +> the prototype of `Foo` but rather to the function object `Foo`. So the +> prototype chain will go over `Function.prototype` and not `Foo.prototype`; +> therefore, `method` will not be on the prototype chain. + +### Property Lookup + +When accessing the properties of an object, JavaScript will traverse the +prototype chain **upwards** until it finds a property with the requested name. + +When it reaches the top of the chain - namely `Object.prototype` - and still +hasn't found the specified property, it will return the value +[undefined](#core.undefined) instead. + +### The Prototype Property + +While the prototype property is used by the language to build the prototype +chains, it is still possible to assign **any** given value to it. Although +primitives will simply get ignored when assigned as a prototype. + + function Foo() {} + Foo.prototype = 1; // no effect + +Assigning objects, as shown in the example above, will work, and allows for dynamic +creation of prototype chains. + +### Performance + +The lookup time for properties that are high up on the prototype chain can have a +negative impact on performance critical sections of code. Additionally, trying to +access non-existent properties will always traverse the full prototype chain. + +Also, when [iterating](#object.forinloop) over the properties of an object +**every** property that is on the prototype chain will get enumerated. + +### Extension of Native Prototypes + +One mis-feature that is often used is to extend `Object.prototype` or one of the +other built in prototypes. + +This technique is called [monkey patching][1] and breaks *encapsulation*. While +used by widely spread frameworks such as [Prototype][2], there is still no good +reason for cluttering built-in types with additional *non-standard* functionality. + +The **only** good reason for extending a built-in prototype is to backport +the features of newer JavaScript engines; for example, +[`Array.forEach`][3]. + +### In Conclusion + +It is a **must** to understand the prototypal inheritance model completely +before writing complex code which makes use of it. Also, watch the length of +the prototype chains and break them up if necessary to avoid possible +performance issues. Further, the native prototypes should **never** be extended +unless it is for the sake of compatibility with newer JavaScript features. + +[1]: http://en.wikipedia.org/wiki/Monkey_patch +[2]: http://prototypejs.org/ +[3]: https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/forEach + diff --git a/doc/ja/other/timeouts.md b/doc/ja/other/timeouts.md new file mode 100644 index 00000000..d196a3b7 --- /dev/null +++ b/doc/ja/other/timeouts.md @@ -0,0 +1,155 @@ +### `setTimeout` and `setInterval` + +Since JavaScript is asynchronous, it is possible to schedule the execution of a +function by using the `setTimeout` and `setInterval` functions. + +> **Note:** Timeouts are **not** part of the ECMAScript Standard. They are +> implemented as part of the [DOM][1]. + + function foo() {} + var id = setTimeout(foo, 1000); // returns a Number > 0 + +When `setTimeout` gets called, it will return the ID of the timeout and schedule +`foo` to run in **approximately** one thousand milliseconds in the future. +`foo` will then get executed exactly **once**. + +Depending on the timer resolution of the JavaScript engine that is running the +code, as well as the fact that JavaScript is single threaded and other code that +gets executed might block the thread, it is by **no means** a safe bet that one +will get the exact delay that was specified in the `setTimeout` call. + +The function that was passed as the first parameter will get called by the +*global object*, that means, that [`this`](#function.this) inside the called function +refers to that very object. + + function Foo() { + this.value = 42; + this.method = function() { + // this refers to the global object + console.log(this.value); // will log undefined + }; + setTimeout(this.method, 500); + } + new Foo(); + + +> **Note:** As `setTimeout` takes a **function object** as its first parameter, an +> often made mistake is to use `setTimeout(foo(), 1000)`, which will use the +> **return value** of the call `foo` and **not** `foo`. This is, most of the time, +> a silent error, since when the function returns `undefined` `setTimeout` will +> **not** raise any error. + +### Stacking Calls with `setInterval` + +While `setTimeout` only runs the function once, `setInterval` - as the name +suggests - will execute the function **every** `X` milliseconds. But its use is +discouraged. + +When code that is being executed blocks the timeout call, `setInterval` will +still issue more calls to the specified function. This can, especially with small +intervals, result in function calls stacking up. + + function foo(){ + // something that blocks for 1 second + } + setInterval(foo, 100); + +In the above code `foo` will get called once and will then block for one second. + +While `foo` blocks the code `setInterval` will still schedule further calls to +it. Now, when `foo` has finished, there will already be **ten** further calls to +it waiting for execution. + +### Dealing with Possible Blocking Code + +The easiest as well as most controllable solution, is to use `setTimeout` within +the function itself. + + function foo(){ + // something that blocks for 1 second + setTimeout(foo, 100); + } + foo(); + +Not only does this encapsulate the `setTimeout` call, but it also prevents the +stacking of calls and it gives additional control.`foo` itself can now decide +whether it wants to run again or not. + +### Manually Clearing Timeouts + +Clearing timeouts and intervals works by passing the respective ID to +`clearTimeout` or `clearInterval`, depending which `set` function was used in +the first place. + + var id = setTimeout(foo, 1000); + clearTimeout(id); + +### Clearing all timeouts + +As there is no built-in method for clearing all timeouts and/or intervals, +it is necessary to use brute force in order to achieve this functionality. + + // clear "all" timeouts + for(var i = 1; i < 1000; i++) { + clearTimeout(i); + } + +There might still be timeouts that are unaffected by this arbitrary number; +therefore, is is instead recommended to keep track of all the timeout IDs, so +they can be cleared specifically. + +### Hidden use of `eval` + +`setTimeout` and `setInterval` can also take a string as their first parameter. +This feature should **never** be used, since it internally makes use of `eval`. + +> **Note:** Since the timeout functions are **not** specified by the ECMAScript +> standard, the exact workings when a string is passed to them might differ in +> various JavaScript implementations. For example, Microsoft's JScript makes use of +> the `Function` constructor in place of `eval`. + + function foo() { + // will get called + } + + function bar() { + function foo() { + // never gets called + } + setTimeout('foo()', 1000); + } + bar(); + +Since `eval` is not getting called [directly](#core.eval) in this case, the string +passed to `setTimeout` will get executed in the *global scope*; thus, it will +not use the local variable `foo` from the scope of `bar`. + +It is further recommended to **not** use a string for passing arguments to the +function that will get called by either of the timeout functions. + + function foo(a, b, c) {} + + // NEVER use this + setTimeout('foo(1,2, 3)', 1000) + + // Instead use an anonymous function + setTimeout(function() { + foo(a, b, c); + }, 1000) + +> **Note:** While it is also possible to use the syntax +> `setTimeout(foo, 1000, a, b, c)`, it is not recommended, as its use may lead +> to subtle errors when used with [methods](#function.this). + +### In Conclusion + +**Never** should a string be used as the parameter of `setTimeout` or +`setInterval`. It is a clear sign of **really** bad code, when arguments need +to be supplied to the function that gets called. An *anonymous function* should +be passed that then takes care of the actual call. + +Further, the use of `setInterval` should be avoided since its scheduler is not +blocked by executing JavaScript. + +[1]: http://en.wikipedia.org/wiki/Document_Object_Model "Document Object Model" + diff --git a/doc/ja/types/casting.md b/doc/ja/types/casting.md new file mode 100644 index 00000000..15d84e74 --- /dev/null +++ b/doc/ja/types/casting.md @@ -0,0 +1,70 @@ +## Type Casting + +JavaScript is a *weakly typed* language, so it will apply *type coercion* +**wherever** possible. + + // These are true + new Number(10) == 10; // Number.toString() is converted + // back to a number + + 10 == '10'; // Strings gets converted to Number + 10 == '+10 '; // More string madness + 10 == '010'; // And more + isNaN(null) == false; // null converts to 0 + // which of course is not NaN + + // These are false + 10 == 010; + 10 == '-10'; + +> **ES5 Note:** Number literals that start with a `0` are interpreted as octal +> (Base 8). Octal support for these has been **removed** in ECMAScript 5 strict +> mode. + +In order to avoid the above, use of the [strict equal operator](#types.equality) +is **highly** recommended. Although this avoids a lot of common pitfalls, there +are still many further issues that arise from JavaScript's weak typing system. + +### Constructors of Built-In Types + +The constructors of the built in types like `Number` and `String` behave +differently when being used with the `new` keyword and without it. + + new Number(10) === 10; // False, Object and Number + Number(10) === 10; // True, Number and Number + new Number(10) + 0 === 10; // True, due to implicit conversion + +Using a built-in type like `Number` as a constructor will create a new `Number` +object, but leaving out the `new` keyword will make the `Number` function behave +like a converter. + +In addition, having literals or non-object values in there will result in even +more type coercion. + +The best option is to cast to one of the three possible types **explicitly**. + +### Casting to a String + + '' + 10 === '10'; // true + +By prepending a empty string a value can easily be casted to a string. + +### Casting to a Number + + +'10' === 10; // true + +Using the **unary** plus operator it is possible to cast to a number. + +### Casting to a Boolean + +By using the **not** operator twice, a value can be converted a boolean. + + !!'foo'; // true + !!''; // false + !!'0'; // true + !!'1'; // true + !!'-1' // true + !!{}; // true + !!true; // true + + diff --git a/doc/ja/types/equality.md b/doc/ja/types/equality.md new file mode 100644 index 00000000..a578b19c --- /dev/null +++ b/doc/ja/types/equality.md @@ -0,0 +1,71 @@ +## Equality and Comparisons + +JavaScript has two different ways of comparing the values of objects for equality. + +### The Equality Operator + +The equality operator consists of two equal signs: `==` + +JavaScript features *weak typing*. This means that the equality operator +**coerces** types in order to compare them. + + "" == "0" // false + 0 == "" // true + 0 == "0" // true + false == "false" // false + false == "0" // true + false == undefined // false + false == null // false + null == undefined // true + " \t\r\n" == 0 // true + +The above table shows the results of the type coercion and it is the main reason +why the use of `==` is widely regarded as bad practice, it introduces hard to +track down bugs due to its complicated conversion rules. + +Additionally there is also a performance impact when type coercion is in play; +for example, a string has to be converted to a number before it can be compared +to another number. + +### The Strict Equality Operator + +The strict equality operator consists of **three** equal signs: `===` + +It works exactly like the normal equality operator, except that strict equality +operator does **not** perform type coercion between its operands. + + "" === "0" // false + 0 === "" // false + 0 === "0" // false + false === "false" // false + false === "0" // false + false === undefined // false + false === null // false + null === undefined // false + " \t\r\n" === 0 // false + +The above results are a lot clearer and allow for early breakage of code. This +hardens code to a certain degree and also gives performance improvements in case +the operands are of different types. + +### Comparing Objects + +While both `==` and `===` are stated as **equality** operators, they behave +different when at least one of their operands happens to be an `Object`. + + {} === {}; // false + new String('foo') === 'foo'; // false + new Number(10) === 10; // false + var foo = {}; + foo === foo; // true + +Here both operators compare for **identity** and **not** equality; that is, they +will compare for the same **instance** of the object, much like `is` in Python +and pointer comparison in C. + +### In Conclusion + +It is highly recommended to only use the **strict equality** operator. In cases +where types need to be coerced, it should be done [explicitly](#types.casting) +and not left to the language's complicated coercion rules. + diff --git a/doc/ja/types/instanceof.md b/doc/ja/types/instanceof.md new file mode 100644 index 00000000..8711331a --- /dev/null +++ b/doc/ja/types/instanceof.md @@ -0,0 +1,38 @@ +## The `instanceof` Operator + +The `instanceof` operator compares the constructors of its two operands. It is +only useful when comparing custom made objects. Used on built-in types, it is +nearly as useless as the [typeof operator](#types.typeof). + +### Comparing Custom Objects + + function Foo() {} + function Bar() {} + Bar.prototype = new Foo(); + + new Bar() instanceof Bar; // true + new Bar() instanceof Foo; // true + + // This just sets Bar.prototype to the function object Foo + // But not to an actual instance of Foo + Bar.prototype = Foo; + new Bar() instanceof Foo; // false + +### Using `instanceof` with Native Types + + new String('foo') instanceof String; // true + new String('foo') instanceof Object; // true + + 'foo' instanceof String; // false + 'foo' instanceof Object; // false + +One important thing to note here is, that `instanceof` does not work on objects +that origin from different JavaScript contexts (e.g. different documents +in a web browser), since their constructors will not be the exact same object. + +### In Conclusion + +The `instanceof` operator should **only** be used when dealing with custom made +objects that origin from the same JavaScript context. Just like the +[`typeof`](#types.typeof) operator, every other use of it should be **avoided**. + diff --git a/doc/ja/types/typeof.md b/doc/ja/types/typeof.md new file mode 100644 index 00000000..e4b28d7f --- /dev/null +++ b/doc/ja/types/typeof.md @@ -0,0 +1,87 @@ +## The `typeof` Operator + +The `typeof` operator (together with +[`instanceof`](#types.instanceof)) is probably the biggest +design flaw of JavaScript, as it is near of being **completely broken**. + +Although `instanceof` still has its limited uses, `typeof` really has only one +practical use case, which does **not** happen to be checking the type of an +object. + +> **Note:** While `typeof` can also be called with a function like syntax +> i.e. `typeof(obj)`, this is not a function call. The two parenthesis will +> behave like normal and the return value will be used as the operand of the +> `typeof` operator. There is **no** `typeof` function. + +### The JavaScript Type Table + + Value Class Type + ------------------------------------- + "foo" String string + new String("foo") String object + 1.2 Number number + new Number(1.2) Number object + true Boolean boolean + new Boolean(true) Boolean object + new Date() Date object + new Error() Error object + [1,2,3] Array object + new Array(1, 2, 3) Array object + new Function("") Function function + /abc/g RegExp object (function in Nitro/V8) + new RegExp("meow") RegExp object (function in Nitro/V8) + {} Object object + new Object() Object object + +In the above table *Type* refers to the value, that the `typeof` operator returns. +As can be clearly seen, this value is anything but consistent. + +The *Class* refers to the value of the internal `[[Class]]` property of an object. + +> **From the Specification:** The value of `[[Class]]` can be one of the +> following strings. `Arguments`, `Array`, `Boolean`, `Date`, `Error`, +> `Function`, `JSON`, `Math`, `Number`, `Object`, `RegExp`, `String`. + +In order to retrieve the value of `[[Class]]` one has to make use of the +`toString` method of `Object.prototype`. + +### The Class of an Object + +The specification gives exactly one way of accessing the `[[Class]]` value, +with the use of `Object.prototype.toString`. + + function is(type, obj) { + var clas = Object.prototype.toString.call(obj).slice(8, -1); + return obj !== undefined && obj !== null && clas === type; + } + + is('String', 'test'); // true + is('String', new String('test')); // true + +In the above example, `Object.prototype.toString` gets called with the value of +[this](#function.this) being set to the object whose `[[Class]]` value should be +retrieved. + +> **ES5 Note:** For convenience the return value of `Object.prototype.toString` +> for both `null` and `undefined` was **changed** from `Object` to `Null` and +> `Undefined` in ECMAScript 5. + +### Testing for Undefined Variables + + typeof foo !== 'undefined' + +The above will check whether `foo` was actually declared or not; just +referencing it would result in a `ReferenceError`. This is the only thing +`typeof` is actually useful for. + +### In Conclusion + +In order to check the type of an object, it is highly recommended to use +`Object.prototype.toString`; as this is the only reliable way of doing so. +As shown in the above type table, some return values of `typeof` are not defined +in the specification; thus, they can differ across various implementations. + +Unless checking whether a variable is defined, `typeof` should be avoided at +**all costs**. + + From 2a24fa87affeb63234d274a7b6525c6eddc05fdd Mon Sep 17 00:00:00 2001 From: Satoru HIRAKI Date: Sat, 2 Jul 2011 22:12:15 +0900 Subject: [PATCH 015/463] translate index.json to Japanese --- doc/ja/index.json | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/doc/ja/index.json b/doc/ja/index.json index d4012ed9..4f263875 100644 --- a/doc/ja/index.json +++ b/doc/ja/index.json @@ -1,64 +1,64 @@ { "title": "JavaScript Garden", - "langTitle": "JavaScript Garden in English", - "description": "A Guide to JavaScript's Quirks and Flaws.", + "langTitle": "JavaScript Garden in Japanese", + "description": "JavaScriptの奇抜さと欠陥についてのガイドライン", "sections": [ { - "title": "Intro", + "title": "イントロ", "dir": "intro", "articles": [] }, { - "title": "Objects", + "title": "オブジェクト", "dir": "object", "articles": [ - "general", + "概論", "prototype", "hasownproperty", - "forinloop" + "forinループ" ] }, { - "title": "Functions", + "title": "関数", "dir": "function", "articles": [ - "general", + "概論", "this", - "closures", - "arguments", - "constructors", - "scopes" + "クロージャ", + "引数", + "コンストラクタ", + "スコープ" ] }, { - "title": "Arrays", + "title": "配列", "dir": "array", "articles": [ - "general", - "constructor" + "概論", + "コンストラクタ" ] }, { - "title": "Types", + "title": "型", "dir": "types", "articles": [ - "equality", + "同値・同価", "typeof", "instanceof", - "casting" + "型変換" ] }, { - "title": "Core", + "title": "コア", "dir": "core", "articles": [ "eval", "undefined", - "semicolon" + "セミコロン" ] }, { - "title": "Other", + "title": "その他", "dir": "other", "articles": [ "timeouts" From d51d1246640443ababb84c5ce94057465e96da0d Mon Sep 17 00:00:00 2001 From: Satoru HIRAKI Date: Sat, 2 Jul 2011 22:13:43 +0900 Subject: [PATCH 016/463] add ja to language.json --- doc/language.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/language.json b/doc/language.json index 1c1bdffc..56774f29 100644 --- a/doc/language.json +++ b/doc/language.json @@ -1,5 +1,5 @@ { "default": "en", - "listed": ["en", "fi", "ru", "zh", "tr", "pl"] + "listed": ["en", "fi", "ru", "zh", "tr", "pl", "ja"] } From 5f190cdb71b117540deaa9f4b3b32da68a30b52a Mon Sep 17 00:00:00 2001 From: Satoru HIRAKI Date: Sat, 2 Jul 2011 22:24:31 +0900 Subject: [PATCH 017/463] fix ariticles --- doc/ja/index.json | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/doc/ja/index.json b/doc/ja/index.json index 4f263875..85e25a6b 100644 --- a/doc/ja/index.json +++ b/doc/ja/index.json @@ -12,40 +12,40 @@ "title": "オブジェクト", "dir": "object", "articles": [ - "概論", + "general", "prototype", "hasownproperty", - "forinループ" + "forinloop" ] }, { "title": "関数", "dir": "function", "articles": [ - "概論", + "general", "this", - "クロージャ", - "引数", - "コンストラクタ", - "スコープ" + "closures", + "arguments", + "constructors", + "scopes" ] }, { "title": "配列", "dir": "array", "articles": [ - "概論", - "コンストラクタ" + "general", + "constructor" ] }, { "title": "型", "dir": "types", "articles": [ - "同値・同価", + "equality", "typeof", "instanceof", - "型変換" + "casting" ] }, { @@ -54,7 +54,7 @@ "articles": [ "eval", "undefined", - "セミコロン" + "semicolon" ] }, { From 91aa9d74bc9dcf5a2c177420a575ffbaf4b816ff Mon Sep 17 00:00:00 2001 From: Satoru HIRAKI Date: Sat, 2 Jul 2011 22:28:29 +0900 Subject: [PATCH 018/463] build ja/index.html --- site/ja/index.html | 1878 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1878 insertions(+) create mode 100644 site/ja/index.html diff --git a/site/ja/index.html b/site/ja/index.html new file mode 100644 index 00000000..60e5d1c9 --- /dev/null +++ b/site/ja/index.html @@ -0,0 +1,1878 @@ +JavaScript Garden +

イントロ

JavaScript Garden is a growing collection of documentation about the most +quirky parts of the JavaScript programming language. It gives advice to +avoid common mistakes, subtle bugs, as well as performance issues and bad +practices that non-expert JavaScript programmers may encounter on their +endeavours into the depths of the language.

+ +

JavaScript Garden does not aim to teach you JavaScript. Former knowledge +of the language is strongly recommended in order to understand the topics covered +in this guide. In order to learn the basics of the language, please head over to +the excellent guide on the Mozilla Developer Network.

+ +

The Authors

+ +

This guide is the work of two lovely Stack Overflow users, Ivo Wetzel +(Writing) and Zhang Yi Jiang (Design).

+ +

Contributors

+ + + +

Hosting

+ +

JavaScript Garden is hosted on GitHub, but Cramer Development supports us +with a mirror at JavaScriptGarden.info.

+ +

License

+ +

JavaScript Garden is published under the MIT license and hosted on +GitHub. If you find errors or typos please file an issue or a pull +request on the repository. You can also find us in the JavaScript room on +Stack Overflow chat.

オブジェクト

Object Usage and Properties

Everything in JavaScript acts like an object, with the only two exceptions being +null and undefined.

+ +
false.toString() // 'false'
+[1, 2, 3].toString(); // '1,2,3'
+
+function Foo(){}
+Foo.bar = 1;
+Foo.bar; // 1
+
+ +

A common misconception is that number literals cannot be used as +objects. That is because a flaw in JavaScript's parser tries to parse the dot +notation on a number as a floating point literal.

+ +
2.toString(); // raises SyntaxError
+
+ +

There are a couple of workarounds which can be used in order make number +literals act as objects too.

+ +
2..toString(); // the second point is correctly recognized
+2 .toString(); // note the space left to the dot
+(2).toString(); // 2 is evaluated first
+
+ +

Objects as a Data Type

+ +

Objects in JavaScript can also be used as a Hashmap, they mainly consist +of named properties mapping to values.

+ +

Using a object literal - {} notation - it is possible to create a +plain object. This new object inherits from Object.prototype and +has no own properties defined on it.

+ +
var foo = {}; // a new empty object
+
+// a new object with a property called 'test' with value 12
+var bar = {test: 12}; 
+
+ +

Accessing Properties

+ +

The properties of an object can be accessed in two ways, via either the dot +notation, or the square bracket notation.

+ +
var foo = {name: 'Kitten'}
+foo.name; // kitten
+foo['name']; // kitten
+
+var get = 'name';
+foo[get]; // kitten
+
+foo.1234; // SyntaxError
+foo['1234']; // works
+
+ +

Both notations are identical in their workings, with the only difference being that +the square bracket notation allows for dynamic setting of properties, as well as +the use of property names that would otherwise lead to a syntax error.

+ +

Deleting Properties

+ +

The only way to actually remove a property from an object is to use the delete +operator; setting the property to undefined or null only remove the +value associated with the property, but not the key.

+ +
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]);
+    }
+}
+
+ +

The above outputs both bar undefined and foo null - only baz was +removed and is therefore missing from the output.

+ +

Notation of Keys

+ +
var test = {
+    'case': 'I am a keyword so I must be notated as a string',
+    delete: 'I am a keyword too so me' // raises SyntaxError
+};
+
+ +

Object properties can be both notated as plain characters and as strings. Due to +another mis-design in JavaScript's parser, the above will throw +a SyntaxError prior to ECMAScript 5.

+ +

This error arises from the fact that delete is a keyword; therefore, it must be +notated as a string literal to ensure that it will be correctly interpreted by +older JavaScript engines.

The Prototype

JavaScript does not feature a classical inheritance model, instead it uses a +prototypal one.

+ +

While this is often considered to be one of JavaScript's weaknesses, the +prototypal inheritance model is in fact more powerful than the classic model. +It is for example fairly trivial to build a classic model on top of it, while the +other way around is a far more difficult task.

+ +

Due to the fact that JavaScript is basically the only widely used language that +features prototypal inheritance, it takes some time to adjust to the +differences between the two models.

+ +

The first major difference is that inheritance in JavaScript is done by using so +called prototype chains.

+ + + +
function Foo() {
+    this.value = 42;
+}
+Foo.prototype = {
+    method: function() {}
+};
+
+function Bar() {}
+
+// Set Bar's prototype to a new instance of Foo
+Bar.prototype = new Foo();
+Bar.prototype.foo = 'Hello World';
+
+// Make sure to list Bar as the actual constructor
+Bar.prototype.constructor = Bar;
+
+var test = new Bar() // create a new bar instance
+
+// The resulting prototype chain
+test [instance of Bar]
+    Bar.prototype [instance of Foo] 
+        { foo: 'Hello World' }
+        Foo.prototype
+            { method: ... }
+            Object.prototype
+                { toString: ... /* etc. */ }
+
+ +

In the above, the object test will inherit from both Bar.prototype and +Foo.prototype; hence, it will have access to the function method that was +defined on Foo. It will also have access to the property value of the +one Foo instance that is its prototype. It is important to note that new +Bar() does not create a new Foo instance, but reuses the one assigned to +its prototype; thus, all Bar instances will share the same value property.

+ + + +

Property Lookup

+ +

When accessing the properties of an object, JavaScript will traverse the +prototype chain upwards until it finds a property with the requested name.

+ +

When it reaches the top of the chain - namely Object.prototype - and still +hasn't found the specified property, it will return the value +undefined instead.

+ +

The Prototype Property

+ +

While the prototype property is used by the language to build the prototype +chains, it is still possible to assign any given value to it. Although +primitives will simply get ignored when assigned as a prototype.

+ +
function Foo() {}
+Foo.prototype = 1; // no effect
+
+ +

Assigning objects, as shown in the example above, will work, and allows for dynamic +creation of prototype chains.

+ +

Performance

+ +

The lookup time for properties that are high up on the prototype chain can have a +negative impact on performance critical sections of code. Additionally, trying to +access non-existent properties will always traverse the full prototype chain.

+ +

Also, when iterating over the properties of an object +every property that is on the prototype chain will get enumerated.

+ +

Extension of Native Prototypes

+ +

One mis-feature that is often used is to extend Object.prototype or one of the +other built in prototypes.

+ +

This technique is called monkey patching and breaks encapsulation. While +used by widely spread frameworks such as Prototype, there is still no good +reason for cluttering built-in types with additional non-standard functionality.

+ +

The only good reason for extending a built-in prototype is to backport +the features of newer JavaScript engines; for example, +Array.forEach.

+ +

In Conclusion

+ +

It is a must to understand the prototypal inheritance model completely +before writing complex code which makes use of it. Also, watch the length of +the prototype chains and break them up if necessary to avoid possible +performance issues. Further, the native prototypes should never be extended +unless it is for the sake of compatibility with newer JavaScript features.

hasOwnProperty

In order to check whether a object has a property defined on itself and not +somewhere on its prototype chain, it is necessary to use the +hasOwnProperty method which all objects inherit from Object.prototype.

+ + + +

hasOwnProperty is the only thing in JavaScript which deals with properties and +does not traverse the prototype chain.

+ +
// Poisoning Object.prototype
+Object.prototype.bar = 1; 
+var foo = {goo: undefined};
+
+foo.bar; // 1
+'bar' in foo; // true
+
+foo.hasOwnProperty('bar'); // false
+foo.hasOwnProperty('goo'); // true
+
+ +

Only hasOwnProperty will give the correct and expected result, this is +essential when iterating over the properties of any object. There is no other +way to exclude properties that are not defined on the object itself, but +somewhere on its prototype chain.

+ +

hasOwnProperty as a Property

+ +

JavaScript does not protect the property name hasOwnProperty; thus, if the +possibility exists that an object might have a property with this name, it is +necessary to use an external hasOwnProperty in order to get correct results.

+ +
var foo = {
+    hasOwnProperty: function() {
+        return false;
+    },
+    bar: 'Here be dragons'
+};
+
+foo.hasOwnProperty('bar'); // always returns false
+
+// Use another Object's hasOwnProperty and call it with 'this' set to foo
+({}).hasOwnProperty.call(foo, 'bar'); // true
+
+ +

In Conclusion

+ +

When checking for the existence of a property on a object, hasOwnProperty is +the only method of doing so. It is also recommended to make hasOwnProperty +part of every for in loop, this will avoid errors from +extended native prototypes.

The for in Loop

Just like the in operator, the for in loop also traverses the prototype +chain when iterating over the properties of an object.

+ + + +
// Poisoning Object.prototype
+Object.prototype.bar = 1;
+
+var foo = {moo: 2};
+for(var i in foo) {
+    console.log(i); // prints both bar and moo
+}
+
+ +

Since it is not possible to change the behavior of the for in loop itself, it +is necessary to filter out the unwanted properties inside the loop body , +this is done by using the hasOwnProperty method of +Object.prototype.

+ + + +

Using hasOwnProperty for Filtering

+ +
// still the foo from above
+for(var i in foo) {
+    if (foo.hasOwnProperty(i)) {
+        console.log(i);
+    }
+}
+
+ +

This version is the only correct one to use. Due to the use of hasOwnProperty it +will only print out moo. When hasOwnProperty is left out, the code is +prone to errors in cases where the native prototypes - e.g. Object.prototype - +have been extended.

+ +

One widely used framework which does this is Prototype. When this +framework is included, for in loops that do not use hasOwnProperty are +guaranteed to break.

+ +

In Conclusion

+ +

It is recommended to always use hasOwnProperty. Never should any +assumptions be made about the environment the code is running in, or whether the +native prototypes have been extended or not.

関数

Function Declarations and Expressions

Functions in JavaScript are first class objects. That means they can be +passed around like any other value. One common use of this feature is to pass +an anonymous function as a callback to another, possibly asynchronous function.

+ +

The function Declaration

+ +
function foo() {}
+
+ +

The above function gets hoisted before the execution of the +program starts; thus, it is available everywhere in the scope it was defined +in, even if called before the actual definition in the source.

+ +
foo(); // Works because foo was created before this code runs
+function foo() {}
+
+ +

The function Expression

+ +
var foo = function() {};
+
+ +

This example assigns the unnamed and anonymous function to the variable foo.

+ +
foo; // 'undefined'
+foo(); // this raises a TypeError
+var foo = function() {};
+
+ +

Due to the fact that var is a declaration, that hoists the variable name foo +before the actual execution of the code starts, foo is already defined when +the script gets executed.

+ +

But since assignments only happen at runtime, the value of foo will default +to undefined before the corresponding code is executed.

+ +

Named Function Expression

+ +

Another special case is the assignment of named functions.

+ +
var foo = function bar() {
+    bar(); // Works
+}
+bar(); // ReferenceError
+
+ +

Here bar is not available in the outer scope, since the function only gets +assigned to foo; however, inside of bar it is available. This is due to +how name resolution in JavaScript works, the name of the +function is always made available in the local scope of the function itself.

How this Works

JavaScript has a different concept of what the special name this refers to +than most other programming languages do. There are exactly five different +ways in which the value of this can be bound in the language.

+ +

The Global Scope

+ +
this;
+
+ +

When using this in global scope, it will simply refer to the global object.

+ +

Calling a Function

+ +
foo();
+
+ +

Here this will again refer to the global object.

+ + + +

Calling a Method

+ +
test.foo(); 
+
+ +

In this example this will refer to test.

+ +

Calling a Constructor

+ +
new foo(); 
+
+ +

A function call that is preceded by the new keyword acts as +a constructor. Inside the function this will refer +to a newly created Object.

+ +

Explicit Setting of this

+ +
function foo(a, b, c) {}
+
+var bar = {};
+foo.apply(bar, [1, 2, 3]); // array will expand to the below
+foo.call(bar, 1, 2, 3); // results in a = 1, b = 2, c = 3
+
+ +

When using the call or apply methods of Function.prototype, the value of +this inside the called function gets explicitly set to the first argument +of the corresponding function call.

+ +

As a result, the above example the method case does not apply, and this +inside of foo will be set to bar.

+ + + +

Common Pitfalls

+ +

While most of these cases make sense, the first one is to be considered another +mis-design of the language, as it never has any practical use.

+ +
Foo.method = function() {
+    function test() {
+        // this is set to the global object
+    }
+    test();
+}
+
+ +

A common misconception is that this inside of test refers to Foo, while in +fact it does not.

+ +

In order to gain access to Foo from within test it is necessary to create a +local variable inside of method which refers to Foo.

+ +
Foo.method = function() {
+    var that = this;
+    function test() {
+        // Use that instead of this here
+    }
+    test();
+}
+
+ +

that is just a normal variable name, but it is commonly used for the reference to an +outer this. In combination with closures, it can also +be used to pass this values around.

+ +

Assigning Methods

+ +

Another thing that does not work in JavaScript is function aliasing, that is, +assigning a method to a variable.

+ +
var test = someObject.methodTest;
+test();
+
+ +

Due to the first case test now acts like a plain function call; therefore, +this inside it will no longer refer to someObject.

+ +

While the late binding of this might seem like a bad idea at first, it is in +fact what makes prototypal inheritance work.

+ +
function Foo() {}
+Foo.prototype.method = function() {};
+
+function Bar() {}
+Bar.prototype = Foo.prototype;
+
+new Bar().method();
+
+ +

When method gets called on a instance of Bar, this will now refer to that +very instance.

Closures and References

One of JavaScript's most powerful features is the availability of closures, +this means that scopes always keep access to the outer scope they were +defined in. Since the only scoping that JavaScript has is +function scope, all functions, by default, act as closures.

+ +

Emulating private variables

+ +
function Counter(start) {
+    var count = start;
+    return {
+        increment: function() {
+            count++;
+        },
+
+        get: function() {
+            return count;
+        }
+    }
+}
+
+var foo = Counter(4);
+foo.increment();
+foo.get(); // 5
+
+ +

Here, Counter returns two closures. The function increment as well as +the function get. Both of these functions keep a reference to the scope of +Counter and, therefore, always keep access to the count variable that was +defined in that very scope.

+ +

Why Private Variables Work

+ +

Since it is not possible to reference or assign scopes in JavaScript, there is +no way of accessing the variable count from the outside. The only way to +interact with it is via the two closures.

+ +
var foo = new Counter(4);
+foo.hack = function() {
+    count = 1337;
+};
+
+ +

The above code will not change the variable count in the scope of Counter, +since foo.hack was not defined in that scope. It will instead create - or +override - the global variable count.

+ +

Closures Inside Loops

+ +

One often made mistake is to use closures inside of loops, as if they were +copying the value of the loops index variable.

+ +
for(var i = 0; i < 10; i++) {
+    setTimeout(function() {
+        console.log(i);  
+    }, 1000);
+}
+
+ +

The above will not output the numbers 0 through 9, but will simply print +the number 10 ten times.

+ +

The anonymous function keeps a reference to i and at the time +console.log gets called, the for loop has already finished and the value of +i as been set to 10.

+ +

In order to get the desired behavior, it is necessary to create a copy of +the value of i.

+ +

Avoiding the Reference Problem

+ +

In order to copy the value of the loop's index variable, it is best to use an +anonymous wrapper.

+ +
for(var i = 0; i < 10; i++) {
+    (function(e) {
+        setTimeout(function() {
+            console.log(e);  
+        }, 1000);
+    })(i);
+}
+
+ +

The anonymous outer function gets called immediately with i as its first +argument and will receive a copy of the value of i as its parameter e.

+ +

The anonymous function that gets passed to setTimeout now has a reference to +e, whose value does not get changed by the loop.

+ +

There is another possible way of achieving this; that is to return a function +from the anonymous wrapper, that will then have the same behavior as the code +above.

+ +
for(var i = 0; i < 10; i++) {
+    setTimeout((function(e) {
+        return function() {
+            console.log(e);
+        }
+    })(i), 1000)
+}
+

The arguments Object

Every function scope in JavaScript can access the special variable arguments. +This variable holds a list of all the arguments that were passed to the function.

+ + + +

The arguments object is not an Array. While it has some of the +semantics of an array - namely the length property - it does not inherit from +Array.prototype and is in fact an Object.

+ +

Due to this, it is not possible to use standard array methods like push, +pop or slice on arguments. While iteration with a plain for loop works +just fine, it is necessary to convert it to a real Array in order to use the +standard Array methods on it.

+ +

Converting to an Array

+ +

The code below will return a new Array containing all the elements of the +arguments object.

+ +
Array.prototype.slice.call(arguments);
+
+ +

This conversion is slow, it is not recommended to use it in performance +critical sections of code.

+ +

Passing Arguments

+ +

The following is the recommended way of passing arguments from one function to +another.

+ +
function foo() {
+    bar.apply(null, arguments);
+}
+function bar(a, b, c) {
+    // do stuff here
+}
+
+ +

Another trick is to use both call and apply together to create fast, unbound +wrappers.

+ +
function Foo() {}
+
+Foo.prototype.method = function(a, b, c) {
+    console.log(this, a, b, c);
+};
+
+// Create an unbound version of "method" 
+// It takes the parameters: this, arg1, arg2...argN
+Foo.method = function() {
+
+    // Result: Foo.prototype.method.call(this, arg1, arg2... argN)
+    Function.call.apply(Foo.prototype.method, arguments);
+};
+
+ +

Formal Parameters and Arguments Indices

+ +

The arguments object creates getter and setter functions for both its +properties as well as the function's formal parameters.

+ +

As a result, changing the value of a formal parameter will also change the value +of the corresponding property on the arguments object, and the other way around.

+ +
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);
+
+ +

Performance Myths and Truths

+ +

The arguments object is always created with the only two exceptions being the +cases where it is declared as a name inside of a function or one of its formal +parameters. It does not matter whether it is used or not.

+ +

Both getters and setters are always created; thus, using it has nearly +no performance impact at all, especially not in real world code where there is +more than a simple access to the arguments object's properties.

+ + + +

However, there is one case which will drastically reduce the performance in +modern JavaScript engines. That case is the use of arguments.callee.

+ +
function foo() {
+    arguments.callee; // do something with this function object
+    arguments.callee.caller; // and the calling function object
+}
+
+function bigLoop() {
+    for(var i = 0; i < 100000; i++) {
+        foo(); // Would normally be inlined...
+    }
+}
+
+ +

In the above code, foo can no longer be a subject to inlining since it +needs to know about both itself and its caller. This not only defeats possible +performance gains that would arise from inlining, it also breaks encapsulation +since the function may now be dependent on a specific calling context.

+ +

It is highly recommended to never make use of arguments.callee or any of +its properties.

+ +

Constructors

Constructors in JavaScript are yet again different from many other languages. Any +function call that is preceded by the new keyword acts as a constructor.

+ +

Inside the constructor - the called function - the value of this refers to a +newly created Object. The prototype of this new +object is set to the prototype of the function object that was invoked as the +constructor.

+ +

If the function that was called has no explicit return statement, then it +implicitly returns the value of this - the new object.

+ +
function Foo() {
+    this.bla = 1;
+}
+
+Foo.prototype.test = function() {
+    console.log(this.bla);
+};
+
+var test = new Foo();
+
+ +

The above calls Foo as constructor and sets the prototype of the newly +created object to Foo.prototype.

+ +

In case of an explicit return statement the function returns the value +specified that statement, but only if the return value is an Object.

+ +
function Bar() {
+    return 2;
+}
+new Bar(); // a new object
+
+function Test() {
+    this.value = 2;
+
+    return {
+        foo: 1
+    };
+}
+new Test(); // the returned object
+
+ +

When the new keyword is omitted, the function will not return a new object.

+ +
function Foo() {
+    this.bla = 1; // gets set on the global object
+}
+Foo(); // undefined
+
+ +

While the above example might still appear to work in some cases, due to the +workings of this in JavaScript, it will use the +global object as the value of this.

+ +

Factories

+ +

In order to be able to omit the new keyword, the constructor function has to +explicitly return a value.

+ +
function Bar() {
+    var value = 1;
+    return {
+        method: function() {
+            return value;
+        }
+    }
+}
+Bar.prototype = {
+    foo: function() {}
+};
+
+new Bar();
+Bar();
+
+ +

Both calls to Bar return the exact same thing, a newly create object which +has a property called method on it, that is a +Closure.

+ +

It is also to note that the call new Bar() does not affect the prototype +of the returned object. While the prototype will be set on the newly created +object, Bar never returns that new object.

+ +

In the above example, there is no functional difference between using and +not using the new keyword.

+ +

Creating New Objects via Factories

+ +

An often made recommendation is to not use new since forgetting its use +may lead to bugs.

+ +

In order to create new object, one should rather use a factory and construct a +new object inside of that factory.

+ +
function Foo() {
+    var obj = {};
+    obj.value = 'blub';
+
+    var private = 2;
+    obj.someMethod = function(value) {
+        this.value = value;
+    }
+
+    obj.getPrivate = function() {
+        return private;
+    }
+    return obj;
+}
+
+ +

While the above is robust against a missing new keyword and certainly makes +the use of private variables easier, it comes with some +downsides.

+ +
    +
  1. It uses more memory since the created objects do not share the methods +on a prototype.
  2. +
  3. In order to inherit the factory needs to copy all the methods from another +object or put that object on the prototype of the new object.
  4. +
  5. Dropping the prototype chain just because of a left out new keyword +somehow goes against the spirit of the language.
  6. +
+ +

In Conclusion

+ +

While omitting the new keyword might lead to bugs, it is certainly not a +reason to drop the use of prototypes altogether. In the end it comes down to +which solution is better suited for the needs of the application, it is +especially important to choose a specific style of object creation and stick +with it.

Scopes and Namespaces

Although JavaScript deals fine with the syntax of two matching curly +braces for blocks, it does not support block scope; hence, all that is left +is in the language is function scope.

+ +
function test() { // a scope
+    for(var i = 0; i < 10; i++) { // not a scope
+        // count
+    }
+    console.log(i); // 10
+}
+
+ + + +

There are also no distinct namespaces in JavaScript, that means that everything +gets defined in one globally shared namespace.

+ +

Each time a variable is referenced, JavaScript will traverse upwards through all +the scopes until it finds it. In the case that it reaches the global scope and +still has not found the requested name, it will raise a ReferenceError.

+ +

The Bane of Global Variables

+ +
// script A
+foo = '42';
+
+// script B
+var foo = '42'
+
+ +

The above two scripts do not have the same effect. Script A defines a +variable called foo in the global scope and script B defines a foo in the +current scope.

+ +

Again, that is not at all the same effect, not using var can have major +implications.

+ +
// global scope
+var foo = 42;
+function test() {
+    // local scope
+    foo = 21;
+}
+test();
+foo; // 21
+
+ +

Leaving out the var statement inside the function test will override the +value of foo. While this might not seem like a big deal at first, having +thousands of lines of JavaScript and not using var will introduce horrible and +hard to track down bugs.

+ +
// global scope
+var items = [/* some list */];
+for(var i = 0; i < 10; i++) {
+    subLoop();
+}
+
+function subLoop() {
+    // scope of subLoop
+    for(i = 0; i < 10; i++) { // missing var statement
+        // do amazing stuff!
+    }
+}
+
+ +

The outer loop will terminate after the first call to subLoop, since subLoop +overwrites the global value of i. Using a var for the second for loop would +have easily avoided this error. The var statement should never be left out +unless the desired effect is to affect the outer scope.

+ +

Local Variables

+ +

The only source for local variables in JavaScript are +function parameters and variables that were declared via the +var statement.

+ +
// global scope
+var foo = 1;
+var bar = 2;
+var i = 2;
+
+function test(i) {
+    // local scope of the function test
+    i = 5;
+
+    var foo = 3;
+    bar = 4;
+}
+test(10);
+
+ +

While foo and i are local variables inside the scope of the function test, +the assignment of bar will override the global variable with the same name.

+ +

Hoisting

+ +

JavaScript hoists declarations. This means that both var statements and +function declarations will be moved to the top of their enclosing scope.

+ +
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];
+    }
+}
+
+ +

The above code gets transformed before any execution is started. JavaScript moves +the var statements as well as the function declarations to the top of the +nearest surrounding scope.

+ +
// var statements got moved here
+var bar, someValue; // default to 'undefined'
+
+// the function declartion got moved up too
+function test(data) {
+    var goo, i, e; // missing block scope moves these here
+    if (false) {
+        goo = 1;
+
+    } else {
+        goo = 2;
+    }
+    for(i = 0; i < 100; i++) {
+        e = data[i];
+    }
+}
+
+bar(); // fails with a TypeError since bar is still 'undefined'
+someValue = 42; // assignments are not affected by hoisting
+bar = function() {};
+
+test();
+
+ +

Missing block scoping will not only move var statements out of loops and +their bodies, it will also make the results of certain if constructs +non-intuitive.

+ +

In the original code the if statement seemed to modify the global +variable goo, while actually it modifies the local variable - after hoisting +has been applied.

+ +

Without the knowledge about hoisting, below code might seem to raise a +ReferenceError.

+ +
// check whether SomeImportantThing has been initiliazed
+if (!SomeImportantThing) {
+    var SomeImportantThing = {};
+}
+
+ +

But of course, the above works due to the fact that the var statement is being +moved to the top of the global scope.

+ +
var SomeImportantThing;
+
+// other code might initiliaze SomeImportantThing here, or not
+
+// make sure it's there
+if (!SomeImportantThing) {
+    SomeImportantThing = {};
+}
+
+ +

Name Resolution Order

+ +

All scopes in JavaScript, including the global scope, have the special name +this defined in them, which refers to the current object.

+ +

Function scopes also have the name arguments defined in +them which contains the arguments that were passed to a function.

+ +

For example, when trying to access a variable named foo inside the scope of a +function, JavaScript will lookup the name in the following order:

+ +
    +
  1. In case there is a var foo statement in the current scope use that.
  2. +
  3. If one of the function parameters is named foo use that.
  4. +
  5. If the function itself is called foo use that.
  6. +
  7. Go to the next outer scope and start with #1 again.
  8. +
+ + + +

Namespaces

+ +

A common problem of having only one global namespace is the likeliness of running +into problems where variable names clash. In JavaScript, this problem can +easily be avoided with the help of anonymous wrappers.

+ +
(function() {
+    // a self contained "namespace"
+
+    window.foo = function() {
+        // an exposed closure
+    };
+
+})(); // execute the function immediately
+
+ +

Unnamed functions are considered expressions; so in order to +being callable, they must first be evaluated.

+ +
( // evaluate the function inside the paranthesis
+function() {}
+) // and return the function object
+() // call the result of the evaluation
+
+ +

There are other ways for evaluating and calling the function expression; which, +while different in syntax, do behave the exact same way.

+ +
// Two other ways
++function(){}();
+(function(){}());
+
+ +

In Conclusion

+ +

It is recommended to always use an anonymous wrapper for encapsulating code in +its own namespace. This does not only protect code against name clashes, it +also allows for better modularization of programs.

+ +

Additionally, the use of global variables is considered bad practice. Any +use of them indicates badly written code that is prone to errors and hard to maintain.

配列

Array Iteration and Properties

Although arrays in JavaScript are objects, there are no good reasons to use +the for in loop in for iteration on them. In fact there +are a number of good reasons against the use of for in on arrays.

+ + + +

Since the for in loop enumerates all the properties that are on the prototype +chain and the only way to exclude those properties is to use +hasOwnProperty, it is already up to twenty times +slower than a normal for loop.

+ +

Iteration

+ +

In order to achieve the best performance when iterating over arrays, it is best +to use the classic for loop.

+ +
var list = [1, 2, 3, 4, 5, ...... 100000000];
+for(var i = 0, l = list.length; i < l; i++) {
+    console.log(list[i]);
+}
+
+ +

There is one extra catch in the above example, that is the caching of the +length of the array via l = list.length.

+ +

Although the length property is defined on the array itself, there is still an +overhead for doing the lookup on each iteration of the loop. And while recent +JavaScript engines may apply optimization in this case, there is no way of +telling whether the code will run on one of these newer engines or not.

+ +

In fact, leaving out the caching may result in the loop being only half as +fast as with the cached length.

+ +

The length Property

+ +

While the getter of the length property simply returns the number of +elements that are contained in the array, the setter can be used to +truncate the array.

+ +
var foo = [1, 2, 3, 4, 5, 6];
+foo.length = 3;
+foo; // [1, 2, 3]
+
+foo.length = 6;
+foo; // [1, 2, 3]
+
+ +

Assigning a smaller length does truncate the array, but increasing the length +does not have any effect on the array.

+ +

In Conclusion

+ +

For the best performance it is recommended to always use the plain for loop +and cache the length property. The use of for in on an array is a sign of +badly written code that is prone to bugs and bad performance.

The Array Constructor

Since the Array constructor is ambiguous in how it deals with its parameters, +it is highly recommended to always use the array literals - [] notation - +when creating new arrays.

+ +
[1, 2, 3]; // Result: [1, 2, 3]
+new Array(1, 2, 3); // Result: [1, 2, 3]
+
+[3]; // Result: [3]
+new Array(3); // Result: []
+new Array('3') // Result: ['3']
+
+ +

In cases when there is only one argument passed to the Array constructor, +and that argument is a Number, the constructor will return a new sparse +array with the length property set to the value of the argument. It should be +noted that only the length property of the new array will be set this way, +the actual indexes of the array will not be initialized.

+ +
var arr = new Array(3);
+arr[1]; // undefined
+1 in arr; // false, the index was not set
+
+ +

The behavior of being able to set the length of the array upfront only comes in +handy in a few cases, like repeating a string, in which it avoids the use of a +for loop code.

+ +
new Array(count + 1).join(stringToRepeat);
+
+ +

In Conclusion

+ +

The use of the Array constructor should be avoided as much as possible. +Literals are definitely preferred. They are shorter and have a clearer syntax; +therefore, they also increase the readability of the code.

Equality and Comparisons

JavaScript has two different ways of comparing the values of objects for equality.

+ +

The Equality Operator

+ +

The equality operator consists of two equal signs: ==

+ +

JavaScript features weak typing. This means that the equality operator +coerces types in order to compare them.

+ +
""           ==   "0"           // false
+0            ==   ""            // true
+0            ==   "0"           // true
+false        ==   "false"       // false
+false        ==   "0"           // true
+false        ==   undefined     // false
+false        ==   null          // false
+null         ==   undefined     // true
+" \t\r\n"    ==   0             // true
+
+ +

The above table shows the results of the type coercion and it is the main reason +why the use of == is widely regarded as bad practice, it introduces hard to +track down bugs due to its complicated conversion rules.

+ +

Additionally there is also a performance impact when type coercion is in play; +for example, a string has to be converted to a number before it can be compared +to another number.

+ +

The Strict Equality Operator

+ +

The strict equality operator consists of three equal signs: ===

+ +

It works exactly like the normal equality operator, except that strict equality +operator does not perform type coercion between its operands.

+ +
""           ===   "0"           // false
+0            ===   ""            // false
+0            ===   "0"           // false
+false        ===   "false"       // false
+false        ===   "0"           // false
+false        ===   undefined     // false
+false        ===   null          // false
+null         ===   undefined     // false
+" \t\r\n"    ===   0             // false
+
+ +

The above results are a lot clearer and allow for early breakage of code. This +hardens code to a certain degree and also gives performance improvements in case +the operands are of different types.

+ +

Comparing Objects

+ +

While both == and === are stated as equality operators, they behave +different when at least one of their operands happens to be an Object.

+ +
{} === {};                   // false
+new String('foo') === 'foo'; // false
+new Number(10) === 10;       // false
+var foo = {};
+foo === foo;                 // true
+
+ +

Here both operators compare for identity and not equality; that is, they +will compare for the same instance of the object, much like is in Python +and pointer comparison in C.

+ +

In Conclusion

+ +

It is highly recommended to only use the strict equality operator. In cases +where types need to be coerced, it should be done explicitly +and not left to the language's complicated coercion rules.

The typeof Operator

The typeof operator (together with +instanceof) is probably the biggest +design flaw of JavaScript, as it is near of being completely broken.

+ +

Although instanceof still has its limited uses, typeof really has only one +practical use case, which does not happen to be checking the type of an +object.

+ + + +

The JavaScript Type Table

+ +
Value               Class      Type
+-------------------------------------
+"foo"               String     string
+new String("foo")   String     object
+1.2                 Number     number
+new Number(1.2)     Number     object
+true                Boolean    boolean
+new Boolean(true)   Boolean    object
+new Date()          Date       object
+new Error()         Error      object
+[1,2,3]             Array      object
+new Array(1, 2, 3)  Array      object
+new Function("")    Function   function
+/abc/g              RegExp     object (function in Nitro/V8)
+new RegExp("meow")  RegExp     object (function in Nitro/V8)
+{}                  Object     object
+new Object()        Object     object
+
+ +

In the above table Type refers to the value, that the typeof operator returns. +As can be clearly seen, this value is anything but consistent.

+ +

The Class refers to the value of the internal [[Class]] property of an object.

+ + + +

In order to retrieve the value of [[Class]] one has to make use of the +toString method of Object.prototype.

+ +

The Class of an Object

+ +

The specification gives exactly one way of accessing the [[Class]] value, +with the use of Object.prototype.toString.

+ +
function is(type, obj) {
+    var clas = Object.prototype.toString.call(obj).slice(8, -1);
+    return obj !== undefined && obj !== null && clas === type;
+}
+
+is('String', 'test'); // true
+is('String', new String('test')); // true
+
+ +

In the above example, Object.prototype.toString gets called with the value of +this being set to the object whose [[Class]] value should be +retrieved.

+ + + +

Testing for Undefined Variables

+ +
typeof foo !== 'undefined'
+
+ +

The above will check whether foo was actually declared or not; just +referencing it would result in a ReferenceError. This is the only thing +typeof is actually useful for.

+ +

In Conclusion

+ +

In order to check the type of an object, it is highly recommended to use +Object.prototype.toString; as this is the only reliable way of doing so. +As shown in the above type table, some return values of typeof are not defined +in the specification; thus, they can differ across various implementations.

+ +

Unless checking whether a variable is defined, typeof should be avoided at +all costs.

The instanceof Operator

The instanceof operator compares the constructors of its two operands. It is +only useful when comparing custom made objects. Used on built-in types, it is +nearly as useless as the typeof operator.

+ +

Comparing Custom Objects

+ +
function Foo() {}
+function Bar() {}
+Bar.prototype = new Foo();
+
+new Bar() instanceof Bar; // true
+new Bar() instanceof Foo; // true
+
+// This just sets Bar.prototype to the function object Foo
+// But not to an actual instance of Foo
+Bar.prototype = Foo;
+new Bar() instanceof Foo; // false
+
+ +

Using instanceof with Native Types

+ +
new String('foo') instanceof String; // true
+new String('foo') instanceof Object; // true
+
+'foo' instanceof String; // false
+'foo' instanceof Object; // false
+
+ +

One important thing to note here is, that instanceof does not work on objects +that origin from different JavaScript contexts (e.g. different documents +in a web browser), since their constructors will not be the exact same object.

+ +

In Conclusion

+ +

The instanceof operator should only be used when dealing with custom made +objects that origin from the same JavaScript context. Just like the +typeof operator, every other use of it should be avoided.

Type Casting

JavaScript is a weakly typed language, so it will apply type coercion +wherever possible.

+ +
// These are true
+new Number(10) == 10; // Number.toString() is converted
+                      // back to a number
+
+10 == '10';           // Strings gets converted to Number
+10 == '+10 ';         // More string madness
+10 == '010';          // And more 
+isNaN(null) == false; // null converts to 0
+                      // which of course is not NaN
+
+// These are false
+10 == 010;
+10 == '-10';
+
+ + + +

In order to avoid the above, use of the strict equal operator +is highly recommended. Although this avoids a lot of common pitfalls, there +are still many further issues that arise from JavaScript's weak typing system.

+ +

Constructors of Built-In Types

+ +

The constructors of the built in types like Number and String behave +differently when being used with the new keyword and without it.

+ +
new Number(10) === 10;     // False, Object and Number
+Number(10) === 10;         // True, Number and Number
+new Number(10) + 0 === 10; // True, due to implicit conversion
+
+ +

Using a built-in type like Number as a constructor will create a new Number +object, but leaving out the new keyword will make the Number function behave +like a converter.

+ +

In addition, having literals or non-object values in there will result in even +more type coercion.

+ +

The best option is to cast to one of the three possible types explicitly.

+ +

Casting to a String

+ +
'' + 10 === '10'; // true
+
+ +

By prepending a empty string a value can easily be casted to a string.

+ +

Casting to a Number

+ +
+'10' === 10; // true
+
+ +

Using the unary plus operator it is possible to cast to a number.

+ +

Casting to a Boolean

+ +

By using the not operator twice, a value can be converted a boolean.

+ +
!!'foo';   // true
+!!'';      // false
+!!'0';     // true
+!!'1';     // true
+!!'-1'     // true
+!!{};      // true
+!!true;    // true
+

コア

Why Not to Use eval

The eval function will execute a string of JavaScript code in the local scope.

+ +
var foo = 1;
+function test() {
+    var foo = 2;
+    eval('foo = 3');
+    return foo;
+}
+test(); // 3
+foo; // 1
+
+ +

But eval only executes in local scope when it is being called directly and +the name of the called function is actually eval.

+ +
var foo = 1;
+function test() {
+    var foo = 2;
+    var bar = eval;
+    bar('foo = 3');
+    return foo;
+}
+test(); // 2
+foo; // 3
+
+ +

The use of eval should be avoided at all costs. 99.9% of its "uses" can be +achieved without it.

+ +

eval in Disguise

+ +

The timeout functions setTimeout and setInterval can both +take a string as their first argument. This string will always get executed +in the global scope since eval is not being called directly in that case.

+ +

Security Issues

+ +

eval also is a security problem as it executes any code given to it, +it should never be used with strings of unknown or untrusted origins.

+ +

In Conclusion

+ +

eval should never be used, any code that makes use of it is to be questioned in +its workings, performance and security. In case something requires eval in +order to work, its design is to be questioned and should not be used in the +first place, a better design should be used, that does not require the use of +eval.

undefined and null

JavaScript has two distinct values for nothing, the more useful of these two +being undefined.

+ +

The Value undefined

+ +

undefined is a type with exactly one value: undefined.

+ +

The language also defines a global variable that has the value of undefined, +this variable is also called undefined. But this variable is not a constant, +nor is it a keyword of the language. This means that its value can be easily +overwritten.

+ + + +

Some examples for when the value undefined is returned:

+ +
    +
  • Accessing the (unmodified) global variable undefined.
  • +
  • Implicit returns of functions due to missing return statements.
  • +
  • return statements which do not explicitly return anything.
  • +
  • Lookups of non-existent properties.
  • +
  • Function parameters which do not had any explicit value passed.
  • +
  • Anything that has been set to the value of undefined.
  • +
+ +

Handling Changes to the Value of undefined

+ +

Since the global variable undefined only holds a copy of the actual value of +undefined, assigning a new value to it does not change the value of the +type undefined.

+ +

Still, in order to compare something against the value of undefined it is +necessary to retrieve the value of undefined first.

+ +

In order to protect code against a possible overwritten undefined variable, a +common technique used is to add an additional parameter to an +anonymous wrapper, that gets no argument passed to it.

+ +
var undefined = 123;
+(function(something, foo, undefined) {
+    // undefined in the local scope does 
+    // now again refer to the value
+
+})('Hello World', 42);
+
+ +

Another way to achieve the same effect would be to use a declaration inside the +wrapper.

+ +
var undefined = 123;
+(function(something, foo) {
+    var undefined;
+    ...
+
+})('Hello World', 42);
+
+ +

The only difference being here, that this version results in 4 more bytes being +used in case it is minified and there is no other var statement inside the +anonymous wrapper.

+ +

Uses of null

+ +

While undefined in the context of the JavaScript language is mostly used in +the sense of a traditional null, the actual null (both a literal and a type) +is more or less just another data type.

+ +

It is used in some JavaScript internals (like declaring the end of the +prototype chain by setting Foo.prototype = null), but in almost all cases it +can be replaced by undefined.

Automatic Semicolon Insertion

Although JavaScript has C style syntax, it does not enforce the use of +semicolons in the source code, it is possible to omit them.

+ +

But JavaScript is not a semicolon-less language, it in fact needs the +semicolons in order to understand the source code. Therefore the JavaScript +parser automatically inserts them whenever it encounters a parse +error due to a missing semicolon.

+ +
var foo = function() {
+} // parse error, semicolon expected
+test()
+
+ +

Insertion happens, and the parser tries again.

+ +
var foo = function() {
+}; // no error, parser continues
+test()
+
+ +

The automatic insertion of semicolon is considered to be one of biggest +design flaws in the language, as it can change the behavior of code.

+ +

How it Works

+ +

The code below has no semicolons in it, so it is up to the parser to decide where +to insert them.

+ +
(function(window, undefined) {
+    function test(options) {
+        log('testing!')
+
+        (options.list || []).forEach(function(i) {
+
+        })
+
+        options.value.test(
+            'long string to pass here',
+            'and another long string to pass'
+        )
+
+        return
+        {
+            foo: function() {}
+        }
+    }
+    window.test = test
+
+})(window)
+
+(function(window) {
+    window.someLibrary = {}
+
+})(window)
+
+ +

Below is the result of the parser's "guessing" game.

+ +
(function(window, undefined) {
+    function test(options) {
+
+        // Not inserted, lines got merged
+        log('testing!')(options.list || []).forEach(function(i) {
+
+        }); // <- inserted
+
+        options.value.test(
+            'long string to pass here',
+            'and another long string to pass'
+        ); // <- inserted
+
+        return; // <- inserted, breaks the return statement
+        { // treated as a block
+
+            // a label and a single expression statement
+            foo: function() {} 
+        }; // <- inserted
+    }
+    window.test = test; // <- inserted
+
+// The lines got merged again
+})(window)(function(window) {
+    window.someLibrary = {}; // <- inserted
+
+})(window); //<- inserted
+
+ + + +

The parser drastically changed the behavior of the code above, in certain cases +it does the wrong thing.

+ +

Leading Parenthesis

+ +

In case of a leading parenthesis, the parser will not insert a semicolon.

+ +
log('testing!')
+(options.list || []).forEach(function(i) {})
+
+ +

This code gets transformed into one line.

+ +
log('testing!')(options.list || []).forEach(function(i) {})
+
+ +

Chances are very high that log does not return a function; therefore, +the above will yield a TypeError stating that undefined is not a function.

+ +

In Conclusion

+ +

It is highly recommended to never omit semicolons, it is also advocated to +keep braces on the same line with their corresponding statements and to never omit +them for one single-line if / else statements. Both of these measures will +not only improve the consistency of the code, they will also prevent the +JavaScript parser from changing its behavior.

その他

setTimeout and setInterval

Since JavaScript is asynchronous, it is possible to schedule the execution of a +function by using the setTimeout and setInterval functions.

+ + + +
function foo() {}
+var id = setTimeout(foo, 1000); // returns a Number > 0
+
+ +

When setTimeout gets called, it will return the ID of the timeout and schedule +foo to run in approximately one thousand milliseconds in the future. +foo will then get executed exactly once.

+ +

Depending on the timer resolution of the JavaScript engine that is running the +code, as well as the fact that JavaScript is single threaded and other code that +gets executed might block the thread, it is by no means a safe bet that one +will get the exact delay that was specified in the setTimeout call.

+ +

The function that was passed as the first parameter will get called by the +global object, that means, that this inside the called function +refers to that very object.

+ +
function Foo() {
+    this.value = 42;
+    this.method = function() {
+        // this refers to the global object
+        console.log(this.value); // will log undefined
+    };
+    setTimeout(this.method, 500);
+}
+new Foo();
+
+ + + +

Stacking Calls with setInterval

+ +

While setTimeout only runs the function once, setInterval - as the name +suggests - will execute the function every X milliseconds. But its use is +discouraged.

+ +

When code that is being executed blocks the timeout call, setInterval will +still issue more calls to the specified function. This can, especially with small +intervals, result in function calls stacking up.

+ +
function foo(){
+    // something that blocks for 1 second
+}
+setInterval(foo, 100);
+
+ +

In the above code foo will get called once and will then block for one second.

+ +

While foo blocks the code setInterval will still schedule further calls to +it. Now, when foo has finished, there will already be ten further calls to +it waiting for execution.

+ +

Dealing with Possible Blocking Code

+ +

The easiest as well as most controllable solution, is to use setTimeout within +the function itself.

+ +
function foo(){
+    // something that blocks for 1 second
+    setTimeout(foo, 100);
+}
+foo();
+
+ +

Not only does this encapsulate the setTimeout call, but it also prevents the +stacking of calls and it gives additional control.foo itself can now decide +whether it wants to run again or not.

+ +

Manually Clearing Timeouts

+ +

Clearing timeouts and intervals works by passing the respective ID to +clearTimeout or clearInterval, depending which set function was used in +the first place.

+ +
var id = setTimeout(foo, 1000);
+clearTimeout(id);
+
+ +

Clearing all timeouts

+ +

As there is no built-in method for clearing all timeouts and/or intervals, +it is necessary to use brute force in order to achieve this functionality.

+ +
// clear "all" timeouts
+for(var i = 1; i < 1000; i++) {
+    clearTimeout(i);
+}
+
+ +

There might still be timeouts that are unaffected by this arbitrary number; +therefore, is is instead recommended to keep track of all the timeout IDs, so +they can be cleared specifically.

+ +

Hidden use of eval

+ +

setTimeout and setInterval can also take a string as their first parameter. +This feature should never be used, since it internally makes use of eval.

+ + + +
function foo() {
+    // will get called
+}
+
+function bar() {
+    function foo() {
+        // never gets called
+    }
+    setTimeout('foo()', 1000);
+}
+bar();
+
+ +

Since eval is not getting called directly in this case, the string +passed to setTimeout will get executed in the global scope; thus, it will +not use the local variable foo from the scope of bar.

+ +

It is further recommended to not use a string for passing arguments to the +function that will get called by either of the timeout functions.

+ +
function foo(a, b, c) {}
+
+// NEVER use this
+setTimeout('foo(1,2, 3)', 1000)
+
+// Instead use an anonymous function
+setTimeout(function() {
+    foo(a, b, c);
+}, 1000)
+
+ + + +

In Conclusion

+ +

Never should a string be used as the parameter of setTimeout or +setInterval. It is a clear sign of really bad code, when arguments need +to be supplied to the function that gets called. An anonymous function should +be passed that then takes care of the actual call.

+ +

Further, the use of setInterval should be avoided since its scheduler is not +blocked by executing JavaScript.

\ No newline at end of file From 292e3e01065d6db9117e45f05f1089d372685cc1 Mon Sep 17 00:00:00 2001 From: Satoru HIRAKI Date: Sat, 2 Jul 2011 23:11:26 +0900 Subject: [PATCH 019/463] Translate Intro to Japanese --- doc/ja/intro/index.md | 40 ++++++++++++++++------------------------ site/ja/index.html | 37 ++++++++++++++----------------------- 2 files changed, 30 insertions(+), 47 deletions(-) diff --git a/doc/ja/intro/index.md b/doc/ja/intro/index.md index 6ddd7c71..7928eadb 100644 --- a/doc/ja/intro/index.md +++ b/doc/ja/intro/index.md @@ -1,37 +1,29 @@ -## Intro +## 前書き -**JavaScript Garden** is a growing collection of documentation about the most -quirky parts of the JavaScript programming language. It gives advice to -avoid common mistakes, subtle bugs, as well as performance issues and bad -practices that non-expert JavaScript programmers may encounter on their -endeavours into the depths of the language. +**JavaScript Garden** はJavaScriptというプログラム言語の一番奇抜な部分についてのドキュメント集です。 +このドキュメントはJavaScriptという言語に対して不慣れなプログラマーがこの言語について深く知ろうとする際に遭遇する、良くある間違い・小さなバグ・パフォーマンスの問題・悪い習慣などを避ける為のアドバイスを与えます。 -JavaScript Garden does **not** aim to teach you JavaScript. Former knowledge -of the language is strongly recommended in order to understand the topics covered -in this guide. In order to learn the basics of the language, please head over to -the excellent [guide][1] on the Mozilla Developer Network. +JavaScript GardenはJavaScriptを教える事を**目的にしていません**。このガイドの項目を理解する為には、この言語に対する前提知識がある事を推奨します。この言語の基礎部分についてはMozilla Developer Networkの[ガイド][1] がオススメです。 -## The Authors +## 著者 -This guide is the work of two lovely [Stack Overflow][2] users, [Ivo Wetzel][3] -(Writing) and [Zhang Yi Jiang][4] (Design). +このガイドは2人の愛すべき[Stack Overflow][2]ユーザーである[Ivo Wetzel][3] +(執筆)と[Zhang Yi Jiang][4] (デザイン)によって作られました。 -## Contributors +## 貢献者 - - [Caio Romão][5] (Spelling corrections) - - [Andreas Blixt][6] (Language corrections) + - [Caio Romão][5] (スペル校正) + - [Andreas Blixt][6] (言語校正) -## Hosting +## ホスティング -JavaScript Garden is hosted on GitHub, but [Cramer Development][7] supports us -with a mirror at [JavaScriptGarden.info][8]. +JavaScript GardenはGitHubでホスティングされていますが、[Cramer Development][7]が[JavaScriptGarden.info][8]というミラーサイトを作ってくれています。 -## License +## ライセンス + +JavaScript Gardenは[MIT license][9]の下で公開されており、[GitHub][10]でホスティングされています。もしもエラーやtypoを見つけたら[file an issue][11]に登録するかレポジトリにプルリクエストを送ってください。 +またStack Overflowチャットの[JavaScript room][12]に私達はいます。 -JavaScript Garden is published under the [MIT license][9] and hosted on -[GitHub][10]. If you find errors or typos please [file an issue][11] or a pull -request on the repository. You can also find us in the [JavaScript room][12] on -Stack Overflow chat. [1]: https://developer.mozilla.org/en/JavaScript/Guide [2]: http://stackoverflow.com/ diff --git a/site/ja/index.html b/site/ja/index.html index 60e5d1c9..ff9f4bb6 100644 --- a/site/ja/index.html +++ b/site/ja/index.html @@ -1,40 +1,31 @@ JavaScript Garden -

イントロ

JavaScript Garden is a growing collection of documentation about the most -quirky parts of the JavaScript programming language. It gives advice to -avoid common mistakes, subtle bugs, as well as performance issues and bad -practices that non-expert JavaScript programmers may encounter on their -endeavours into the depths of the language.

+

前書き

JavaScript Garden はJavaScriptというプログラム言語の一番奇抜な部分についてのドキュメント集です。 +このドキュメントはJavaScriptという言語に対して不慣れなプログラマーがこの言語について深く知ろうとする際に遭遇する、良くある間違い・小さなバグ・パフォーマンスの問題・悪い習慣などを避ける為のアドバイスを与えます。

-

JavaScript Garden does not aim to teach you JavaScript. Former knowledge -of the language is strongly recommended in order to understand the topics covered -in this guide. In order to learn the basics of the language, please head over to -the excellent guide on the Mozilla Developer Network.

+

JavaScript GardenはJavaScriptを教える事を目的にしていません。このガイドの項目を理解する為には、この言語に対する前提知識がある事を推奨します。この言語の基礎部分についてはMozilla Developer Networkのガイド がオススメです。

-

The Authors

+

著者

-

This guide is the work of two lovely Stack Overflow users, Ivo Wetzel -(Writing) and Zhang Yi Jiang (Design).

+

このガイドは2人の愛すべきStack OverflowユーザーであるIvo Wetzel +(執筆)とZhang Yi Jiang (デザイン)によって作られました。

-

Contributors

+

貢献者

-

Hosting

+

ホスティング

-

JavaScript Garden is hosted on GitHub, but Cramer Development supports us -with a mirror at JavaScriptGarden.info.

+

JavaScript GardenはGitHubでホスティングされていますが、Cramer DevelopmentJavaScriptGarden.infoというミラーサイトを作ってくれています。

-

License

+

ライセンス

-

JavaScript Garden is published under the MIT license and hosted on -GitHub. If you find errors or typos please file an issue or a pull -request on the repository. You can also find us in the JavaScript room on -Stack Overflow chat.

オブジェクト

Object Usage and Properties

Everything in JavaScript acts like an object, with the only two exceptions being +

JavaScript GardenはMIT licenseの下で公開されており、GitHubでホスティングされています。もしもエラーやtypoを見つけたらfile an issueに登録するかレポジトリにプルリクエストを送ってください。 +またStack OverflowチャットのJavaScript roomに私達はいます。

オブジェクト

Object Usage and Properties

Everything in JavaScript acts like an object, with the only two exceptions being null and undefined.

false.toString() // 'false'

From b0ec092a040f7174c286142e261176794084fb37 Mon Sep 17 00:00:00 2001
From: Satoru HIRAKI 
Date: Sat, 2 Jul 2011 23:11:42 +0900
Subject: [PATCH 020/463] Fix intro in index.json

---
 doc/ja/index.json | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/doc/ja/index.json b/doc/ja/index.json
index 85e25a6b..cea3fb99 100644
--- a/doc/ja/index.json
+++ b/doc/ja/index.json
@@ -4,7 +4,7 @@
     "description": "JavaScriptの奇抜さと欠陥についてのガイドライン",
     "sections": [
         {
-            "title": "イントロ",
+            "title": "前書き",
             "dir": "intro",
             "articles": []
         },

From 843b159e60daf0609f4a2cecb5eb85059e0d542e Mon Sep 17 00:00:00 2001
From: Satoru HIRAKI 
Date: Sun, 3 Jul 2011 00:05:22 +0900
Subject: [PATCH 021/463] fix typo

---
 doc/ja/intro/index.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/doc/ja/intro/index.md b/doc/ja/intro/index.md
index 7928eadb..b2fcfb3c 100644
--- a/doc/ja/intro/index.md
+++ b/doc/ja/intro/index.md
@@ -21,7 +21,7 @@ JavaScript GardenはGitHubでホスティングされていますが、[Cramer D
 
 ## ライセンス
 
-JavaScript Gardenは[MIT license][9]の下で公開されており、[GitHub][10]でホスティングされています。もしもエラーやtypoを見つけたら[file an issue][11]に登録するかレポジトリにプルリクエストを送ってください。
+JavaScript Gardenは[MIT license][9]の下で公開されており、[GitHub][10]でホスティングされています。もしもエラーやtypoを見つけたら[file an issue][11]に登録するかリポジトリにプルリクエストを送ってください。
 またStack Overflowチャットの[JavaScript room][12]に私達はいます。
 
 

From f2082d261b5fa806a5cac511ec1d7dd705dfb6d6 Mon Sep 17 00:00:00 2001
From: Satoru HIRAKI 
Date: Sun, 3 Jul 2011 00:07:37 +0900
Subject: [PATCH 022/463] build pl/index.html I don't know why...

---
 site/pl/index.html | 1914 ++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 1914 insertions(+)
 create mode 100644 site/pl/index.html

diff --git a/site/pl/index.html b/site/pl/index.html
new file mode 100644
index 00000000..cfeeb4fa
--- /dev/null
+++ b/site/pl/index.html
@@ -0,0 +1,1914 @@
+JavaScript Garden
+

Wstęp

JavaScript Garden jest rosnącą kolekcją dokumentów o najdziwniejszych +częściach języka JavaScript. Dokumentacja pomaga uniknąć najczęściej popełnianych +błędów, sybtelnych bugów, problemów wydajnościowych oraz złych praktyk, na które +niedoświadczeni programiści JavaScript mogą natrafić próbując poznać tajniki tego +języka.

+ +

JavaScript Garden nie ma na celu nauczyć Cię języka JavaScript. Podstawowa +wiedza na temat języka jest wymagana do zrozumienia zagadnień poruszanych w tym +przewodniku. Aby nauczyć się podstaw jezyka JavaScript, odwiedź znakomity +przewodnik na stronach Mozilla Developer Network.

Licencja

JavaScript Garden jest publikowany w ramach licencji MIT i kod źródłowy znajduje +się na serwerze GitHub. Jeśli znajdziesz jakieś błędy lub literówek zgłoś proszę +problem lub rozwiązag go i zglosić pull request ze swojego repozytorium. +Możesz nas także znaleźć w pokoju JavaScript na chacie Stack Overflow.

Obiekty

Wykorzystanie obiektów i ich właściwości

Wszystko w JavaScripcie zachowuje sie jak obiekt, z dwoma wyjątkami +null oraz undefined.

+ +
false.toString() // 'false'
+[1, 2, 3].toString(); // '1,2,3'
+
+function Foo(){}
+Foo.bar = 1;
+Foo.bar; // 1
+
+ +

Popularnym błędem jest wykorzystanie literałów liczbowych jako obiektu. +Spowodowanie jest to usterką w parserze JavaScript, który interpretuje kropkę +po literale liczbowym jako rozdzielenie części całkowitej od części po przecinku +liczby.

+ +
2.toString(); // wyrzuca błąd SyntaxError
+
+ +

Istnieje kilka rozwiązań, dzieki którym literał liczbowy będzie zachowywał się +jak obiekt.

+ +
2..toString(); // druga kropka jest poprawnie rozpoznana
+2 .toString(); // zauważ, że pozostawiona jest spacja przed kropką
+(2).toString(); // 2 zostanie zewaluowane najpiewr
+
+ +

Obiekty jako typy danych

+ +

Obiekty w języku JavaScript mogą być używana jako tablice asocjacyjne. +Ponieważ obiekty głównie składają się z mapowań pomiędzy nazwanymi właściwościami (kluczami) +a wartościami dla tych atrybutów.

+ +

Używając literału obiektu - notacji {} - istnieje możliwość stworzenie obiektu prostego. +Ten nowy obiekt bedzie dziedziczył z Object.prototype oraz +nie bedzie posiadał żadnych własnych właściwości zdefiniowanych w sobie.

+ +
var foo = {}; // nowy pusty obiekt
+
+// nowy obiekt z właściwością test o wartości 12
+var bar = {test: 12}; 
+
+ +

Dostęp do właściwości

+ +

Właściwości obiektu można uzyskać na dwa sposoby, poprzez notację z kropką +lub notacje z nawiasami kwadratowymi.

+ +
var foo = {name: 'Kitten'}
+foo.name; // kitten
+foo['name']; // kitten
+
+var get = 'name';
+foo[get]; // kitten
+
+foo.1234; // wyrzuca błąd SyntaxError
+foo['1234']; // działa, zwraca undefined
+
+ +

Obie notacje są identyczne w swoim działaniu, z tą tylko różnicą że notacja z nawiasami +kwadratowymi pozwala na dynamiczne dodawanie właściwości i nie prowadzi do wyrzycenia +błędu podczas odczytu nieistniejącej właściwości.

+ +

Usuwanie właściwości

+ +

Jedynym sposobem na faktycze usunięcie własności z obiektu jest użycie operatora +delete. Ustawienie własności na undefined lub null usunie tylko wartość +związaną z własnością, ale nie usunie to klucza (nazwy własności) z obiektu.

+ +
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]);
+    }
+}
+
+ +

Powyższy kod wypisuje dwie linie bar undefined i foo null - tylko własność baz +została usunięta i dlatego nie została wypisana.

+ +

Notacja właściwości

+ +
var test = {
+    'case': 'I am a keyword so I must be notated as a string',
+    delete: 'I am a keyword too so me' // wyrzuca błąd SyntaxError
+};
+
+ +

Nazwy właściwości obiektu mogą być zarówno zapisane jako tekst(bez cudzysłowów +lub apostrofów) lub jako string (w cudzisłowach lub apostrofach). +Ze względu na kolejne niedociągnięcie w parserze JavaScript +powyższy kod wyrzuci błąd SyntaxError dla implementacji JavaScript ponizej ECMAScript 5.

+ +

Ten błąd wynika z faktu, że delete jest słowem kluczowym, dlatego musi zostać +zapisany jako string (z cudzysłowami lub apostrofami), aby zapewnić, że zostanie +to poprawnie zinterpretowane przez starsze silniki języka JavaScript.

Prototyp

JavaScript nie posiada klasycznego modelu dziedziczenia, lecz zamiast tego +dziedziczenie jest realizowane poprzez prototypy.

+ +

Choć jest to często uważane za jedną ze słabości języka JavaScript, +prototypowy model dziedziczenia, jest w rzeczywistości potężniejszy od klasycznego +modelu. Na przykład stworzenia klasycznego modelu na podstawie modelu prototypowym +jest dość proste, podczas gdy zrobienie odwrotnie to już o wiele trudniejsze zadanie.

+ +

Ze względu na fakt, że w JavaScript jest w zasadzie jedynym powszechnie stosowanym +językiem, któy posiada prototypowy model dziedziczenia, to wymaga troche czasu aby +dostosować się do różnic pomiędzy tymi dwoma modelami.

+ +

Pierwszą znaczącą różnicą jest to, że dziedziczenie w JavaScript odbywa się za pomocą +tak zwanych łańcuchów prototypów.

+ + + +
function Foo() {
+    this.value = 42;
+}
+Foo.prototype = {
+    method: function() {}
+};
+
+function Bar() {}
+
+// Ustawienie prototypu Bar na nową instancję Foo
+Bar.prototype = new Foo();
+Bar.prototype.foo = 'Hello World';
+
+// Upewniamy się, że Bar jest ustawiony jako rzeczywisty konstruktor
+Bar.prototype.constructor = Bar;
+
+var test = new Bar() // tworzymy nową instancję Bar
+
+// The resulting prototype chain
+test [instance of Bar]
+    Bar.prototype [instance of Foo] 
+        { foo: 'Hello World' }
+        Foo.prototype
+            { method: ... }
+            Object.prototype
+                { toString: ... /* etc. */ }
+
+ +

W powyższym przykładzie obiekt test będzie dziedziczył z obydwu tj. +Bar.prototyp i Foo.prototyp, stąd będzie miał dostęp do funkcji method, +która była zdefiniowana w Foo. Ponadto obiekt będzie miał dostęp do +właściwości value, która jest jednyną instancją Foo i stała się jego prototypem. +Ważne jest, aby pamiętać new Bar nie tworzy nowej instancji Foo, +ale wykorzystuje instancje, którą jest przypisana do własności prototype. +Zatem Wszystkie instancje Bar będą dzieliły tą samą własność value.

+ + + +

Wyszukiwanie własności

+ +

Podczas dostępu do właściwości obiektu, JavaScript przejdzie w górę łańcucha +prototypów dopóki nie znajdzie właściwości z żądaną nazwą.

+ +

Gdy przeszukiwanie dotrze do końca (szczytu) łańcucha mianowicie Object.prototype +i nadal nie znajdzie określonej właściwości, to zwróci wartość +undefined.

+ +

Właściwość prototype

+ +

Podczas gdy właściwość prototype jest używana przez język do budowania łańcucha +prototypów, istnieje możliwość przypisania do niej dowolnej wartości. Jednakże +prymitywne typy będą po prostu ignorowanie, jeżeli zostaną ustawione jako prototype.

+ +
function Foo() {}
+Foo.prototype = 1; // nie ma wpływu
+
+ +

Przypisywanie obiektów, jak pokazano w powyższym przykładzie, zadziała i pozwala +na dynamiczne tworzenie łańcuchów prototypów.

+ +

Wydajność

+ +

Czas wyszukiwania właściwości, które są na końcu łańcucha prototypów może mieć +negatywny wpływ na wydajność krytycznych części kodu. Dodatkowo, próba dostępu +do nieistniejącej właściwości powoduje zawsze przeszukanie całego łańcucha prototypów.

+ +

Również, podczas iteracji po właściwościach obiektu +każda właściwość, która znajduje się w łańcuchu prototypów niezależnie +na jakim znajduje się poziomie zostanie wyliczona.

+ +

Rozszerzanie natywnych prototypów

+ +

Rozszerzanie Object.prototype lub innego prototypu wbudowanych typów jest jednym z +najczęściej używanych niedoskonałej częsci języka JavaScript.

+ +

Technika ta nazywana jest monkey patching i łamie zasady enkapsulacji. +Jednak jest szeroko rozpowszechniona w frameworkach takich jak Prototype. +Nie ma jednak dobrego powodu, aby zaśmiecać wbudowane typy poprzez dodawanie do nich +niestandardowych funkcjonalności.

+ +

Jedynym dobrym powodem do rozszerzania wbudowanych prototypów jest portowanie
+funkcjonalności znajdujących sie w nowszych silnikach JavaScript np. Array.forEach

+ +

Wnioski

+ +

Zanim przystąpi się do pisania skomplikowanego kodu korzystającego z dziedziczanie +należy całkowicie rozumieć prototypowy model dziedziczenia. Ponadto należy uważać +na długość łańcucha prototypów i w razie potrzeby zmniejszać ilość dziedziczeń +aby uniknąć problemów z wydajnością. Natywne prototypy nie powinny nigdy być +rozszerzane, chyba że ze względu na wprowadzanie kompatybilności z nowszymi silnikami +JavaScript.

hasOwnProperty

W celu sprawdzenia czy dana właściwość została zdefiniowana w tym obiekcie a nie +w łańcuchu prototypów niezbędne jest skorzystanie z metody +hasOwnProperty, która wszystkie obiekty dziedziczą z Object.prototype.

+ + + +

hasOwnProperty jest jedyna metodą w języku JavaScript która operuje na właściwościach +i nie przegląda całego łańcucha prototypów.

+ +
// Zatrucie Object.prototype
+Object.prototype.bar = 1; 
+var foo = {goo: undefined};
+
+foo.bar; // 1
+'bar' in foo; // true
+
+foo.hasOwnProperty('bar'); // false
+foo.hasOwnProperty('goo'); // true
+
+ +

Tylko hasOwnProperty da prawidłowy i oczekiwany rezultat. Jest to istotne podczas +iteracji po właściwościach obiektu. Nie ma innego sposobu na ominięcie +właściwości, która nie została zdefiniowana przez ten konkretny obiekt, +ale gdzieś indziej w łańcuchu prototypów.

+ +

hasOwnProperty jako właściwość

+ +

JavaScript nie chroni właściwości o nazwie hasOwnProperty, zatem istnieje +możliwość, że obiekt może posiadać tak nazwaną właściwość. Konieczne jest użycie +zewnętrznego hasOwnProperty, aby otrzymać poprawne rezultaty.

+ +
var foo = {
+    hasOwnProperty: function() {
+        return false;
+    },
+    bar: 'Here be dragons'
+};
+
+foo.hasOwnProperty('bar'); // zawsze zwraca false
+
+// Została użyta metoda innego obiektu i wywołana z konkekstem 
+// `this` ustawionym na foo
+({}).hasOwnProperty.call(foo, 'bar'); // true
+
+ +

Wnioski

+ +

Jedyną metodą służącą do sprawdzenia zdefiniowania jakiejś właściwości w konkretnym +obiekcie jest metoda hasOwnProperty. Zaleca się korzystać z hasOwnProperty jako część +każdej pętli for in, pozwoli to uniknąć błędów pochodzących z +rozszerzonych natywnych prototypów.

The for in Loop

Podobnie jak operator in, pętla for in przeszukuje łańcuch prototypów +podczas iteracji po właściwościach obiektu.

+ + + +
// Zatrucie Object.prototype
+Object.prototype.bar = 1;
+
+var foo = {moo: 2};
+for(var i in foo) {
+    console.log(i); // wyświetla obie właściwości: bar i moo
+}
+
+ +

Ponieważ nie jest możliwe, aby zmienić zachowanie pętli for in to niezbędne +jest odfiltrowanie niechcianych właściwości wewnątrz ciała pętli, korzystając +z metody hasOwnProperty z Object.prototype.

+ + + +

Korzystanie z hasOwnProperty do odfiltrowania

+ +
// foo z przykładu powyżej
+for(var i in foo) {
+    if (foo.hasOwnProperty(i)) {
+        console.log(i);
+    }
+}
+
+ +

To jest jedyna poprawna wersja, którą należy używać. Ze względu na użycie +hasOwnProperty zostanie wypisane jedynie moo. Gdy opuścimy hasOwnProperty +kod będzie podatny na błędy, gdy natywne prototypy np. Object.prototype +zostanie rozszerzony.

+ +

Prototype jest jednym z szeroko rozpowszechniony frameworków, który dokonuje +takiego rozszerzenia. Używanie tego frameworku oraz nie używanie w pętle for in +metody hasOwnProperty gwarantuje błędy w wykonaniu.

+ +

Wnioski

+ +

Zaleca się aby zawsze używać metody hasOwnProperty. Nigdy nie powinno się dokonywać +żadnych założeń na temat środowiska, w którym kod będzie wykonywany i czy natywne +prototypy zostały rozszerzone czy nie.

Funkcje

Deklaracje funkcji i wyrażenia funkcyjne

Funcje w języku JavaScript są typami pierwszoklasowymi. Co oznacza, że mogą +być przekazywane jak każda inna wartość. Jednym z typowych zastosowań tej cechy +jest przekazywanie anonimowej funkcji jako callback do innej, prawdopodobnie +asynchronicznej funkcji.

+ +

Deklaracja funckcji

+ +
function foo() {}
+
+ +

Powyższa funkcja zostaje wyniesiona zanim program wystartuje, dzięki temu +jest dostępna wszędzie w ramach zasięgu, w którym została zadeklarowana, +nawet jeżeli ta funkcja została wywołana przed faktyczną definicją w kodzie źródłowym.

+ +
foo(); // Działa ponieważ definicja funkcji została wyniesiona 
+       // na początek zasięgu przed uruchomieniem kodu
+function foo() {}
+
+ +

Wyrażenie funkcyjne

+ +
var foo = function() {};
+
+ +

Ten przykład przypisuje nienazwaną i anonimową funkcję do zmiennej foo.

+ +
foo; // 'undefined'
+foo(); // wyrzuca błąd TypeError
+var foo = function() {};
+
+ +

Ze względu na fakt, że deklaracja var wynosi zmienną foo na początek zasięgu, +zanim kod faktycznie zostanie uruchomiony, foo będzie zdefiniowane kiedy skrypt +będzie wykonywany.

+ +

Ale ponieważ przypisania robione są dopiero podczas wykonania, wartość foo będzie +ustawiona na domyślną wartość undefined zanim powyższy kod +zostanie uruchomiony.

+ +

Nazwane wyrażenia funkdyjne

+ +

Kolejnym specjalnym przypadkiem jest przypisanie nazwanej funkcji.

+ +
var foo = function bar() {
+    bar(); // Działa
+}
+bar(); // wyrzuca ReferenceError
+
+ +

W zewnętrznym zakresie bar nie będzie dostępne, ponieważ funkcja zostaje +przypisana do foo, jednakże w wewnętrznym zakresie bar będzie dostępna. +Jest to spowodowane tym, jak działa rozwiązywanie nazw +w języku JavaScript. Nazwa funkcji jest zawsze dostępna w lokalnym +zakresie tej funkcji.

Jak działa this

JavaScript posiada inną koncepcję odnośnie tego na co wskazuje specjalna +nazwa this, niż większość innych języków programowania. Istnieją dokładnie +pięć różnych sytuacji w których wartość this zostaje przypisana w języku JavaScript.

+ +

JavaScript has a different concept of what the special name this refers to +than most other programming languages do. There are exactly five different +ways in which the value of this can be bound in the language.

+ +

Zasięg globalny

+ +
this;
+
+ +

Używanie this w globalnym zasięgu, zwróci po prostu referencje do obiektu global.

+ +

Wywołanie funkcji

+ +
foo();
+
+ +

Tutaj this również będzie wkazywało na obiekt global

+ + + +

Wywoływanie metody

+ +
test.foo(); 
+
+ +

W tym przypadku this będzie wskazywało na test.

+ +

Wywołanie konstruktora

+ +
new foo(); 
+
+ +

Wywołanie funkcji, które jest poprzedzone słowem kluczowym new zachowuje się +jak konstruktor. Wewnątrz funkcji this będzie +wskazywało na nowo utworzony obiekt.

+ +

Jawne ustawienie this

+ +
function foo(a, b, c) {}
+
+var bar = {};
+foo.apply(bar, [1, 2, 3]); // tablica zostanie zamieniona w to co poniżej
+foo.call(bar, 1, 2, 3); // rezultat a = 1, b = 2, c = 3
+
+ +

Używając metod call lub apply z prototypu Function.prototype, wartość this +wewnątrz wołanej funkcji zostanie jawnie ustawiona na pierwszy argument przekazany +podczas wywołania tych metod.

+ +

Zatem w powyższym przykładzie przypadek Wywoływanie metody nie będzie miał +miejsca i this wewnątrz foo będzie wskazywać na bar.

+ + + +

Częste pułapki

+ +

Mimo iż Większość z tych przypadków ma sens, to pierwszy przypadek powinien być +traktorany jako błąd podczas projektowania języka i nigdy nie wykorzystywany +w praktyce.

+ +
Foo.method = function() {
+    function test() {
+        // wewnątrz tej funkcji this wskazuje na obiekt global
+    }
+    test();
+}
+
+ +

Powszechnym nieporozumieniem jest, że this wewnątrz test wskazuje na Foo, +podczas gdy w rzeczywistości tak nie jest.

+ +

Aby uzyskać dostęp do Foo wewnątrz test niezbędne jest stworzenie wewnątrz +metody lokalnej zmiennej, która będzie wskazywała na Foo.

+ +
Foo.method = function() {
+    var that = this;
+    function test() {
+        // Należy używać that zamiast this wewnątrz tej funkcji
+    }
+    test();
+}
+
+ +

that jest zwykłą zmienną, ale jest to powszechnie stosowana konwencja, aby otrzymać +wartość zewnętrznego this. W połączeniu z domknięciami(closures) +jest to sposób na przekazywanie wartości this wokoło.

+ +

Metody przypisywania

+ +

Kolejną rzeczą, która nie działa w języku JavaScript jest nadawanie aliasów +funkcjom, co oznacza przypisanie metody do zmiennej.

+ +
var test = someObject.methodTest;
+test();
+
+ +

Podobnie jak w pierwszym przypadku test zachowuje się jak wywołanie zwykłej +funkcji, a zatem wewnątrz funkcji this już nie będzie wskazywało someObject.

+ +

Podczas gdy późne wiązanie this może się na początku wydawać złym pomysłem, +to w rzeczywistości jest to rzecz, która powoduje że +dziedziczenie prototypowe działa.

+ +
function Foo() {}
+Foo.prototype.method = function() {};
+
+function Bar() {}
+Bar.prototype = Foo.prototype;
+
+new Bar().method();
+
+ +

Kiedy metoda method zostanie wywołana na instancji Bar, this będzie +wskazywało właśnie tą instancję.

Domknięcia i referencje

Jedną z najpotężniejszych funkcjonalności języka JavaScript są domknięcia, +oznacza to że zasięg zawsze posiada dostęp do zewnętrznego zasięgu w którym +został zdefiniowany. Ponieważ zasięg w JavaScript można definiować tylko poprzez +funckję, wszystkie funkcje domyślnie zachowują się jak domknięcia.

+ +

Emulowanie prywatnych zmiennych

+ +
function Counter(start) {
+    var count = start;
+    return {
+        increment: function() {
+            count++;
+        },
+
+        get: function() {
+            return count;
+        }
+    }
+}
+
+var foo = Counter(4);
+foo.increment();
+foo.get(); // 5
+
+ +

Tutaj Counter zwraca dwa domknięcia: funkcję increment oraz funckję get. +Obie te funkcję trzymają referencję do zasięgu Counter a co za tym idzie +zawsze posiadają dostęp do zmiennej count tak, jakby ta zmienna była zdefiniowana +w zasięgu tych funkcji.

+ +

Dlaczego zmienne przywatne działają

+ +

Ponieważ nie ma możliwości wskazania lub przypisania zasięgu w JavaScript, to +nie istnieje sposób aby uzyskać dostęp do zmiennej count z zewnątrz. +Wykorzystanie tych dwóch domkinęć jest jedynym sposobem na interakcję z tą zmienną.

+ +
var foo = new Counter(4);
+foo.hack = function() {
+    count = 1337;
+};
+
+ +

Powyższy kod nie zmieni wartości zmiennej count wewnątrz zasięgu Counter, +ponieważ foo.hack nie została zadeklarowana wewnątrz tego konkretnego zasięgu. +Zamiast tego funkcja utworzy lub nadpisze globalną zmienną count.

+ +

Domknięcia wewnątrz pętli

+ +

Jednym z częstrzych błędów jest wykorzystywanie domknięć wewnątrz pętli, +aby wartość zmiennej po której odbywa się iteracja był kopiowana do +wewnętrznej funkcji.

+ +
for(var i = 0; i < 10; i++) {
+    setTimeout(function() {
+        console.log(i);  
+    }, 1000);
+}
+
+ +

Powyższy kod nie wypisze numerów od 0 do 9, ale wypisze +dziesięć razy liczbę 10.

+ +

Anonimowa funkcja trzyma wskaźnik do zmiennej i i podczas uruchomienia +console.log, pętla for już zakończyła działanie i wartość zmiennej i +została ustawiona na 10.

+ +

Aby otrzymać zamierzony efekt, niezbędne jest skopiowanie wartości +zmiennej i.

+ +

Unikanie problemu z referencją

+ +

Aby skopiować wartość zmiennej, po której iterujemy w pętli, należy skorzystać +z anonimowego wrappera.

+ +
for(var i = 0; i < 10; i++) {
+    (function(e) {
+        setTimeout(function() {
+            console.log(e);  
+        }, 1000);
+    })(i);
+}
+
+ +

Zewnętrzna anonimowa funkcja zostaje wywołana od razu z parametrem i +jako pierwszym argumentem i otrzyma kopię wartości zmiennej i jako +zmienną e.

+ +

Anonimowa funkcja która zostaje przekazana do setTimeout teraz posiada +referencję do zmiennej e, która nie zostanie zmieniona przez pętle for.

+ +

Istnieje jeszcze jeden sposób na osiągnięcie tego samego efektu. Należy zwrócic +fukcję z anonimowego wrappera, wówczas kod będzie zachowywał się jak ten +wcześniejszy.

+ +
for(var i = 0; i < 10; i++) {
+    setTimeout((function(e) {
+        return function() {
+            console.log(e);
+        }
+    })(i), 1000)
+}
+

Obiekt arguments

Każda zasięg funkcyjny w języku JavaScript ma dostęp do specjalnej zmiennej arguments. +Ta zmienna trzyma listę wszystkich argumentów przekazanych do funkcji.

+ + + +

Obiekt arguments nie jest typu Array. Mimo, że posiada pewne cechy +semantyki tablic - właściwość length - to nie dziedziczy on z Array.prototype, +ale w rzeczywistości z Object.

+ +

Ze względu na to nie można używać standardowych dla tablic metod takich jak +push, pop czy slice na obiekcie arguments. Mimo, że iteracja przy pomocy +pętli for działa dobrze, to aby skorzystać ze standardowych metod tablicowych +należy skonwertować arguments do prawdziwego obiekt Array.

+ +

Konwersja do tablicy

+ +

Poniższy kod zwróci nowy obiekt Array zawierający wszystkie elementy +obiektu arguments.

+ +
Array.prototype.slice.call(arguments);
+
+ +

Jednakże konwersja ta jest wolna i nie jest zalecana w sekcjach, +które mają duży wpływ na wydajność.

+ +

Przekazywanie argumentów

+ +

Zalecany sposób przekazywania argumentów z jednej funkcji do następnej +wyglada następująco.

+ +
function foo() {
+    bar.apply(null, arguments);
+}
+function bar(a, b, c) {
+    // do stuff here
+}
+
+ +

Kolejną sztuczką jest użycie razem call i apply w celu stworzenia +szybkich i nieograniczonych wrapperów.

+ +
function Foo() {}
+
+Foo.prototype.method = function(a, b, c) {
+    console.log(this, a, b, c);
+};
+
+// Stworzenie nieograniczoną wersję metody "method" 
+// która przyjmuje parametry: this, arg1, arg2...argN
+Foo.method = function() {
+
+    // Rezultat: Foo.prototype.method.call(this, arg1, arg2... argN)
+    Function.call.apply(Foo.prototype.method, arguments);
+};
+
+ +

Parametry formalne i indeksy argumentów

+ +

Obiekt arguments tworzy funckje getter i setter nie tylko dla swoich +właściwości, ale również dla parametrów formalnych funkcji.

+ +

W rezultacie zmiana wartości parametru formalnego zmieni również wartość +odpowiadającemu mu wpisowi w obiekcie arguments, zachodzi to również w drugą stronę.

+ +
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);
+
+ +

Mity i prawdy o wydajności

+ +

Obiekt arguments jest zawsze tworzony z wyjątkiem dwóch przypadków, gdy +zmienna o takiej nazwie jest zdefiniowana wewnątrz funkcji lub jeden z parametrów +formalnych funkcji ma taką nazwę. Nie ma znaczenia czy obiekt arguments jest +używany czy nie.

+ +

Zarówno gettery jak i settery są zawsze tworzone, zatem używanie ich nie ma +praktycznie żadnego wpływu na wydajność. Zwłaszcza w rzeczywistym kodzie, który +wykorzystuje coś więcej niż tylko prosty dostęp do właściwości obiektu arguments.

+ + + +

Jednakże, istnieje jeden przypadek w którym wydajność drastycznie spada w +nowoczesnych silnikach JavaScript. Ten przypadek to wykorzystanie +arguments.callee.

+ +
function foo() {
+    arguments.callee; // operowanie na obiekcie funkcji
+    arguments.callee.caller; // i obiekcie funkcji wywołującej
+}
+
+function bigLoop() {
+    for(var i = 0; i < 100000; i++) {
+        foo(); // Normalnie zostałaby wykorzystana metoda inline
+    }
+}
+
+ +

W powyższym przykładzie foo nie może zostać wykorzystana metoda inline +ponieważ potrzebne są nie tylko informacje na własny temat ale również +na temat funkcji wywołującej. Takie użycie nie tylko uniemożliwia +inlining i korzyści z niej wynikające, ale również stanowi złamanie +zasad enkapsulacji ponieważ ta funkcja jest zależna od kontekstu +w jakim została wywołana.

+ +

Mocno zalecane jest aby nigdy nie korzystać z arguments.callee +i żadnej jej własności.

+ +

Konstruktory

Konstruktory w JavaScript również wyglądają inaczej niż innych języka. Każde +wywołanie funkcji, które jest poprzedone słowem kluczowym new zachowuje się +jak konstruktor.

+ +

Wewnątrz konstruktora - wywoływanej fukcji - wartość this wskazuje na +nowo utworzony obiekt Object. Prototyp prototype tego +nowego obiektu będzie wskazywał na prototyp prototype obiektu fukcji, +która została wywołana jako konstruktor.

+ +

Jeżeli wywołana funkcja nie posiada jawnej deklaracji return, wówczas +fukcja domyślnie zwraca wartość this - nowy obiekt.

+ +
function Foo() {
+    this.bla = 1;
+}
+
+Foo.prototype.test = function() {
+    console.log(this.bla);
+};
+
+var test = new Foo();
+
+ +

Powyżej wywołanya została funkcja Foo jako konstruktor oraz ustawia +nowo utworzonemu obiektowi właściwość prototype na Foo.prototype.

+ +

W tym przypadku jawna deklaracja return w funkcji zwraca wartość +ustawioną w deklaracji, ale tylko jeżeli zwracaną wartością jest +obiekt Object.

+ +
function Bar() {
+    return 2;
+}
+new Bar(); // nowy obiekt
+
+function Test() {
+    this.value = 2;
+
+    return {
+        foo: 1
+    };
+}
+new Test(); // zwrócony obiekt
+
+ +

Jeżeli słowo kluczowe new zostanie pominięte funkcja nie zwróci nowego +obiektu.

+ +
function Foo() {
+    this.bla = 1; // zostanie ustawiona w obiekcie global
+}
+Foo(); // undefined
+
+ +

Mimo, że powyższy kod może zadziałać w pewnych przypadkach, w związku +z działaniem this w języku JavaScript to jako +wartość thiszostanie wykorzystany obiekt global.

+ +

Fabryki

+ +

Aby móc ominąć słowo kluczowe new konstruktor musi jawnie zwracać wartość.

+ +
function Bar() {
+    var value = 1;
+    return {
+        method: function() {
+            return value;
+        }
+    }
+}
+Bar.prototype = {
+    foo: function() {}
+};
+
+new Bar();
+Bar();
+
+ +

Oba wywołania Bar zwrócą tą samą rzecz, nowo utworzony obiekt, który posiada +właściwość nazwaną method w sobie, dla którego Bar jest Domknięciem.

+ +

Należy również pamiętać, że wywołanie new Bar() nie ma wpływu na +prototyp zwróconego obiektu (prototypem będzie object.prototype a nie Bar.prototype). +Podczas gdy prototyp zostanie przypisany do nowo utworzonego obiektu, to jednak Bar +nidgy nie zwróci tego nowego obiektu Bar, ale literał obiektu, który jest po +słowie kluczowym return.

+ +

W powyższym przykładzie nie ma żadnej różnicy w działaniu pomiędzy użyciem +i nieużyciem słowa kluczowego new.

+ +

Tworzenie nowych obiektów korzystając z fabryk

+ +

Często zaleca się nie korzystać z operatora new ponieważ zapominając +go zastosować może prowadzić do błędów.

+ +

W celu stworzenia nowego obiektu, powinno się używać fabryki i konstruować +nowy obiekt wewnątrz tej fabryki.

+ +
function Foo() {
+    var obj = {};
+    obj.value = 'blub';
+
+    var private = 2;
+    obj.someMethod = function(value) {
+        this.value = value;
+    }
+
+    obj.getPrivate = function() {
+        return private;
+    }
+    return obj;
+}
+
+ +

Mimo, że powyższy kod jest odporny na brak słowa kluczowego new i ułatwia +korzystanie ze zmiennych prywatnych, to posiada +pewne wady. +While the above is robust against a missing new keyword and certainly makes +the use of private variables easier, it comes with some +downsides. + 1. Zużywa więcej pamięci, ponieważ tworzony obiekt nie współdzieli metod + poprzez prototyp + 2. Aby móc dziedziczyć fabryka musi skopiować wszystkie metody z dziedziczonego + obiektu lub przypisać ten obiekt, z którego się dziedziczy, jako prototyp + do nowo utworzonego obiektu. + 3. Porzucenie łańcucha prototypów tylko ze względu na opuszczone słowo kluczowe + new jest sprzeczne z duchem języka.

+ +

Wnioski

+ +

Pominięcie słowa kluczowego new może prowadzić do błędów, ale na pewno nie +powinno to być powodem odrzucenia używania prototypów w ogóle. Sprowadza się to +do wyboru rozwiązania, które bardziej pasuje do potrzeb aplikacji. Szczególnie +ważne jest aby wybrać określony styl tworzenia obiektów i się go trzymać.

Zasięg zmiennych i przestrzenie nazw

Mimo, że JavaScript radzi sobie dobrze ze składnią, opisującą dwa pasujące +nawiasy klamrowe jako blok, to jednak nie wspiera zasięgu blokowego. +Jedynym zasięgiem jaki istnieje w JavaScript jest zasięg funkcyjny.

+ +
function test() { // definiuje zasięg (scope)
+    for(var i = 0; i < 10; i++) { // nie definiuje zasięgu (scope)
+        // count
+    }
+    console.log(i); // 10
+}
+
+ + + +

W JavaScripcie nie ma również przestrzeni nazw, co oznacza, że wszystko jest +definiowane w jednej globalnie współdzielonej przestrzeni nazw.

+ +

Za każdym razem gdy zmienna jest +Z każdym odwołaniem do zmiennej JavaScript przeszukuje w górę wszystkie zasięgi +dopóki nie znajdzie tej zmiennej. W przypadku gdy przeszukiwanie dotrze do globalnego +zasięgu i nadal nie znajdzie żądanej nazwy to wyrzuca błąd ReferenceError.

+ +

Zmora globalnych zmiennych

+ +
// script A
+foo = '42';
+
+// script B
+var foo = '42'
+
+ +

Powyższe dwa skrypty nie dają tego samego efektu. Skrypt A definiuje zmienna +nazwaną foo w globalnym zasięgu natomiast skrypt B definiuje foo +w aktualnym zasięgu.

+ +

Jeszcze raz, to wcale nie daje tego samego efektu, nie użycie var może mieć +poważne konsekwencje.

+ +
// globalny zasięg
+var foo = 42;
+function test() {
+    // lokalny zasięg
+    foo = 21;
+}
+test();
+foo; // 21
+
+ +

Pominięcie słowa var w deklaracji wewnątrz funkcji test nadpisze wartość +zmiennej globalnej foo. Mimo, że nie wygląda to na początku jak duży problem, +to posiadając wiele tysięcy linii kodu w JavaScript i nie korzystanie z var +wprowadzi straszne i trudne do wyśledzenia błędy.

+ +
// globalny zasięg 
+var items = [/* jakaś lista */];
+for(var i = 0; i < 10; i++) {
+    subLoop();
+}
+
+function subLoop() {
+    // scope of subLoop
+    for(i = 0; i < 10; i++) { // brakuje słowa var w deklaracji
+        // do amazing stuff!
+    }
+}
+
+ +

Zewnętrzna pętla zakończy działanie po pierwszym wywołaniu subLoop, ponieważ +subLoop nadpisuje wartość globalnej zmiennej i. Użycie var w drugiej pętli +for pozwoliło by łatwo uniknąć problemu. Słowo kluczowe var nie powinno być +nigdy pominięte w deklaracji, chyba że pożądanym skutkiem jest wpłynięcie na +zewnętrzny zasięg.

+ +

Lokalne zmienne

+ +

Jedynym źródłem zmiennych lokalnych w JavaScripcie są parametry funkcji +oraz zmienne zadeklarowane poprzez deklaracje var wewnątrz funkcji.

+ +
// globalny zasięg
+var foo = 1;
+var bar = 2;
+var i = 2;
+
+function test(i) {
+    // lokalny zasięg fukcji test
+    i = 5;
+
+    var foo = 3;
+    bar = 4;
+}
+test(10);
+
+ +

Zmienne foo oraz i są lokalnymi zmiennymi wewnątrz zasiegu funkcji test, +natomiast przypisanie wartości do bar nadpisze zmienną globalną o tej samej nazwie.

+ +

"Hoisting" - wywindowanie, podnoszenie

+ +

JavaScript winduje deklaracje. Oznacza to, że zarówno deklaracja ze słowem +kluczowym var jak i deklaracje funkcji function zostaną przeniesione na +początek otaczającego zasięgu.

+ +
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];
+    }
+}
+
+ +

Powyższy kod zostanie przekształcony przed rozpoczęciem wykonania. JavaScript +przeniesie deklarację zmiennej var oraz deklarację funkcji function na szczyt +najbliższego zasięgu.

+ +
// deklaracje var zostaną przeniesione tutaj
+var bar, someValue; // ustawione domyślnie na 'undefined'
+
+// deklaracje funkcji zostaną również przeniesione na górę
+function test(data) {
+    var goo, i, e; // brak blokowego zasięgu spowoduje przeniesienie tutaj
+    if (false) {
+        goo = 1;
+
+    } else {
+        goo = 2;
+    }
+    for(i = 0; i < 100; i++) {
+        e = data[i];
+    }
+}
+
+bar(); // powoduje błąd TypeError ponieważ bar jest nadal 'undefined'
+someValue = 42; // przypisania nie zostają zmienione przez 'hoisting'
+bar = function() {};
+
+test();
+
+ +

Brak blokowego zasięgu nie tylko przeniesie deklaracje var poza ciało pętle, +ale również spowoduje, że niektóre porównania if staną się nieintuicyjne.

+ +

W oryginalnym kodzie wewnątrz deklaracja if zdaje się modyfikować zmienną +globalną goo, podczas gdy faktycznie modyfikuje ona zmienną lokalną - po tym +jak zostało zastosowane windowanie (hoisting).

+ +

Bez wiedzy na temat podnoszenia (hoistingu), poniższy kod może wydawać się +wyrzucać błąd ReferenceError.

+ +
// sprawdz czy SomeImportantThing zostało zainicjalizowane
+if (!SomeImportantThing) {
+    var SomeImportantThing = {};
+}
+
+ +

Oczywiście powyższy kod działa ze względu na fakt, że deklaracja var zostanie +przeniesiona na początek globalnego zasięgu.

+ +
var SomeImportantThing;
+
+// inny kod który może ale nie musi zainicjalizować SomeImportantThing
+
+// upewnienie sie że SomeImportantThing zostało zainicjalizowane
+if (!SomeImportantThing) {
+    SomeImportantThing = {};
+}
+
+ +

Kolejność rozwiązywania nazw

+ +

Wszystkie zasięgi w JavaScripcie, włączając globalny zasięg, posiadają +zdefiniowana wewnątrz specjalną nazwę this, która wskazuje +na aktualny obiekt.

+ +

Zasięg funkcyjny posiada również zdefiniowaną wewnętrznie nazwę +arguments, która zawiera listę argumentów przekazaną do +funkcji.

+ +

Na przykład, kiedy próbujemy odczytać zmienną foo wewnątrz zasięgu funkcji, +JavaScript będzie szukać nazwy w określonej kolejności: + 1. Jeżeli wewnątrz aktualnego zasięgu znajduje się deklaracja var foo skorzystaj z niej. + 2. Jeżeli jeden z parametrów fukcji został nazwany foo użyj go. + 3. Jeżeli fukcja została nazwana foo skorzystaj z tego. + 4. Przejdz do zewnętrznego zasięgu i przejdz do kroku #1.

+ + + +

Przestrzenie nazw

+ +

Powszechnym problemem posiadania tylko jednej globalnej przestrzeni nazw jest +prawdopodobieństwo wystąpienia kolizji nazw. W JavaScripcie, można łatwo uniknąć +tego problemu korzystając z anonimowych wrapperów.

+ +
(function() {
+    // autonomiczna "przestrzeń nazw"
+
+    window.foo = function() {
+        // wyeksponowane domkniecie (closure)
+    };
+
+})(); // natychmiastowe wykonanie funkcji
+
+ +

Nienazwane funkcje są rozpoznane jako wyrażenia, więc +aby mogły zostać wywołane muszą zostać zewaluowane.

+ +
( // zewaluowanie fukcji znajdującej się wewnątrz nawiasów
+function() {}
+) // zwrócenie obiektu funkcji
+() // wywołanie rezultatu ewaluacji
+
+ +

Istnieją inne sposoby aby zewaluować i wykonać wyrażenie funkcyjne. Mimo, że +mają inną składnie, zachowują się dokładnie tak samo.

+ +
// Trzy inne sposoby
+!function(){}();
++function(){}();
+(function(){}());
+
+ +

Wnioski

+ +

Zaleca się aby zawsze używać anonimowych wrapperów do hermetyzacji kodu wewnątrz +jego własnej przestrzeni nazw. To nie tylko chroni kod przed kolizją nazw, ale +również wprowadza lepszą modularyzację programów.

+ +

Ponadto, stosowanie zmiennych globalnych jest uznawane za złą praktykę. +Jakiekolwiek wykorzystanie zmiennych globalnych wskazuje na źle napisany kod, +który jest podatny na błędy i trudny do utrzymania.

Tablice

Iterowanie po tablicach oraz właściwości tablic

Mimo, że tablice w JavaScript są obiektami, nie ma dobrych powodów do używania +pętli for in do iteracji po nich. W rzeczywiści istnieje +wiele dobrych powodów przeciwko wykorzystania for in na tablicach.

+ + + +

Ponieważ pętla for in wylicza wszystkie właściwości, które są wewnątrz +łańcucha prototypów i jedynym sposobem aby wykluczyć te właściwości to użycie +hasOwnProperty, ale wówczas pętla staje się +dwadzieście razy wolniejsza od normalnej pętli for.

+ +

Iteracja

+ +

W celu osiągnięcia najlepszej wydajności podczas iteracji po tablicach należy +użyć klasycznej pętli for.

+ +
var list = [1, 2, 3, 4, 5, ...... 100000000];
+for(var i = 0, l = list.length; i < l; i++) {
+    console.log(list[i]);
+}
+
+ +

Jest tam jeszcze jeden dodatkowy haczyk w przykładzie powyżej. Jest to zbuforowanie +długości tablicy poprzez l = list.length.

+ +

Mimo, że właściwość length jest zdefiniowana w wewnątrz tablicy, istnieje nadal +dodatkowy koszt na wyszukiwanie tej właściwości przy każdej iteracji w pętli. +Chociaż najnowsze silniki JavaScript mogą zastosować optymalizację w tym +przypadku. Nie ma jednak możliwość ustalenia czy kod będzie wykonywany w jednym +z tych nowych silników czy też nie.

+ +

W rzeczywistości pomijając buforowanie długości tablicy może spowodować, że pętla +będzie tylko w połowie tak szybka jak ta z buforowaniem długości.

+ +

Właściwość length

+ +

Mimo, że getter właściwości length po prostu zwraca liczbę elementów, które są +zawarte w tablicy, to setter może być użyta do skracania tablicy.

+ +
var foo = [1, 2, 3, 4, 5, 6];
+foo.length = 3;
+foo; // [1, 2, 3]
+
+foo.length = 6;
+foo; // [1, 2, 3]
+
+ +

Przypisanie mniejszej długości spowoduje skrócenie tablicy, ale zwiększenie wartości +length nie ma żadnego wpływu na tablicę.

+ +

Wnioski

+ +

Aby uzyskać najlepszą wydajność zaleca się, aby zawsze używać zwykłej pętli for +i zbuforowanie właściwości length. Korzystanie z pętli for in na tablicy jest +znakiem źle napisanego kodu, który jest podatny na błędy i ma słabą wydajność.

Konstruktor Array

Zaleca się zawsze korzystać z literału tablicy - notacja [] - podczas tworzenia +nowych tablic, ponieważ konstruktor Array niejednoznacznie interpretuje +parametry do niego przekazane.

+ +
[1, 2, 3]; // Rezultat: [1, 2, 3]
+new Array(1, 2, 3); // Rezultat: [1, 2, 3]
+
+[3]; // Rezultat: [3]
+new Array(3); // Rezultat: []
+new Array('3') // Rezultat: ['3']
+
+ +

W przypadku gdy tylko jeden argument zostanie przekazany do kostruktora Array i +ten argument jest typu Number, konstruktor zwróci nową dziwną tablicę +z ustawioną właściwością length na wartość przekazaną jako argument. Należy +zauważyć, że tylko właściwość length zostanie ustawiona w ten sposób, +rzeczywiste indeksy w tej tablicy nie zostaną zainicjalizowane.

+ +
var arr = new Array(3);
+arr[1]; // undefined
+1 in arr; // zwraca false, indeks nie został ustawiony
+
+ +

Możliwość ustanienia z góry długości tablicy jest użyteczna tylko w kilku +przypadkach, jak powtarzanie ciągu znaków, w którym unika się stosowania +pętli for.

+ +
// count - ilosc powtorzen
+// stringToRepeat - ciąg znaków do powtórzenia 
+new Array(count + 1).join(stringToRepeat); 
+
+ +

Wnioski

+ +

W miare możliwości należy unikać używania konstruktora Array. Literały są +zdecydowanie lepszym rozwiązaniem, są krótsze i mają bardziej precyzyjną składnię. +Zwiększają również czytelność kodu.

Typy

Równość i porównania

JavaScript posiada dwa różne sposoby równościowego porównywania obiektów.

+ +

Operator równości

+ +

Operator równości składa się z dwóch znaków "równa się": ==

+ +

JavaScript jest słabo typowanym językiem. Oznacza to, że operator równości +konwertuje typy (dokonuje koercji), aby wykonać porównanie.

+ +
""           ==   "0"           // false
+0            ==   ""            // true
+0            ==   "0"           // true
+false        ==   "false"       // false
+false        ==   "0"           // true
+false        ==   undefined     // false
+false        ==   null          // false
+null         ==   undefined     // true
+" \t\r\n"    ==   0             // true
+
+ +

Powyższa tabela przedstawia wyniki koercji typów. Nieprzewidywalne wyniki +porównania są głównym powodem, że stosowanie == jest powszechnie uważane za złą +praktykę. Skomplikowane reguły konwersji są powodem trudnych do wyśledzenia błędy.

+ +

Ponadto koercja ma również wpływ na wydajność na przykład gdy typ String musi zostać +przekształcony na typ Number przed porównaniem z drugą liczbą.

+ +

Operator ścisłej równości

+ +

Operator ścisłej równości składa się z trzech znaków "równa się": ===

+ +

Działa on dokładnie tak jak normalny operator równości, z jednym wyjątkiem nie +dokonuje koercji typów przed porównaniem.

+ +
""           ===   "0"           // false
+0            ===   ""            // false
+0            ===   "0"           // false
+false        ===   "false"       // false
+false        ===   "0"           // false
+false        ===   undefined     // false
+false        ===   null          // false
+null         ===   undefined     // false
+" \t\r\n"    ===   0             // false
+
+ +

Powyższe rezultaty są o wiele bardziej przejrzyste. Powoduje to "ustatycznienie" +języka do pewnego stopnia oraz pozwala na wprowadzenie optymalizacji porównań +obiektów o różnych typach.

+ +

Porównywanie obiektów

+ +

Mimo, że oba operatory == i === nazywane są operatorami równościowymi, +to zachowują się różnie gdy jednym z operandów jest obiekt typu Object.

+ +
{} === {};                   // false
+new String('foo') === 'foo'; // false
+new Number(10) === 10;       // false
+var foo = {};
+foo === foo;                 // true
+
+ +

Oba operatory porównują toższmość a nie równość, czyli będą porównywać czy +jeden i drugi operand jest tą samą instancją obiektu, podobnie jak operator +is w Pythonie i porównanie wskaźników w C.

+ +

Wnioski

+ +

Zaleca się aby używać tylko operatora ścisłej równości. W sytuacjach gdy +potrzebna jest koercja (porównanie obiektów różnych typów), konwersja powinna +być dokonana jawnie a nie pozostawiona trudnym regułom koercji +obowiązującym w języku.

Operator typeof

Operator typeof (razem z operatorem instanceof) jest +prawdopodobnie najwiekszą wadą konstrukcji języka JavaScript, jest on praktycznie +całkowicie wadliwy.

+ +

Mimo, że instanceof ma swoje wady to nadal ma ograniczone zastosowanie w praktyce, +natomiast typeof ma tylko jeden praktyczny przypadek użycia, który na dodatek +nie jest związany z sprawdzaniem typu obiektu.

+ + + +

Tablica typów JavaScript

+ +
Wartość             Klasa      Typ
+-------------------------------------
+"foo"               String     string
+new String("foo")   String     object
+1.2                 Number     number
+new Number(1.2)     Number     object
+true                Boolean    boolean
+new Boolean(true)   Boolean    object
+new Date()          Date       object
+new Error()         Error      object
+[1,2,3]             Array      object
+new Array(1, 2, 3)  Array      object
+new Function("")    Function   function
+/abc/g              RegExp     object (function w Nitro i V8)
+new RegExp("meow")  RegExp     object (function w Nitro i V8)
+{}                  Object     object
+new Object()        Object     object
+
+ +

W powyższej tabeli Typ odnosi się do wartości zwracanej przez operator typeof. +Wyraźnie widać, że zwracane wartości w ogóle nie są spójne.

+ +

Klasa odnosi sie do wartości wewnętrznej właściwości [[Class]] obiektu.

+ + + +

W celu uzyskania wartości właściwości [[Class]] trzeba skorzystać z metody +toString z Object.prototype.

+ +

Klasa obiektu

+ +

Specyfikacja zawiera dokładnie jeden sposób dostepu do wartości [[Class]], +wykorzystując Object.prototype.toString.

+ +
function is(type, obj) {
+    var clas = Object.prototype.toString.call(obj).slice(8, -1);
+    return obj !== undefined && obj !== null && clas === type;
+}
+
+is('String', 'test'); // true
+is('String', new String('test')); // true
+
+ +

Powyższy przykład wywołuje Object.prototype.toString z wartością +this ustawioną na obiekt, dla której wartość właściwości +[[Class]] ma zostać odczytana.

+ + + +

Testowanie niezdefiniowania zmiennej

+ +
typeof foo !== 'undefined'
+
+ +

Powyższy kod sprawdza czy foo została faktycznie zadeklarowana czy też nie. +Próba odwołania się do zmiennej spowodowała by wyrzucenie błędu ReferenceError. +Jest to jedyne praktyczne wykorzystanie operatora typeof.

+ +

Wnioski

+ +

W celu sprawdzenia typu obiektu zalecane jest skorzystanie z +Object.prototype.toString, ponieważ jest to jedyny wiarygodny sposób. Jak +pokazano w powyższej tabeli typów, niektóre wartości zwracane przez typeof nie +są zdefiniowane w specyfikacji, co za tym idzie mogą się różnić w różnych +implementacjach.

+ +

O ile nie operator typeof nie jest użyty do sprawdzania czy zmienna została +zdefiniowana, powinien być unikany o ile to tylko możliwe.

Operator instanceof

Operator instanceof porównuje konstruktory obiektów przekazanych jako operendy. +Jest on jedynie użyteczny do porównywania obiektów utworzonych klas. Stosowanie +go na wbudowanych typach jest praktycznie tak samo bezużyteczne jak operatora +typeof.

+ +

Porównywanie obiektów utworzonych klas

+ +
function Foo() {}
+function Bar() {}
+Bar.prototype = new Foo();
+
+new Bar() instanceof Bar; // true
+new Bar() instanceof Foo; // true
+
+// Poniżej kod który przypisuje do Bar.prototype obiekt funkcji Foo
+// a nie faktyczną instancję Foo
+Bar.prototype = Foo;
+new Bar() instanceof Foo; // false
+
+ +

Stosowanie instanceof na natywnych typach

+ +
new String('foo') instanceof String; // true
+new String('foo') instanceof Object; // true
+
+'foo' instanceof String; // false
+'foo' instanceof Object; // false
+
+ +

Jedną ważną rzeczą, którą należy zauważyć jest to, że instanceof nie zadziała +na obiektach, które pochodzą z różnych kontekstów JavaScript (np. z różnych +dokumentów wewnątrz przeglądarki), ponieważ ich konstruktory nie będą tymi +samymi obiektami.

+ +

Wnioski

+ +

Operator instanceof powinien być tylko używany podczas korzystania z obiektów +klas utworzonych, które były zdefiniowane w tym samym kontekscie JavaScriptowym. +Podobnie jak operator typeof, należy unikać korzystania +z tego operatora w innych sytuacjach.

Rzutowanie typów

JavaScript jest językiem słabo typowanym, co za tym idzie będzie stosować koercję +typów gdziekolwiek jest to możliwe.

+ +
// These are true
+new Number(10) == 10; // Number.toString() zostanie przekształcone
+                      // z powrotem do liczby
+
+10 == '10';           // Stringi zostaną przekształcone do typu Number
+10 == '+10 ';         // Kolejne wariacje
+10 == '010';          // i następne
+isNaN(null) == false; // null zostanie przekształcony do 0
+                      // który oczywiście nie jest NaN
+
+// Poniższe zwracają false
+10 == 010;
+10 == '-10';
+
+ + + +

Aby uniknąć powyższych problemów, należy koniecznie skorzystać ze +ściełego operatora równości. Mimo, że pozwala to uniknąć wiele +typowych problemów to nadal istnieje wiele innych, które powstają na bazie słabego +typowania języka JavaScript.

+ +

Konstruktory typów wbudowanych

+ +

Konstruktory typów wbudowanych takich, jak Number lub String zachowują się +inaczej jeżeli są poprzedzone słowem kluczowym new a inaczej jeżeli nie są.

+ +
new Number(10) === 10;     // False, Object i Number
+Number(10) === 10;         // True, Number i Number
+new Number(10) + 0 === 10; // True, ponieważ dokonano jawnej konwersji
+
+ +

Korzystanie z wbudowanych typów jak Number jako konstruktor utworzy nowy obiekt +typu Number, natomiast opuszczenie słowa kluczowego new spowoduje, że funkcja +Number zachowa się jak konwerter.

+ +

Ponadto, użycie literałów lub wartości nieobiektowych zaowocuje jeszcze większą +ilością rzutowań (koercją) typów.

+ +

Najlepszym rozwiązaniem jest jawne rzutowanie do jednego z trzech typów.

+ +

Rzutowanie do typu String

+ +
'' + 10 === '10'; // true
+
+ +

Konkatenacja pustego stringu i wartości powoduje rzutowanie do typu String.

+ +

Rzutowanie do typu Number

+ +
+'10' === 10; // true
+
+ +

Zastosowanie unarnego operatora + spowoduje rzutowanie do typu Number.

+ +

Rzutowanie do typu Boolean

+ +

Używając dwukrotnie operatora negacji dowolna wartość może zostać zrzutowana +do typu Boolean

+ +
!!'foo';   // true
+!!'';      // false
+!!'0';     // true
+!!'1';     // true
+!!'-1'     // true
+!!{};      // true
+!!true;    // true
+

Jądro

Dlaczego nie należy używać eval

Funkcja eval uruchomi podany string jako kod JavaScript w lokalnym zasięgu (scopie).

+ +
var foo = 1;
+function test() {
+    var foo = 2;
+    eval('foo = 3');
+    return foo;
+}
+test(); // 3
+foo; // 1
+
+ +

Niestaty eval zostanie wykonana w lokalnym zasięgu tylko jeżeli została wywołana +bezpośrednio i nazwa wołanej funkcji równa sie eval.

+ +
var foo = 1;
+function test() {
+    var foo = 2;
+    var bar = eval;
+    bar('foo = 3');
+    return foo;
+}
+test(); // 2
+foo; // 3
+
+ +

Należy unikać stosowania eval o ile to tylko możliwe. W 99.9% przypadków można +osiągnąć ten sam efekt nie używając eval.

+ +

eval w przebraniu

+ +

Funkcje wykonywane po upływie czasu setTimeout i setInterval +mogą przyjąć string jako pierwszy argument. String ten zostanie zawsze wykonany +w globalnym zasięgu, ponieważ funkcja eval zostanie wywołana niebezpośrednio w tym +przypadku.

+ +

Problemy z bezpieczeństwem

+ +

Funkcja eval jest również problematyczna od strony bezpieczeństwa, ponieważ +wykonuje każdy kod, który zostanie do niej przekazany i nie należy nigdy +używać jej na stringach nieznanego lub niezaufanego pochodzenia.

+ +

Wnioski

+ +

Funkcja eval nie powinna być w ogole używana, każdy kod, który ją wykorzystuje +powinien zostać sprawdzony pod względem działania, wydajności i bezpieczeństwa. +W przypadku gdy użycie eval jest niezbędne do działania, wówczas taki kod +należy przemyśleć raz jeszcze i ulepszyć kod aby nie wymagał użycia eval.

undefined i null

JavaScript ma dwie różne wartości dla pustych wartości, bardziej użyteczną +z tych dwóch jest undefined.

+ +

Wartość undefined

+ +

undefined jest typem z dokładnie jedną wartością: undefined.

+ +

Język również definiuje globalną zmienną, która ma wartość undefined, zmienna +ta jest nazwana undefined. Jednakże jest to zmienna a nie stała czy słowo +kluczowe w języku. Oznacza to że możliwe jest nadpisanie wartości tej zmiennej.

+ + + +

Kilka przykładów kiedy wartość undefined jest zwracana:

+ +
    +
  • Dostęp do (niemodyfikowalnej) zmiennej globalnej undefined.
  • +
  • Wyjście z funkcji, która nie ma deklaracji return.
  • +
  • Deklaracja return, która nic jawnie nie zwraca.
  • +
  • Poszukiwanie nieistniejącej właściwości.
  • +
  • Parametr funkcji, który nie został jawnie przekazany podczas wywołania funkcji
  • +
  • Wszystko co zostało ustawione na wartość undefined
  • +
+ +

Obsługa przypadku zmiany wartości undefined

+ +

Ponieważ globalna zmienna undeined tylko zawiera kopię prawdziwej wartości typu +undefined, przypisanie nowej wartości do tej zmiennej nie zmienia wartości +typu undefined.

+ +

Jednak, aby porównać coś do wartości undefined potrzebne jest odczytanie wartości +undefined.

+ +

Aby uchronić swój kod przeciwko możliwemu nadpisaniu zmiennej undefined, korzysta +się z powszechnej techniki dodania dodatkowego parametru do +anonimowego wrappera, do którego nie zostanie przekazany +argument.

+ +
var undefined = 123;
+(function(something, foo, undefined) {
+    // undefined lokalnym zasięgu znowu 
+    // odnosi się do poprawnej wartości
+
+})('Hello World', 42);
+
+ +

Kolejnym sposobem aby osiągnąć ten sam efekt jest użycie deklaracji zmiennej +wewnątrz wrappera.

+ +
var undefined = 123;
+(function(something, foo) {
+    var undefined;
+    ...
+
+})('Hello World', 42);
+
+ +

Jedyną różnicą pomięcy tymi sposobami są dodatkowe 4 bajty przeznaczone na słowo +kluczowe var i spację po nim.

+ +

Zastosowanie null

+ +

Podczas gdy undefined w kontekście języka jest używany jak null w sensie +tradycyjnych języków, to null w JavaScript (jako literał i jako typ) jest po +prostu kolejnym typem danych.

+ +

Jest wykorzystywany we wnętrzu JavaScript (np. deklaracji końca łańcucha prototypów +poprzez ustawienie Foo.prototype = null), ale prawie w każdym przypadku można go +zastąpić przez undefined.

Automatyczne wstawianie średnika

Mimo, że JavaScript ma składnię podobną do języka C, to nie wymusza stosowania +średników w kodzie źródłowym. Istnieje możliwość ich pominięcia.

+ +

Lecz JavaScript nie jest językiem bez średników, tak na prawdę potrzebuje +średników aby zinterpretować kod źródłowy. Jednakże parser JavaScript +automatycznie wstawia średniki o ile napotka błąd parsowania związany z +brakiem średnika.

+ +
var foo = function() {
+} // błąd parsowania, oczekiwany był w tym miejscu średnik
+test()
+
+ +

Parser dodaje średnik, i próbuje jeszcze raz sparsować skrypt.

+ +
var foo = function() {
+}; // bez błędu parser kontynuuje
+test()
+
+ +

Automatyczne wstawianie średników jest uważane za jeden z największych błędów +konstrukcji języka, ponieważ może ono zachowanie kodu.

+ +

Jak działa wstawianie

+ +

Kod poniżej nie ma żadnych średników, więc parser zdecyduje, w których miejscach +je wstawi.

+ +
(function(window, undefined) {
+    function test(options) {
+        log('testing!')
+
+        (options.list || []).forEach(function(i) {
+
+        })
+
+        options.value.test(
+            'long string to pass here',
+            'and another long string to pass'
+        )
+
+        return
+        {
+            foo: function() {}
+        }
+    }
+    window.test = test
+
+})(window)
+
+(function(window) {
+    window.someLibrary = {}
+
+})(window)
+
+ +

Poniżej znajduje się rezultat "zgadywania" parsera.

+ +
(function(window, undefined) {
+    function test(options) {
+
+        // Nie wstaniony średnik, linie zostały połączone
+        log('testing!')(options.list || []).forEach(function(i) {
+
+        }); // <- wstawiony
+
+        options.value.test(
+            'long string to pass here',
+            'and another long string to pass'
+        ); // <- wstawiony
+
+        return; // <- wstawiony, psując deklarację return
+        { // potraktowane jako definicja bloku
+
+            // etykieta oraz pojedyncze wyrażenie
+            foo: function() {} 
+        }; // <- wstawiony
+    }
+    window.test = test; // <- wstawiony
+
+// Kolejna połączona linia
+})(window)(function(window) {
+    window.someLibrary = {}; // <- wstawiony
+
+})(window); //<- wstawiony
+
+ + + +

Parser drastycznie zmienił działanie powyższego kodu, w niektórych przypadkach +zmienił go źle.

+ +

Nawiasy

+ +

W przypadku, gdy w następnej linii znajduje się nawias, parser nie wstawi +średnika.

+ +
log('testing!')
+(options.list || []).forEach(function(i) {})
+
+ +

Ten kod zostanie zmieniony w poniższą jedną linię.

+ +
log('testing!')(options.list || []).forEach(function(i) {})
+
+ +

Jest bardzo prawdopodobne, że log nie zwróci fukcji, co za tym idzie +powyższy kod wyrzuci błąd TypeError oznajmując, że undefined is not a +function - undefined nie jest funkcją.

+ +

Wnioski

+ +

Zaleca się aby nigdy nie pomijać średników, pozostawiać nawias otwierający +w tej samej linii co odpowiadająca mu definicja i nigdy nie pozostawiać deklaracji +if / else bez nawiasów nawet jeżeli są jednolinijkowe. Wszystkie te uwagi nie +tylko pomagają poprawić spójność kodu, ale również zapobiegają parser JavaScript +przed zmianą działania kod.

Inne

setTimeout i setInterval

Ponieważ JavaScript jest asynchroniczny, istnieje możliwość zaplanowania wykonania +funkcji korzystając z funkcji setTimeout i setInterval. +Since JavaScript is asynchronous, it is possible to schedule the execution of a +function by using the setTimeout and setInterval functions.

+ + + +
function foo() {}
+var id = setTimeout(foo, 1000); // zwraca licznę typu Number > 0
+
+ +

Powyższe wywołanie setTimeout zwraca ID budzika i planuje wywołanie foo za +około tysiąc milisekund. foo zostanie wykonana dokładnie jeden raz.

+ +

Nie ma pewności, że kod zaplanowany do wykonania wykona się dokładnie po +upłynięciu zadanego czasu podanego jako parametr do setTimeout, ponieważ zależy +to od dokładności zegara w silniku JavaScript, który wykonuje kod oraz od tego, +że inny kawałek kodu może zablokować wątek, ponieważ JavaScript jest tylko +jedno wątkowy.

+ +

Funkcja, która została przekazana jako pierwszy parametr zostanie wykonana w +globalnym zasięgu, co oznacza, że this wewnątrz tej funkcji +będzie wkazywać na obiekt global.

+ +
function Foo() {
+    this.value = 42;
+    this.method = function() {
+        // this wskazuje na obiekt global
+        console.log(this.value); // wypisze undefined
+    };
+    setTimeout(this.method, 500);
+}
+new Foo();
+
+ + + +

Kolejkowanie wywołań z setInterval

+ +

Podczas, gdy setTimeout wywołuje podaną funkcję tylko raz, setInterval - +jak wskazuje nazwa - będzie wykonywać funkcję w odstępach czasowych co X +milisekund. Jednakże korzystanie z tej funkcji jest odradzane.

+ +

Kiedy wykonywany kod zablokuje możliwość uruchomienia zaplanowanej funkcji, +setInterval będzie próbować uruchamiać daną funkcję co będzie powodować +kolejkowanie wykonania tej samej funkcji kilkakrotnie. W szczególności może się +to wydarzyć przy krótkim interwale.

+ +
function foo(){
+    // coś co blokuje wykonanie na 1 sekundę 
+}
+setInterval(foo, 100);
+
+ +

W powyższym kodzie kod foo zostanie wywołany tylko raz i zablokuje wywołanie na +jedną sekundę.

+ +

Podczas, gdy funkcja foo blokuje wykonanie setInterval będzie planować kolejne +wywołania foo. W momencie, gdy pierwsze wywołanie foo się zakończy, już +w kolejce do wywołania będą czekały kolejne dziesięć wywołań tej funkcji.

+ +

Radzenie sobie z możliwymi blokadami

+ +

Najprostrzym jak również najbardziej kontrolowaną sytuacją jest użycie setTimeout +wewnątrz wywoływanej funkcji.

+ +
function foo(){
+    // coś co blokuje wykonanie na 1 sekundę
+    setTimeout(foo, 100);
+}
+foo();
+
+ +

Powyższy kod nie tylko hermetyzuje wywołanie setTimeout ale również zapobiega +kolejkowaniu wywołań fukcji i daje dodatkową kontrolę. W tym przypadku funkcja +foo może zdecydować czy powinna się wywołać ponownie czy też nie.

+ +

Ręczne usuwanie budzików

+ +

Usuwanie budzików i interwałów dokonywane jest przez przekazanie odpowiedniego ID +do clearTimeout lub clearInterval, w zależności z jakiej funkcji zostało +zwrócone ID.

+ +
var id = setTimeout(foo, 1000);
+clearTimeout(id);
+
+ +

Usuwanie wszystkich budzików

+ +

Ponieważ nie istnieje wbudowana metoda na usunięcie wszystkich budzików i/lub +interwałów, konieczne jest użycie metody brute force aby osiągnąć ten efekt.

+ +
// usunięcie "wszystkich" budzików 
+for(var i = 1; i < 1000; i++) {
+    clearTimeout(i);
+}
+
+ +

Nadal może istnieć jakieś budziki, na które powyższy kawałek kodu nie zadziała, +ponieważ ID było z innego przedziału, dlatego zamiast korzystania z metody brute +force, zaleca się śledzić wszystkie numery ID budzików, aby można je było usunąć.

+ +

Ukryte wykorzystanie eval

+ +

Do setTimeout i setInterval można również przekazać string jako pierwszy +parametr zamiast obiektu funkcji, jednakże nigdy nie należy korzystać z tej +możliwości, ponieważ wewnętrznie setTimeout i setInterval wykorzystują eval.

+ + + +
function foo() {
+    // zostanie wykonane 
+}
+
+function bar() {
+    function foo() {
+        // nigdy nie zostanie wywołane
+    }
+    setTimeout('foo()', 1000);
+}
+bar();
+
+ +

Ponieważ eval nie zostało wywołane wprost w tym przypadku, to +string przekazany do setTimeout zostanie uruchomiony w zasięgu globalnym, +co za tym idzie lokalna zmienna foo z zasięgu bar nie zostanie użyta.

+ +

Kolejnym zaleceniem jest aby nie stosować stringów do przekazywania argumentów +do funkcji, która ma zostać wywołana przez budzik.

+ +
function foo(a, b, c) {}
+
+// NIGDY nie należy tak robić 
+setTimeout('foo(1,2, 3)', 1000)
+
+// Zamiast tego należy skorzystać z anonimowej funkcji
+setTimeout(function() {
+    foo(a, b, c);
+}, 1000)
+
+ + + +

Wnioski

+ +

Nie należy nigdy przekazywać stringu jako parametru do setTimeout lub +setInterval. Jest to wyraźną oznaką bardzo złego kodu, jeżeli potrzebne jest +przekazanie argumentów do funkcji należy skorzystać z anonimowej funkcji i +wewnątrz niej dokonać przekazania argumentów.

+ +

Ponadto, należy unikać korzystanie z setInterval, ponieważ planista może +zablokować wykonanie JavaScriptu.

\ No newline at end of file From 7155c9e223d326fe17a55904d247d551e0d3b18f Mon Sep 17 00:00:00 2001 From: Colinvivy Date: Mon, 4 Jul 2011 00:21:27 +0800 Subject: [PATCH 023/463] modify a wrong word --- doc/zh/other/timeouts.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/zh/other/timeouts.md b/doc/zh/other/timeouts.md index 5993e362..e404a6d1 100755 --- a/doc/zh/other/timeouts.md +++ b/doc/zh/other/timeouts.md @@ -35,7 +35,7 @@ `setTimeout` 只会执行回调函数一次,不过 `setInterval` - 正如名字建议的 - 会每隔 `X` 毫秒执行函数一次。 但是却不鼓励使用这个函数。 -当回调函数的执行被阻塞时,`setInterval` 仍然会发布更多的毁掉指令。在很小的定时间隔情况下,这会导致回调函数被堆积起来。 +当回调函数的执行被阻塞时,`setInterval` 仍然会发布更多的回调指令。在很小的定时间隔情况下,这会导致回调函数被堆积起来。 function foo(){ // 阻塞执行 1 秒 From be35c3e5ad40bad69a0c7471b30e21f13a434bac Mon Sep 17 00:00:00 2001 From: Satoru HIRAKI Date: Mon, 4 Jul 2011 03:03:53 +0900 Subject: [PATCH 024/463] translate object/general.md to Japanese --- doc/ja/object/general.md | 74 ++++++++++++++++------------------------ site/ja/index.html | 70 +++++++++++++++---------------------- 2 files changed, 56 insertions(+), 88 deletions(-) diff --git a/doc/ja/object/general.md b/doc/ja/object/general.md index cbad5f11..2838cf91 100644 --- a/doc/ja/object/general.md +++ b/doc/ja/object/general.md @@ -1,7 +1,7 @@ -## Object Usage and Properties +## オブジェクトの使用法とプロパティ -Everything in JavaScript acts like an object, with the only two exceptions being -[`null`](#core.undefined) and [`undefined`](#core.undefined). +JavaScriptの全ての要素は2つの例外を除いて、オブジェクトのように振る舞います。 +その2つとは[`null`](#core.undefined)と[`undefined`](#core.undefined)です。 false.toString() // 'false' [1, 2, 3].toString(); // '1,2,3' @@ -10,57 +10,46 @@ Everything in JavaScript acts like an object, with the only two exceptions being Foo.bar = 1; Foo.bar; // 1 -A common misconception is that number literals cannot be used as -objects. That is because a flaw in JavaScript's parser tries to parse the *dot -notation* on a number as a floating point literal. +良くありがちな誤解として、数値リテラルがオブジェクトとして使用できないというものがあります。この理由としては、JavaScriptパーサーが浮動小数点のドットを*ドット記法*として解釈しようとしてしまうからです。 - 2.toString(); // raises SyntaxError + 2.toString(); // シンタックスエラーが発生する -There are a couple of workarounds which can be used in order make number -literals act as objects too. +数値リテラルをオブジェクトとして使用する為の回避策がいくつかあります。 - 2..toString(); // the second point is correctly recognized - 2 .toString(); // note the space left to the dot - (2).toString(); // 2 is evaluated first + 2..toString(); // 2つ目のドットが正しく解釈される + 2 .toString(); // ドットの左隣のスペースがポイント + (2).toString(); // 2が一番最初に評価される -### Objects as a Data Type +### オブジェクトはデータタイプ -Objects in JavaScript can also be used as a [*Hashmap*][1], they mainly consist -of named properties mapping to values. +JavaScriptのオブジェクトは[*ハッシュマップ*][1]としても使用されます。これは名前付きのプロパティと値として構成されています。 -Using a object literal - `{}` notation - it is possible to create a -plain object. This new object [inherits](#object.prototype) from `Object.prototype` and -has no [own properties](#object.hasownproperty) defined on it. +オブジェクトリテラル(`{}`記法)を使用すると、オブジェクトそのものを作る事ができます。この方法で作られたオブジェクトは`Object.prototype`から[継承](#object.prototype)され、[own properties](#object.hasownproperty)が何も設定されてない状態になります。 - var foo = {}; // a new empty object + var foo = {}; // 新しい空のオブジェクト - // a new object with a property called 'test' with value 12 + // 12という値の'test'というプロパティを持った新しいオブジェクト var bar = {test: 12}; -### Accessing Properties +### プロパティへのアクセス + +オブジェクトのプロパティには2通りのアクセス方法があります。1つはドット記法によるアクセス、もう1つはブラケット記法です。 -The properties of an object can be accessed in two ways, via either the dot -notation, or the square bracket notation. - var foo = {name: 'Kitten'} foo.name; // kitten foo['name']; // kitten - + var get = 'name'; foo[get]; // kitten - - foo.1234; // SyntaxError - foo['1234']; // works -Both notations are identical in their workings, with the only difference being that -the square bracket notation allows for dynamic setting of properties, as well as -the use of property names that would otherwise lead to a syntax error. + foo.1234; // シンタックスエラー + foo['1234']; // 動作する + +どちらの記法も働きとしての違いは無いですが、唯一の違いとしてブラケット記法は通常のプロパティ名と同様に動的にプロパティを設定する事ができます。これ以外で動的にプロパティを設定しようとするとシンタックスエラーになります。 -### Deleting Properties +### プロパティの削除 -The only way to actually remove a property from an object is to use the `delete` -operator; setting the property to `undefined` or `null` only remove the -*value* associated with the property, but not the *key*. +実際にオブジェクトからプロパティを削除する唯一の方法は`delete`演算子を使う事です。プロパティに`undefined`や`null`をセットしても、プロパティ自身ではなく、*キー*に設定された*値*を削除するだけです。 var obj = { bar: 1, @@ -77,23 +66,18 @@ operator; setting the property to `undefined` or `null` only remove the } } -The above outputs both `bar undefined` and `foo null` - only `baz` was -removed and is therefore missing from the output. +上記の例では、`baz`は完全に削除されて出力がされていませんが、それ以外の2つ`bar undefined`と`foo null`はどちらも出力されてしまっています。 -### Notation of Keys +### キーの記法 var test = { 'case': 'I am a keyword so I must be notated as a string', - delete: 'I am a keyword too so me' // raises SyntaxError + delete: 'I am a keyword too so me' // シンタックスエラーが起こる }; -Object properties can be both notated as plain characters and as strings. Due to -another mis-design in JavaScript's parser, the above will throw -a `SyntaxError` prior to ECMAScript 5. +オブジェクトのプロパティは普通の文字か文字列として記述する事が出来ます。JavaScriptパーサーの設計ミスが原因ですが、ECMAScript5以前では上記のコードは`シンタックスエラー`を表示するでしょう。 -This error arises from the fact that `delete` is a *keyword*; therefore, it must be -notated as a *string literal* to ensure that it will be correctly interpreted by -older JavaScript engines. +このエラーは`delete`が*予約語*になっているのが原因なので、古いJavaScriptエンジンに正しく解釈させる為には*文字リテラル*を使って記述する事を推奨します。 [1]: http://en.wikipedia.org/wiki/Hashmap diff --git a/site/ja/index.html b/site/ja/index.html index ff9f4bb6..874fa097 100644 --- a/site/ja/index.html +++ b/site/ja/index.html @@ -1,7 +1,7 @@ JavaScript Garden -

前書き

JavaScript Garden はJavaScriptというプログラム言語の一番奇抜な部分についてのドキュメント集です。 +

前書き

JavaScript Garden はJavaScriptというプログラム言語の一番奇抜な部分についてのドキュメント集です。 このドキュメントはJavaScriptという言語に対して不慣れなプログラマーがこの言語について深く知ろうとする際に遭遇する、良くある間違い・小さなバグ・パフォーマンスの問題・悪い習慣などを避ける為のアドバイスを与えます。

JavaScript GardenはJavaScriptを教える事を目的にしていません。このガイドの項目を理解する為には、この言語に対する前提知識がある事を推奨します。この言語の基礎部分についてはMozilla Developer Networkのガイド がオススメです。

@@ -24,9 +24,9 @@

ホスティング

ライセンス

-

JavaScript GardenはMIT licenseの下で公開されており、GitHubでホスティングされています。もしもエラーやtypoを見つけたらfile an issueに登録するかレポジトリにプルリクエストを送ってください。 -またStack OverflowチャットのJavaScript roomに私達はいます。

オブジェクト

Object Usage and Properties

Everything in JavaScript acts like an object, with the only two exceptions being -null and undefined.

+

JavaScript GardenはMIT licenseの下で公開されており、GitHubでホスティングされています。もしもエラーやtypoを見つけたらfile an issueに登録するかリポジトリにプルリクエストを送ってください。 +またStack OverflowチャットのJavaScript roomに私達はいます。

オブジェクト

オブジェクトの使用法とプロパティ

JavaScriptの全ての要素は2つの例外を除いて、オブジェクトのように振る舞います。 +その2つとはnullundefinedです。

false.toString() // 'false'
 [1, 2, 3].toString(); // '1,2,3'
@@ -36,40 +36,33 @@ 

ライセンス

Foo.bar; // 1
-

A common misconception is that number literals cannot be used as -objects. That is because a flaw in JavaScript's parser tries to parse the dot -notation on a number as a floating point literal.

+

良くありがちな誤解として、数値リテラルがオブジェクトとして使用できないというものがあります。この理由としては、JavaScriptパーサーが浮動小数点のドットをドット記法として解釈しようとしてしまうからです。

-
2.toString(); // raises SyntaxError
+
2.toString(); // シンタックスエラーが発生する
 
-

There are a couple of workarounds which can be used in order make number -literals act as objects too.

+

数値リテラルをオブジェクトとして使用する為の回避策がいくつかあります。

-
2..toString(); // the second point is correctly recognized
-2 .toString(); // note the space left to the dot
-(2).toString(); // 2 is evaluated first
+
2..toString(); // 2つ目のドットが正しく解釈される
+2 .toString(); // ドットの左隣のスペースがポイント
+(2).toString(); // 2が一番最初に評価される
 
-

Objects as a Data Type

+

オブジェクトはデータタイプ

-

Objects in JavaScript can also be used as a Hashmap, they mainly consist -of named properties mapping to values.

+

JavaScriptのオブジェクトはハッシュマップとしても使用されます。これは名前付きのプロパティと値として構成されています。

-

Using a object literal - {} notation - it is possible to create a -plain object. This new object inherits from Object.prototype and -has no own properties defined on it.

+

オブジェクトリテラル({}記法)を使用すると、オブジェクトそのものを作る事ができます。この方法で作られたオブジェクトはObject.prototypeから継承され、own propertiesが何も設定されてない状態になります。

-
var foo = {}; // a new empty object
+
var foo = {}; // 新しい空のオブジェクト
 
-// a new object with a property called 'test' with value 12
+// 12という値の'test'というプロパティを持った新しいオブジェクト
 var bar = {test: 12}; 
 
-

Accessing Properties

+

プロパティへのアクセス

-

The properties of an object can be accessed in two ways, via either the dot -notation, or the square bracket notation.

+

オブジェクトのプロパティには2通りのアクセス方法があります。1つはドット記法によるアクセス、もう1つはブラケット記法です。

var foo = {name: 'Kitten'}
 foo.name; // kitten
@@ -78,19 +71,15 @@ 

ライセンス

var get = 'name'; foo[get]; // kitten -foo.1234; // SyntaxError -foo['1234']; // works +foo.1234; // シンタックスエラー +foo['1234']; // 動作する
-

Both notations are identical in their workings, with the only difference being that -the square bracket notation allows for dynamic setting of properties, as well as -the use of property names that would otherwise lead to a syntax error.

+

どちらの記法も働きとしての違いは無いですが、唯一の違いとしてブラケット記法は通常のプロパティ名と同様に動的にプロパティを設定する事ができます。これ以外で動的にプロパティを設定しようとするとシンタックスエラーになります。

-

Deleting Properties

+

プロパティの削除

-

The only way to actually remove a property from an object is to use the delete -operator; setting the property to undefined or null only remove the -value associated with the property, but not the key.

+

実際にオブジェクトからプロパティを削除する唯一の方法はdelete演算子を使う事です。プロパティにundefinednullをセットしても、プロパティ自身ではなく、キーに設定されたを削除するだけです。

var obj = {
     bar: 1,
@@ -108,24 +97,19 @@ 

ライセンス

}
-

The above outputs both bar undefined and foo null - only baz was -removed and is therefore missing from the output.

+

上記の例では、bazは完全に削除されて出力がされていませんが、それ以外の2つbar undefinedfoo nullはどちらも出力されてしまっています。

-

Notation of Keys

+

キーの記法

var test = {
     'case': 'I am a keyword so I must be notated as a string',
-    delete: 'I am a keyword too so me' // raises SyntaxError
+    delete: 'I am a keyword too so me' // シンタックスエラーが起こる
 };
 
-

Object properties can be both notated as plain characters and as strings. Due to -another mis-design in JavaScript's parser, the above will throw -a SyntaxError prior to ECMAScript 5.

+

オブジェクトのプロパティは普通の文字か文字列として記述する事が出来ます。JavaScriptパーサーの設計ミスが原因ですが、ECMAScript5以前では上記のコードはシンタックスエラーを表示するでしょう。

-

This error arises from the fact that delete is a keyword; therefore, it must be -notated as a string literal to ensure that it will be correctly interpreted by -older JavaScript engines.

The Prototype

JavaScript does not feature a classical inheritance model, instead it uses a +

このエラーはdelete予約語になっているのが原因なので、古いJavaScriptエンジンに正しく解釈させる為には文字リテラルを使って記述する事を推奨します。

The Prototype

JavaScript does not feature a classical inheritance model, instead it uses a prototypal one.

While this is often considered to be one of JavaScript's weaknesses, the From 4f3c32ff9e1a5e0ac0d3ece07610ea1d0f8513ea Mon Sep 17 00:00:00 2001 From: Satoru HIRAKI Date: Mon, 4 Jul 2011 03:16:12 +0900 Subject: [PATCH 025/463] add ja and pl --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index fecb262f..a602d945 100644 --- a/.gitignore +++ b/.gitignore @@ -9,5 +9,7 @@ /site/en /site/fi /site/tr +/site/pl +/site/ja *.md~ *.src.md From 5e4532f0f6adc593ecf4795bfdbe003b8a54a5d8 Mon Sep 17 00:00:00 2001 From: Satoru HIRAKI Date: Mon, 4 Jul 2011 03:19:06 +0900 Subject: [PATCH 026/463] delate ja and pl from repository --- site/ja/index.html | 1853 ------------------------------------------ site/pl/index.html | 1914 -------------------------------------------- 2 files changed, 3767 deletions(-) delete mode 100644 site/ja/index.html delete mode 100644 site/pl/index.html diff --git a/site/ja/index.html b/site/ja/index.html deleted file mode 100644 index 874fa097..00000000 --- a/site/ja/index.html +++ /dev/null @@ -1,1853 +0,0 @@ -JavaScript Garden -

前書き

JavaScript Garden はJavaScriptというプログラム言語の一番奇抜な部分についてのドキュメント集です。 -このドキュメントはJavaScriptという言語に対して不慣れなプログラマーがこの言語について深く知ろうとする際に遭遇する、良くある間違い・小さなバグ・パフォーマンスの問題・悪い習慣などを避ける為のアドバイスを与えます。

- -

JavaScript GardenはJavaScriptを教える事を目的にしていません。このガイドの項目を理解する為には、この言語に対する前提知識がある事を推奨します。この言語の基礎部分についてはMozilla Developer Networkのガイド がオススメです。

- -

著者

- -

このガイドは2人の愛すべきStack OverflowユーザーであるIvo Wetzel -(執筆)とZhang Yi Jiang (デザイン)によって作られました。

- -

貢献者

- - - -

ホスティング

- -

JavaScript GardenはGitHubでホスティングされていますが、Cramer DevelopmentJavaScriptGarden.infoというミラーサイトを作ってくれています。

- -

ライセンス

- -

JavaScript GardenはMIT licenseの下で公開されており、GitHubでホスティングされています。もしもエラーやtypoを見つけたらfile an issueに登録するかリポジトリにプルリクエストを送ってください。 -またStack OverflowチャットのJavaScript roomに私達はいます。

オブジェクト

オブジェクトの使用法とプロパティ

JavaScriptの全ての要素は2つの例外を除いて、オブジェクトのように振る舞います。 -その2つとはnullundefinedです。

- -
false.toString() // 'false'
-[1, 2, 3].toString(); // '1,2,3'
-
-function Foo(){}
-Foo.bar = 1;
-Foo.bar; // 1
-
- -

良くありがちな誤解として、数値リテラルがオブジェクトとして使用できないというものがあります。この理由としては、JavaScriptパーサーが浮動小数点のドットをドット記法として解釈しようとしてしまうからです。

- -
2.toString(); // シンタックスエラーが発生する
-
- -

数値リテラルをオブジェクトとして使用する為の回避策がいくつかあります。

- -
2..toString(); // 2つ目のドットが正しく解釈される
-2 .toString(); // ドットの左隣のスペースがポイント
-(2).toString(); // 2が一番最初に評価される
-
- -

オブジェクトはデータタイプ

- -

JavaScriptのオブジェクトはハッシュマップとしても使用されます。これは名前付きのプロパティと値として構成されています。

- -

オブジェクトリテラル({}記法)を使用すると、オブジェクトそのものを作る事ができます。この方法で作られたオブジェクトはObject.prototypeから継承され、own propertiesが何も設定されてない状態になります。

- -
var foo = {}; // 新しい空のオブジェクト
-
-// 12という値の'test'というプロパティを持った新しいオブジェクト
-var bar = {test: 12}; 
-
- -

プロパティへのアクセス

- -

オブジェクトのプロパティには2通りのアクセス方法があります。1つはドット記法によるアクセス、もう1つはブラケット記法です。

- -
var foo = {name: 'Kitten'}
-foo.name; // kitten
-foo['name']; // kitten
-
-var get = 'name';
-foo[get]; // kitten
-
-foo.1234; // シンタックスエラー
-foo['1234']; // 動作する
-
- -

どちらの記法も働きとしての違いは無いですが、唯一の違いとしてブラケット記法は通常のプロパティ名と同様に動的にプロパティを設定する事ができます。これ以外で動的にプロパティを設定しようとするとシンタックスエラーになります。

- -

プロパティの削除

- -

実際にオブジェクトからプロパティを削除する唯一の方法はdelete演算子を使う事です。プロパティにundefinednullをセットしても、プロパティ自身ではなく、キーに設定されたを削除するだけです。

- -
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]);
-    }
-}
-
- -

上記の例では、bazは完全に削除されて出力がされていませんが、それ以外の2つbar undefinedfoo nullはどちらも出力されてしまっています。

- -

キーの記法

- -
var test = {
-    'case': 'I am a keyword so I must be notated as a string',
-    delete: 'I am a keyword too so me' // シンタックスエラーが起こる
-};
-
- -

オブジェクトのプロパティは普通の文字か文字列として記述する事が出来ます。JavaScriptパーサーの設計ミスが原因ですが、ECMAScript5以前では上記のコードはシンタックスエラーを表示するでしょう。

- -

このエラーはdelete予約語になっているのが原因なので、古いJavaScriptエンジンに正しく解釈させる為には文字リテラルを使って記述する事を推奨します。

The Prototype

JavaScript does not feature a classical inheritance model, instead it uses a -prototypal one.

- -

While this is often considered to be one of JavaScript's weaknesses, the -prototypal inheritance model is in fact more powerful than the classic model. -It is for example fairly trivial to build a classic model on top of it, while the -other way around is a far more difficult task.

- -

Due to the fact that JavaScript is basically the only widely used language that -features prototypal inheritance, it takes some time to adjust to the -differences between the two models.

- -

The first major difference is that inheritance in JavaScript is done by using so -called prototype chains.

- - - -
function Foo() {
-    this.value = 42;
-}
-Foo.prototype = {
-    method: function() {}
-};
-
-function Bar() {}
-
-// Set Bar's prototype to a new instance of Foo
-Bar.prototype = new Foo();
-Bar.prototype.foo = 'Hello World';
-
-// Make sure to list Bar as the actual constructor
-Bar.prototype.constructor = Bar;
-
-var test = new Bar() // create a new bar instance
-
-// The resulting prototype chain
-test [instance of Bar]
-    Bar.prototype [instance of Foo] 
-        { foo: 'Hello World' }
-        Foo.prototype
-            { method: ... }
-            Object.prototype
-                { toString: ... /* etc. */ }
-
- -

In the above, the object test will inherit from both Bar.prototype and -Foo.prototype; hence, it will have access to the function method that was -defined on Foo. It will also have access to the property value of the -one Foo instance that is its prototype. It is important to note that new -Bar() does not create a new Foo instance, but reuses the one assigned to -its prototype; thus, all Bar instances will share the same value property.

- - - -

Property Lookup

- -

When accessing the properties of an object, JavaScript will traverse the -prototype chain upwards until it finds a property with the requested name.

- -

When it reaches the top of the chain - namely Object.prototype - and still -hasn't found the specified property, it will return the value -undefined instead.

- -

The Prototype Property

- -

While the prototype property is used by the language to build the prototype -chains, it is still possible to assign any given value to it. Although -primitives will simply get ignored when assigned as a prototype.

- -
function Foo() {}
-Foo.prototype = 1; // no effect
-
- -

Assigning objects, as shown in the example above, will work, and allows for dynamic -creation of prototype chains.

- -

Performance

- -

The lookup time for properties that are high up on the prototype chain can have a -negative impact on performance critical sections of code. Additionally, trying to -access non-existent properties will always traverse the full prototype chain.

- -

Also, when iterating over the properties of an object -every property that is on the prototype chain will get enumerated.

- -

Extension of Native Prototypes

- -

One mis-feature that is often used is to extend Object.prototype or one of the -other built in prototypes.

- -

This technique is called monkey patching and breaks encapsulation. While -used by widely spread frameworks such as Prototype, there is still no good -reason for cluttering built-in types with additional non-standard functionality.

- -

The only good reason for extending a built-in prototype is to backport -the features of newer JavaScript engines; for example, -Array.forEach.

- -

In Conclusion

- -

It is a must to understand the prototypal inheritance model completely -before writing complex code which makes use of it. Also, watch the length of -the prototype chains and break them up if necessary to avoid possible -performance issues. Further, the native prototypes should never be extended -unless it is for the sake of compatibility with newer JavaScript features.

hasOwnProperty

In order to check whether a object has a property defined on itself and not -somewhere on its prototype chain, it is necessary to use the -hasOwnProperty method which all objects inherit from Object.prototype.

- - - -

hasOwnProperty is the only thing in JavaScript which deals with properties and -does not traverse the prototype chain.

- -
// Poisoning Object.prototype
-Object.prototype.bar = 1; 
-var foo = {goo: undefined};
-
-foo.bar; // 1
-'bar' in foo; // true
-
-foo.hasOwnProperty('bar'); // false
-foo.hasOwnProperty('goo'); // true
-
- -

Only hasOwnProperty will give the correct and expected result, this is -essential when iterating over the properties of any object. There is no other -way to exclude properties that are not defined on the object itself, but -somewhere on its prototype chain.

- -

hasOwnProperty as a Property

- -

JavaScript does not protect the property name hasOwnProperty; thus, if the -possibility exists that an object might have a property with this name, it is -necessary to use an external hasOwnProperty in order to get correct results.

- -
var foo = {
-    hasOwnProperty: function() {
-        return false;
-    },
-    bar: 'Here be dragons'
-};
-
-foo.hasOwnProperty('bar'); // always returns false
-
-// Use another Object's hasOwnProperty and call it with 'this' set to foo
-({}).hasOwnProperty.call(foo, 'bar'); // true
-
- -

In Conclusion

- -

When checking for the existence of a property on a object, hasOwnProperty is -the only method of doing so. It is also recommended to make hasOwnProperty -part of every for in loop, this will avoid errors from -extended native prototypes.

The for in Loop

Just like the in operator, the for in loop also traverses the prototype -chain when iterating over the properties of an object.

- - - -
// Poisoning Object.prototype
-Object.prototype.bar = 1;
-
-var foo = {moo: 2};
-for(var i in foo) {
-    console.log(i); // prints both bar and moo
-}
-
- -

Since it is not possible to change the behavior of the for in loop itself, it -is necessary to filter out the unwanted properties inside the loop body , -this is done by using the hasOwnProperty method of -Object.prototype.

- - - -

Using hasOwnProperty for Filtering

- -
// still the foo from above
-for(var i in foo) {
-    if (foo.hasOwnProperty(i)) {
-        console.log(i);
-    }
-}
-
- -

This version is the only correct one to use. Due to the use of hasOwnProperty it -will only print out moo. When hasOwnProperty is left out, the code is -prone to errors in cases where the native prototypes - e.g. Object.prototype - -have been extended.

- -

One widely used framework which does this is Prototype. When this -framework is included, for in loops that do not use hasOwnProperty are -guaranteed to break.

- -

In Conclusion

- -

It is recommended to always use hasOwnProperty. Never should any -assumptions be made about the environment the code is running in, or whether the -native prototypes have been extended or not.

関数

Function Declarations and Expressions

Functions in JavaScript are first class objects. That means they can be -passed around like any other value. One common use of this feature is to pass -an anonymous function as a callback to another, possibly asynchronous function.

- -

The function Declaration

- -
function foo() {}
-
- -

The above function gets hoisted before the execution of the -program starts; thus, it is available everywhere in the scope it was defined -in, even if called before the actual definition in the source.

- -
foo(); // Works because foo was created before this code runs
-function foo() {}
-
- -

The function Expression

- -
var foo = function() {};
-
- -

This example assigns the unnamed and anonymous function to the variable foo.

- -
foo; // 'undefined'
-foo(); // this raises a TypeError
-var foo = function() {};
-
- -

Due to the fact that var is a declaration, that hoists the variable name foo -before the actual execution of the code starts, foo is already defined when -the script gets executed.

- -

But since assignments only happen at runtime, the value of foo will default -to undefined before the corresponding code is executed.

- -

Named Function Expression

- -

Another special case is the assignment of named functions.

- -
var foo = function bar() {
-    bar(); // Works
-}
-bar(); // ReferenceError
-
- -

Here bar is not available in the outer scope, since the function only gets -assigned to foo; however, inside of bar it is available. This is due to -how name resolution in JavaScript works, the name of the -function is always made available in the local scope of the function itself.

How this Works

JavaScript has a different concept of what the special name this refers to -than most other programming languages do. There are exactly five different -ways in which the value of this can be bound in the language.

- -

The Global Scope

- -
this;
-
- -

When using this in global scope, it will simply refer to the global object.

- -

Calling a Function

- -
foo();
-
- -

Here this will again refer to the global object.

- - - -

Calling a Method

- -
test.foo(); 
-
- -

In this example this will refer to test.

- -

Calling a Constructor

- -
new foo(); 
-
- -

A function call that is preceded by the new keyword acts as -a constructor. Inside the function this will refer -to a newly created Object.

- -

Explicit Setting of this

- -
function foo(a, b, c) {}
-
-var bar = {};
-foo.apply(bar, [1, 2, 3]); // array will expand to the below
-foo.call(bar, 1, 2, 3); // results in a = 1, b = 2, c = 3
-
- -

When using the call or apply methods of Function.prototype, the value of -this inside the called function gets explicitly set to the first argument -of the corresponding function call.

- -

As a result, the above example the method case does not apply, and this -inside of foo will be set to bar.

- - - -

Common Pitfalls

- -

While most of these cases make sense, the first one is to be considered another -mis-design of the language, as it never has any practical use.

- -
Foo.method = function() {
-    function test() {
-        // this is set to the global object
-    }
-    test();
-}
-
- -

A common misconception is that this inside of test refers to Foo, while in -fact it does not.

- -

In order to gain access to Foo from within test it is necessary to create a -local variable inside of method which refers to Foo.

- -
Foo.method = function() {
-    var that = this;
-    function test() {
-        // Use that instead of this here
-    }
-    test();
-}
-
- -

that is just a normal variable name, but it is commonly used for the reference to an -outer this. In combination with closures, it can also -be used to pass this values around.

- -

Assigning Methods

- -

Another thing that does not work in JavaScript is function aliasing, that is, -assigning a method to a variable.

- -
var test = someObject.methodTest;
-test();
-
- -

Due to the first case test now acts like a plain function call; therefore, -this inside it will no longer refer to someObject.

- -

While the late binding of this might seem like a bad idea at first, it is in -fact what makes prototypal inheritance work.

- -
function Foo() {}
-Foo.prototype.method = function() {};
-
-function Bar() {}
-Bar.prototype = Foo.prototype;
-
-new Bar().method();
-
- -

When method gets called on a instance of Bar, this will now refer to that -very instance.

Closures and References

One of JavaScript's most powerful features is the availability of closures, -this means that scopes always keep access to the outer scope they were -defined in. Since the only scoping that JavaScript has is -function scope, all functions, by default, act as closures.

- -

Emulating private variables

- -
function Counter(start) {
-    var count = start;
-    return {
-        increment: function() {
-            count++;
-        },
-
-        get: function() {
-            return count;
-        }
-    }
-}
-
-var foo = Counter(4);
-foo.increment();
-foo.get(); // 5
-
- -

Here, Counter returns two closures. The function increment as well as -the function get. Both of these functions keep a reference to the scope of -Counter and, therefore, always keep access to the count variable that was -defined in that very scope.

- -

Why Private Variables Work

- -

Since it is not possible to reference or assign scopes in JavaScript, there is -no way of accessing the variable count from the outside. The only way to -interact with it is via the two closures.

- -
var foo = new Counter(4);
-foo.hack = function() {
-    count = 1337;
-};
-
- -

The above code will not change the variable count in the scope of Counter, -since foo.hack was not defined in that scope. It will instead create - or -override - the global variable count.

- -

Closures Inside Loops

- -

One often made mistake is to use closures inside of loops, as if they were -copying the value of the loops index variable.

- -
for(var i = 0; i < 10; i++) {
-    setTimeout(function() {
-        console.log(i);  
-    }, 1000);
-}
-
- -

The above will not output the numbers 0 through 9, but will simply print -the number 10 ten times.

- -

The anonymous function keeps a reference to i and at the time -console.log gets called, the for loop has already finished and the value of -i as been set to 10.

- -

In order to get the desired behavior, it is necessary to create a copy of -the value of i.

- -

Avoiding the Reference Problem

- -

In order to copy the value of the loop's index variable, it is best to use an -anonymous wrapper.

- -
for(var i = 0; i < 10; i++) {
-    (function(e) {
-        setTimeout(function() {
-            console.log(e);  
-        }, 1000);
-    })(i);
-}
-
- -

The anonymous outer function gets called immediately with i as its first -argument and will receive a copy of the value of i as its parameter e.

- -

The anonymous function that gets passed to setTimeout now has a reference to -e, whose value does not get changed by the loop.

- -

There is another possible way of achieving this; that is to return a function -from the anonymous wrapper, that will then have the same behavior as the code -above.

- -
for(var i = 0; i < 10; i++) {
-    setTimeout((function(e) {
-        return function() {
-            console.log(e);
-        }
-    })(i), 1000)
-}
-

The arguments Object

Every function scope in JavaScript can access the special variable arguments. -This variable holds a list of all the arguments that were passed to the function.

- - - -

The arguments object is not an Array. While it has some of the -semantics of an array - namely the length property - it does not inherit from -Array.prototype and is in fact an Object.

- -

Due to this, it is not possible to use standard array methods like push, -pop or slice on arguments. While iteration with a plain for loop works -just fine, it is necessary to convert it to a real Array in order to use the -standard Array methods on it.

- -

Converting to an Array

- -

The code below will return a new Array containing all the elements of the -arguments object.

- -
Array.prototype.slice.call(arguments);
-
- -

This conversion is slow, it is not recommended to use it in performance -critical sections of code.

- -

Passing Arguments

- -

The following is the recommended way of passing arguments from one function to -another.

- -
function foo() {
-    bar.apply(null, arguments);
-}
-function bar(a, b, c) {
-    // do stuff here
-}
-
- -

Another trick is to use both call and apply together to create fast, unbound -wrappers.

- -
function Foo() {}
-
-Foo.prototype.method = function(a, b, c) {
-    console.log(this, a, b, c);
-};
-
-// Create an unbound version of "method" 
-// It takes the parameters: this, arg1, arg2...argN
-Foo.method = function() {
-
-    // Result: Foo.prototype.method.call(this, arg1, arg2... argN)
-    Function.call.apply(Foo.prototype.method, arguments);
-};
-
- -

Formal Parameters and Arguments Indices

- -

The arguments object creates getter and setter functions for both its -properties as well as the function's formal parameters.

- -

As a result, changing the value of a formal parameter will also change the value -of the corresponding property on the arguments object, and the other way around.

- -
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);
-
- -

Performance Myths and Truths

- -

The arguments object is always created with the only two exceptions being the -cases where it is declared as a name inside of a function or one of its formal -parameters. It does not matter whether it is used or not.

- -

Both getters and setters are always created; thus, using it has nearly -no performance impact at all, especially not in real world code where there is -more than a simple access to the arguments object's properties.

- - - -

However, there is one case which will drastically reduce the performance in -modern JavaScript engines. That case is the use of arguments.callee.

- -
function foo() {
-    arguments.callee; // do something with this function object
-    arguments.callee.caller; // and the calling function object
-}
-
-function bigLoop() {
-    for(var i = 0; i < 100000; i++) {
-        foo(); // Would normally be inlined...
-    }
-}
-
- -

In the above code, foo can no longer be a subject to inlining since it -needs to know about both itself and its caller. This not only defeats possible -performance gains that would arise from inlining, it also breaks encapsulation -since the function may now be dependent on a specific calling context.

- -

It is highly recommended to never make use of arguments.callee or any of -its properties.

- -

Constructors

Constructors in JavaScript are yet again different from many other languages. Any -function call that is preceded by the new keyword acts as a constructor.

- -

Inside the constructor - the called function - the value of this refers to a -newly created Object. The prototype of this new -object is set to the prototype of the function object that was invoked as the -constructor.

- -

If the function that was called has no explicit return statement, then it -implicitly returns the value of this - the new object.

- -
function Foo() {
-    this.bla = 1;
-}
-
-Foo.prototype.test = function() {
-    console.log(this.bla);
-};
-
-var test = new Foo();
-
- -

The above calls Foo as constructor and sets the prototype of the newly -created object to Foo.prototype.

- -

In case of an explicit return statement the function returns the value -specified that statement, but only if the return value is an Object.

- -
function Bar() {
-    return 2;
-}
-new Bar(); // a new object
-
-function Test() {
-    this.value = 2;
-
-    return {
-        foo: 1
-    };
-}
-new Test(); // the returned object
-
- -

When the new keyword is omitted, the function will not return a new object.

- -
function Foo() {
-    this.bla = 1; // gets set on the global object
-}
-Foo(); // undefined
-
- -

While the above example might still appear to work in some cases, due to the -workings of this in JavaScript, it will use the -global object as the value of this.

- -

Factories

- -

In order to be able to omit the new keyword, the constructor function has to -explicitly return a value.

- -
function Bar() {
-    var value = 1;
-    return {
-        method: function() {
-            return value;
-        }
-    }
-}
-Bar.prototype = {
-    foo: function() {}
-};
-
-new Bar();
-Bar();
-
- -

Both calls to Bar return the exact same thing, a newly create object which -has a property called method on it, that is a -Closure.

- -

It is also to note that the call new Bar() does not affect the prototype -of the returned object. While the prototype will be set on the newly created -object, Bar never returns that new object.

- -

In the above example, there is no functional difference between using and -not using the new keyword.

- -

Creating New Objects via Factories

- -

An often made recommendation is to not use new since forgetting its use -may lead to bugs.

- -

In order to create new object, one should rather use a factory and construct a -new object inside of that factory.

- -
function Foo() {
-    var obj = {};
-    obj.value = 'blub';
-
-    var private = 2;
-    obj.someMethod = function(value) {
-        this.value = value;
-    }
-
-    obj.getPrivate = function() {
-        return private;
-    }
-    return obj;
-}
-
- -

While the above is robust against a missing new keyword and certainly makes -the use of private variables easier, it comes with some -downsides.

- -
    -
  1. It uses more memory since the created objects do not share the methods -on a prototype.
  2. -
  3. In order to inherit the factory needs to copy all the methods from another -object or put that object on the prototype of the new object.
  4. -
  5. Dropping the prototype chain just because of a left out new keyword -somehow goes against the spirit of the language.
  6. -
- -

In Conclusion

- -

While omitting the new keyword might lead to bugs, it is certainly not a -reason to drop the use of prototypes altogether. In the end it comes down to -which solution is better suited for the needs of the application, it is -especially important to choose a specific style of object creation and stick -with it.

Scopes and Namespaces

Although JavaScript deals fine with the syntax of two matching curly -braces for blocks, it does not support block scope; hence, all that is left -is in the language is function scope.

- -
function test() { // a scope
-    for(var i = 0; i < 10; i++) { // not a scope
-        // count
-    }
-    console.log(i); // 10
-}
-
- - - -

There are also no distinct namespaces in JavaScript, that means that everything -gets defined in one globally shared namespace.

- -

Each time a variable is referenced, JavaScript will traverse upwards through all -the scopes until it finds it. In the case that it reaches the global scope and -still has not found the requested name, it will raise a ReferenceError.

- -

The Bane of Global Variables

- -
// script A
-foo = '42';
-
-// script B
-var foo = '42'
-
- -

The above two scripts do not have the same effect. Script A defines a -variable called foo in the global scope and script B defines a foo in the -current scope.

- -

Again, that is not at all the same effect, not using var can have major -implications.

- -
// global scope
-var foo = 42;
-function test() {
-    // local scope
-    foo = 21;
-}
-test();
-foo; // 21
-
- -

Leaving out the var statement inside the function test will override the -value of foo. While this might not seem like a big deal at first, having -thousands of lines of JavaScript and not using var will introduce horrible and -hard to track down bugs.

- -
// global scope
-var items = [/* some list */];
-for(var i = 0; i < 10; i++) {
-    subLoop();
-}
-
-function subLoop() {
-    // scope of subLoop
-    for(i = 0; i < 10; i++) { // missing var statement
-        // do amazing stuff!
-    }
-}
-
- -

The outer loop will terminate after the first call to subLoop, since subLoop -overwrites the global value of i. Using a var for the second for loop would -have easily avoided this error. The var statement should never be left out -unless the desired effect is to affect the outer scope.

- -

Local Variables

- -

The only source for local variables in JavaScript are -function parameters and variables that were declared via the -var statement.

- -
// global scope
-var foo = 1;
-var bar = 2;
-var i = 2;
-
-function test(i) {
-    // local scope of the function test
-    i = 5;
-
-    var foo = 3;
-    bar = 4;
-}
-test(10);
-
- -

While foo and i are local variables inside the scope of the function test, -the assignment of bar will override the global variable with the same name.

- -

Hoisting

- -

JavaScript hoists declarations. This means that both var statements and -function declarations will be moved to the top of their enclosing scope.

- -
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];
-    }
-}
-
- -

The above code gets transformed before any execution is started. JavaScript moves -the var statements as well as the function declarations to the top of the -nearest surrounding scope.

- -
// var statements got moved here
-var bar, someValue; // default to 'undefined'
-
-// the function declartion got moved up too
-function test(data) {
-    var goo, i, e; // missing block scope moves these here
-    if (false) {
-        goo = 1;
-
-    } else {
-        goo = 2;
-    }
-    for(i = 0; i < 100; i++) {
-        e = data[i];
-    }
-}
-
-bar(); // fails with a TypeError since bar is still 'undefined'
-someValue = 42; // assignments are not affected by hoisting
-bar = function() {};
-
-test();
-
- -

Missing block scoping will not only move var statements out of loops and -their bodies, it will also make the results of certain if constructs -non-intuitive.

- -

In the original code the if statement seemed to modify the global -variable goo, while actually it modifies the local variable - after hoisting -has been applied.

- -

Without the knowledge about hoisting, below code might seem to raise a -ReferenceError.

- -
// check whether SomeImportantThing has been initiliazed
-if (!SomeImportantThing) {
-    var SomeImportantThing = {};
-}
-
- -

But of course, the above works due to the fact that the var statement is being -moved to the top of the global scope.

- -
var SomeImportantThing;
-
-// other code might initiliaze SomeImportantThing here, or not
-
-// make sure it's there
-if (!SomeImportantThing) {
-    SomeImportantThing = {};
-}
-
- -

Name Resolution Order

- -

All scopes in JavaScript, including the global scope, have the special name -this defined in them, which refers to the current object.

- -

Function scopes also have the name arguments defined in -them which contains the arguments that were passed to a function.

- -

For example, when trying to access a variable named foo inside the scope of a -function, JavaScript will lookup the name in the following order:

- -
    -
  1. In case there is a var foo statement in the current scope use that.
  2. -
  3. If one of the function parameters is named foo use that.
  4. -
  5. If the function itself is called foo use that.
  6. -
  7. Go to the next outer scope and start with #1 again.
  8. -
- - - -

Namespaces

- -

A common problem of having only one global namespace is the likeliness of running -into problems where variable names clash. In JavaScript, this problem can -easily be avoided with the help of anonymous wrappers.

- -
(function() {
-    // a self contained "namespace"
-
-    window.foo = function() {
-        // an exposed closure
-    };
-
-})(); // execute the function immediately
-
- -

Unnamed functions are considered expressions; so in order to -being callable, they must first be evaluated.

- -
( // evaluate the function inside the paranthesis
-function() {}
-) // and return the function object
-() // call the result of the evaluation
-
- -

There are other ways for evaluating and calling the function expression; which, -while different in syntax, do behave the exact same way.

- -
// Two other ways
-+function(){}();
-(function(){}());
-
- -

In Conclusion

- -

It is recommended to always use an anonymous wrapper for encapsulating code in -its own namespace. This does not only protect code against name clashes, it -also allows for better modularization of programs.

- -

Additionally, the use of global variables is considered bad practice. Any -use of them indicates badly written code that is prone to errors and hard to maintain.

配列

Array Iteration and Properties

Although arrays in JavaScript are objects, there are no good reasons to use -the for in loop in for iteration on them. In fact there -are a number of good reasons against the use of for in on arrays.

- - - -

Since the for in loop enumerates all the properties that are on the prototype -chain and the only way to exclude those properties is to use -hasOwnProperty, it is already up to twenty times -slower than a normal for loop.

- -

Iteration

- -

In order to achieve the best performance when iterating over arrays, it is best -to use the classic for loop.

- -
var list = [1, 2, 3, 4, 5, ...... 100000000];
-for(var i = 0, l = list.length; i < l; i++) {
-    console.log(list[i]);
-}
-
- -

There is one extra catch in the above example, that is the caching of the -length of the array via l = list.length.

- -

Although the length property is defined on the array itself, there is still an -overhead for doing the lookup on each iteration of the loop. And while recent -JavaScript engines may apply optimization in this case, there is no way of -telling whether the code will run on one of these newer engines or not.

- -

In fact, leaving out the caching may result in the loop being only half as -fast as with the cached length.

- -

The length Property

- -

While the getter of the length property simply returns the number of -elements that are contained in the array, the setter can be used to -truncate the array.

- -
var foo = [1, 2, 3, 4, 5, 6];
-foo.length = 3;
-foo; // [1, 2, 3]
-
-foo.length = 6;
-foo; // [1, 2, 3]
-
- -

Assigning a smaller length does truncate the array, but increasing the length -does not have any effect on the array.

- -

In Conclusion

- -

For the best performance it is recommended to always use the plain for loop -and cache the length property. The use of for in on an array is a sign of -badly written code that is prone to bugs and bad performance.

The Array Constructor

Since the Array constructor is ambiguous in how it deals with its parameters, -it is highly recommended to always use the array literals - [] notation - -when creating new arrays.

- -
[1, 2, 3]; // Result: [1, 2, 3]
-new Array(1, 2, 3); // Result: [1, 2, 3]
-
-[3]; // Result: [3]
-new Array(3); // Result: []
-new Array('3') // Result: ['3']
-
- -

In cases when there is only one argument passed to the Array constructor, -and that argument is a Number, the constructor will return a new sparse -array with the length property set to the value of the argument. It should be -noted that only the length property of the new array will be set this way, -the actual indexes of the array will not be initialized.

- -
var arr = new Array(3);
-arr[1]; // undefined
-1 in arr; // false, the index was not set
-
- -

The behavior of being able to set the length of the array upfront only comes in -handy in a few cases, like repeating a string, in which it avoids the use of a -for loop code.

- -
new Array(count + 1).join(stringToRepeat);
-
- -

In Conclusion

- -

The use of the Array constructor should be avoided as much as possible. -Literals are definitely preferred. They are shorter and have a clearer syntax; -therefore, they also increase the readability of the code.

Equality and Comparisons

JavaScript has two different ways of comparing the values of objects for equality.

- -

The Equality Operator

- -

The equality operator consists of two equal signs: ==

- -

JavaScript features weak typing. This means that the equality operator -coerces types in order to compare them.

- -
""           ==   "0"           // false
-0            ==   ""            // true
-0            ==   "0"           // true
-false        ==   "false"       // false
-false        ==   "0"           // true
-false        ==   undefined     // false
-false        ==   null          // false
-null         ==   undefined     // true
-" \t\r\n"    ==   0             // true
-
- -

The above table shows the results of the type coercion and it is the main reason -why the use of == is widely regarded as bad practice, it introduces hard to -track down bugs due to its complicated conversion rules.

- -

Additionally there is also a performance impact when type coercion is in play; -for example, a string has to be converted to a number before it can be compared -to another number.

- -

The Strict Equality Operator

- -

The strict equality operator consists of three equal signs: ===

- -

It works exactly like the normal equality operator, except that strict equality -operator does not perform type coercion between its operands.

- -
""           ===   "0"           // false
-0            ===   ""            // false
-0            ===   "0"           // false
-false        ===   "false"       // false
-false        ===   "0"           // false
-false        ===   undefined     // false
-false        ===   null          // false
-null         ===   undefined     // false
-" \t\r\n"    ===   0             // false
-
- -

The above results are a lot clearer and allow for early breakage of code. This -hardens code to a certain degree and also gives performance improvements in case -the operands are of different types.

- -

Comparing Objects

- -

While both == and === are stated as equality operators, they behave -different when at least one of their operands happens to be an Object.

- -
{} === {};                   // false
-new String('foo') === 'foo'; // false
-new Number(10) === 10;       // false
-var foo = {};
-foo === foo;                 // true
-
- -

Here both operators compare for identity and not equality; that is, they -will compare for the same instance of the object, much like is in Python -and pointer comparison in C.

- -

In Conclusion

- -

It is highly recommended to only use the strict equality operator. In cases -where types need to be coerced, it should be done explicitly -and not left to the language's complicated coercion rules.

The typeof Operator

The typeof operator (together with -instanceof) is probably the biggest -design flaw of JavaScript, as it is near of being completely broken.

- -

Although instanceof still has its limited uses, typeof really has only one -practical use case, which does not happen to be checking the type of an -object.

- - - -

The JavaScript Type Table

- -
Value               Class      Type
--------------------------------------
-"foo"               String     string
-new String("foo")   String     object
-1.2                 Number     number
-new Number(1.2)     Number     object
-true                Boolean    boolean
-new Boolean(true)   Boolean    object
-new Date()          Date       object
-new Error()         Error      object
-[1,2,3]             Array      object
-new Array(1, 2, 3)  Array      object
-new Function("")    Function   function
-/abc/g              RegExp     object (function in Nitro/V8)
-new RegExp("meow")  RegExp     object (function in Nitro/V8)
-{}                  Object     object
-new Object()        Object     object
-
- -

In the above table Type refers to the value, that the typeof operator returns. -As can be clearly seen, this value is anything but consistent.

- -

The Class refers to the value of the internal [[Class]] property of an object.

- - - -

In order to retrieve the value of [[Class]] one has to make use of the -toString method of Object.prototype.

- -

The Class of an Object

- -

The specification gives exactly one way of accessing the [[Class]] value, -with the use of Object.prototype.toString.

- -
function is(type, obj) {
-    var clas = Object.prototype.toString.call(obj).slice(8, -1);
-    return obj !== undefined && obj !== null && clas === type;
-}
-
-is('String', 'test'); // true
-is('String', new String('test')); // true
-
- -

In the above example, Object.prototype.toString gets called with the value of -this being set to the object whose [[Class]] value should be -retrieved.

- - - -

Testing for Undefined Variables

- -
typeof foo !== 'undefined'
-
- -

The above will check whether foo was actually declared or not; just -referencing it would result in a ReferenceError. This is the only thing -typeof is actually useful for.

- -

In Conclusion

- -

In order to check the type of an object, it is highly recommended to use -Object.prototype.toString; as this is the only reliable way of doing so. -As shown in the above type table, some return values of typeof are not defined -in the specification; thus, they can differ across various implementations.

- -

Unless checking whether a variable is defined, typeof should be avoided at -all costs.

The instanceof Operator

The instanceof operator compares the constructors of its two operands. It is -only useful when comparing custom made objects. Used on built-in types, it is -nearly as useless as the typeof operator.

- -

Comparing Custom Objects

- -
function Foo() {}
-function Bar() {}
-Bar.prototype = new Foo();
-
-new Bar() instanceof Bar; // true
-new Bar() instanceof Foo; // true
-
-// This just sets Bar.prototype to the function object Foo
-// But not to an actual instance of Foo
-Bar.prototype = Foo;
-new Bar() instanceof Foo; // false
-
- -

Using instanceof with Native Types

- -
new String('foo') instanceof String; // true
-new String('foo') instanceof Object; // true
-
-'foo' instanceof String; // false
-'foo' instanceof Object; // false
-
- -

One important thing to note here is, that instanceof does not work on objects -that origin from different JavaScript contexts (e.g. different documents -in a web browser), since their constructors will not be the exact same object.

- -

In Conclusion

- -

The instanceof operator should only be used when dealing with custom made -objects that origin from the same JavaScript context. Just like the -typeof operator, every other use of it should be avoided.

Type Casting

JavaScript is a weakly typed language, so it will apply type coercion -wherever possible.

- -
// These are true
-new Number(10) == 10; // Number.toString() is converted
-                      // back to a number
-
-10 == '10';           // Strings gets converted to Number
-10 == '+10 ';         // More string madness
-10 == '010';          // And more 
-isNaN(null) == false; // null converts to 0
-                      // which of course is not NaN
-
-// These are false
-10 == 010;
-10 == '-10';
-
- - - -

In order to avoid the above, use of the strict equal operator -is highly recommended. Although this avoids a lot of common pitfalls, there -are still many further issues that arise from JavaScript's weak typing system.

- -

Constructors of Built-In Types

- -

The constructors of the built in types like Number and String behave -differently when being used with the new keyword and without it.

- -
new Number(10) === 10;     // False, Object and Number
-Number(10) === 10;         // True, Number and Number
-new Number(10) + 0 === 10; // True, due to implicit conversion
-
- -

Using a built-in type like Number as a constructor will create a new Number -object, but leaving out the new keyword will make the Number function behave -like a converter.

- -

In addition, having literals or non-object values in there will result in even -more type coercion.

- -

The best option is to cast to one of the three possible types explicitly.

- -

Casting to a String

- -
'' + 10 === '10'; // true
-
- -

By prepending a empty string a value can easily be casted to a string.

- -

Casting to a Number

- -
+'10' === 10; // true
-
- -

Using the unary plus operator it is possible to cast to a number.

- -

Casting to a Boolean

- -

By using the not operator twice, a value can be converted a boolean.

- -
!!'foo';   // true
-!!'';      // false
-!!'0';     // true
-!!'1';     // true
-!!'-1'     // true
-!!{};      // true
-!!true;    // true
-

コア

Why Not to Use eval

The eval function will execute a string of JavaScript code in the local scope.

- -
var foo = 1;
-function test() {
-    var foo = 2;
-    eval('foo = 3');
-    return foo;
-}
-test(); // 3
-foo; // 1
-
- -

But eval only executes in local scope when it is being called directly and -the name of the called function is actually eval.

- -
var foo = 1;
-function test() {
-    var foo = 2;
-    var bar = eval;
-    bar('foo = 3');
-    return foo;
-}
-test(); // 2
-foo; // 3
-
- -

The use of eval should be avoided at all costs. 99.9% of its "uses" can be -achieved without it.

- -

eval in Disguise

- -

The timeout functions setTimeout and setInterval can both -take a string as their first argument. This string will always get executed -in the global scope since eval is not being called directly in that case.

- -

Security Issues

- -

eval also is a security problem as it executes any code given to it, -it should never be used with strings of unknown or untrusted origins.

- -

In Conclusion

- -

eval should never be used, any code that makes use of it is to be questioned in -its workings, performance and security. In case something requires eval in -order to work, its design is to be questioned and should not be used in the -first place, a better design should be used, that does not require the use of -eval.

undefined and null

JavaScript has two distinct values for nothing, the more useful of these two -being undefined.

- -

The Value undefined

- -

undefined is a type with exactly one value: undefined.

- -

The language also defines a global variable that has the value of undefined, -this variable is also called undefined. But this variable is not a constant, -nor is it a keyword of the language. This means that its value can be easily -overwritten.

- - - -

Some examples for when the value undefined is returned:

- -
    -
  • Accessing the (unmodified) global variable undefined.
  • -
  • Implicit returns of functions due to missing return statements.
  • -
  • return statements which do not explicitly return anything.
  • -
  • Lookups of non-existent properties.
  • -
  • Function parameters which do not had any explicit value passed.
  • -
  • Anything that has been set to the value of undefined.
  • -
- -

Handling Changes to the Value of undefined

- -

Since the global variable undefined only holds a copy of the actual value of -undefined, assigning a new value to it does not change the value of the -type undefined.

- -

Still, in order to compare something against the value of undefined it is -necessary to retrieve the value of undefined first.

- -

In order to protect code against a possible overwritten undefined variable, a -common technique used is to add an additional parameter to an -anonymous wrapper, that gets no argument passed to it.

- -
var undefined = 123;
-(function(something, foo, undefined) {
-    // undefined in the local scope does 
-    // now again refer to the value
-
-})('Hello World', 42);
-
- -

Another way to achieve the same effect would be to use a declaration inside the -wrapper.

- -
var undefined = 123;
-(function(something, foo) {
-    var undefined;
-    ...
-
-})('Hello World', 42);
-
- -

The only difference being here, that this version results in 4 more bytes being -used in case it is minified and there is no other var statement inside the -anonymous wrapper.

- -

Uses of null

- -

While undefined in the context of the JavaScript language is mostly used in -the sense of a traditional null, the actual null (both a literal and a type) -is more or less just another data type.

- -

It is used in some JavaScript internals (like declaring the end of the -prototype chain by setting Foo.prototype = null), but in almost all cases it -can be replaced by undefined.

Automatic Semicolon Insertion

Although JavaScript has C style syntax, it does not enforce the use of -semicolons in the source code, it is possible to omit them.

- -

But JavaScript is not a semicolon-less language, it in fact needs the -semicolons in order to understand the source code. Therefore the JavaScript -parser automatically inserts them whenever it encounters a parse -error due to a missing semicolon.

- -
var foo = function() {
-} // parse error, semicolon expected
-test()
-
- -

Insertion happens, and the parser tries again.

- -
var foo = function() {
-}; // no error, parser continues
-test()
-
- -

The automatic insertion of semicolon is considered to be one of biggest -design flaws in the language, as it can change the behavior of code.

- -

How it Works

- -

The code below has no semicolons in it, so it is up to the parser to decide where -to insert them.

- -
(function(window, undefined) {
-    function test(options) {
-        log('testing!')
-
-        (options.list || []).forEach(function(i) {
-
-        })
-
-        options.value.test(
-            'long string to pass here',
-            'and another long string to pass'
-        )
-
-        return
-        {
-            foo: function() {}
-        }
-    }
-    window.test = test
-
-})(window)
-
-(function(window) {
-    window.someLibrary = {}
-
-})(window)
-
- -

Below is the result of the parser's "guessing" game.

- -
(function(window, undefined) {
-    function test(options) {
-
-        // Not inserted, lines got merged
-        log('testing!')(options.list || []).forEach(function(i) {
-
-        }); // <- inserted
-
-        options.value.test(
-            'long string to pass here',
-            'and another long string to pass'
-        ); // <- inserted
-
-        return; // <- inserted, breaks the return statement
-        { // treated as a block
-
-            // a label and a single expression statement
-            foo: function() {} 
-        }; // <- inserted
-    }
-    window.test = test; // <- inserted
-
-// The lines got merged again
-})(window)(function(window) {
-    window.someLibrary = {}; // <- inserted
-
-})(window); //<- inserted
-
- - - -

The parser drastically changed the behavior of the code above, in certain cases -it does the wrong thing.

- -

Leading Parenthesis

- -

In case of a leading parenthesis, the parser will not insert a semicolon.

- -
log('testing!')
-(options.list || []).forEach(function(i) {})
-
- -

This code gets transformed into one line.

- -
log('testing!')(options.list || []).forEach(function(i) {})
-
- -

Chances are very high that log does not return a function; therefore, -the above will yield a TypeError stating that undefined is not a function.

- -

In Conclusion

- -

It is highly recommended to never omit semicolons, it is also advocated to -keep braces on the same line with their corresponding statements and to never omit -them for one single-line if / else statements. Both of these measures will -not only improve the consistency of the code, they will also prevent the -JavaScript parser from changing its behavior.

その他

setTimeout and setInterval

Since JavaScript is asynchronous, it is possible to schedule the execution of a -function by using the setTimeout and setInterval functions.

- - - -
function foo() {}
-var id = setTimeout(foo, 1000); // returns a Number > 0
-
- -

When setTimeout gets called, it will return the ID of the timeout and schedule -foo to run in approximately one thousand milliseconds in the future. -foo will then get executed exactly once.

- -

Depending on the timer resolution of the JavaScript engine that is running the -code, as well as the fact that JavaScript is single threaded and other code that -gets executed might block the thread, it is by no means a safe bet that one -will get the exact delay that was specified in the setTimeout call.

- -

The function that was passed as the first parameter will get called by the -global object, that means, that this inside the called function -refers to that very object.

- -
function Foo() {
-    this.value = 42;
-    this.method = function() {
-        // this refers to the global object
-        console.log(this.value); // will log undefined
-    };
-    setTimeout(this.method, 500);
-}
-new Foo();
-
- - - -

Stacking Calls with setInterval

- -

While setTimeout only runs the function once, setInterval - as the name -suggests - will execute the function every X milliseconds. But its use is -discouraged.

- -

When code that is being executed blocks the timeout call, setInterval will -still issue more calls to the specified function. This can, especially with small -intervals, result in function calls stacking up.

- -
function foo(){
-    // something that blocks for 1 second
-}
-setInterval(foo, 100);
-
- -

In the above code foo will get called once and will then block for one second.

- -

While foo blocks the code setInterval will still schedule further calls to -it. Now, when foo has finished, there will already be ten further calls to -it waiting for execution.

- -

Dealing with Possible Blocking Code

- -

The easiest as well as most controllable solution, is to use setTimeout within -the function itself.

- -
function foo(){
-    // something that blocks for 1 second
-    setTimeout(foo, 100);
-}
-foo();
-
- -

Not only does this encapsulate the setTimeout call, but it also prevents the -stacking of calls and it gives additional control.foo itself can now decide -whether it wants to run again or not.

- -

Manually Clearing Timeouts

- -

Clearing timeouts and intervals works by passing the respective ID to -clearTimeout or clearInterval, depending which set function was used in -the first place.

- -
var id = setTimeout(foo, 1000);
-clearTimeout(id);
-
- -

Clearing all timeouts

- -

As there is no built-in method for clearing all timeouts and/or intervals, -it is necessary to use brute force in order to achieve this functionality.

- -
// clear "all" timeouts
-for(var i = 1; i < 1000; i++) {
-    clearTimeout(i);
-}
-
- -

There might still be timeouts that are unaffected by this arbitrary number; -therefore, is is instead recommended to keep track of all the timeout IDs, so -they can be cleared specifically.

- -

Hidden use of eval

- -

setTimeout and setInterval can also take a string as their first parameter. -This feature should never be used, since it internally makes use of eval.

- - - -
function foo() {
-    // will get called
-}
-
-function bar() {
-    function foo() {
-        // never gets called
-    }
-    setTimeout('foo()', 1000);
-}
-bar();
-
- -

Since eval is not getting called directly in this case, the string -passed to setTimeout will get executed in the global scope; thus, it will -not use the local variable foo from the scope of bar.

- -

It is further recommended to not use a string for passing arguments to the -function that will get called by either of the timeout functions.

- -
function foo(a, b, c) {}
-
-// NEVER use this
-setTimeout('foo(1,2, 3)', 1000)
-
-// Instead use an anonymous function
-setTimeout(function() {
-    foo(a, b, c);
-}, 1000)
-
- - - -

In Conclusion

- -

Never should a string be used as the parameter of setTimeout or -setInterval. It is a clear sign of really bad code, when arguments need -to be supplied to the function that gets called. An anonymous function should -be passed that then takes care of the actual call.

- -

Further, the use of setInterval should be avoided since its scheduler is not -blocked by executing JavaScript.

\ No newline at end of file diff --git a/site/pl/index.html b/site/pl/index.html deleted file mode 100644 index cfeeb4fa..00000000 --- a/site/pl/index.html +++ /dev/null @@ -1,1914 +0,0 @@ -JavaScript Garden -

Wstęp

JavaScript Garden jest rosnącą kolekcją dokumentów o najdziwniejszych -częściach języka JavaScript. Dokumentacja pomaga uniknąć najczęściej popełnianych -błędów, sybtelnych bugów, problemów wydajnościowych oraz złych praktyk, na które -niedoświadczeni programiści JavaScript mogą natrafić próbując poznać tajniki tego -języka.

- -

JavaScript Garden nie ma na celu nauczyć Cię języka JavaScript. Podstawowa -wiedza na temat języka jest wymagana do zrozumienia zagadnień poruszanych w tym -przewodniku. Aby nauczyć się podstaw jezyka JavaScript, odwiedź znakomity -przewodnik na stronach Mozilla Developer Network.

Licencja

JavaScript Garden jest publikowany w ramach licencji MIT i kod źródłowy znajduje -się na serwerze GitHub. Jeśli znajdziesz jakieś błędy lub literówek zgłoś proszę -problem lub rozwiązag go i zglosić pull request ze swojego repozytorium. -Możesz nas także znaleźć w pokoju JavaScript na chacie Stack Overflow.

Obiekty

Wykorzystanie obiektów i ich właściwości

Wszystko w JavaScripcie zachowuje sie jak obiekt, z dwoma wyjątkami -null oraz undefined.

- -
false.toString() // 'false'
-[1, 2, 3].toString(); // '1,2,3'
-
-function Foo(){}
-Foo.bar = 1;
-Foo.bar; // 1
-
- -

Popularnym błędem jest wykorzystanie literałów liczbowych jako obiektu. -Spowodowanie jest to usterką w parserze JavaScript, który interpretuje kropkę -po literale liczbowym jako rozdzielenie części całkowitej od części po przecinku -liczby.

- -
2.toString(); // wyrzuca błąd SyntaxError
-
- -

Istnieje kilka rozwiązań, dzieki którym literał liczbowy będzie zachowywał się -jak obiekt.

- -
2..toString(); // druga kropka jest poprawnie rozpoznana
-2 .toString(); // zauważ, że pozostawiona jest spacja przed kropką
-(2).toString(); // 2 zostanie zewaluowane najpiewr
-
- -

Obiekty jako typy danych

- -

Obiekty w języku JavaScript mogą być używana jako tablice asocjacyjne. -Ponieważ obiekty głównie składają się z mapowań pomiędzy nazwanymi właściwościami (kluczami) -a wartościami dla tych atrybutów.

- -

Używając literału obiektu - notacji {} - istnieje możliwość stworzenie obiektu prostego. -Ten nowy obiekt bedzie dziedziczył z Object.prototype oraz -nie bedzie posiadał żadnych własnych właściwości zdefiniowanych w sobie.

- -
var foo = {}; // nowy pusty obiekt
-
-// nowy obiekt z właściwością test o wartości 12
-var bar = {test: 12}; 
-
- -

Dostęp do właściwości

- -

Właściwości obiektu można uzyskać na dwa sposoby, poprzez notację z kropką -lub notacje z nawiasami kwadratowymi.

- -
var foo = {name: 'Kitten'}
-foo.name; // kitten
-foo['name']; // kitten
-
-var get = 'name';
-foo[get]; // kitten
-
-foo.1234; // wyrzuca błąd SyntaxError
-foo['1234']; // działa, zwraca undefined
-
- -

Obie notacje są identyczne w swoim działaniu, z tą tylko różnicą że notacja z nawiasami -kwadratowymi pozwala na dynamiczne dodawanie właściwości i nie prowadzi do wyrzycenia -błędu podczas odczytu nieistniejącej właściwości.

- -

Usuwanie właściwości

- -

Jedynym sposobem na faktycze usunięcie własności z obiektu jest użycie operatora -delete. Ustawienie własności na undefined lub null usunie tylko wartość -związaną z własnością, ale nie usunie to klucza (nazwy własności) z obiektu.

- -
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]);
-    }
-}
-
- -

Powyższy kod wypisuje dwie linie bar undefined i foo null - tylko własność baz -została usunięta i dlatego nie została wypisana.

- -

Notacja właściwości

- -
var test = {
-    'case': 'I am a keyword so I must be notated as a string',
-    delete: 'I am a keyword too so me' // wyrzuca błąd SyntaxError
-};
-
- -

Nazwy właściwości obiektu mogą być zarówno zapisane jako tekst(bez cudzysłowów -lub apostrofów) lub jako string (w cudzisłowach lub apostrofach). -Ze względu na kolejne niedociągnięcie w parserze JavaScript -powyższy kod wyrzuci błąd SyntaxError dla implementacji JavaScript ponizej ECMAScript 5.

- -

Ten błąd wynika z faktu, że delete jest słowem kluczowym, dlatego musi zostać -zapisany jako string (z cudzysłowami lub apostrofami), aby zapewnić, że zostanie -to poprawnie zinterpretowane przez starsze silniki języka JavaScript.

Prototyp

JavaScript nie posiada klasycznego modelu dziedziczenia, lecz zamiast tego -dziedziczenie jest realizowane poprzez prototypy.

- -

Choć jest to często uważane za jedną ze słabości języka JavaScript, -prototypowy model dziedziczenia, jest w rzeczywistości potężniejszy od klasycznego -modelu. Na przykład stworzenia klasycznego modelu na podstawie modelu prototypowym -jest dość proste, podczas gdy zrobienie odwrotnie to już o wiele trudniejsze zadanie.

- -

Ze względu na fakt, że w JavaScript jest w zasadzie jedynym powszechnie stosowanym -językiem, któy posiada prototypowy model dziedziczenia, to wymaga troche czasu aby -dostosować się do różnic pomiędzy tymi dwoma modelami.

- -

Pierwszą znaczącą różnicą jest to, że dziedziczenie w JavaScript odbywa się za pomocą -tak zwanych łańcuchów prototypów.

- - - -
function Foo() {
-    this.value = 42;
-}
-Foo.prototype = {
-    method: function() {}
-};
-
-function Bar() {}
-
-// Ustawienie prototypu Bar na nową instancję Foo
-Bar.prototype = new Foo();
-Bar.prototype.foo = 'Hello World';
-
-// Upewniamy się, że Bar jest ustawiony jako rzeczywisty konstruktor
-Bar.prototype.constructor = Bar;
-
-var test = new Bar() // tworzymy nową instancję Bar
-
-// The resulting prototype chain
-test [instance of Bar]
-    Bar.prototype [instance of Foo] 
-        { foo: 'Hello World' }
-        Foo.prototype
-            { method: ... }
-            Object.prototype
-                { toString: ... /* etc. */ }
-
- -

W powyższym przykładzie obiekt test będzie dziedziczył z obydwu tj. -Bar.prototyp i Foo.prototyp, stąd będzie miał dostęp do funkcji method, -która była zdefiniowana w Foo. Ponadto obiekt będzie miał dostęp do -właściwości value, która jest jednyną instancją Foo i stała się jego prototypem. -Ważne jest, aby pamiętać new Bar nie tworzy nowej instancji Foo, -ale wykorzystuje instancje, którą jest przypisana do własności prototype. -Zatem Wszystkie instancje Bar będą dzieliły tą samą własność value.

- - - -

Wyszukiwanie własności

- -

Podczas dostępu do właściwości obiektu, JavaScript przejdzie w górę łańcucha -prototypów dopóki nie znajdzie właściwości z żądaną nazwą.

- -

Gdy przeszukiwanie dotrze do końca (szczytu) łańcucha mianowicie Object.prototype -i nadal nie znajdzie określonej właściwości, to zwróci wartość -undefined.

- -

Właściwość prototype

- -

Podczas gdy właściwość prototype jest używana przez język do budowania łańcucha -prototypów, istnieje możliwość przypisania do niej dowolnej wartości. Jednakże -prymitywne typy będą po prostu ignorowanie, jeżeli zostaną ustawione jako prototype.

- -
function Foo() {}
-Foo.prototype = 1; // nie ma wpływu
-
- -

Przypisywanie obiektów, jak pokazano w powyższym przykładzie, zadziała i pozwala -na dynamiczne tworzenie łańcuchów prototypów.

- -

Wydajność

- -

Czas wyszukiwania właściwości, które są na końcu łańcucha prototypów może mieć -negatywny wpływ na wydajność krytycznych części kodu. Dodatkowo, próba dostępu -do nieistniejącej właściwości powoduje zawsze przeszukanie całego łańcucha prototypów.

- -

Również, podczas iteracji po właściwościach obiektu -każda właściwość, która znajduje się w łańcuchu prototypów niezależnie -na jakim znajduje się poziomie zostanie wyliczona.

- -

Rozszerzanie natywnych prototypów

- -

Rozszerzanie Object.prototype lub innego prototypu wbudowanych typów jest jednym z -najczęściej używanych niedoskonałej częsci języka JavaScript.

- -

Technika ta nazywana jest monkey patching i łamie zasady enkapsulacji. -Jednak jest szeroko rozpowszechniona w frameworkach takich jak Prototype. -Nie ma jednak dobrego powodu, aby zaśmiecać wbudowane typy poprzez dodawanie do nich -niestandardowych funkcjonalności.

- -

Jedynym dobrym powodem do rozszerzania wbudowanych prototypów jest portowanie
-funkcjonalności znajdujących sie w nowszych silnikach JavaScript np. Array.forEach

- -

Wnioski

- -

Zanim przystąpi się do pisania skomplikowanego kodu korzystającego z dziedziczanie -należy całkowicie rozumieć prototypowy model dziedziczenia. Ponadto należy uważać -na długość łańcucha prototypów i w razie potrzeby zmniejszać ilość dziedziczeń -aby uniknąć problemów z wydajnością. Natywne prototypy nie powinny nigdy być -rozszerzane, chyba że ze względu na wprowadzanie kompatybilności z nowszymi silnikami -JavaScript.

hasOwnProperty

W celu sprawdzenia czy dana właściwość została zdefiniowana w tym obiekcie a nie -w łańcuchu prototypów niezbędne jest skorzystanie z metody -hasOwnProperty, która wszystkie obiekty dziedziczą z Object.prototype.

- - - -

hasOwnProperty jest jedyna metodą w języku JavaScript która operuje na właściwościach -i nie przegląda całego łańcucha prototypów.

- -
// Zatrucie Object.prototype
-Object.prototype.bar = 1; 
-var foo = {goo: undefined};
-
-foo.bar; // 1
-'bar' in foo; // true
-
-foo.hasOwnProperty('bar'); // false
-foo.hasOwnProperty('goo'); // true
-
- -

Tylko hasOwnProperty da prawidłowy i oczekiwany rezultat. Jest to istotne podczas -iteracji po właściwościach obiektu. Nie ma innego sposobu na ominięcie -właściwości, która nie została zdefiniowana przez ten konkretny obiekt, -ale gdzieś indziej w łańcuchu prototypów.

- -

hasOwnProperty jako właściwość

- -

JavaScript nie chroni właściwości o nazwie hasOwnProperty, zatem istnieje -możliwość, że obiekt może posiadać tak nazwaną właściwość. Konieczne jest użycie -zewnętrznego hasOwnProperty, aby otrzymać poprawne rezultaty.

- -
var foo = {
-    hasOwnProperty: function() {
-        return false;
-    },
-    bar: 'Here be dragons'
-};
-
-foo.hasOwnProperty('bar'); // zawsze zwraca false
-
-// Została użyta metoda innego obiektu i wywołana z konkekstem 
-// `this` ustawionym na foo
-({}).hasOwnProperty.call(foo, 'bar'); // true
-
- -

Wnioski

- -

Jedyną metodą służącą do sprawdzenia zdefiniowania jakiejś właściwości w konkretnym -obiekcie jest metoda hasOwnProperty. Zaleca się korzystać z hasOwnProperty jako część -każdej pętli for in, pozwoli to uniknąć błędów pochodzących z -rozszerzonych natywnych prototypów.

The for in Loop

Podobnie jak operator in, pętla for in przeszukuje łańcuch prototypów -podczas iteracji po właściwościach obiektu.

- - - -
// Zatrucie Object.prototype
-Object.prototype.bar = 1;
-
-var foo = {moo: 2};
-for(var i in foo) {
-    console.log(i); // wyświetla obie właściwości: bar i moo
-}
-
- -

Ponieważ nie jest możliwe, aby zmienić zachowanie pętli for in to niezbędne -jest odfiltrowanie niechcianych właściwości wewnątrz ciała pętli, korzystając -z metody hasOwnProperty z Object.prototype.

- - - -

Korzystanie z hasOwnProperty do odfiltrowania

- -
// foo z przykładu powyżej
-for(var i in foo) {
-    if (foo.hasOwnProperty(i)) {
-        console.log(i);
-    }
-}
-
- -

To jest jedyna poprawna wersja, którą należy używać. Ze względu na użycie -hasOwnProperty zostanie wypisane jedynie moo. Gdy opuścimy hasOwnProperty -kod będzie podatny na błędy, gdy natywne prototypy np. Object.prototype -zostanie rozszerzony.

- -

Prototype jest jednym z szeroko rozpowszechniony frameworków, który dokonuje -takiego rozszerzenia. Używanie tego frameworku oraz nie używanie w pętle for in -metody hasOwnProperty gwarantuje błędy w wykonaniu.

- -

Wnioski

- -

Zaleca się aby zawsze używać metody hasOwnProperty. Nigdy nie powinno się dokonywać -żadnych założeń na temat środowiska, w którym kod będzie wykonywany i czy natywne -prototypy zostały rozszerzone czy nie.

Funkcje

Deklaracje funkcji i wyrażenia funkcyjne

Funcje w języku JavaScript są typami pierwszoklasowymi. Co oznacza, że mogą -być przekazywane jak każda inna wartość. Jednym z typowych zastosowań tej cechy -jest przekazywanie anonimowej funkcji jako callback do innej, prawdopodobnie -asynchronicznej funkcji.

- -

Deklaracja funckcji

- -
function foo() {}
-
- -

Powyższa funkcja zostaje wyniesiona zanim program wystartuje, dzięki temu -jest dostępna wszędzie w ramach zasięgu, w którym została zadeklarowana, -nawet jeżeli ta funkcja została wywołana przed faktyczną definicją w kodzie źródłowym.

- -
foo(); // Działa ponieważ definicja funkcji została wyniesiona 
-       // na początek zasięgu przed uruchomieniem kodu
-function foo() {}
-
- -

Wyrażenie funkcyjne

- -
var foo = function() {};
-
- -

Ten przykład przypisuje nienazwaną i anonimową funkcję do zmiennej foo.

- -
foo; // 'undefined'
-foo(); // wyrzuca błąd TypeError
-var foo = function() {};
-
- -

Ze względu na fakt, że deklaracja var wynosi zmienną foo na początek zasięgu, -zanim kod faktycznie zostanie uruchomiony, foo będzie zdefiniowane kiedy skrypt -będzie wykonywany.

- -

Ale ponieważ przypisania robione są dopiero podczas wykonania, wartość foo będzie -ustawiona na domyślną wartość undefined zanim powyższy kod -zostanie uruchomiony.

- -

Nazwane wyrażenia funkdyjne

- -

Kolejnym specjalnym przypadkiem jest przypisanie nazwanej funkcji.

- -
var foo = function bar() {
-    bar(); // Działa
-}
-bar(); // wyrzuca ReferenceError
-
- -

W zewnętrznym zakresie bar nie będzie dostępne, ponieważ funkcja zostaje -przypisana do foo, jednakże w wewnętrznym zakresie bar będzie dostępna. -Jest to spowodowane tym, jak działa rozwiązywanie nazw -w języku JavaScript. Nazwa funkcji jest zawsze dostępna w lokalnym -zakresie tej funkcji.

Jak działa this

JavaScript posiada inną koncepcję odnośnie tego na co wskazuje specjalna -nazwa this, niż większość innych języków programowania. Istnieją dokładnie -pięć różnych sytuacji w których wartość this zostaje przypisana w języku JavaScript.

- -

JavaScript has a different concept of what the special name this refers to -than most other programming languages do. There are exactly five different -ways in which the value of this can be bound in the language.

- -

Zasięg globalny

- -
this;
-
- -

Używanie this w globalnym zasięgu, zwróci po prostu referencje do obiektu global.

- -

Wywołanie funkcji

- -
foo();
-
- -

Tutaj this również będzie wkazywało na obiekt global

- - - -

Wywoływanie metody

- -
test.foo(); 
-
- -

W tym przypadku this będzie wskazywało na test.

- -

Wywołanie konstruktora

- -
new foo(); 
-
- -

Wywołanie funkcji, które jest poprzedzone słowem kluczowym new zachowuje się -jak konstruktor. Wewnątrz funkcji this będzie -wskazywało na nowo utworzony obiekt.

- -

Jawne ustawienie this

- -
function foo(a, b, c) {}
-
-var bar = {};
-foo.apply(bar, [1, 2, 3]); // tablica zostanie zamieniona w to co poniżej
-foo.call(bar, 1, 2, 3); // rezultat a = 1, b = 2, c = 3
-
- -

Używając metod call lub apply z prototypu Function.prototype, wartość this -wewnątrz wołanej funkcji zostanie jawnie ustawiona na pierwszy argument przekazany -podczas wywołania tych metod.

- -

Zatem w powyższym przykładzie przypadek Wywoływanie metody nie będzie miał -miejsca i this wewnątrz foo będzie wskazywać na bar.

- - - -

Częste pułapki

- -

Mimo iż Większość z tych przypadków ma sens, to pierwszy przypadek powinien być -traktorany jako błąd podczas projektowania języka i nigdy nie wykorzystywany -w praktyce.

- -
Foo.method = function() {
-    function test() {
-        // wewnątrz tej funkcji this wskazuje na obiekt global
-    }
-    test();
-}
-
- -

Powszechnym nieporozumieniem jest, że this wewnątrz test wskazuje na Foo, -podczas gdy w rzeczywistości tak nie jest.

- -

Aby uzyskać dostęp do Foo wewnątrz test niezbędne jest stworzenie wewnątrz -metody lokalnej zmiennej, która będzie wskazywała na Foo.

- -
Foo.method = function() {
-    var that = this;
-    function test() {
-        // Należy używać that zamiast this wewnątrz tej funkcji
-    }
-    test();
-}
-
- -

that jest zwykłą zmienną, ale jest to powszechnie stosowana konwencja, aby otrzymać -wartość zewnętrznego this. W połączeniu z domknięciami(closures) -jest to sposób na przekazywanie wartości this wokoło.

- -

Metody przypisywania

- -

Kolejną rzeczą, która nie działa w języku JavaScript jest nadawanie aliasów -funkcjom, co oznacza przypisanie metody do zmiennej.

- -
var test = someObject.methodTest;
-test();
-
- -

Podobnie jak w pierwszym przypadku test zachowuje się jak wywołanie zwykłej -funkcji, a zatem wewnątrz funkcji this już nie będzie wskazywało someObject.

- -

Podczas gdy późne wiązanie this może się na początku wydawać złym pomysłem, -to w rzeczywistości jest to rzecz, która powoduje że -dziedziczenie prototypowe działa.

- -
function Foo() {}
-Foo.prototype.method = function() {};
-
-function Bar() {}
-Bar.prototype = Foo.prototype;
-
-new Bar().method();
-
- -

Kiedy metoda method zostanie wywołana na instancji Bar, this będzie -wskazywało właśnie tą instancję.

Domknięcia i referencje

Jedną z najpotężniejszych funkcjonalności języka JavaScript są domknięcia, -oznacza to że zasięg zawsze posiada dostęp do zewnętrznego zasięgu w którym -został zdefiniowany. Ponieważ zasięg w JavaScript można definiować tylko poprzez -funckję, wszystkie funkcje domyślnie zachowują się jak domknięcia.

- -

Emulowanie prywatnych zmiennych

- -
function Counter(start) {
-    var count = start;
-    return {
-        increment: function() {
-            count++;
-        },
-
-        get: function() {
-            return count;
-        }
-    }
-}
-
-var foo = Counter(4);
-foo.increment();
-foo.get(); // 5
-
- -

Tutaj Counter zwraca dwa domknięcia: funkcję increment oraz funckję get. -Obie te funkcję trzymają referencję do zasięgu Counter a co za tym idzie -zawsze posiadają dostęp do zmiennej count tak, jakby ta zmienna była zdefiniowana -w zasięgu tych funkcji.

- -

Dlaczego zmienne przywatne działają

- -

Ponieważ nie ma możliwości wskazania lub przypisania zasięgu w JavaScript, to -nie istnieje sposób aby uzyskać dostęp do zmiennej count z zewnątrz. -Wykorzystanie tych dwóch domkinęć jest jedynym sposobem na interakcję z tą zmienną.

- -
var foo = new Counter(4);
-foo.hack = function() {
-    count = 1337;
-};
-
- -

Powyższy kod nie zmieni wartości zmiennej count wewnątrz zasięgu Counter, -ponieważ foo.hack nie została zadeklarowana wewnątrz tego konkretnego zasięgu. -Zamiast tego funkcja utworzy lub nadpisze globalną zmienną count.

- -

Domknięcia wewnątrz pętli

- -

Jednym z częstrzych błędów jest wykorzystywanie domknięć wewnątrz pętli, -aby wartość zmiennej po której odbywa się iteracja był kopiowana do -wewnętrznej funkcji.

- -
for(var i = 0; i < 10; i++) {
-    setTimeout(function() {
-        console.log(i);  
-    }, 1000);
-}
-
- -

Powyższy kod nie wypisze numerów od 0 do 9, ale wypisze -dziesięć razy liczbę 10.

- -

Anonimowa funkcja trzyma wskaźnik do zmiennej i i podczas uruchomienia -console.log, pętla for już zakończyła działanie i wartość zmiennej i -została ustawiona na 10.

- -

Aby otrzymać zamierzony efekt, niezbędne jest skopiowanie wartości -zmiennej i.

- -

Unikanie problemu z referencją

- -

Aby skopiować wartość zmiennej, po której iterujemy w pętli, należy skorzystać -z anonimowego wrappera.

- -
for(var i = 0; i < 10; i++) {
-    (function(e) {
-        setTimeout(function() {
-            console.log(e);  
-        }, 1000);
-    })(i);
-}
-
- -

Zewnętrzna anonimowa funkcja zostaje wywołana od razu z parametrem i -jako pierwszym argumentem i otrzyma kopię wartości zmiennej i jako -zmienną e.

- -

Anonimowa funkcja która zostaje przekazana do setTimeout teraz posiada -referencję do zmiennej e, która nie zostanie zmieniona przez pętle for.

- -

Istnieje jeszcze jeden sposób na osiągnięcie tego samego efektu. Należy zwrócic -fukcję z anonimowego wrappera, wówczas kod będzie zachowywał się jak ten -wcześniejszy.

- -
for(var i = 0; i < 10; i++) {
-    setTimeout((function(e) {
-        return function() {
-            console.log(e);
-        }
-    })(i), 1000)
-}
-

Obiekt arguments

Każda zasięg funkcyjny w języku JavaScript ma dostęp do specjalnej zmiennej arguments. -Ta zmienna trzyma listę wszystkich argumentów przekazanych do funkcji.

- - - -

Obiekt arguments nie jest typu Array. Mimo, że posiada pewne cechy -semantyki tablic - właściwość length - to nie dziedziczy on z Array.prototype, -ale w rzeczywistości z Object.

- -

Ze względu na to nie można używać standardowych dla tablic metod takich jak -push, pop czy slice na obiekcie arguments. Mimo, że iteracja przy pomocy -pętli for działa dobrze, to aby skorzystać ze standardowych metod tablicowych -należy skonwertować arguments do prawdziwego obiekt Array.

- -

Konwersja do tablicy

- -

Poniższy kod zwróci nowy obiekt Array zawierający wszystkie elementy -obiektu arguments.

- -
Array.prototype.slice.call(arguments);
-
- -

Jednakże konwersja ta jest wolna i nie jest zalecana w sekcjach, -które mają duży wpływ na wydajność.

- -

Przekazywanie argumentów

- -

Zalecany sposób przekazywania argumentów z jednej funkcji do następnej -wyglada następująco.

- -
function foo() {
-    bar.apply(null, arguments);
-}
-function bar(a, b, c) {
-    // do stuff here
-}
-
- -

Kolejną sztuczką jest użycie razem call i apply w celu stworzenia -szybkich i nieograniczonych wrapperów.

- -
function Foo() {}
-
-Foo.prototype.method = function(a, b, c) {
-    console.log(this, a, b, c);
-};
-
-// Stworzenie nieograniczoną wersję metody "method" 
-// która przyjmuje parametry: this, arg1, arg2...argN
-Foo.method = function() {
-
-    // Rezultat: Foo.prototype.method.call(this, arg1, arg2... argN)
-    Function.call.apply(Foo.prototype.method, arguments);
-};
-
- -

Parametry formalne i indeksy argumentów

- -

Obiekt arguments tworzy funckje getter i setter nie tylko dla swoich -właściwości, ale również dla parametrów formalnych funkcji.

- -

W rezultacie zmiana wartości parametru formalnego zmieni również wartość -odpowiadającemu mu wpisowi w obiekcie arguments, zachodzi to również w drugą stronę.

- -
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);
-
- -

Mity i prawdy o wydajności

- -

Obiekt arguments jest zawsze tworzony z wyjątkiem dwóch przypadków, gdy -zmienna o takiej nazwie jest zdefiniowana wewnątrz funkcji lub jeden z parametrów -formalnych funkcji ma taką nazwę. Nie ma znaczenia czy obiekt arguments jest -używany czy nie.

- -

Zarówno gettery jak i settery są zawsze tworzone, zatem używanie ich nie ma -praktycznie żadnego wpływu na wydajność. Zwłaszcza w rzeczywistym kodzie, który -wykorzystuje coś więcej niż tylko prosty dostęp do właściwości obiektu arguments.

- - - -

Jednakże, istnieje jeden przypadek w którym wydajność drastycznie spada w -nowoczesnych silnikach JavaScript. Ten przypadek to wykorzystanie -arguments.callee.

- -
function foo() {
-    arguments.callee; // operowanie na obiekcie funkcji
-    arguments.callee.caller; // i obiekcie funkcji wywołującej
-}
-
-function bigLoop() {
-    for(var i = 0; i < 100000; i++) {
-        foo(); // Normalnie zostałaby wykorzystana metoda inline
-    }
-}
-
- -

W powyższym przykładzie foo nie może zostać wykorzystana metoda inline -ponieważ potrzebne są nie tylko informacje na własny temat ale również -na temat funkcji wywołującej. Takie użycie nie tylko uniemożliwia -inlining i korzyści z niej wynikające, ale również stanowi złamanie -zasad enkapsulacji ponieważ ta funkcja jest zależna od kontekstu -w jakim została wywołana.

- -

Mocno zalecane jest aby nigdy nie korzystać z arguments.callee -i żadnej jej własności.

- -

Konstruktory

Konstruktory w JavaScript również wyglądają inaczej niż innych języka. Każde -wywołanie funkcji, które jest poprzedone słowem kluczowym new zachowuje się -jak konstruktor.

- -

Wewnątrz konstruktora - wywoływanej fukcji - wartość this wskazuje na -nowo utworzony obiekt Object. Prototyp prototype tego -nowego obiektu będzie wskazywał na prototyp prototype obiektu fukcji, -która została wywołana jako konstruktor.

- -

Jeżeli wywołana funkcja nie posiada jawnej deklaracji return, wówczas -fukcja domyślnie zwraca wartość this - nowy obiekt.

- -
function Foo() {
-    this.bla = 1;
-}
-
-Foo.prototype.test = function() {
-    console.log(this.bla);
-};
-
-var test = new Foo();
-
- -

Powyżej wywołanya została funkcja Foo jako konstruktor oraz ustawia -nowo utworzonemu obiektowi właściwość prototype na Foo.prototype.

- -

W tym przypadku jawna deklaracja return w funkcji zwraca wartość -ustawioną w deklaracji, ale tylko jeżeli zwracaną wartością jest -obiekt Object.

- -
function Bar() {
-    return 2;
-}
-new Bar(); // nowy obiekt
-
-function Test() {
-    this.value = 2;
-
-    return {
-        foo: 1
-    };
-}
-new Test(); // zwrócony obiekt
-
- -

Jeżeli słowo kluczowe new zostanie pominięte funkcja nie zwróci nowego -obiektu.

- -
function Foo() {
-    this.bla = 1; // zostanie ustawiona w obiekcie global
-}
-Foo(); // undefined
-
- -

Mimo, że powyższy kod może zadziałać w pewnych przypadkach, w związku -z działaniem this w języku JavaScript to jako -wartość thiszostanie wykorzystany obiekt global.

- -

Fabryki

- -

Aby móc ominąć słowo kluczowe new konstruktor musi jawnie zwracać wartość.

- -
function Bar() {
-    var value = 1;
-    return {
-        method: function() {
-            return value;
-        }
-    }
-}
-Bar.prototype = {
-    foo: function() {}
-};
-
-new Bar();
-Bar();
-
- -

Oba wywołania Bar zwrócą tą samą rzecz, nowo utworzony obiekt, który posiada -właściwość nazwaną method w sobie, dla którego Bar jest Domknięciem.

- -

Należy również pamiętać, że wywołanie new Bar() nie ma wpływu na -prototyp zwróconego obiektu (prototypem będzie object.prototype a nie Bar.prototype). -Podczas gdy prototyp zostanie przypisany do nowo utworzonego obiektu, to jednak Bar -nidgy nie zwróci tego nowego obiektu Bar, ale literał obiektu, który jest po -słowie kluczowym return.

- -

W powyższym przykładzie nie ma żadnej różnicy w działaniu pomiędzy użyciem -i nieużyciem słowa kluczowego new.

- -

Tworzenie nowych obiektów korzystając z fabryk

- -

Często zaleca się nie korzystać z operatora new ponieważ zapominając -go zastosować może prowadzić do błędów.

- -

W celu stworzenia nowego obiektu, powinno się używać fabryki i konstruować -nowy obiekt wewnątrz tej fabryki.

- -
function Foo() {
-    var obj = {};
-    obj.value = 'blub';
-
-    var private = 2;
-    obj.someMethod = function(value) {
-        this.value = value;
-    }
-
-    obj.getPrivate = function() {
-        return private;
-    }
-    return obj;
-}
-
- -

Mimo, że powyższy kod jest odporny na brak słowa kluczowego new i ułatwia -korzystanie ze zmiennych prywatnych, to posiada -pewne wady. -While the above is robust against a missing new keyword and certainly makes -the use of private variables easier, it comes with some -downsides. - 1. Zużywa więcej pamięci, ponieważ tworzony obiekt nie współdzieli metod - poprzez prototyp - 2. Aby móc dziedziczyć fabryka musi skopiować wszystkie metody z dziedziczonego - obiektu lub przypisać ten obiekt, z którego się dziedziczy, jako prototyp - do nowo utworzonego obiektu. - 3. Porzucenie łańcucha prototypów tylko ze względu na opuszczone słowo kluczowe - new jest sprzeczne z duchem języka.

- -

Wnioski

- -

Pominięcie słowa kluczowego new może prowadzić do błędów, ale na pewno nie -powinno to być powodem odrzucenia używania prototypów w ogóle. Sprowadza się to -do wyboru rozwiązania, które bardziej pasuje do potrzeb aplikacji. Szczególnie -ważne jest aby wybrać określony styl tworzenia obiektów i się go trzymać.

Zasięg zmiennych i przestrzenie nazw

Mimo, że JavaScript radzi sobie dobrze ze składnią, opisującą dwa pasujące -nawiasy klamrowe jako blok, to jednak nie wspiera zasięgu blokowego. -Jedynym zasięgiem jaki istnieje w JavaScript jest zasięg funkcyjny.

- -
function test() { // definiuje zasięg (scope)
-    for(var i = 0; i < 10; i++) { // nie definiuje zasięgu (scope)
-        // count
-    }
-    console.log(i); // 10
-}
-
- - - -

W JavaScripcie nie ma również przestrzeni nazw, co oznacza, że wszystko jest -definiowane w jednej globalnie współdzielonej przestrzeni nazw.

- -

Za każdym razem gdy zmienna jest -Z każdym odwołaniem do zmiennej JavaScript przeszukuje w górę wszystkie zasięgi -dopóki nie znajdzie tej zmiennej. W przypadku gdy przeszukiwanie dotrze do globalnego -zasięgu i nadal nie znajdzie żądanej nazwy to wyrzuca błąd ReferenceError.

- -

Zmora globalnych zmiennych

- -
// script A
-foo = '42';
-
-// script B
-var foo = '42'
-
- -

Powyższe dwa skrypty nie dają tego samego efektu. Skrypt A definiuje zmienna -nazwaną foo w globalnym zasięgu natomiast skrypt B definiuje foo -w aktualnym zasięgu.

- -

Jeszcze raz, to wcale nie daje tego samego efektu, nie użycie var może mieć -poważne konsekwencje.

- -
// globalny zasięg
-var foo = 42;
-function test() {
-    // lokalny zasięg
-    foo = 21;
-}
-test();
-foo; // 21
-
- -

Pominięcie słowa var w deklaracji wewnątrz funkcji test nadpisze wartość -zmiennej globalnej foo. Mimo, że nie wygląda to na początku jak duży problem, -to posiadając wiele tysięcy linii kodu w JavaScript i nie korzystanie z var -wprowadzi straszne i trudne do wyśledzenia błędy.

- -
// globalny zasięg 
-var items = [/* jakaś lista */];
-for(var i = 0; i < 10; i++) {
-    subLoop();
-}
-
-function subLoop() {
-    // scope of subLoop
-    for(i = 0; i < 10; i++) { // brakuje słowa var w deklaracji
-        // do amazing stuff!
-    }
-}
-
- -

Zewnętrzna pętla zakończy działanie po pierwszym wywołaniu subLoop, ponieważ -subLoop nadpisuje wartość globalnej zmiennej i. Użycie var w drugiej pętli -for pozwoliło by łatwo uniknąć problemu. Słowo kluczowe var nie powinno być -nigdy pominięte w deklaracji, chyba że pożądanym skutkiem jest wpłynięcie na -zewnętrzny zasięg.

- -

Lokalne zmienne

- -

Jedynym źródłem zmiennych lokalnych w JavaScripcie są parametry funkcji -oraz zmienne zadeklarowane poprzez deklaracje var wewnątrz funkcji.

- -
// globalny zasięg
-var foo = 1;
-var bar = 2;
-var i = 2;
-
-function test(i) {
-    // lokalny zasięg fukcji test
-    i = 5;
-
-    var foo = 3;
-    bar = 4;
-}
-test(10);
-
- -

Zmienne foo oraz i są lokalnymi zmiennymi wewnątrz zasiegu funkcji test, -natomiast przypisanie wartości do bar nadpisze zmienną globalną o tej samej nazwie.

- -

"Hoisting" - wywindowanie, podnoszenie

- -

JavaScript winduje deklaracje. Oznacza to, że zarówno deklaracja ze słowem -kluczowym var jak i deklaracje funkcji function zostaną przeniesione na -początek otaczającego zasięgu.

- -
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];
-    }
-}
-
- -

Powyższy kod zostanie przekształcony przed rozpoczęciem wykonania. JavaScript -przeniesie deklarację zmiennej var oraz deklarację funkcji function na szczyt -najbliższego zasięgu.

- -
// deklaracje var zostaną przeniesione tutaj
-var bar, someValue; // ustawione domyślnie na 'undefined'
-
-// deklaracje funkcji zostaną również przeniesione na górę
-function test(data) {
-    var goo, i, e; // brak blokowego zasięgu spowoduje przeniesienie tutaj
-    if (false) {
-        goo = 1;
-
-    } else {
-        goo = 2;
-    }
-    for(i = 0; i < 100; i++) {
-        e = data[i];
-    }
-}
-
-bar(); // powoduje błąd TypeError ponieważ bar jest nadal 'undefined'
-someValue = 42; // przypisania nie zostają zmienione przez 'hoisting'
-bar = function() {};
-
-test();
-
- -

Brak blokowego zasięgu nie tylko przeniesie deklaracje var poza ciało pętle, -ale również spowoduje, że niektóre porównania if staną się nieintuicyjne.

- -

W oryginalnym kodzie wewnątrz deklaracja if zdaje się modyfikować zmienną -globalną goo, podczas gdy faktycznie modyfikuje ona zmienną lokalną - po tym -jak zostało zastosowane windowanie (hoisting).

- -

Bez wiedzy na temat podnoszenia (hoistingu), poniższy kod może wydawać się -wyrzucać błąd ReferenceError.

- -
// sprawdz czy SomeImportantThing zostało zainicjalizowane
-if (!SomeImportantThing) {
-    var SomeImportantThing = {};
-}
-
- -

Oczywiście powyższy kod działa ze względu na fakt, że deklaracja var zostanie -przeniesiona na początek globalnego zasięgu.

- -
var SomeImportantThing;
-
-// inny kod który może ale nie musi zainicjalizować SomeImportantThing
-
-// upewnienie sie że SomeImportantThing zostało zainicjalizowane
-if (!SomeImportantThing) {
-    SomeImportantThing = {};
-}
-
- -

Kolejność rozwiązywania nazw

- -

Wszystkie zasięgi w JavaScripcie, włączając globalny zasięg, posiadają -zdefiniowana wewnątrz specjalną nazwę this, która wskazuje -na aktualny obiekt.

- -

Zasięg funkcyjny posiada również zdefiniowaną wewnętrznie nazwę -arguments, która zawiera listę argumentów przekazaną do -funkcji.

- -

Na przykład, kiedy próbujemy odczytać zmienną foo wewnątrz zasięgu funkcji, -JavaScript będzie szukać nazwy w określonej kolejności: - 1. Jeżeli wewnątrz aktualnego zasięgu znajduje się deklaracja var foo skorzystaj z niej. - 2. Jeżeli jeden z parametrów fukcji został nazwany foo użyj go. - 3. Jeżeli fukcja została nazwana foo skorzystaj z tego. - 4. Przejdz do zewnętrznego zasięgu i przejdz do kroku #1.

- - - -

Przestrzenie nazw

- -

Powszechnym problemem posiadania tylko jednej globalnej przestrzeni nazw jest -prawdopodobieństwo wystąpienia kolizji nazw. W JavaScripcie, można łatwo uniknąć -tego problemu korzystając z anonimowych wrapperów.

- -
(function() {
-    // autonomiczna "przestrzeń nazw"
-
-    window.foo = function() {
-        // wyeksponowane domkniecie (closure)
-    };
-
-})(); // natychmiastowe wykonanie funkcji
-
- -

Nienazwane funkcje są rozpoznane jako wyrażenia, więc -aby mogły zostać wywołane muszą zostać zewaluowane.

- -
( // zewaluowanie fukcji znajdującej się wewnątrz nawiasów
-function() {}
-) // zwrócenie obiektu funkcji
-() // wywołanie rezultatu ewaluacji
-
- -

Istnieją inne sposoby aby zewaluować i wykonać wyrażenie funkcyjne. Mimo, że -mają inną składnie, zachowują się dokładnie tak samo.

- -
// Trzy inne sposoby
-!function(){}();
-+function(){}();
-(function(){}());
-
- -

Wnioski

- -

Zaleca się aby zawsze używać anonimowych wrapperów do hermetyzacji kodu wewnątrz -jego własnej przestrzeni nazw. To nie tylko chroni kod przed kolizją nazw, ale -również wprowadza lepszą modularyzację programów.

- -

Ponadto, stosowanie zmiennych globalnych jest uznawane za złą praktykę. -Jakiekolwiek wykorzystanie zmiennych globalnych wskazuje na źle napisany kod, -który jest podatny na błędy i trudny do utrzymania.

Tablice

Iterowanie po tablicach oraz właściwości tablic

Mimo, że tablice w JavaScript są obiektami, nie ma dobrych powodów do używania -pętli for in do iteracji po nich. W rzeczywiści istnieje -wiele dobrych powodów przeciwko wykorzystania for in na tablicach.

- - - -

Ponieważ pętla for in wylicza wszystkie właściwości, które są wewnątrz -łańcucha prototypów i jedynym sposobem aby wykluczyć te właściwości to użycie -hasOwnProperty, ale wówczas pętla staje się -dwadzieście razy wolniejsza od normalnej pętli for.

- -

Iteracja

- -

W celu osiągnięcia najlepszej wydajności podczas iteracji po tablicach należy -użyć klasycznej pętli for.

- -
var list = [1, 2, 3, 4, 5, ...... 100000000];
-for(var i = 0, l = list.length; i < l; i++) {
-    console.log(list[i]);
-}
-
- -

Jest tam jeszcze jeden dodatkowy haczyk w przykładzie powyżej. Jest to zbuforowanie -długości tablicy poprzez l = list.length.

- -

Mimo, że właściwość length jest zdefiniowana w wewnątrz tablicy, istnieje nadal -dodatkowy koszt na wyszukiwanie tej właściwości przy każdej iteracji w pętli. -Chociaż najnowsze silniki JavaScript mogą zastosować optymalizację w tym -przypadku. Nie ma jednak możliwość ustalenia czy kod będzie wykonywany w jednym -z tych nowych silników czy też nie.

- -

W rzeczywistości pomijając buforowanie długości tablicy może spowodować, że pętla -będzie tylko w połowie tak szybka jak ta z buforowaniem długości.

- -

Właściwość length

- -

Mimo, że getter właściwości length po prostu zwraca liczbę elementów, które są -zawarte w tablicy, to setter może być użyta do skracania tablicy.

- -
var foo = [1, 2, 3, 4, 5, 6];
-foo.length = 3;
-foo; // [1, 2, 3]
-
-foo.length = 6;
-foo; // [1, 2, 3]
-
- -

Przypisanie mniejszej długości spowoduje skrócenie tablicy, ale zwiększenie wartości -length nie ma żadnego wpływu na tablicę.

- -

Wnioski

- -

Aby uzyskać najlepszą wydajność zaleca się, aby zawsze używać zwykłej pętli for -i zbuforowanie właściwości length. Korzystanie z pętli for in na tablicy jest -znakiem źle napisanego kodu, który jest podatny na błędy i ma słabą wydajność.

Konstruktor Array

Zaleca się zawsze korzystać z literału tablicy - notacja [] - podczas tworzenia -nowych tablic, ponieważ konstruktor Array niejednoznacznie interpretuje -parametry do niego przekazane.

- -
[1, 2, 3]; // Rezultat: [1, 2, 3]
-new Array(1, 2, 3); // Rezultat: [1, 2, 3]
-
-[3]; // Rezultat: [3]
-new Array(3); // Rezultat: []
-new Array('3') // Rezultat: ['3']
-
- -

W przypadku gdy tylko jeden argument zostanie przekazany do kostruktora Array i -ten argument jest typu Number, konstruktor zwróci nową dziwną tablicę -z ustawioną właściwością length na wartość przekazaną jako argument. Należy -zauważyć, że tylko właściwość length zostanie ustawiona w ten sposób, -rzeczywiste indeksy w tej tablicy nie zostaną zainicjalizowane.

- -
var arr = new Array(3);
-arr[1]; // undefined
-1 in arr; // zwraca false, indeks nie został ustawiony
-
- -

Możliwość ustanienia z góry długości tablicy jest użyteczna tylko w kilku -przypadkach, jak powtarzanie ciągu znaków, w którym unika się stosowania -pętli for.

- -
// count - ilosc powtorzen
-// stringToRepeat - ciąg znaków do powtórzenia 
-new Array(count + 1).join(stringToRepeat); 
-
- -

Wnioski

- -

W miare możliwości należy unikać używania konstruktora Array. Literały są -zdecydowanie lepszym rozwiązaniem, są krótsze i mają bardziej precyzyjną składnię. -Zwiększają również czytelność kodu.

Typy

Równość i porównania

JavaScript posiada dwa różne sposoby równościowego porównywania obiektów.

- -

Operator równości

- -

Operator równości składa się z dwóch znaków "równa się": ==

- -

JavaScript jest słabo typowanym językiem. Oznacza to, że operator równości -konwertuje typy (dokonuje koercji), aby wykonać porównanie.

- -
""           ==   "0"           // false
-0            ==   ""            // true
-0            ==   "0"           // true
-false        ==   "false"       // false
-false        ==   "0"           // true
-false        ==   undefined     // false
-false        ==   null          // false
-null         ==   undefined     // true
-" \t\r\n"    ==   0             // true
-
- -

Powyższa tabela przedstawia wyniki koercji typów. Nieprzewidywalne wyniki -porównania są głównym powodem, że stosowanie == jest powszechnie uważane za złą -praktykę. Skomplikowane reguły konwersji są powodem trudnych do wyśledzenia błędy.

- -

Ponadto koercja ma również wpływ na wydajność na przykład gdy typ String musi zostać -przekształcony na typ Number przed porównaniem z drugą liczbą.

- -

Operator ścisłej równości

- -

Operator ścisłej równości składa się z trzech znaków "równa się": ===

- -

Działa on dokładnie tak jak normalny operator równości, z jednym wyjątkiem nie -dokonuje koercji typów przed porównaniem.

- -
""           ===   "0"           // false
-0            ===   ""            // false
-0            ===   "0"           // false
-false        ===   "false"       // false
-false        ===   "0"           // false
-false        ===   undefined     // false
-false        ===   null          // false
-null         ===   undefined     // false
-" \t\r\n"    ===   0             // false
-
- -

Powyższe rezultaty są o wiele bardziej przejrzyste. Powoduje to "ustatycznienie" -języka do pewnego stopnia oraz pozwala na wprowadzenie optymalizacji porównań -obiektów o różnych typach.

- -

Porównywanie obiektów

- -

Mimo, że oba operatory == i === nazywane są operatorami równościowymi, -to zachowują się różnie gdy jednym z operandów jest obiekt typu Object.

- -
{} === {};                   // false
-new String('foo') === 'foo'; // false
-new Number(10) === 10;       // false
-var foo = {};
-foo === foo;                 // true
-
- -

Oba operatory porównują toższmość a nie równość, czyli będą porównywać czy -jeden i drugi operand jest tą samą instancją obiektu, podobnie jak operator -is w Pythonie i porównanie wskaźników w C.

- -

Wnioski

- -

Zaleca się aby używać tylko operatora ścisłej równości. W sytuacjach gdy -potrzebna jest koercja (porównanie obiektów różnych typów), konwersja powinna -być dokonana jawnie a nie pozostawiona trudnym regułom koercji -obowiązującym w języku.

Operator typeof

Operator typeof (razem z operatorem instanceof) jest -prawdopodobnie najwiekszą wadą konstrukcji języka JavaScript, jest on praktycznie -całkowicie wadliwy.

- -

Mimo, że instanceof ma swoje wady to nadal ma ograniczone zastosowanie w praktyce, -natomiast typeof ma tylko jeden praktyczny przypadek użycia, który na dodatek -nie jest związany z sprawdzaniem typu obiektu.

- - - -

Tablica typów JavaScript

- -
Wartość             Klasa      Typ
--------------------------------------
-"foo"               String     string
-new String("foo")   String     object
-1.2                 Number     number
-new Number(1.2)     Number     object
-true                Boolean    boolean
-new Boolean(true)   Boolean    object
-new Date()          Date       object
-new Error()         Error      object
-[1,2,3]             Array      object
-new Array(1, 2, 3)  Array      object
-new Function("")    Function   function
-/abc/g              RegExp     object (function w Nitro i V8)
-new RegExp("meow")  RegExp     object (function w Nitro i V8)
-{}                  Object     object
-new Object()        Object     object
-
- -

W powyższej tabeli Typ odnosi się do wartości zwracanej przez operator typeof. -Wyraźnie widać, że zwracane wartości w ogóle nie są spójne.

- -

Klasa odnosi sie do wartości wewnętrznej właściwości [[Class]] obiektu.

- - - -

W celu uzyskania wartości właściwości [[Class]] trzeba skorzystać z metody -toString z Object.prototype.

- -

Klasa obiektu

- -

Specyfikacja zawiera dokładnie jeden sposób dostepu do wartości [[Class]], -wykorzystując Object.prototype.toString.

- -
function is(type, obj) {
-    var clas = Object.prototype.toString.call(obj).slice(8, -1);
-    return obj !== undefined && obj !== null && clas === type;
-}
-
-is('String', 'test'); // true
-is('String', new String('test')); // true
-
- -

Powyższy przykład wywołuje Object.prototype.toString z wartością -this ustawioną na obiekt, dla której wartość właściwości -[[Class]] ma zostać odczytana.

- - - -

Testowanie niezdefiniowania zmiennej

- -
typeof foo !== 'undefined'
-
- -

Powyższy kod sprawdza czy foo została faktycznie zadeklarowana czy też nie. -Próba odwołania się do zmiennej spowodowała by wyrzucenie błędu ReferenceError. -Jest to jedyne praktyczne wykorzystanie operatora typeof.

- -

Wnioski

- -

W celu sprawdzenia typu obiektu zalecane jest skorzystanie z -Object.prototype.toString, ponieważ jest to jedyny wiarygodny sposób. Jak -pokazano w powyższej tabeli typów, niektóre wartości zwracane przez typeof nie -są zdefiniowane w specyfikacji, co za tym idzie mogą się różnić w różnych -implementacjach.

- -

O ile nie operator typeof nie jest użyty do sprawdzania czy zmienna została -zdefiniowana, powinien być unikany o ile to tylko możliwe.

Operator instanceof

Operator instanceof porównuje konstruktory obiektów przekazanych jako operendy. -Jest on jedynie użyteczny do porównywania obiektów utworzonych klas. Stosowanie -go na wbudowanych typach jest praktycznie tak samo bezużyteczne jak operatora -typeof.

- -

Porównywanie obiektów utworzonych klas

- -
function Foo() {}
-function Bar() {}
-Bar.prototype = new Foo();
-
-new Bar() instanceof Bar; // true
-new Bar() instanceof Foo; // true
-
-// Poniżej kod który przypisuje do Bar.prototype obiekt funkcji Foo
-// a nie faktyczną instancję Foo
-Bar.prototype = Foo;
-new Bar() instanceof Foo; // false
-
- -

Stosowanie instanceof na natywnych typach

- -
new String('foo') instanceof String; // true
-new String('foo') instanceof Object; // true
-
-'foo' instanceof String; // false
-'foo' instanceof Object; // false
-
- -

Jedną ważną rzeczą, którą należy zauważyć jest to, że instanceof nie zadziała -na obiektach, które pochodzą z różnych kontekstów JavaScript (np. z różnych -dokumentów wewnątrz przeglądarki), ponieważ ich konstruktory nie będą tymi -samymi obiektami.

- -

Wnioski

- -

Operator instanceof powinien być tylko używany podczas korzystania z obiektów -klas utworzonych, które były zdefiniowane w tym samym kontekscie JavaScriptowym. -Podobnie jak operator typeof, należy unikać korzystania -z tego operatora w innych sytuacjach.

Rzutowanie typów

JavaScript jest językiem słabo typowanym, co za tym idzie będzie stosować koercję -typów gdziekolwiek jest to możliwe.

- -
// These are true
-new Number(10) == 10; // Number.toString() zostanie przekształcone
-                      // z powrotem do liczby
-
-10 == '10';           // Stringi zostaną przekształcone do typu Number
-10 == '+10 ';         // Kolejne wariacje
-10 == '010';          // i następne
-isNaN(null) == false; // null zostanie przekształcony do 0
-                      // który oczywiście nie jest NaN
-
-// Poniższe zwracają false
-10 == 010;
-10 == '-10';
-
- - - -

Aby uniknąć powyższych problemów, należy koniecznie skorzystać ze -ściełego operatora równości. Mimo, że pozwala to uniknąć wiele -typowych problemów to nadal istnieje wiele innych, które powstają na bazie słabego -typowania języka JavaScript.

- -

Konstruktory typów wbudowanych

- -

Konstruktory typów wbudowanych takich, jak Number lub String zachowują się -inaczej jeżeli są poprzedzone słowem kluczowym new a inaczej jeżeli nie są.

- -
new Number(10) === 10;     // False, Object i Number
-Number(10) === 10;         // True, Number i Number
-new Number(10) + 0 === 10; // True, ponieważ dokonano jawnej konwersji
-
- -

Korzystanie z wbudowanych typów jak Number jako konstruktor utworzy nowy obiekt -typu Number, natomiast opuszczenie słowa kluczowego new spowoduje, że funkcja -Number zachowa się jak konwerter.

- -

Ponadto, użycie literałów lub wartości nieobiektowych zaowocuje jeszcze większą -ilością rzutowań (koercją) typów.

- -

Najlepszym rozwiązaniem jest jawne rzutowanie do jednego z trzech typów.

- -

Rzutowanie do typu String

- -
'' + 10 === '10'; // true
-
- -

Konkatenacja pustego stringu i wartości powoduje rzutowanie do typu String.

- -

Rzutowanie do typu Number

- -
+'10' === 10; // true
-
- -

Zastosowanie unarnego operatora + spowoduje rzutowanie do typu Number.

- -

Rzutowanie do typu Boolean

- -

Używając dwukrotnie operatora negacji dowolna wartość może zostać zrzutowana -do typu Boolean

- -
!!'foo';   // true
-!!'';      // false
-!!'0';     // true
-!!'1';     // true
-!!'-1'     // true
-!!{};      // true
-!!true;    // true
-

Jądro

Dlaczego nie należy używać eval

Funkcja eval uruchomi podany string jako kod JavaScript w lokalnym zasięgu (scopie).

- -
var foo = 1;
-function test() {
-    var foo = 2;
-    eval('foo = 3');
-    return foo;
-}
-test(); // 3
-foo; // 1
-
- -

Niestaty eval zostanie wykonana w lokalnym zasięgu tylko jeżeli została wywołana -bezpośrednio i nazwa wołanej funkcji równa sie eval.

- -
var foo = 1;
-function test() {
-    var foo = 2;
-    var bar = eval;
-    bar('foo = 3');
-    return foo;
-}
-test(); // 2
-foo; // 3
-
- -

Należy unikać stosowania eval o ile to tylko możliwe. W 99.9% przypadków można -osiągnąć ten sam efekt nie używając eval.

- -

eval w przebraniu

- -

Funkcje wykonywane po upływie czasu setTimeout i setInterval -mogą przyjąć string jako pierwszy argument. String ten zostanie zawsze wykonany -w globalnym zasięgu, ponieważ funkcja eval zostanie wywołana niebezpośrednio w tym -przypadku.

- -

Problemy z bezpieczeństwem

- -

Funkcja eval jest również problematyczna od strony bezpieczeństwa, ponieważ -wykonuje każdy kod, który zostanie do niej przekazany i nie należy nigdy -używać jej na stringach nieznanego lub niezaufanego pochodzenia.

- -

Wnioski

- -

Funkcja eval nie powinna być w ogole używana, każdy kod, który ją wykorzystuje -powinien zostać sprawdzony pod względem działania, wydajności i bezpieczeństwa. -W przypadku gdy użycie eval jest niezbędne do działania, wówczas taki kod -należy przemyśleć raz jeszcze i ulepszyć kod aby nie wymagał użycia eval.

undefined i null

JavaScript ma dwie różne wartości dla pustych wartości, bardziej użyteczną -z tych dwóch jest undefined.

- -

Wartość undefined

- -

undefined jest typem z dokładnie jedną wartością: undefined.

- -

Język również definiuje globalną zmienną, która ma wartość undefined, zmienna -ta jest nazwana undefined. Jednakże jest to zmienna a nie stała czy słowo -kluczowe w języku. Oznacza to że możliwe jest nadpisanie wartości tej zmiennej.

- - - -

Kilka przykładów kiedy wartość undefined jest zwracana:

- -
    -
  • Dostęp do (niemodyfikowalnej) zmiennej globalnej undefined.
  • -
  • Wyjście z funkcji, która nie ma deklaracji return.
  • -
  • Deklaracja return, która nic jawnie nie zwraca.
  • -
  • Poszukiwanie nieistniejącej właściwości.
  • -
  • Parametr funkcji, który nie został jawnie przekazany podczas wywołania funkcji
  • -
  • Wszystko co zostało ustawione na wartość undefined
  • -
- -

Obsługa przypadku zmiany wartości undefined

- -

Ponieważ globalna zmienna undeined tylko zawiera kopię prawdziwej wartości typu -undefined, przypisanie nowej wartości do tej zmiennej nie zmienia wartości -typu undefined.

- -

Jednak, aby porównać coś do wartości undefined potrzebne jest odczytanie wartości -undefined.

- -

Aby uchronić swój kod przeciwko możliwemu nadpisaniu zmiennej undefined, korzysta -się z powszechnej techniki dodania dodatkowego parametru do -anonimowego wrappera, do którego nie zostanie przekazany -argument.

- -
var undefined = 123;
-(function(something, foo, undefined) {
-    // undefined lokalnym zasięgu znowu 
-    // odnosi się do poprawnej wartości
-
-})('Hello World', 42);
-
- -

Kolejnym sposobem aby osiągnąć ten sam efekt jest użycie deklaracji zmiennej -wewnątrz wrappera.

- -
var undefined = 123;
-(function(something, foo) {
-    var undefined;
-    ...
-
-})('Hello World', 42);
-
- -

Jedyną różnicą pomięcy tymi sposobami są dodatkowe 4 bajty przeznaczone na słowo -kluczowe var i spację po nim.

- -

Zastosowanie null

- -

Podczas gdy undefined w kontekście języka jest używany jak null w sensie -tradycyjnych języków, to null w JavaScript (jako literał i jako typ) jest po -prostu kolejnym typem danych.

- -

Jest wykorzystywany we wnętrzu JavaScript (np. deklaracji końca łańcucha prototypów -poprzez ustawienie Foo.prototype = null), ale prawie w każdym przypadku można go -zastąpić przez undefined.

Automatyczne wstawianie średnika

Mimo, że JavaScript ma składnię podobną do języka C, to nie wymusza stosowania -średników w kodzie źródłowym. Istnieje możliwość ich pominięcia.

- -

Lecz JavaScript nie jest językiem bez średników, tak na prawdę potrzebuje -średników aby zinterpretować kod źródłowy. Jednakże parser JavaScript -automatycznie wstawia średniki o ile napotka błąd parsowania związany z -brakiem średnika.

- -
var foo = function() {
-} // błąd parsowania, oczekiwany był w tym miejscu średnik
-test()
-
- -

Parser dodaje średnik, i próbuje jeszcze raz sparsować skrypt.

- -
var foo = function() {
-}; // bez błędu parser kontynuuje
-test()
-
- -

Automatyczne wstawianie średników jest uważane za jeden z największych błędów -konstrukcji języka, ponieważ może ono zachowanie kodu.

- -

Jak działa wstawianie

- -

Kod poniżej nie ma żadnych średników, więc parser zdecyduje, w których miejscach -je wstawi.

- -
(function(window, undefined) {
-    function test(options) {
-        log('testing!')
-
-        (options.list || []).forEach(function(i) {
-
-        })
-
-        options.value.test(
-            'long string to pass here',
-            'and another long string to pass'
-        )
-
-        return
-        {
-            foo: function() {}
-        }
-    }
-    window.test = test
-
-})(window)
-
-(function(window) {
-    window.someLibrary = {}
-
-})(window)
-
- -

Poniżej znajduje się rezultat "zgadywania" parsera.

- -
(function(window, undefined) {
-    function test(options) {
-
-        // Nie wstaniony średnik, linie zostały połączone
-        log('testing!')(options.list || []).forEach(function(i) {
-
-        }); // <- wstawiony
-
-        options.value.test(
-            'long string to pass here',
-            'and another long string to pass'
-        ); // <- wstawiony
-
-        return; // <- wstawiony, psując deklarację return
-        { // potraktowane jako definicja bloku
-
-            // etykieta oraz pojedyncze wyrażenie
-            foo: function() {} 
-        }; // <- wstawiony
-    }
-    window.test = test; // <- wstawiony
-
-// Kolejna połączona linia
-})(window)(function(window) {
-    window.someLibrary = {}; // <- wstawiony
-
-})(window); //<- wstawiony
-
- - - -

Parser drastycznie zmienił działanie powyższego kodu, w niektórych przypadkach -zmienił go źle.

- -

Nawiasy

- -

W przypadku, gdy w następnej linii znajduje się nawias, parser nie wstawi -średnika.

- -
log('testing!')
-(options.list || []).forEach(function(i) {})
-
- -

Ten kod zostanie zmieniony w poniższą jedną linię.

- -
log('testing!')(options.list || []).forEach(function(i) {})
-
- -

Jest bardzo prawdopodobne, że log nie zwróci fukcji, co za tym idzie -powyższy kod wyrzuci błąd TypeError oznajmując, że undefined is not a -function - undefined nie jest funkcją.

- -

Wnioski

- -

Zaleca się aby nigdy nie pomijać średników, pozostawiać nawias otwierający -w tej samej linii co odpowiadająca mu definicja i nigdy nie pozostawiać deklaracji -if / else bez nawiasów nawet jeżeli są jednolinijkowe. Wszystkie te uwagi nie -tylko pomagają poprawić spójność kodu, ale również zapobiegają parser JavaScript -przed zmianą działania kod.

Inne

setTimeout i setInterval

Ponieważ JavaScript jest asynchroniczny, istnieje możliwość zaplanowania wykonania -funkcji korzystając z funkcji setTimeout i setInterval. -Since JavaScript is asynchronous, it is possible to schedule the execution of a -function by using the setTimeout and setInterval functions.

- - - -
function foo() {}
-var id = setTimeout(foo, 1000); // zwraca licznę typu Number > 0
-
- -

Powyższe wywołanie setTimeout zwraca ID budzika i planuje wywołanie foo za -około tysiąc milisekund. foo zostanie wykonana dokładnie jeden raz.

- -

Nie ma pewności, że kod zaplanowany do wykonania wykona się dokładnie po -upłynięciu zadanego czasu podanego jako parametr do setTimeout, ponieważ zależy -to od dokładności zegara w silniku JavaScript, który wykonuje kod oraz od tego, -że inny kawałek kodu może zablokować wątek, ponieważ JavaScript jest tylko -jedno wątkowy.

- -

Funkcja, która została przekazana jako pierwszy parametr zostanie wykonana w -globalnym zasięgu, co oznacza, że this wewnątrz tej funkcji -będzie wkazywać na obiekt global.

- -
function Foo() {
-    this.value = 42;
-    this.method = function() {
-        // this wskazuje na obiekt global
-        console.log(this.value); // wypisze undefined
-    };
-    setTimeout(this.method, 500);
-}
-new Foo();
-
- - - -

Kolejkowanie wywołań z setInterval

- -

Podczas, gdy setTimeout wywołuje podaną funkcję tylko raz, setInterval - -jak wskazuje nazwa - będzie wykonywać funkcję w odstępach czasowych co X -milisekund. Jednakże korzystanie z tej funkcji jest odradzane.

- -

Kiedy wykonywany kod zablokuje możliwość uruchomienia zaplanowanej funkcji, -setInterval będzie próbować uruchamiać daną funkcję co będzie powodować -kolejkowanie wykonania tej samej funkcji kilkakrotnie. W szczególności może się -to wydarzyć przy krótkim interwale.

- -
function foo(){
-    // coś co blokuje wykonanie na 1 sekundę 
-}
-setInterval(foo, 100);
-
- -

W powyższym kodzie kod foo zostanie wywołany tylko raz i zablokuje wywołanie na -jedną sekundę.

- -

Podczas, gdy funkcja foo blokuje wykonanie setInterval będzie planować kolejne -wywołania foo. W momencie, gdy pierwsze wywołanie foo się zakończy, już -w kolejce do wywołania będą czekały kolejne dziesięć wywołań tej funkcji.

- -

Radzenie sobie z możliwymi blokadami

- -

Najprostrzym jak również najbardziej kontrolowaną sytuacją jest użycie setTimeout -wewnątrz wywoływanej funkcji.

- -
function foo(){
-    // coś co blokuje wykonanie na 1 sekundę
-    setTimeout(foo, 100);
-}
-foo();
-
- -

Powyższy kod nie tylko hermetyzuje wywołanie setTimeout ale również zapobiega -kolejkowaniu wywołań fukcji i daje dodatkową kontrolę. W tym przypadku funkcja -foo może zdecydować czy powinna się wywołać ponownie czy też nie.

- -

Ręczne usuwanie budzików

- -

Usuwanie budzików i interwałów dokonywane jest przez przekazanie odpowiedniego ID -do clearTimeout lub clearInterval, w zależności z jakiej funkcji zostało -zwrócone ID.

- -
var id = setTimeout(foo, 1000);
-clearTimeout(id);
-
- -

Usuwanie wszystkich budzików

- -

Ponieważ nie istnieje wbudowana metoda na usunięcie wszystkich budzików i/lub -interwałów, konieczne jest użycie metody brute force aby osiągnąć ten efekt.

- -
// usunięcie "wszystkich" budzików 
-for(var i = 1; i < 1000; i++) {
-    clearTimeout(i);
-}
-
- -

Nadal może istnieć jakieś budziki, na które powyższy kawałek kodu nie zadziała, -ponieważ ID było z innego przedziału, dlatego zamiast korzystania z metody brute -force, zaleca się śledzić wszystkie numery ID budzików, aby można je było usunąć.

- -

Ukryte wykorzystanie eval

- -

Do setTimeout i setInterval można również przekazać string jako pierwszy -parametr zamiast obiektu funkcji, jednakże nigdy nie należy korzystać z tej -możliwości, ponieważ wewnętrznie setTimeout i setInterval wykorzystują eval.

- - - -
function foo() {
-    // zostanie wykonane 
-}
-
-function bar() {
-    function foo() {
-        // nigdy nie zostanie wywołane
-    }
-    setTimeout('foo()', 1000);
-}
-bar();
-
- -

Ponieważ eval nie zostało wywołane wprost w tym przypadku, to -string przekazany do setTimeout zostanie uruchomiony w zasięgu globalnym, -co za tym idzie lokalna zmienna foo z zasięgu bar nie zostanie użyta.

- -

Kolejnym zaleceniem jest aby nie stosować stringów do przekazywania argumentów -do funkcji, która ma zostać wywołana przez budzik.

- -
function foo(a, b, c) {}
-
-// NIGDY nie należy tak robić 
-setTimeout('foo(1,2, 3)', 1000)
-
-// Zamiast tego należy skorzystać z anonimowej funkcji
-setTimeout(function() {
-    foo(a, b, c);
-}, 1000)
-
- - - -

Wnioski

- -

Nie należy nigdy przekazywać stringu jako parametru do setTimeout lub -setInterval. Jest to wyraźną oznaką bardzo złego kodu, jeżeli potrzebne jest -przekazanie argumentów do funkcji należy skorzystać z anonimowej funkcji i -wewnątrz niej dokonać przekazania argumentów.

- -

Ponadto, należy unikać korzystanie z setInterval, ponieważ planista może -zablokować wykonanie JavaScriptu.

\ No newline at end of file From 51baba21de57c1661d7ab8d8679aeb803327b946 Mon Sep 17 00:00:00 2001 From: HIRAKI Satoru Date: Mon, 4 Jul 2011 08:13:43 +0900 Subject: [PATCH 027/463] fix representation --- doc/ja/intro/index.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/ja/intro/index.md b/doc/ja/intro/index.md index b2fcfb3c..0f7ad2c4 100644 --- a/doc/ja/intro/index.md +++ b/doc/ja/intro/index.md @@ -1,13 +1,13 @@ ## 前書き -**JavaScript Garden** はJavaScriptというプログラム言語の一番奇抜な部分についてのドキュメント集です。 -このドキュメントはJavaScriptという言語に対して不慣れなプログラマーがこの言語について深く知ろうとする際に遭遇する、良くある間違い・小さなバグ・パフォーマンスの問題・悪い習慣などを避ける為のアドバイスを与えます。 +**JavaScript Garden** はJavaScriptというプログラム言語の一番奇妙な部分についてのドキュメント集です。 +このドキュメントはJavaScriptという言語に慣れていないプログラマーがこの言語について深く知ろうとする際に遭遇する、良くある間違い・小さなバグ・パフォーマンスの問題・悪い習慣などを避ける為のアドバイスを与えます。 JavaScript GardenはJavaScriptを教える事を**目的にしていません**。このガイドの項目を理解する為には、この言語に対する前提知識がある事を推奨します。この言語の基礎部分についてはMozilla Developer Networkの[ガイド][1] がオススメです。 ## 著者 -このガイドは2人の愛すべき[Stack Overflow][2]ユーザーである[Ivo Wetzel][3] +このガイドは愛すべき[Stack Overflow][2]の2人のユーザー[Ivo Wetzel][3] (執筆)と[Zhang Yi Jiang][4] (デザイン)によって作られました。 ## 貢献者 From 0cc2e8d1e0c88a0389d89b55bb77ae46dc7c2533 Mon Sep 17 00:00:00 2001 From: HIRAKI Satoru Date: Mon, 4 Jul 2011 08:18:04 +0900 Subject: [PATCH 028/463] fix representation of index.json --- doc/ja/index.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/ja/index.json b/doc/ja/index.json index cea3fb99..70be20fc 100644 --- a/doc/ja/index.json +++ b/doc/ja/index.json @@ -1,7 +1,7 @@ { "title": "JavaScript Garden", "langTitle": "JavaScript Garden in Japanese", - "description": "JavaScriptの奇抜さと欠陥についてのガイドライン", + "description": "JavaScriptの奇妙さと欠陥についてのガイドライン", "sections": [ { "title": "前書き", From a3f77751e32e31bb4a2875cb47e51e34fa0ff742 Mon Sep 17 00:00:00 2001 From: Lukasz Kufel Date: Fri, 8 Jul 2011 12:40:35 +0200 Subject: [PATCH 029/463] Small lang fixes. --- doc/pl/intro/contributors.md | 2 +- doc/pl/intro/hosting.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/pl/intro/contributors.md b/doc/pl/intro/contributors.md index a71575a1..7fc5675d 100644 --- a/doc/pl/intro/contributors.md +++ b/doc/pl/intro/contributors.md @@ -1,4 +1,4 @@ -## Kontrybutorzy +## Współtwórcy - [Caio Romão][1] (Poprawki pisowni) - [Andreas Blixt][2] (Poprawki językowe) diff --git a/doc/pl/intro/hosting.md b/doc/pl/intro/hosting.md index 96bc2a1d..19ac9028 100644 --- a/doc/pl/intro/hosting.md +++ b/doc/pl/intro/hosting.md @@ -1,6 +1,6 @@ ## Hosting JavaScript Garden znajduje się na serwerach GitHub, ale dzięki wsparciu -[Cramer Rozwoju] [1] posiadamy mirror na serwerze [JavaScriptGarden.info] [2]. +[Cramer Development] [1] posiadamy również mirror na serwerze [JavaScriptGarden.info] [2]. [1]: http://cramerdev.com/ [2]: http://javascriptgarden.info/ From 409fc68ee3d11d107993ea8fd8b6175691691643 Mon Sep 17 00:00:00 2001 From: HIRAKI Satoru Date: Wed, 13 Jul 2011 02:49:33 +0900 Subject: [PATCH 030/463] translate "prototype" to ja --- doc/ja/object/prototype.md | 53 ++++++++++++++------------------------ 1 file changed, 20 insertions(+), 33 deletions(-) diff --git a/doc/ja/object/prototype.md b/doc/ja/object/prototype.md index f780eba2..93aa4361 100644 --- a/doc/ja/object/prototype.md +++ b/doc/ja/object/prototype.md @@ -1,24 +1,16 @@ -## The Prototype +## プロトタイプ -JavaScript does not feature a classical inheritance model, instead it uses a -*prototypal* one. +JavaScriptはクラスベース継承モデルは実装されておらず、この代わりに*プロトタイプ*を用いています。 -While this is often considered to be one of JavaScript's weaknesses, the -prototypal inheritance model is in fact more powerful than the classic model. -It is for example fairly trivial to build a classic model on top of it, while the -other way around is a far more difficult task. +プロトタイプモデルを使っている事が、JavaScriptの弱点の一つになっていると良く考えられがちですが、プロトタイプ継承モデルはクラスベース継承モデルよりパワフルだというのは事実です。この事はちょっとしたものでもクラスベースの継承で実装しようとすると、プロトタイプベースの継承よりも作業が難しくなるという事でも分かります。 -Due to the fact that JavaScript is basically the only widely used language that -features prototypal inheritance, it takes some time to adjust to the -differences between the two models. +JavaScriptはプロトタイプベースが採用されている唯一の広範に使用されている基本的なプログラミング言語という現実があるので、プロトタイプベースとクラスベースの違いを時々調整しないとなりません。 -The first major difference is that inheritance in JavaScript is done by using so -called *prototype chains*. +最初の大きな違いはJavaScriptの継承は*プロトタイプチェーン*と呼ばれるもので実行されているという事です。 -> **Note:** Simply using `Bar.prototype = Foo.prototype` will result in both objects -> sharing the **same** prototype. Therefore, changes to either object's prototype -> will affect the prototype of the other as well, which in most cases is not the -> desired effect. +> **注意:** 単に`Bar.prototype = Foo.prototype`を使った場合、両方のオブジェクトは、 +> **同じ**プロトタイプを共有する事になります。その為、片方のオブジェクトのプロトタイプの変更は +> もう一方のオブジェクトに影響します。大部分の場合、このような影響を及ぼしたく無いと思います。 function Foo() { this.value = 42; @@ -29,35 +21,30 @@ called *prototype chains*. function Bar() {} - // Set Bar's prototype to a new instance of Foo + // BarのプロトタイプをFooの新しいインスタンスとしてセットする Bar.prototype = new Foo(); Bar.prototype.foo = 'Hello World'; - // Make sure to list Bar as the actual constructor + // Barを実際のコンストラクタとして確実にする為に代入する Bar.prototype.constructor = Bar; - var test = new Bar() // create a new bar instance + var test = new Bar() // 新しくbarインスタンスを作成 - // The resulting prototype chain + // プロトタイプチェーンの結果 test [instance of Bar] Bar.prototype [instance of Foo] { foo: 'Hello World' } Foo.prototype { method: ... } Object.prototype - { toString: ... /* etc. */ } - -In the above, the object `test` will inherit from both `Bar.prototype` and -`Foo.prototype`; hence, it will have access to the function `method` that was -defined on `Foo`. It will also have access to the property `value` of the -**one** `Foo` instance that is its prototype. It is important to note that `new -Bar()` does **not** create a new `Foo` instance, but reuses the one assigned to -its prototype; thus, all `Bar` instances will share the **same** `value` property. - -> **Note:** Do **not** use `Bar.prototype = Foo`, since it will not point to -> the prototype of `Foo` but rather to the function object `Foo`. So the -> prototype chain will go over `Function.prototype` and not `Foo.prototype`; -> therefore, `method` will not be on the prototype chain. + { toString: ... /* その他 */ } + +上記では`test`は`Bar.prototype`と`Foo.prototype`の2つのオブジェクトより継承されます。その為`Foo`の中で設定された`method`関数にアクセスできるようになります。また、`Foo`のプロトタイプとしてのインスタンス**それ自体**の`value`プロパティにもアクセスが可能です。`new Bar()`は`Foo`のインスタンスを新しく作ら**ない**という事は非常に注目されるべき点ですが、それ自身のプロトタイプを再利用しています。従って全ての`Bar`インスタンスは**同じ**`value`プロパティを共有します。 + +> **注意:** `Bar.prototype = Foo`のような使い方は**しない**で下さい。`Foo`はそのプロトタイプではなく、 +> 関数オブジェクト`Foo`自体を指しているからです。 +> プロトタイプチェーンは`Foo.prototype`ではなく`Function.prototype`まで遡るので、 +> `method`はプロトタイプチェーン上に出現しなくなります。 ### Property Lookup From 1a51e8e198702e4ce9b4d032171388f855fbe4cd Mon Sep 17 00:00:00 2001 From: HIRAKI Satoru Date: Thu, 14 Jul 2011 00:46:37 +0900 Subject: [PATCH 031/463] translate "Property Lookup" to ja --- doc/ja/object/prototype.md | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/doc/ja/object/prototype.md b/doc/ja/object/prototype.md index 93aa4361..88c7922f 100644 --- a/doc/ja/object/prototype.md +++ b/doc/ja/object/prototype.md @@ -46,14 +46,11 @@ JavaScriptはプロトタイプベースが採用されている唯一の広範 > プロトタイプチェーンは`Foo.prototype`ではなく`Function.prototype`まで遡るので、 > `method`はプロトタイプチェーン上に出現しなくなります。 -### Property Lookup +### プロパティ探索 -When accessing the properties of an object, JavaScript will traverse the -prototype chain **upwards** until it finds a property with the requested name. +オブジェクトのプロパティにアクセスする時には、JavaScriptはプロトタイプチェーンを要求された名前を見つけるまで**遡って**探索します。 -When it reaches the top of the chain - namely `Object.prototype` - and still -hasn't found the specified property, it will return the value -[undefined](#core.undefined) instead. +チェーンの先頭(すなわち`Object.prototype`)に到達した際に、まだ指定されたプロパティが見つからなければ、代わりに[undefined](#core.undefined)という値を返します。 ### The Prototype Property From 924d4cafaa4b4189d4009d650bce62ddbf551051 Mon Sep 17 00:00:00 2001 From: HIRAKI Satoru Date: Thu, 14 Jul 2011 00:53:09 +0900 Subject: [PATCH 032/463] translate "The Prototype Property" to ja --- doc/ja/object/prototype.md | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/doc/ja/object/prototype.md b/doc/ja/object/prototype.md index 88c7922f..c58bc72e 100644 --- a/doc/ja/object/prototype.md +++ b/doc/ja/object/prototype.md @@ -52,17 +52,14 @@ JavaScriptはプロトタイプベースが採用されている唯一の広範 チェーンの先頭(すなわち`Object.prototype`)に到達した際に、まだ指定されたプロパティが見つからなければ、代わりに[undefined](#core.undefined)という値を返します。 -### The Prototype Property +### プロトタイププロパティ -While the prototype property is used by the language to build the prototype -chains, it is still possible to assign **any** given value to it. Although -primitives will simply get ignored when assigned as a prototype. +プロトタイププロパティはJavaScriptの中でプロトタイプチェーンを構築する為に使われていますが、**任意**の値を代入する事も可能になっています。この時プロトタイプに代入されている値は単に無視されるだけです。 function Foo() {} - Foo.prototype = 1; // no effect + Foo.prototype = 1; // 効果無し -Assigning objects, as shown in the example above, will work, and allows for dynamic -creation of prototype chains. +割り当てられているオブジェクトは上記の例で示されている通りに動作し、動的にプロトタイプチェーンを作ります。 ### Performance From dfb53e503d3a7298d2db68e037706d1953fbfa9c Mon Sep 17 00:00:00 2001 From: HIRAKI Satoru Date: Thu, 14 Jul 2011 00:58:34 +0900 Subject: [PATCH 033/463] translate "Performance" to ja --- doc/ja/object/prototype.md | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/doc/ja/object/prototype.md b/doc/ja/object/prototype.md index c58bc72e..b4d555d6 100644 --- a/doc/ja/object/prototype.md +++ b/doc/ja/object/prototype.md @@ -61,14 +61,12 @@ JavaScriptはプロトタイプベースが採用されている唯一の広範 割り当てられているオブジェクトは上記の例で示されている通りに動作し、動的にプロトタイプチェーンを作ります。 -### Performance +### パフォーマンス -The lookup time for properties that are high up on the prototype chain can have a -negative impact on performance critical sections of code. Additionally, trying to -access non-existent properties will always traverse the full prototype chain. +プロトタイプチェーンの上位にあるプロパティを探索する時間はコードの実行パフォーマンスに重大な悪影響を与えます。特に存在しないプロパティにアクセスしようとすると、プロトタイプチェーンの全てのプロパティを探索してしまいます。 + +また、オブジェクトのプロパティに対して[反復](#object.forinloop)処理をすると、プロトタイプチェーン上の**全て**のプロパティを列挙してしまいます。 -Also, when [iterating](#object.forinloop) over the properties of an object -**every** property that is on the prototype chain will get enumerated. ### Extension of Native Prototypes From a4a7721901841f4a036ae0d9edd19be9e5826b28 Mon Sep 17 00:00:00 2001 From: HIRAKI Satoru Date: Sun, 17 Jul 2011 00:35:31 +0900 Subject: [PATCH 034/463] taranslate "Extension of Native Prototpes" to ja --- doc/ja/object/prototype.md | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/doc/ja/object/prototype.md b/doc/ja/object/prototype.md index b4d555d6..34008306 100644 --- a/doc/ja/object/prototype.md +++ b/doc/ja/object/prototype.md @@ -68,18 +68,14 @@ JavaScriptはプロトタイプベースが採用されている唯一の広範 また、オブジェクトのプロパティに対して[反復](#object.forinloop)処理をすると、プロトタイプチェーン上の**全て**のプロパティを列挙してしまいます。 -### Extension of Native Prototypes +### 既存のプロトタイプの拡張 -One mis-feature that is often used is to extend `Object.prototype` or one of the -other built in prototypes. +元々組み込まれてるプロトタイプや`Object.prototype`を拡張するのは、良くありがちなイケていない実装方法になります。 -This technique is called [monkey patching][1] and breaks *encapsulation*. While -used by widely spread frameworks such as [Prototype][2], there is still no good -reason for cluttering built-in types with additional *non-standard* functionality. +このテクニックは[monkey patching][1]と呼ばれるもので*カプセル化*を壊してしまいます。このテクニックは[Prototype][2]のようなフレームワークにより広まりましたが、*非標準*の機能を持っている組み込み型のオブジェクトの乱立という点でも推奨されません。 -The **only** good reason for extending a built-in prototype is to backport -the features of newer JavaScript engines; for example, -[`Array.forEach`][3]. +**唯一**組み込みのプロトタイプを拡張しても良い理由としては、JavaScriptエンジンに将来実装されるであろう機能の移植だけです。 +例えば[`Array.forEach`][3]などが、それに当たります。 ### In Conclusion From d2ebee9695c92a19c9c7928cb331a15bc1088334 Mon Sep 17 00:00:00 2001 From: HIRAKI Satoru Date: Sun, 17 Jul 2011 00:44:36 +0900 Subject: [PATCH 035/463] translate "In Concluseion" to ja --- doc/ja/object/prototype.md | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/doc/ja/object/prototype.md b/doc/ja/object/prototype.md index 34008306..eb37cc39 100644 --- a/doc/ja/object/prototype.md +++ b/doc/ja/object/prototype.md @@ -77,14 +77,9 @@ JavaScriptはプロトタイプベースが採用されている唯一の広範 **唯一**組み込みのプロトタイプを拡張しても良い理由としては、JavaScriptエンジンに将来実装されるであろう機能の移植だけです。 例えば[`Array.forEach`][3]などが、それに当たります。 -### In Conclusion - -It is a **must** to understand the prototypal inheritance model completely -before writing complex code which makes use of it. Also, watch the length of -the prototype chains and break them up if necessary to avoid possible -performance issues. Further, the native prototypes should **never** be extended -unless it is for the sake of compatibility with newer JavaScript features. +### 終わりに +ここまでがプロトタイプベース継承モデルを使って複雑なコードを書く前に**必ず**理解すべき事です。また、プロパティチェーンの長さを観察して、もしパフォーマンスに悪影響を及ぼすのを防ぐ為ならば、これを分割をしなければなりません。さらに組み込みのプロトタイプは新しいJavaScriptの機能と互換性が無い限りは**絶対**に拡張してはいけません。 [1]: http://en.wikipedia.org/wiki/Monkey_patch [2]: http://prototypejs.org/ [3]: https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/forEach From 1e723d94e630a42b4bedc45364f3746383931b90 Mon Sep 17 00:00:00 2001 From: HIRAKI Satoru Date: Mon, 25 Jul 2011 00:45:58 +0900 Subject: [PATCH 036/463] translate "hasOwnProperty" to ja --- doc/ja/object/hasownproperty.md | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/doc/ja/object/hasownproperty.md b/doc/ja/object/hasownproperty.md index 319a8801..4d0785c8 100644 --- a/doc/ja/object/hasownproperty.md +++ b/doc/ja/object/hasownproperty.md @@ -1,30 +1,24 @@ ## `hasOwnProperty` -In order to check whether a object has a property defined on *itself* and **not** -somewhere on its [prototype chain](#object.prototype), it is necessary to use the -`hasOwnProperty` method which all objects inherit from `Object.prototype`. +オブジェクトは*自分自身*と**自分以外**のどちらで定義されたプロパティかを[prototype chain](#object.prototype)のどこかでチェックしなくてはなりません。これは`Object.prototype`から継承される全てのオブジェクトの`hasOwnProperty`メソッドを使う必要があります。 -> **Note:** It is **not** enough to check whether a property is `undefined`. The -> property might very well exist, but its value just happens to be set to -> `undefined`. +> **注意:** この方法はプロパティが`undefined`かどうかを調べるには十分では**無い**方法です。 +> プロパティは、ほとんどのオブジェクトで存在しているはずの物ではありますが、`undefined`が +> 値に設定される事態は起こり得ます。 -`hasOwnProperty` is the only thing in JavaScript which deals with properties and -does **not** traverse the prototype chain. +`hasOwnProperty`はJavaScriptで唯一プロトタイプチェーン内を**遡らず**にプロパティを扱う事が出来ます。 - // Poisoning Object.prototype + // Object.prototype汚染 Object.prototype.bar = 1; var foo = {goo: undefined}; - + foo.bar; // 1 'bar' in foo; // true foo.hasOwnProperty('bar'); // false foo.hasOwnProperty('goo'); // true -Only `hasOwnProperty` will give the correct and expected result, this is -essential when iterating over the properties of any object. There is **no** other -way to exclude properties that are not defined on the object *itself*, but -somewhere on its prototype chain. +`hasOwnProperty`だけが、正しく期待した結果を出すでしょう。これはあらゆるオブジェクトのプロパティの繰り返し処理をする時必須の事です。オブジェクト**自身**に定義されておらず、プロトタイプチェーンのどこかには定義されているというプロパティを除外する手段が他に**ありません**。 ### `hasOwnProperty` as a Property From 7497534df9a21cfee7d1d879fbcb9295ea201e3c Mon Sep 17 00:00:00 2001 From: HIRAKI Satoru Date: Mon, 25 Jul 2011 00:48:06 +0900 Subject: [PATCH 037/463] fix ittalian to bold --- doc/ja/object/hasownproperty.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/ja/object/hasownproperty.md b/doc/ja/object/hasownproperty.md index 4d0785c8..edb717ca 100644 --- a/doc/ja/object/hasownproperty.md +++ b/doc/ja/object/hasownproperty.md @@ -18,7 +18,7 @@ foo.hasOwnProperty('bar'); // false foo.hasOwnProperty('goo'); // true -`hasOwnProperty`だけが、正しく期待した結果を出すでしょう。これはあらゆるオブジェクトのプロパティの繰り返し処理をする時必須の事です。オブジェクト**自身**に定義されておらず、プロトタイプチェーンのどこかには定義されているというプロパティを除外する手段が他に**ありません**。 +`hasOwnProperty`だけが、正しく期待した結果を出すでしょう。これはあらゆるオブジェクトのプロパティの繰り返し処理をする時必須の事です。オブジェクト*自身*に定義されておらず、プロトタイプチェーンのどこかには定義されているというプロパティを除外する手段が他に**ありません**。 ### `hasOwnProperty` as a Property From 531d4cefc917c5420155d95c38cca6b97ba5e038 Mon Sep 17 00:00:00 2001 From: HIRAKI Satoru Date: Mon, 25 Jul 2011 01:05:20 +0900 Subject: [PATCH 038/463] translate "hasOwnProperty as a Property" to ja --- doc/ja/object/hasownproperty.md | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/doc/ja/object/hasownproperty.md b/doc/ja/object/hasownproperty.md index edb717ca..2d4d4f65 100644 --- a/doc/ja/object/hasownproperty.md +++ b/doc/ja/object/hasownproperty.md @@ -20,11 +20,9 @@ `hasOwnProperty`だけが、正しく期待した結果を出すでしょう。これはあらゆるオブジェクトのプロパティの繰り返し処理をする時必須の事です。オブジェクト*自身*に定義されておらず、プロトタイプチェーンのどこかには定義されているというプロパティを除外する手段が他に**ありません**。 -### `hasOwnProperty` as a Property +### プロパティとしての`hasOwnProperty` -JavaScript does **not** protect the property name `hasOwnProperty`; thus, if the -possibility exists that an object might have a property with this name, it is -necessary to use an *external* `hasOwnProperty` in order to get correct results. +JavaScriptはプロパティ名として`hasOwnProperty`を保護して**いません**。;従って、この名前のプロパティを持ったオブジェクトが存在する事がありえます。正しい結果を得る為には*外部*の`hasOwnProperty`を使う必要があります。 var foo = { hasOwnProperty: function() { @@ -33,9 +31,9 @@ necessary to use an *external* `hasOwnProperty` in order to get correct results. bar: 'Here be dragons' }; - foo.hasOwnProperty('bar'); // always returns false + foo.hasOwnProperty('bar'); // 常にfalseを返す - // Use another Object's hasOwnProperty and call it with 'this' set to foo + // 他のオブジェクトのhasOwnPropertyを使い、fooの'this'にセットして呼び出す ({}).hasOwnProperty.call(foo, 'bar'); // true ### In Conclusion From f6bd59610e895b98028e076fdc5fbde9a9de5945 Mon Sep 17 00:00:00 2001 From: HIRAKI Satoru Date: Mon, 25 Jul 2011 01:09:44 +0900 Subject: [PATCH 039/463] translate "In Conclusion" to ja --- doc/ja/object/hasownproperty.md | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/doc/ja/object/hasownproperty.md b/doc/ja/object/hasownproperty.md index 2d4d4f65..fb9c7ead 100644 --- a/doc/ja/object/hasownproperty.md +++ b/doc/ja/object/hasownproperty.md @@ -36,10 +36,9 @@ JavaScriptはプロパティ名として`hasOwnProperty`を保護して**いま // 他のオブジェクトのhasOwnPropertyを使い、fooの'this'にセットして呼び出す ({}).hasOwnProperty.call(foo, 'bar'); // true -### In Conclusion +### 終わりに -When checking for the existence of a property on a object, `hasOwnProperty` is -the **only** method of doing so. It is also recommended to make `hasOwnProperty` -part of **every** [`for in` loop](#object.forinloop), this will avoid errors from -extended native [prototypes](#object.prototype). +オブジェクトのプロパティの存在判定をする時は、`hasOwnProperty`が**唯一**のメソッドになります。 +また、**全て**の[`for in` loop](#object.forinloop)内で`hasOwnProperty`を使う事を推奨します。 +そうする事により組み込みの[prototypes](#object.prototype)の拡張が原因のエラーを避ける事が出来ます。 From b9fb15e27242fe2b1702a7f77bd14644a9ecb33e Mon Sep 17 00:00:00 2001 From: HIRAKI Satoru Date: Mon, 25 Jul 2011 01:11:07 +0900 Subject: [PATCH 040/463] fix representation --- doc/ja/object/hasownproperty.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/ja/object/hasownproperty.md b/doc/ja/object/hasownproperty.md index fb9c7ead..7b02305f 100644 --- a/doc/ja/object/hasownproperty.md +++ b/doc/ja/object/hasownproperty.md @@ -39,6 +39,6 @@ JavaScriptはプロパティ名として`hasOwnProperty`を保護して**いま ### 終わりに オブジェクトのプロパティの存在判定をする時は、`hasOwnProperty`が**唯一**のメソッドになります。 -また、**全て**の[`for in` loop](#object.forinloop)内で`hasOwnProperty`を使う事を推奨します。 +また、**全て**の[`for in` ループ](#object.forinloop)内で`hasOwnProperty`を使う事を推奨します。 そうする事により組み込みの[prototypes](#object.prototype)の拡張が原因のエラーを避ける事が出来ます。 From 04b6f1c285d9bf341b5c545ffc440654d359804c Mon Sep 17 00:00:00 2001 From: HIRAKI Satoru Date: Tue, 26 Jul 2011 01:18:01 +0900 Subject: [PATCH 041/463] translate "The for in Loop" in "Object" to ja --- doc/ja/object/forinloop.md | 27 +++++++++++---------------- 1 file changed, 11 insertions(+), 16 deletions(-) diff --git a/doc/ja/object/forinloop.md b/doc/ja/object/forinloop.md index 30751ed9..4dcf71fd 100644 --- a/doc/ja/object/forinloop.md +++ b/doc/ja/object/forinloop.md @@ -1,29 +1,24 @@ -## The `for in` Loop +## `for in`ループ -Just like the `in` operator, the `for in` loop also traverses the prototype -chain when iterating over the properties of an object. +`in`オペレーターは単に、`for in`ループの中でオブジェクトのプロパティをプロトタイプチェーンの中で繰り返し遡る為にあるものです。 -> **Note:** The `for in` loop will **not** iterate over any properties that -> have their `enumerable` attribute set to `false`; for example, the `length` -> property of an array. - - // Poisoning Object.prototype +> **注意:** `for in`ループは`列挙`される属性が`false`にセットされているプロパティを反復処理**しません**。; +> 例えば、配列の`length`プロパティなどがそれに当たります。 + + // Object.prototype汚染 Object.prototype.bar = 1; var foo = {moo: 2}; for(var i in foo) { - console.log(i); // prints both bar and moo + console.log(i); // barとmooが両方とも表示される } -Since it is not possible to change the behavior of the `for in` loop itself, it -is necessary to filter out the unwanted properties inside the loop body , -this is done by using the [`hasOwnProperty`](#object.hasownproperty) method of -`Object.prototype`. +`for in`ループそれ自体の動作を変更する事は不可能ですが、ループ内にある要らないプロパティをフィルタリングする必要があります。そんな時は`Object.prototype`の[`hasOwnProperty`](#object.hasownproperty)メソッドを使うと解決します。 -> **Note:** Since the `for in` always traverses the complete prototype chain, it -> will get slower with each additional layer of inheritance added to an object. +> **注意:** `for in`は常にプロトタイプチェーンを完全に遡ります。これにより +> オブジェクトに追加されている継承が多ければ多い程、速度は遅くなります。 -### Using `hasOwnProperty` for Filtering +### `hasOwnProperty` for Filtering // still the foo from above for(var i in foo) { From f8fe974e14fa7ff3734dc89dd44febbd2db90cc1 Mon Sep 17 00:00:00 2001 From: HIRAKI Satoru Date: Tue, 26 Jul 2011 01:33:35 +0900 Subject: [PATCH 042/463] translate "Using 'hasOwnProperty' for Filtering" in "Object" to ja --- doc/ja/object/forinloop.md | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/doc/ja/object/forinloop.md b/doc/ja/object/forinloop.md index 4dcf71fd..6bf2e97f 100644 --- a/doc/ja/object/forinloop.md +++ b/doc/ja/object/forinloop.md @@ -18,23 +18,21 @@ > **注意:** `for in`は常にプロトタイプチェーンを完全に遡ります。これにより > オブジェクトに追加されている継承が多ければ多い程、速度は遅くなります。 -### `hasOwnProperty` for Filtering +### `hasOwnProperty`をフィルタリングに使用する - // still the foo from above + // 継承されているfoo for(var i in foo) { if (foo.hasOwnProperty(i)) { console.log(i); } } -This version is the only correct one to use. Due to the use of `hasOwnProperty` it -will **only** print out `moo`. When `hasOwnProperty` is left out, the code is -prone to errors in cases where the native prototypes - e.g. `Object.prototype` - -have been extended. +このループの唯一正しい使い方がこの方法です。`hasOwnProperty`を使用しているので、 +`moo`**のみ**が表示されるようになります。`hasOwnProperty`が省略されている場合は、このコードは +組み込みのプロトタイプが存在する場合に(特に`Object.prototype`が拡張されている場合)エラーを発生しやすくなります。 -One widely used framework which does this is [Prototype][1]. When this -framework is included, `for in` loops that do not use `hasOwnProperty` are -guaranteed to break. +一般に広く使用されているJavaScriptフレームワークとして[Prototype][1]が挙げられます。このフレームワークには、 +`for in` 内で`hasOwnProperty`が使用されプロトタプチェーン内を頭まで遡るのを中断する事が保証されています。 ### In Conclusion From 498f057da5b15d4e4761dbebfd49debf93082f5e Mon Sep 17 00:00:00 2001 From: HIRAKI Satoru Date: Tue, 26 Jul 2011 01:38:08 +0900 Subject: [PATCH 043/463] translate "In Conclusion" in "Object" to ja --- doc/ja/object/forinloop.md | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/doc/ja/object/forinloop.md b/doc/ja/object/forinloop.md index 6bf2e97f..ffd6eb1c 100644 --- a/doc/ja/object/forinloop.md +++ b/doc/ja/object/forinloop.md @@ -34,11 +34,9 @@ 一般に広く使用されているJavaScriptフレームワークとして[Prototype][1]が挙げられます。このフレームワークには、 `for in` 内で`hasOwnProperty`が使用されプロトタプチェーン内を頭まで遡るのを中断する事が保証されています。 -### In Conclusion +### 終わりに -It is recommended to **always** use `hasOwnProperty`. Never should any -assumptions be made about the environment the code is running in, or whether the -native prototypes have been extended or not. +**常に**`hasOwnProperty`を使用する事を推奨します。コードの実行環境や、組み込みのプロトタイプが拡張されているかどうかを仮定して書くようなコードを絶対書いてはいけません。 [1]: http://www.prototypejs.org/ From e38236fd7ba5704e71d9cae5c65c21624eb53a64 Mon Sep 17 00:00:00 2001 From: Adam Bowen Date: Fri, 29 Jul 2011 19:59:21 -0300 Subject: [PATCH 044/463] fixed grammar, typo in "notation of keys" --- doc/en/object/general.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/en/object/general.md b/doc/en/object/general.md index cbad5f11..dccf468b 100644 --- a/doc/en/object/general.md +++ b/doc/en/object/general.md @@ -83,8 +83,8 @@ removed and is therefore missing from the output. ### Notation of Keys var test = { - 'case': 'I am a keyword so I must be notated as a string', - delete: 'I am a keyword too so me' // raises SyntaxError + 'case': 'I am a keyword, so I must be notated as a string', + delete: 'I am a keyword, so me too' // raises SyntaxError }; Object properties can be both notated as plain characters and as strings. Due to From 15573af0ffad252b83023bcaa9ee9d38fa992f79 Mon Sep 17 00:00:00 2001 From: HIRAKI Satoru Date: Sun, 31 Jul 2011 21:40:35 +0900 Subject: [PATCH 045/463] translate "Function Declarations and Expressions" in "Function" to ja --- doc/ja/function/general.md | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/doc/ja/function/general.md b/doc/ja/function/general.md index 64c9e0c9..1d95010a 100644 --- a/doc/ja/function/general.md +++ b/doc/ja/function/general.md @@ -1,8 +1,6 @@ -## Function Declarations and Expressions +## 関数の宣言と式 -Functions in JavaScript are first class objects. That means they can be -passed around like any other value. One common use of this feature is to pass -an *anonymous function* as a callback to another, possibly asynchronous function. +関数はJavaScriptの第一級オブジェクトです。この事は、その他の値と同じように渡す事が出来るという事です。この機能で良く使われる一つとして**匿名関数**を他のオジェクトにコールバックとして渡すというものがあり、これで非同期での実装が可能になります。 ### The `function` Declaration From 96307ba950290d4a3832a3ac306e16d9f79cc477 Mon Sep 17 00:00:00 2001 From: HIRAKI Satoru Date: Sun, 31 Jul 2011 22:44:05 +0900 Subject: [PATCH 046/463] translate "The function Declaration" in "Function" to ja --- doc/ja/function/general.md | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/doc/ja/function/general.md b/doc/ja/function/general.md index 1d95010a..a0746a44 100644 --- a/doc/ja/function/general.md +++ b/doc/ja/function/general.md @@ -2,15 +2,13 @@ 関数はJavaScriptの第一級オブジェクトです。この事は、その他の値と同じように渡す事が出来るという事です。この機能で良く使われる一つとして**匿名関数**を他のオジェクトにコールバックとして渡すというものがあり、これで非同期での実装が可能になります。 -### The `function` Declaration +### `関数`宣言 function foo() {} -The above function gets [hoisted](#function.scopes) before the execution of the -program starts; thus, it is available *everywhere* in the scope it was *defined* -in, even if called before the actual definition in the source. +上記の関数はプログラムの開始時の前に評価されるように[巻き上げ](#function.scopes)られます。従って*定義*されたスコープ内の*どこでも*使用する事が可能になります。ソース内での実際の定義が呼ばれる前でもです。 - foo(); // Works because foo was created before this code runs + foo(); // このコードが動作する前にfooが作られているので、ちゃんと動作する function foo() {} ### The `function` Expression From 8395ac3aecf6a39e168a76841f10db42c3eade52 Mon Sep 17 00:00:00 2001 From: HIRAKI Satoru Date: Sun, 31 Jul 2011 23:10:05 +0900 Subject: [PATCH 047/463] translate "The function Expression" in "Function" to ja --- doc/ja/function/general.md | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/doc/ja/function/general.md b/doc/ja/function/general.md index a0746a44..6de7950a 100644 --- a/doc/ja/function/general.md +++ b/doc/ja/function/general.md @@ -11,22 +11,19 @@ foo(); // このコードが動作する前にfooが作られているので、ちゃんと動作する function foo() {} -### The `function` Expression +### `関数`式 var foo = function() {}; -This example assigns the unnamed and *anonymous* function to the variable `foo`. +この例では、`foo`という変数に無名で*匿名*の関数が割り当てられています。 foo; // 'undefined' - foo(); // this raises a TypeError + foo(); // これはTypeErrorが起こる var foo = function() {}; -Due to the fact that `var` is a declaration, that hoists the variable name `foo` -before the actual execution of the code starts, `foo` is already defined when -the script gets executed. +`var`は宣言である為に、変数名`foo`がコードが開始される実際の評価時より前のタイミングにまで巻き上げられています。`foo`は既にスクリプトが評価される時には定義されているのです。 -But since assignments only happen at runtime, the value of `foo` will default -to [undefined](#core.undefined) before the corresponding code is executed. +しかし、コードの実行時にのみこの割り当てがされるため、`foo`という変数は対応するコードが実行される前にデフォルト値である[undefined](#core.undefined)が代入されるのです。 ### Named Function Expression From 113d685f8debaa1fff5439b4f3210d335bacfe10 Mon Sep 17 00:00:00 2001 From: HIRAKI Satoru Date: Sun, 31 Jul 2011 23:18:04 +0900 Subject: [PATCH 048/463] translate "Named Function Expression" to ja --- doc/ja/function/general.md | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/doc/ja/function/general.md b/doc/ja/function/general.md index 6de7950a..d3ce0237 100644 --- a/doc/ja/function/general.md +++ b/doc/ja/function/general.md @@ -25,17 +25,14 @@ しかし、コードの実行時にのみこの割り当てがされるため、`foo`という変数は対応するコードが実行される前にデフォルト値である[undefined](#core.undefined)が代入されるのです。 -### Named Function Expression +### 名前付き関数宣言 -Another special case is the assignment of named functions. +他に特殊なケースとして、命名関数があります。 var foo = function bar() { - bar(); // Works + bar(); // 動作する } bar(); // ReferenceError -Here `bar` is not available in the outer scope, since the function only gets -assigned to `foo`; however, inside of `bar` it is available. This is due to -how [name resolution](#function.scopes) in JavaScript works, the name of the -function is *always* made available in the local scope of the function itself. +この場合の`bar`は`foo`に対して関数を割り当てるだけなので、外部スコープでは使用できません。しかし、`bar`は内部では使用できます。これはJavaScriptでは[名前解決](#function.scopes)による動作です。関数名は*いつも*関数自体のローカルスコープ内で有効になっています。 From 42c398b9ed382e8245df3106879ea81f467cfcff Mon Sep 17 00:00:00 2001 From: HIRAKI Satoru Date: Sun, 31 Jul 2011 23:43:57 +0900 Subject: [PATCH 049/463] translate "How this Works" in "Function" to ja --- doc/ja/function/this.md | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/doc/ja/function/this.md b/doc/ja/function/this.md index 85b11f0f..7bea0323 100644 --- a/doc/ja/function/this.md +++ b/doc/ja/function/this.md @@ -1,8 +1,6 @@ -## How `this` Works +## `this`はどのように動作するのか -JavaScript has a different concept of what the special name `this` refers to -than most other programming languages do. There are exactly **five** different -ways in which the value of `this` can be bound in the language. +JavaScriptの`this`と名付けられた特殊なキーワードは他のプログラム言語と違うコンセプトを持っています。JavaScriptの`this`は正確に**5個**の別々の使い道が存在しています。 ### The Global Scope From 6a9b7574471d2f9f2bee03e51e4fb7f76965bc30 Mon Sep 17 00:00:00 2001 From: HIRAKI Satoru Date: Sun, 31 Jul 2011 23:45:41 +0900 Subject: [PATCH 050/463] translate "The Global Scope" in "Function" to ja --- doc/ja/function/this.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/ja/function/this.md b/doc/ja/function/this.md index 7bea0323..a050aa0d 100644 --- a/doc/ja/function/this.md +++ b/doc/ja/function/this.md @@ -2,11 +2,11 @@ JavaScriptの`this`と名付けられた特殊なキーワードは他のプログラム言語と違うコンセプトを持っています。JavaScriptの`this`は正確に**5個**の別々の使い道が存在しています。 -### The Global Scope +### グローバルスコープとして this; -When using `this` in global scope, it will simply refer to the *global* object. +`this`をグローバルスコープ内で使用すると、単純に*グローバル*オブジェクトを参照するようになります。 ### Calling a Function From 269bc5bdf4bed129ba6a8a2972e421c8cc8beb56 Mon Sep 17 00:00:00 2001 From: HIRAKI Satoru Date: Sun, 31 Jul 2011 23:50:20 +0900 Subject: [PATCH 051/463] translate "Calling a Function" in "Function" to ja --- doc/ja/function/this.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/doc/ja/function/this.md b/doc/ja/function/this.md index a050aa0d..59926dc7 100644 --- a/doc/ja/function/this.md +++ b/doc/ja/function/this.md @@ -9,14 +9,14 @@ JavaScriptの`this`と名付けられた特殊なキーワードは他のプロ `this`をグローバルスコープ内で使用すると、単純に*グローバル*オブジェクトを参照するようになります。 -### Calling a Function +### 関数呼び出しとして foo(); -Here `this` will again refer to the *global* object. +この`this`は、再度*グローバル*オブジェクトを参照しています。 -> **ES5 Note:** In strict mode, the global case **no longer** exists. -> `this` will instead have the value of `undefined` in that case. +> **ES5での注意点:** strictモードでは、このグローバルのケースは**もはや**存在していません。 +> この場合`this`の代わりに`undefined`値を持つことになります。 ### Calling a Method From 6e9a08cfd095e97a53ebdff47c569ccb167207de Mon Sep 17 00:00:00 2001 From: HIRAKI Satoru Date: Sun, 31 Jul 2011 23:53:41 +0900 Subject: [PATCH 052/463] translate "Calling a Method" in "Function" to ja --- doc/ja/function/this.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/ja/function/this.md b/doc/ja/function/this.md index 59926dc7..99b0534e 100644 --- a/doc/ja/function/this.md +++ b/doc/ja/function/this.md @@ -18,11 +18,11 @@ JavaScriptの`this`と名付けられた特殊なキーワードは他のプロ > **ES5での注意点:** strictモードでは、このグローバルのケースは**もはや**存在していません。 > この場合`this`の代わりに`undefined`値を持つことになります。 -### Calling a Method +### メソッド呼び出しとして test.foo(); -In this example `this` will refer to `test`. +この例では`this`は`test`を参照します。 ### Calling a Constructor From 58fabd8135b1b2c1d28f28349b576e6ee713aff8 Mon Sep 17 00:00:00 2001 From: HIRAKI Satoru Date: Mon, 1 Aug 2011 00:12:15 +0900 Subject: [PATCH 053/463] translate "Calling a Constructor" in "Function" to ja --- doc/ja/function/this.md | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/doc/ja/function/this.md b/doc/ja/function/this.md index 99b0534e..6db607d7 100644 --- a/doc/ja/function/this.md +++ b/doc/ja/function/this.md @@ -24,13 +24,11 @@ JavaScriptの`this`と名付けられた特殊なキーワードは他のプロ この例では`this`は`test`を参照します。 -### Calling a Constructor +### コンストラクター呼び出し new foo(); -A function call that is preceded by the `new` keyword acts as -a [constructor](#function.constructors). Inside the function `this` will refer -to a *newly created* `Object`. +`new`キーワードが付いた関数呼び出しは[コンストラクター](#function.constructors)として機能します。関数内部では`this`は*新規に作成された*`Oject`を参照します。 ### Explicit Setting of `this` From 0c6bb4d438a4bf54bd7aa7e3410a30d74ffe31a1 Mon Sep 17 00:00:00 2001 From: HIRAKI Satoru Date: Mon, 1 Aug 2011 00:14:24 +0900 Subject: [PATCH 054/463] fix misspelling --- doc/ja/function/this.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/ja/function/this.md b/doc/ja/function/this.md index 6db607d7..713fb250 100644 --- a/doc/ja/function/this.md +++ b/doc/ja/function/this.md @@ -28,7 +28,7 @@ JavaScriptの`this`と名付けられた特殊なキーワードは他のプロ new foo(); -`new`キーワードが付いた関数呼び出しは[コンストラクター](#function.constructors)として機能します。関数内部では`this`は*新規に作成された*`Oject`を参照します。 +`new`キーワードが付いた関数呼び出しは[コンストラクター](#function.constructors)として機能します。関数内部では`this`は*新規に作成された*`Object`を参照します。 ### Explicit Setting of `this` From c4f53c5e0f8846a55932385df2f41561d347a391 Mon Sep 17 00:00:00 2001 From: HIRAKI Satoru Date: Mon, 1 Aug 2011 01:04:21 +0900 Subject: [PATCH 055/463] translate "Explicit Setting of this" in "Function" to ja --- doc/ja/function/this.md | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/doc/ja/function/this.md b/doc/ja/function/this.md index 713fb250..18a6c4e2 100644 --- a/doc/ja/function/this.md +++ b/doc/ja/function/this.md @@ -30,24 +30,21 @@ JavaScriptの`this`と名付けられた特殊なキーワードは他のプロ `new`キーワードが付いた関数呼び出しは[コンストラクター](#function.constructors)として機能します。関数内部では`this`は*新規に作成された*`Object`を参照します。 -### Explicit Setting of `this` +### `this`の明示的な設定 function foo(a, b, c) {} - + var bar = {}; - foo.apply(bar, [1, 2, 3]); // array will expand to the below - foo.call(bar, 1, 2, 3); // results in a = 1, b = 2, c = 3 + foo.apply(bar, [1, 2, 3]); // 配列は下記で展開される + foo.call(bar, 1, 2, 3); // 結果はa = 1, b = 2, c = 3 -When using the `call` or `apply` methods of `Function.prototype`, the value of -`this` inside the called function gets **explicitly set** to the first argument -of the corresponding function call. + `Function.prototype`の`call`や`apply`メソッドを使用した時には、呼び出された関数の内部での`this`の値は、対応する関数呼び出しの最初の引数に**明示的に設定**されます。 -As a result, the above example the *method case* does **not** apply, and `this` -inside of `foo` will be set to `bar`. +結果として、上記の例では*メソッドケース*が適用**されず**、`foo`の内部の`this`は`bar`に設定されます。 -> **Note:** `this` **cannot** be used to refer to the object inside of an `Object` -> literal. So `var obj = {me: this}` will **not** result in `me` referring to -> `obj`, since `this` only gets bound by one of the five listed cases. +> **注意:** `this`は`Object`リテラル内部のオブジェクトを参照**しません**。 +> ですので、`var obj = {me: this}`での`me`は`obj`を参照**しません**。 +> `this`はここで紹介ている5個のケースの内どれか一つに束縛されます。 ### Common Pitfalls From 181069363875e9e7bb58a8bcc302a75a64d2ff20 Mon Sep 17 00:00:00 2001 From: HIRAKI Satoru Date: Mon, 1 Aug 2011 01:09:58 +0900 Subject: [PATCH 056/463] fix representation --- doc/ja/function/this.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/ja/function/this.md b/doc/ja/function/this.md index 18a6c4e2..0f6b7c7e 100644 --- a/doc/ja/function/this.md +++ b/doc/ja/function/this.md @@ -15,7 +15,7 @@ JavaScriptの`this`と名付けられた特殊なキーワードは他のプロ この`this`は、再度*グローバル*オブジェクトを参照しています。 -> **ES5での注意点:** strictモードでは、このグローバルのケースは**もはや**存在していません。 +> **ES5での注意:** strictモードでは、このグローバルのケースは**もはや**存在していません。 > この場合`this`の代わりに`undefined`値を持つことになります。 ### メソッド呼び出しとして From 6ecc8ff0eeaf89a15927a66a067692362e2c9a86 Mon Sep 17 00:00:00 2001 From: Adam Bowen Date: Wed, 10 Aug 2011 10:48:36 -0300 Subject: [PATCH 057/463] Removed a hell of a lot of spaces: they were breaking layout --- doc/en/function/arguments.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/en/function/arguments.md b/doc/en/function/arguments.md index 3d551ad5..037a9020 100644 --- a/doc/en/function/arguments.md +++ b/doc/en/function/arguments.md @@ -66,7 +66,7 @@ of the corresponding property on the `arguments` object, and the other way aroun function foo(a, b, c) { arguments[0] = 2; - a; // 2 + a; // 2 b = 4; arguments[1]; // 4 From 205a10bb55e6b7c11f799a140b7bb4c63f4ae820 Mon Sep 17 00:00:00 2001 From: HIRAKI Satoru Date: Fri, 12 Aug 2011 01:30:14 +0900 Subject: [PATCH 058/463] translate "Common Pitfalls" in "Function" to ja --- doc/ja/function/this.md | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/doc/ja/function/this.md b/doc/ja/function/this.md index 0f6b7c7e..ce43c20a 100644 --- a/doc/ja/function/this.md +++ b/doc/ja/function/this.md @@ -46,35 +46,30 @@ JavaScriptの`this`と名付けられた特殊なキーワードは他のプロ > ですので、`var obj = {me: this}`での`me`は`obj`を参照**しません**。 > `this`はここで紹介ている5個のケースの内どれか一つに束縛されます。 -### Common Pitfalls +### 良くある落し穴 -While most of these cases make sense, the first one is to be considered another -mis-design of the language, as it **never** has any practical use. +これらほとんどのケースで見てきたように、最初のケースでは**絶対に**実用化できないという言語設計のミスを考慮しないとなりません。 Foo.method = function() { function test() { - // this is set to the global object + // このファンクションはグローバルオブジェクトに設定される } test(); } -A common misconception is that `this` inside of `test` refers to `Foo`, while in -fact it **does not**. +良くある誤解として`test`の中の`this`が`Foo`を参照しているというものがありますが、そのような事実は**一切**ありません。 -In order to gain access to `Foo` from within `test` it is necessary to create a -local variable inside of `method` which refers to `Foo`. +`test`の中の`Foo`にアクセスする為には、`Foo`を参照する`method`のローカル変数を作る必要があります。 Foo.method = function() { var that = this; function test() { - // Use that instead of this here + // ここでthisの代わりに使用する } test(); } -`that` is just a normal variable name, but it is commonly used for the reference to an -outer `this`. In combination with [closures](#function.closures), it can also -be used to pass `this` values around. +`that`は通常の変数名ですが、外部の`this`の参照の為に良く使われます。[closures](#function.closures)と組み合わせる事で`this`の値を渡す事ができるようになります。 ### Assigning Methods From ffc33672745f4c85428cd57fc73dc4cd2bf4084b Mon Sep 17 00:00:00 2001 From: HIRAKI Satoru Date: Fri, 12 Aug 2011 12:38:31 +0900 Subject: [PATCH 059/463] translate the word of "clousures" --- doc/ja/function/this.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/ja/function/this.md b/doc/ja/function/this.md index ce43c20a..586004a7 100644 --- a/doc/ja/function/this.md +++ b/doc/ja/function/this.md @@ -69,7 +69,7 @@ JavaScriptの`this`と名付けられた特殊なキーワードは他のプロ test(); } -`that`は通常の変数名ですが、外部の`this`の参照の為に良く使われます。[closures](#function.closures)と組み合わせる事で`this`の値を渡す事ができるようになります。 +`that`は通常の変数名ですが、外部の`this`の参照の為に良く使われます。[クロージャ](#function.closures)と組み合わせる事で`this`の値を渡す事ができるようになります。 ### Assigning Methods From 0d40977ebde7940d2d8606f1a68ec62222827e6c Mon Sep 17 00:00:00 2001 From: HIRAKI Satoru Date: Fri, 12 Aug 2011 18:05:50 +0900 Subject: [PATCH 060/463] translate "Assigning Methods" in "Function" to ja --- doc/ja/function/this.md | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/doc/ja/function/this.md b/doc/ja/function/this.md index 586004a7..424760d9 100644 --- a/doc/ja/function/this.md +++ b/doc/ja/function/this.md @@ -71,19 +71,16 @@ JavaScriptの`this`と名付けられた特殊なキーワードは他のプロ `that`は通常の変数名ですが、外部の`this`の参照の為に良く使われます。[クロージャ](#function.closures)と組み合わせる事で`this`の値を渡す事ができるようになります。 -### Assigning Methods +### メソッドの割り当て -Another thing that does **not** work in JavaScript is function aliasing, that is, -**assigning** a method to a variable. +JavaScriptを使用する上で、もう一つ動か**ない**ものが関数のエイリアスです。これは変数へメソッドを**割り当て**する事です。 var test = someObject.methodTest; test(); -Due to the first case `test` now acts like a plain function call; therefore, -`this` inside it will no longer refer to `someObject`. +最初のケースの`test`は通常の関数呼び出しになる為に、この中の`this`は、最早`someobject`を参照できなくなってしまいます。 -While the late binding of `this` might seem like a bad idea at first, it is in -fact what makes [prototypal inheritance](#object.prototype) work. +`this`の遅延バインディングは最初見た時にはダメなアイデアに見えますが、[プロトタイプ継承](#object.prototype)により、きちんと動作します。 function Foo() {} Foo.prototype.method = function() {}; @@ -93,7 +90,4 @@ fact what makes [prototypal inheritance](#object.prototype) work. new Bar().method(); -When `method` gets called on a instance of `Bar`, `this` will now refer to that -very instance. - - +`method`が`Bar`のインスタンスにより呼び出された時に、`this`はまさにそのインスタンスを参照するようになります。 From fca2945eefbbefa6f0bf28b234562a8dd0be46e9 Mon Sep 17 00:00:00 2001 From: HIRAKI Satoru Date: Fri, 12 Aug 2011 20:19:30 +0900 Subject: [PATCH 061/463] translate "Closures and References" in "Function" to ja --- doc/ja/function/closures.md | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/doc/ja/function/closures.md b/doc/ja/function/closures.md index 17554dcb..5f1f62f4 100644 --- a/doc/ja/function/closures.md +++ b/doc/ja/function/closures.md @@ -1,9 +1,6 @@ -## Closures and References +## クロージャと参照 -One of JavaScript's most powerful features is the availability of *closures*, -this means that scopes **always** keep access to the outer scope they were -defined in. Since the only scoping that JavaScript has is -[function scope](#function.scopes), all functions, by default, act as closures. +JavaScriptの一番パワフルな特徴の一つとして*クロージャ*が使える事が挙げられます。これはスコープが**いつも**外部に定義されたスコープにアクセスできるという事です。JavaScriptの唯一のスコープは[関数スコープ](#function.scopes)ですが、全ての関数は標準でクロージャとして振る舞います。 ### Emulating private variables From d78a399fe9d8cb36f209177f7fd30b2db204a13d Mon Sep 17 00:00:00 2001 From: HIRAKI Satoru Date: Fri, 12 Aug 2011 20:50:39 +0900 Subject: [PATCH 062/463] translate "Emulating private variables" in "Function" to ja --- doc/ja/function/closures.md | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/doc/ja/function/closures.md b/doc/ja/function/closures.md index 5f1f62f4..74d4327d 100644 --- a/doc/ja/function/closures.md +++ b/doc/ja/function/closures.md @@ -2,7 +2,7 @@ JavaScriptの一番パワフルな特徴の一つとして*クロージャ*が使える事が挙げられます。これはスコープが**いつも**外部に定義されたスコープにアクセスできるという事です。JavaScriptの唯一のスコープは[関数スコープ](#function.scopes)ですが、全ての関数は標準でクロージャとして振る舞います。 -### Emulating private variables +### プライベート変数をエミュレートする function Counter(start) { var count = start; @@ -21,10 +21,7 @@ JavaScriptの一番パワフルな特徴の一つとして*クロージャ*が foo.increment(); foo.get(); // 5 -Here, `Counter` returns **two** closures. The function `increment` as well as -the function `get`. Both of these functions keep a **reference** to the scope of -`Counter` and, therefore, always keep access to the `count` variable that was -defined in that very scope. +ここで`Counter`は**2つ**のクロージャを返します。関数`increment`と同じく関数`get`です。これら両方の関数は`Counter`のスコープを**参照**し続けます。その為、そのスコープ内に定義されている`count`変数に対していつもアクセスできるようになっています。 ### Why Private Variables Work From ae603647c5a5e010ebfb3f6afedf5067d86d8196 Mon Sep 17 00:00:00 2001 From: HIRAKI Satoru Date: Sat, 13 Aug 2011 00:46:39 +0900 Subject: [PATCH 063/463] translate "Why Private Variables Work" in "Function" to ja --- doc/ja/function/closures.md | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/doc/ja/function/closures.md b/doc/ja/function/closures.md index 74d4327d..53b8f795 100644 --- a/doc/ja/function/closures.md +++ b/doc/ja/function/closures.md @@ -23,20 +23,16 @@ JavaScriptの一番パワフルな特徴の一つとして*クロージャ*が ここで`Counter`は**2つ**のクロージャを返します。関数`increment`と同じく関数`get`です。これら両方の関数は`Counter`のスコープを**参照**し続けます。その為、そのスコープ内に定義されている`count`変数に対していつもアクセスできるようになっています。 -### Why Private Variables Work +### なぜプライベート変数が動作するのか? -Since it is not possible to reference or assign scopes in JavaScript, there is -**no** way of accessing the variable `count` from the outside. The only way to -interact with it is via the two closures. +JavaScriptでは、スコープ自体を参照・代入する事が出来無い為に、外部から変数`count`にアクセスする手段が**ありません**。唯一の手段は、2つのクロージャを介してアクセスする方法だけです。 var foo = new Counter(4); foo.hack = function() { count = 1337; }; -The above code will **not** change the variable `count` in the scope of `Counter`, -since `foo.hack` was not defined in **that** scope. It will instead create - or -override - the *global* variable `count`. +上記のコードは`Counter`のスコープ中にある変数`count`の値を変更する事は**ありません**。`foo.hack`は**その**スコープで定義されていないからです。これは*グローバル*変数`count`の作成 -またはオーバーライド- の代わりになるでしょう。 ### Closures Inside Loops From 860f7c2b9cfda8710d5d8bc2bc75bb991043b535 Mon Sep 17 00:00:00 2001 From: HIRAKI Satoru Date: Sat, 13 Aug 2011 01:06:16 +0900 Subject: [PATCH 064/463] translate "Closures Inside Loops" in "Function" to ja --- doc/ja/function/closures.md | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/doc/ja/function/closures.md b/doc/ja/function/closures.md index 53b8f795..2ae7b2ff 100644 --- a/doc/ja/function/closures.md +++ b/doc/ja/function/closures.md @@ -34,26 +34,21 @@ JavaScriptでは、スコープ自体を参照・代入する事が出来無い 上記のコードは`Counter`のスコープ中にある変数`count`の値を変更する事は**ありません**。`foo.hack`は**その**スコープで定義されていないからです。これは*グローバル*変数`count`の作成 -またはオーバーライド- の代わりになるでしょう。 -### Closures Inside Loops +### ループ中のクロージャ -One often made mistake is to use closures inside of loops, as if they were -copying the value of the loops index variable. +一つ良くある間違いとして、ループのインデックス変数をコピーしようとしてか、ループの中でクロージャを使用してしまうというものがあります。 for(var i = 0; i < 10; i++) { setTimeout(function() { - console.log(i); + console.log(i); }, 1000); } -The above will **not** output the numbers `0` through `9`, but will simply print -the number `10` ten times. +上記の例では`0`から`9`の数値が出力される事は**ありません**。もっと簡単に`10`という数字が10回出力されるだけです。 -The *anonymous* function keeps a **reference** to `i` and at the time -`console.log` gets called, the `for loop` has already finished and the value of -`i` as been set to `10`. +**匿名**関数は`i`への**参照**を維持しており、同時に`forループ`は既に`i`の値に`10`をセットし終った`console.log`が呼ばれてしまいます。 -In order to get the desired behavior, it is necessary to create a **copy** of -the value of `i`. +期待した動作をする為には、`i`の値の**コピー**を作る必要があります。 ### Avoiding the Reference Problem From ce166853a58dcdd3bd67b53ef5f7cb7168bc75ac Mon Sep 17 00:00:00 2001 From: HIRAKI Satoru Date: Sat, 13 Aug 2011 01:34:36 +0900 Subject: [PATCH 065/463] translate "Avoiding the Reference Problem" in "Function" to ja --- doc/ja/function/closures.md | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/doc/ja/function/closures.md b/doc/ja/function/closures.md index 2ae7b2ff..618af73f 100644 --- a/doc/ja/function/closures.md +++ b/doc/ja/function/closures.md @@ -50,10 +50,9 @@ JavaScriptでは、スコープ自体を参照・代入する事が出来無い 期待した動作をする為には、`i`の値の**コピー**を作る必要があります。 -### Avoiding the Reference Problem +### 参照問題を回避するには -In order to copy the value of the loop's index variable, it is best to use an -[anonymous wrapper](#function.scopes). +ループのインデックス変数をコピーする為には、[匿名ラッパー](#function.scopes)を使うのがベストです。 for(var i = 0; i < 10; i++) { (function(e) { @@ -63,15 +62,11 @@ In order to copy the value of the loop's index variable, it is best to use an })(i); } -The anonymous outer function gets called immediately with `i` as its first -argument and will receive a copy of the **value** of `i` as its parameter `e`. +外部の匿名関数は`i`を即座に第一引数として呼び出し、引数`e`を`i`の**値**のコピーとして受け取ります。 -The anonymous function that gets passed to `setTimeout` now has a reference to -`e`, whose value does **not** get changed by the loop. +`e`を参照している`setTimeout`を受け取った匿名関数はループによって値が変わる事が**ありません**。 -There is another possible way of achieving this; that is to return a function -from the anonymous wrapper, that will then have the same behavior as the code -above. +他にこのような事を実現する方法があります。それは匿名ラッパーから関数を返してあげる事です。これは上記のコードと同じような効果があります。 for(var i = 0; i < 10; i++) { setTimeout((function(e) { From 35830832ff2b68570f8f754f1be46ccd689931d8 Mon Sep 17 00:00:00 2001 From: HIRAKI Satoru Date: Sat, 13 Aug 2011 03:26:04 +0900 Subject: [PATCH 066/463] translate "The arguments Object" in "Function" to ja --- doc/ja/function/arguments.md | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/doc/ja/function/arguments.md b/doc/ja/function/arguments.md index 3d551ad5..8276ab2e 100644 --- a/doc/ja/function/arguments.md +++ b/doc/ja/function/arguments.md @@ -1,20 +1,14 @@ -## The `arguments` Object +## オブジェクトの`arguments` -Every function scope in JavaScript can access the special variable `arguments`. -This variable holds a list of all the arguments that were passed to the function. +JavaScriptの全ての関数スコープは`arguments`と呼ばれる特別な変数にアクセスできます。この変数は関数が受け取った全ての引数を保持する変数です。 -> **Note:** In case `arguments` has already been defined inside the function's -> scope either via a `var` statement or being the name of a formal parameter, -> the `arguments` object will not be created. +> **注意:** `arguments`が既に`var`や正式なパラメーターにより +> 関数のスコープが定義されている場合は +> `arguments`オブジェクトは作られません。 -The `arguments` object is **not** an `Array`. While it has some of the -semantics of an array - namely the `length` property - it does not inherit from -`Array.prototype` and is in fact an `Object`. +`arguments`オブジェクトは`配列`では**ありません**。これは配列と同じような -`length`プロパティと名付けられています- 文法を持っていますが、`Array.prototype`を継承している訳では無いので、実際`Object`になります。 -Due to this, it is **not** possible to use standard array methods like `push`, -`pop` or `slice` on `arguments`. While iteration with a plain `for` loop works -just fine, it is necessary to convert it to a real `Array` in order to use the -standard `Array` methods on it. +この為、`arguments`で`push`や`pop`、`slice`といった通常の配列メソッドは使用する事が**出来ません**。プレーンな`for`ループのような繰り返しでは上手く動作しますが、通常の`Array`メソッドを使いたい場合は本当の`配列`に変換しなければなりません。 ### Converting to an Array From 0ddab9c6fb8063eb8c6e3f0db8c7915dc5406258 Mon Sep 17 00:00:00 2001 From: HIRAKI Satoru Date: Sat, 13 Aug 2011 03:26:45 +0900 Subject: [PATCH 067/463] fix representation --- doc/ja/function/arguments.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/ja/function/arguments.md b/doc/ja/function/arguments.md index 8276ab2e..29fc40cb 100644 --- a/doc/ja/function/arguments.md +++ b/doc/ja/function/arguments.md @@ -8,7 +8,7 @@ JavaScriptの全ての関数スコープは`arguments`と呼ばれる特別な `arguments`オブジェクトは`配列`では**ありません**。これは配列と同じような -`length`プロパティと名付けられています- 文法を持っていますが、`Array.prototype`を継承している訳では無いので、実際`Object`になります。 -この為、`arguments`で`push`や`pop`、`slice`といった通常の配列メソッドは使用する事が**出来ません**。プレーンな`for`ループのような繰り返しでは上手く動作しますが、通常の`Array`メソッドを使いたい場合は本当の`配列`に変換しなければなりません。 +この為、`arguments`で`push`や`pop`、`slice`といった通常の配列メソッドは使用する事が**出来ません**。プレーンな`for`ループのような繰り返しでは上手く動作しますが、通常の`配列`メソッドを使いたい場合は本当の`配列`に変換しなければなりません。 ### Converting to an Array From 926b46e9b9923548b19dc670478dbf5c574fc8d5 Mon Sep 17 00:00:00 2001 From: HIRAKI Satoru Date: Sat, 13 Aug 2011 03:40:50 +0900 Subject: [PATCH 068/463] translate "Converting to an Array" in "Function" to ja --- doc/ja/function/arguments.md | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/doc/ja/function/arguments.md b/doc/ja/function/arguments.md index 29fc40cb..da616095 100644 --- a/doc/ja/function/arguments.md +++ b/doc/ja/function/arguments.md @@ -10,15 +10,13 @@ JavaScriptの全ての関数スコープは`arguments`と呼ばれる特別な この為、`arguments`で`push`や`pop`、`slice`といった通常の配列メソッドは使用する事が**出来ません**。プレーンな`for`ループのような繰り返しでは上手く動作しますが、通常の`配列`メソッドを使いたい場合は本当の`配列`に変換しなければなりません。 -### Converting to an Array +### 配列への変換 -The code below will return a new `Array` containing all the elements of the -`arguments` object. +下のコードは`arguments`オブジェクトの全ての要素を含んだ新しい`配列`を返します。 Array.prototype.slice.call(arguments); -This conversion is **slow**, it is **not recommended** to use it in performance -critical sections of code. +この変換は**遅い**です。コードのパフォーマンスに関わる重要な部分での使用は**推奨しません**。 ### Passing Arguments From 3c8b234dab404a61af01e2a62233ac71843df799 Mon Sep 17 00:00:00 2001 From: HIRAKI Satoru Date: Sun, 14 Aug 2011 00:34:58 +0900 Subject: [PATCH 069/463] translate "Passing Arguments" in "Function" to ja --- doc/ja/function/arguments.md | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/doc/ja/function/arguments.md b/doc/ja/function/arguments.md index da616095..c5ceca67 100644 --- a/doc/ja/function/arguments.md +++ b/doc/ja/function/arguments.md @@ -18,10 +18,9 @@ JavaScriptの全ての関数スコープは`arguments`と呼ばれる特別な この変換は**遅い**です。コードのパフォーマンスに関わる重要な部分での使用は**推奨しません**。 -### Passing Arguments +### 引き数の受け渡し -The following is the recommended way of passing arguments from one function to -another. +下記の例はある関数から別の関数に引数を引き渡す際に推奨される方法です。 function foo() { bar.apply(null, arguments); @@ -30,8 +29,7 @@ another. // do stuff here } -Another trick is to use both `call` and `apply` together to create fast, unbound -wrappers. +他の技法として、高速で非結合のラッパーとし`call`と`apply`両方を一緒に使用するという物があります。 function Foo() {} @@ -39,11 +37,11 @@ wrappers. console.log(this, a, b, c); }; - // Create an unbound version of "method" - // It takes the parameters: this, arg1, arg2...argN + // "メソッド"の非結合バージョンを作成する + // このメソッドはthis, arg1, arg2...argNのパラメーターを持っている Foo.method = function() { - // Result: Foo.prototype.method.call(this, arg1, arg2... argN) + // 結果: Foo.prototype.method.call(this, arg1, arg2... argN) Function.call.apply(Foo.prototype.method, arguments); }; From 6d72a9e9ca55446dbd7f07f1c274bb005d67b34c Mon Sep 17 00:00:00 2001 From: HIRAKI Satoru Date: Sun, 14 Aug 2011 17:36:38 +0900 Subject: [PATCH 070/463] fix representation --- doc/ja/function/arguments.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/ja/function/arguments.md b/doc/ja/function/arguments.md index c5ceca67..c03d98f8 100644 --- a/doc/ja/function/arguments.md +++ b/doc/ja/function/arguments.md @@ -29,7 +29,7 @@ JavaScriptの全ての関数スコープは`arguments`と呼ばれる特別な // do stuff here } -他の技法として、高速で非結合のラッパーとし`call`と`apply`両方を一緒に使用するという物があります。 +他のテクニックとして、高速で非結合のラッパーとして`call`と`apply`両方を一緒に使用するという物があります。 function Foo() {} From c4255294f66352b55b5157dd39dac2368e6022a7 Mon Sep 17 00:00:00 2001 From: HIRAKI Satoru Date: Sun, 14 Aug 2011 17:56:51 +0900 Subject: [PATCH 071/463] translate "Formal Parameters and Arguments Indices" in "Function" to ja --- doc/ja/function/arguments.md | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/doc/ja/function/arguments.md b/doc/ja/function/arguments.md index c03d98f8..b449226b 100644 --- a/doc/ja/function/arguments.md +++ b/doc/ja/function/arguments.md @@ -46,17 +46,15 @@ JavaScriptの全ての関数スコープは`arguments`と呼ばれる特別な }; -### Formal Parameters and Arguments Indices +### 仮パラメーターと引数のインデックス -The `arguments` object creates *getter* and *setter* functions for both its -properties as well as the function's formal parameters. +`arguments`オブジェクトは*ゲッター*と*セッター*機能を自身のプロパティと同様に関数の仮パラメーターとして作成します。 -As a result, changing the value of a formal parameter will also change the value -of the corresponding property on the `arguments` object, and the other way around. +結果として、仮パラメーターを変更すると`arguments`の対応する値も変更されますし、逆もしかりです。 function foo(a, b, c) { arguments[0] = 2; - a; // 2 + a; // 2 b = 4; arguments[1]; // 4 From a17a0040cbbd7b6ce19e81e2fafbda105b5caf18 Mon Sep 17 00:00:00 2001 From: HIRAKI Satoru Date: Sun, 14 Aug 2011 18:00:42 +0900 Subject: [PATCH 072/463] fix orthographical variants --- doc/ja/function/arguments.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/ja/function/arguments.md b/doc/ja/function/arguments.md index b449226b..d4ab5faf 100644 --- a/doc/ja/function/arguments.md +++ b/doc/ja/function/arguments.md @@ -6,13 +6,13 @@ JavaScriptの全ての関数スコープは`arguments`と呼ばれる特別な > 関数のスコープが定義されている場合は > `arguments`オブジェクトは作られません。 -`arguments`オブジェクトは`配列`では**ありません**。これは配列と同じような -`length`プロパティと名付けられています- 文法を持っていますが、`Array.prototype`を継承している訳では無いので、実際`Object`になります。 +`arguments`オブジェクトは`Array`では**ありません**。これは配列と同じような -`length`プロパティと名付けられています- 文法を持っていますが、`Array.prototype`を継承している訳では無いので、実際`Object`になります。 -この為、`arguments`で`push`や`pop`、`slice`といった通常の配列メソッドは使用する事が**出来ません**。プレーンな`for`ループのような繰り返しでは上手く動作しますが、通常の`配列`メソッドを使いたい場合は本当の`配列`に変換しなければなりません。 +この為、`arguments`で`push`や`pop`、`slice`といった通常の配列メソッドは使用する事が**出来ません**。プレーンな`for`ループのような繰り返しでは上手く動作しますが、通常の`Array`メソッドを使いたい場合は本当の`Array`に変換しなければなりません。 ### 配列への変換 -下のコードは`arguments`オブジェクトの全ての要素を含んだ新しい`配列`を返します。 +下のコードは`arguments`オブジェクトの全ての要素を含んだ新しい`Array`を返します。 Array.prototype.slice.call(arguments); From a8fa0662d4a0dd64222930d057059750fca53e2e Mon Sep 17 00:00:00 2001 From: HIRAKI Satoru Date: Sun, 14 Aug 2011 23:23:58 +0900 Subject: [PATCH 073/463] translate "Performance Myths and Truths" in "Function" to ja --- doc/ja/function/arguments.md | 33 ++++++++++++--------------------- 1 file changed, 12 insertions(+), 21 deletions(-) diff --git a/doc/ja/function/arguments.md b/doc/ja/function/arguments.md index d4ab5faf..e1738aaf 100644 --- a/doc/ja/function/arguments.md +++ b/doc/ja/function/arguments.md @@ -65,42 +65,33 @@ JavaScriptの全ての関数スコープは`arguments`と呼ばれる特別な } foo(1, 2, 3); -### Performance Myths and Truths +### パフォーマンスの神話と真実 -The `arguments` object is always created with the only two exceptions being the -cases where it is declared as a name inside of a function or one of its formal -parameters. It does not matter whether it is used or not. +`arguments`オブジェクトは、関数の内部の名前宣言と仮パラメーターという2つの例外を常に持ちながら生成されます。これは、使用されているかどうかは関係がありません。 -Both *getters* and *setters* are **always** created; thus, using it has nearly -no performance impact at all, especially not in real world code where there is -more than a simple access to the `arguments` object's properties. +*ゲッター*と*セッター*は両方とも**常に**生成されます。その為これを使用してもパフォーマンスに影響は全くといって言い程ありません。`arguments`オブジェクトのパラメーターに単純にアクセスしているような、実際のコードであれば尚更です。 -> **ES5 Note:** These *getters* and *setters* are not created in strict mode. +> **ES5での注意:** strictモードでは、これら*ゲッター*と*セッター*は生成されません。 -However, there is one case which will drastically reduce the performance in -modern JavaScript engines. That case is the use of `arguments.callee`. +しかし、一つだけモダンJavaScriptエンジンにおいて劇的にパフォーマンスが低下するケースがあります。そのケースとは`arguments.callee`を使用した場合です。 function foo() { - arguments.callee; // do something with this function object - arguments.callee.caller; // and the calling function object + arguments.callee; // この関数オブジェクトで何かする + arguments.callee.caller; // そして関数オブジェクトを呼び出す } function bigLoop() { for(var i = 0; i < 100000; i++) { - foo(); // Would normally be inlined... + foo(); // 通常はインライン展開する } } -In the above code, `foo` can no longer be a subject to [inlining][1] since it -needs to know about both itself and its caller. This not only defeats possible -performance gains that would arise from inlining, it also breaks encapsulation -since the function may now be dependent on a specific calling context. +上記のコードでは、`foo`は自身と自身の呼び出し元の両方を知らないと[インライン展開][1]の対象になる事が出来ません。この事は、インライン展開によるパフォーマンスの向上の機会を失くす事になり、また、特定のコンテクストの呼び出しに依存する関数のせいで、カプセル化が解除されてしまいます。 -It is **highly recommended** to **never** make use of `arguments.callee` or any of -its properties. +この為に`arguments.callee`を使用または、そのプロパティを**決して**使用しない事を**強く推奨**します。 -> **ES5 Note:** In strict mode, `arguments.callee` will throw a `TypeError` since -> its use has been deprecated. +> **ES5での注意:** strictモードでは、`arguments.callee`は推奨されていない為に +> `Typeerror`が返るようになっています。 [1]: http://en.wikipedia.org/wiki/Inlining From 710bdfa5e767be74a4c0d9d1051f25b4baa58a1d Mon Sep 17 00:00:00 2001 From: HIRAKI Satoru Date: Tue, 16 Aug 2011 21:23:43 +0900 Subject: [PATCH 074/463] translate "Constructors" in "Function" to ja --- doc/ja/function/constructors.md | 33 ++++++++++++--------------------- 1 file changed, 12 insertions(+), 21 deletions(-) diff --git a/doc/ja/function/constructors.md b/doc/ja/function/constructors.md index ad90b028..7d5b0770 100644 --- a/doc/ja/function/constructors.md +++ b/doc/ja/function/constructors.md @@ -1,15 +1,10 @@ -## Constructors +## コンストラクタ -Constructors in JavaScript are yet again different from many other languages. Any -function call that is preceded by the `new` keyword acts as a constructor. +JavaScriptのコンストラクタは色々ある他のプログラム言語とは一味違います。`new`キーワードが付いているどんな関数呼び出しも、コンストラクタとして機能します。 -Inside the constructor - the called function - the value of `this` refers to a -newly created `Object`. The [`prototype`](#object.prototype) of this **new** -object is set to the `prototype` of the function object that was invoked as the -constructor. +コンストラクタ内部では -呼び出された関数の事です- `this`の値は新規に生成された`Object`を参照しています。この**新規**のオブジェクトの[`prototype`](#object.prototype)は、コンストラクタとして起動した関数オブジェクトの`prototype`として設定されています。 -If the function that was called has no explicit `return` statement, then it -implicitly returns the value of `this` - the new object. +もし呼び出された関数が、`return`ステートメントを明示していない場合は、暗黙の了解で`this`の値を -新規のオブジェクトとして- 返します。 function Foo() { this.bla = 1; @@ -21,16 +16,14 @@ implicitly returns the value of `this` - the new object. var test = new Foo(); -The above calls `Foo` as constructor and sets the `prototype` of the newly -created object to `Foo.prototype`. +上記で`Foo`はコンストラクタとして呼び出され、`Foo.prototype`として新規に生成された`prototype`を設定されています。 -In case of an explicit `return` statement the function returns the value -specified that statement, **but only** if the return value is an `Object`. +明示的に`return`ステートメントがある場合、`Object`の値を返す**だけでなく**関数はこのステートメントを返します。 function Bar() { return 2; } - new Bar(); // a new object + new Bar(); // 新しいオブジェクト function Test() { this.value = 2; @@ -39,18 +32,16 @@ specified that statement, **but only** if the return value is an `Object`. foo: 1 }; } - new Test(); // the returned object + new Test(); // 返ってきたオブジェクト -When the `new` keyword is omitted, the function will **not** return a new object. +`new`キーワードが省略されている場合は、関数は新しいオブジェクトを返す事は**ありません**。 function Foo() { - this.bla = 1; // gets set on the global object + this.bla = 1; // グローバルオブジェクトに設定される } - Foo(); // undefined + Foo(); // undefinedが返る -While the above example might still appear to work in some cases, due to the -workings of [`this`](#function.this) in JavaScript, it will use the -*global object* as the value of `this`. +上記の例では、いくつかのケースでは動作するように見える場合があります。JavaScriptの[`this`](#function.this)の働きのせいで、*グローバルオブジェクト*が`this`の値として使用されるからです。 ### Factories From 7c37e0612984782867bc4f4f6ec9bb736a7e2a66 Mon Sep 17 00:00:00 2001 From: HIRAKI Satoru Date: Fri, 19 Aug 2011 00:25:20 +0900 Subject: [PATCH 075/463] taranslate "Factories" in "Function" to ja --- doc/ja/function/constructors.md | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/doc/ja/function/constructors.md b/doc/ja/function/constructors.md index 7d5b0770..f6f8b11a 100644 --- a/doc/ja/function/constructors.md +++ b/doc/ja/function/constructors.md @@ -43,10 +43,9 @@ JavaScriptのコンストラクタは色々ある他のプログラム言語と 上記の例では、いくつかのケースでは動作するように見える場合があります。JavaScriptの[`this`](#function.this)の働きのせいで、*グローバルオブジェクト*が`this`の値として使用されるからです。 -### Factories +### ファクトリー -In order to be able to omit the `new` keyword, the constructor function has to -explicitly return a value. +`new`キーワードを省略するためには、コンストラクタ関数が明示的に値を返す必要があります。 function Bar() { var value = 1; @@ -63,16 +62,11 @@ explicitly return a value. new Bar(); Bar(); -Both calls to `Bar` return the exact same thing, a newly create object which -has a property called `method` on it, that is a -[Closure](#function.closures). +`Bar`で呼び出されたものは両方とも全く同じものものになります。これには、`method`と呼ばれるプロパティを持ったオブジェクトが新しく生成されますが、これは[クロージャ](#function.closures)です。 -It is also to note that the call `new Bar()` does **not** affect the prototype -of the returned object. While the prototype will be set on the newly created -object, `Bar` never returns that new object. +また、注意する点として呼び出された`new Bar()`は返ってきたオブジェクトのプロトタイプに影響**しません**。プロトタイプが新しく生成されたオブジェクトにセットされるまで、`Bar`は絶対に新しいオブジェクトを返さないのです。 -In the above example, there is no functional difference between using and -not using the `new` keyword. +上記の例では、`new`キーワードの使用の有無は機能的に違いがありません。 ### Creating New Objects via Factories From 8c1cb005e830270dea7814eb640a5f0b3d93e1dd Mon Sep 17 00:00:00 2001 From: HIRAKI Satoru Date: Fri, 19 Aug 2011 00:26:30 +0900 Subject: [PATCH 076/463] translate "Creating New Objects via Factories" in "Function" to ja --- doc/ja/function/constructors.md | 21 +++++++-------------- 1 file changed, 7 insertions(+), 14 deletions(-) diff --git a/doc/ja/function/constructors.md b/doc/ja/function/constructors.md index f6f8b11a..fe6aec5a 100644 --- a/doc/ja/function/constructors.md +++ b/doc/ja/function/constructors.md @@ -69,13 +69,11 @@ JavaScriptのコンストラクタは色々ある他のプログラム言語と 上記の例では、`new`キーワードの使用の有無は機能的に違いがありません。 -### Creating New Objects via Factories +### ファクトリーとして新しくオブジェクトを作成する -An often made recommendation is to **not** use `new` since forgetting its use -may lead to bugs. +大半の場合に推奨されるのは、`new`はバグを引き起こしやすいので使用**しない**事です。 -In order to create new object, one should rather use a factory and construct a -new object inside of that factory. +新しいオブジェクトを作成するためにファクトリーを使用するか、そのファクトリー内部に新しいオブジェクトを構築する必要があります。 function Foo() { var obj = {}; @@ -92,16 +90,11 @@ new object inside of that factory. return obj; } -While the above is robust against a missing `new` keyword and certainly makes -the use of [private variables](#function.closures) easier, it comes with some -downsides. +上記の例では`new`キーワードが無いため堅牢になりますし、確実に[プライベート変数](#function.closures)を使用するのが簡単になりますが、いくつかの欠点があります。 - 1. It uses more memory since the created objects do **not** share the methods - on a prototype. - 2. In order to inherit the factory needs to copy all the methods from another - object or put that object on the prototype of the new object. - 3. Dropping the prototype chain just because of a left out `new` keyword - somehow goes against the spirit of the language. + 1. 作られたオブジェクトがプロトタイプ上のメソッドを共有しないために、よりメモリーを消費してしまいます。 + 2. ファクトリーを継承するために、他のオブジェクトの全てのメソッドをコピーする必要があるか、新しいオブジェクトのプロトタイプ上にそのオブジェクトを設置する必要があります。 + 3. `new`キーワードが無いという理由だけで、プロトタイプチェーンから外れてしまうのは、どことなく言語の精神に反します。 ### In Conclusion From cee47403b14d0427dfa5ba3d3d37e114134832eb Mon Sep 17 00:00:00 2001 From: HIRAKI Satoru Date: Fri, 19 Aug 2011 00:37:08 +0900 Subject: [PATCH 077/463] translate "In Conclusion" in "Function" to ja --- doc/ja/function/constructors.md | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/doc/ja/function/constructors.md b/doc/ja/function/constructors.md index fe6aec5a..f4ec1fab 100644 --- a/doc/ja/function/constructors.md +++ b/doc/ja/function/constructors.md @@ -96,11 +96,8 @@ JavaScriptのコンストラクタは色々ある他のプログラム言語と 2. ファクトリーを継承するために、他のオブジェクトの全てのメソッドをコピーする必要があるか、新しいオブジェクトのプロトタイプ上にそのオブジェクトを設置する必要があります。 3. `new`キーワードが無いという理由だけで、プロトタイプチェーンから外れてしまうのは、どことなく言語の精神に反します。 -### In Conclusion +### 終わりに + +`new`キーワードが省略される事により、バグの可能性がもたらされます。それは確かにプロトタイプを使わない理由には**なりません**。最終的には、アプリケーションの必要性により、どちらの解決法がより良いかが決まってきます。特に大切なのは、オブジェクトの作成に特定のスタイルを選ぶ事、また**そのスタイルに固執する事**です。 -While omitting the `new` keyword might lead to bugs, it is certainly **not** a -reason to drop the use of prototypes altogether. In the end it comes down to -which solution is better suited for the needs of the application, it is -especially important to choose a specific style of object creation **and stick** -with it. From 052a084d014410f6a1f8e4fcca84519a92cf60be Mon Sep 17 00:00:00 2001 From: HIRAKI Satoru Date: Fri, 19 Aug 2011 00:39:02 +0900 Subject: [PATCH 078/463] fix tarnslattion --- doc/ja/function/constructors.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/ja/function/constructors.md b/doc/ja/function/constructors.md index f4ec1fab..df7fc281 100644 --- a/doc/ja/function/constructors.md +++ b/doc/ja/function/constructors.md @@ -71,7 +71,7 @@ JavaScriptのコンストラクタは色々ある他のプログラム言語と ### ファクトリーとして新しくオブジェクトを作成する -大半の場合に推奨されるのは、`new`はバグを引き起こしやすいので使用**しない**事です。 +大半の場合に推奨されるのは、`new`の付け忘れによるバグを引き起こしやすいので使用**しない**事です。 新しいオブジェクトを作成するためにファクトリーを使用するか、そのファクトリー内部に新しいオブジェクトを構築する必要があります。 From 6893bc689d4409f30dfccd7c3570c218d08f5741 Mon Sep 17 00:00:00 2001 From: HIRAKI Satoru Date: Fri, 19 Aug 2011 00:43:10 +0900 Subject: [PATCH 079/463] fix representation --- doc/ja/function/constructors.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/ja/function/constructors.md b/doc/ja/function/constructors.md index df7fc281..99290411 100644 --- a/doc/ja/function/constructors.md +++ b/doc/ja/function/constructors.md @@ -98,6 +98,6 @@ JavaScriptのコンストラクタは色々ある他のプログラム言語と ### 終わりに -`new`キーワードが省略される事により、バグの可能性がもたらされます。それは確かにプロトタイプを使わない理由には**なりません**。最終的には、アプリケーションの必要性により、どちらの解決法がより良いかが決まってきます。特に大切なのは、オブジェクトの作成に特定のスタイルを選ぶ事、また**そのスタイルに固執する事**です。 +`new`キーワードが省略される事により、バグの可能性がもたらされますがプロトタイプを使わない確実な理由には**なりません**。最終的には、アプリケーションの必要性により、どちらの解決法がより良いかが決まってきます。特に大切なのは、オブジェクトの作成に特定のスタイルを選ぶ事、また**そのスタイルに固執する事**です。 From 682252a68a6e4063b5bd307bd2038787d014aeef Mon Sep 17 00:00:00 2001 From: HIRAKI Satoru Date: Tue, 23 Aug 2011 02:14:10 +0900 Subject: [PATCH 080/463] translate "Scopes and Namespaces" in "Function" to ja --- doc/ja/function/scopes.md | 26 ++++++++++---------------- 1 file changed, 10 insertions(+), 16 deletions(-) diff --git a/doc/ja/function/scopes.md b/doc/ja/function/scopes.md index 7ae5e4f5..58db046f 100644 --- a/doc/ja/function/scopes.md +++ b/doc/ja/function/scopes.md @@ -1,27 +1,21 @@ -## Scopes and Namespaces +## スコープと名前空間 -Although JavaScript deals fine with the syntax of two matching curly -braces for blocks, it does **not** support block scope; hence, all that is left -is in the language is *function scope*. +JavaScriptはブロックに2つのペアの中括弧を使うのが素晴しいですが、これはブロックスコープをサポートして**いません**。その為、この言語に残されているのは*関数スコープ*だけです。 - function test() { // a scope - for(var i = 0; i < 10; i++) { // not a scope - // count + function test() { // スコープ + for(var i = 0; i < 10; i++) { // スコープではない + // 数える } console.log(i); // 10 } -> **Note:** When not used in an assignment, return statement or as a function -> argument, the `{...}` notation will get interpreted as a block statement and -> **not** as an object literal. This, in conjunction with -> [automatic insertion of semicolons](#core.semicolon), can lead to subtle errors. +> **注意:** 代入が使用されてない時、return文や関数の引数、`{...}`表記はブロック文として +> 解釈されて、オブジェクトリテラルトは**なりません**。これは[セミコロン自動挿入](#core.semicolon) +> と連動して奇妙なエラーを引き起こすことになります。 -There are also no distinct namespaces in JavaScript, that means that everything -gets defined in one *globally shared* namespace. +JavaScriptはまた明確な名前空間を持ちません。この事は全て一つの*グローバルで共有された*名前空間で定義されるという事です。 -Each time a variable is referenced, JavaScript will traverse upwards through all -the scopes until it finds it. In the case that it reaches the global scope and -still has not found the requested name, it will raise a `ReferenceError`. +変数が参照されるまでの間、JavaScriptはスコープ全てを遡って参照を探索します。グローバルスコープまで遡っても要求した名前が無いと`ReferenceError`が発生します。 ### The Bane of Global Variables From 576287975aba77af32feaf6539970c191fae84cb Mon Sep 17 00:00:00 2001 From: HIRAKI Satoru Date: Sat, 27 Aug 2011 19:09:09 +0900 Subject: [PATCH 081/463] translate "The Bane of Global Variables" in "Function" to ja --- doc/ja/function/scopes.md | 41 +++++++++++++++------------------------ 1 file changed, 16 insertions(+), 25 deletions(-) diff --git a/doc/ja/function/scopes.md b/doc/ja/function/scopes.md index 58db046f..7ec1c7c9 100644 --- a/doc/ja/function/scopes.md +++ b/doc/ja/function/scopes.md @@ -17,52 +17,43 @@ JavaScriptはまた明確な名前空間を持ちません。この事は全て 変数が参照されるまでの間、JavaScriptはスコープ全てを遡って参照を探索します。グローバルスコープまで遡っても要求した名前が無いと`ReferenceError`が発生します。 -### The Bane of Global Variables +### グローバル変数の致命傷 - // script A + // スクリプト A foo = '42'; - // script B + // スクリプト B var foo = '42' -The above two scripts do **not** have the same effect. Script A defines a -variable called `foo` in the *global* scope and script B defines a `foo` in the -*current* scope. +上記の2つのスクリプトは同じ効果を持って**いません**。スクリプト Aは`foo`と呼ばれる変数を、*グローバル*スコープに定義しており、スクリプト Bは`foo`を*現在*のスコープで定義ています。 -Again, that is **not** at all the *same effect*, not using `var` can have major -implications. +再び、`var`が重大な影響を持っていない、*同じ効果*では**無い**スクリプトになります。 - // global scope + // グローバルスコープ var foo = 42; function test() { - // local scope + // ローカルスコープ foo = 21; } test(); foo; // 21 -Leaving out the `var` statement inside the function `test` will override the -value of `foo`. While this might not seem like a big deal at first, having -thousands of lines of JavaScript and not using `var` will introduce horrible and -hard to track down bugs. - - // global scope - var items = [/* some list */]; +`test`関数の中の`var`ステートメントを省略すると`foo`の値をオーバーライドします。最初の内は大した事ではないように思いますが、JavaScriptが何千行規模になると、`var`を使っていない事で恐怖とバグの追跡の困難さを招くことになります。 + + // グローバルスコープ + var items = [/* 同じリスト */]; for(var i = 0; i < 10; i++) { subLoop(); } function subLoop() { - // scope of subLoop - for(i = 0; i < 10; i++) { // missing var statement - // do amazing stuff! + // サブループのスコープ + for(i = 0; i < 10; i++) { // varステートメントが無くなった + // 素敵な実装を! } } - -The outer loop will terminate after the first call to `subLoop`, since `subLoop` -overwrites the global value of `i`. Using a `var` for the second `for` loop would -have easily avoided this error. The `var` statement should **never** be left out -unless the *desired effect* is to affect the outer scope. + +外側のループは`subloop`が最初に呼ばれた後に終了します。なぜなら、`subloop`がグローバル変数`i`の値で上書きされているからです。2番目の`for`ループに`var`を使用する事によって簡単にこのエラーを回避する事ができます。`var`ステートメントは*希望する影響*を外側のスコープに与える場合を除いては、**絶対**に残してはいけません。 ### Local Variables From a384f44cc1ebd01f00c89e0e8380172c377d08d2 Mon Sep 17 00:00:00 2001 From: HIRAKI Satoru Date: Sat, 27 Aug 2011 19:23:38 +0900 Subject: [PATCH 082/463] translate "Local Variables" in "Function" to ja --- doc/ja/function/scopes.md | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/doc/ja/function/scopes.md b/doc/ja/function/scopes.md index 7ec1c7c9..88d27066 100644 --- a/doc/ja/function/scopes.md +++ b/doc/ja/function/scopes.md @@ -55,19 +55,17 @@ JavaScriptはまた明確な名前空間を持ちません。この事は全て 外側のループは`subloop`が最初に呼ばれた後に終了します。なぜなら、`subloop`がグローバル変数`i`の値で上書きされているからです。2番目の`for`ループに`var`を使用する事によって簡単にこのエラーを回避する事ができます。`var`ステートメントは*希望する影響*を外側のスコープに与える場合を除いては、**絶対**に残してはいけません。 -### Local Variables +### ローカル変数 -The only source for local variables in JavaScript are -[function](#function.general) parameters and variables that were declared via the -`var` statement. +JavaScriptのローカル変数の為の唯一のソースは[function](#function.general)パラメーターと`var`ステートメントを宣言された変数になります。 - // global scope + // グローバルスコープ var foo = 1; var bar = 2; var i = 2; function test(i) { - // local scope of the function test + // 関数testのローカル変数 i = 5; var foo = 3; @@ -75,8 +73,7 @@ The only source for local variables in JavaScript are } test(10); -While `foo` and `i` are local variables inside the scope of the function `test`, -the assignment of `bar` will override the global variable with the same name. +`foo`と`i`は、関数`test`のスコープ内のローカル変数ですが、`bar`の割り当ては同じ名前のグローバル変数で上書きされてしまいます。 ### Hoisting From eaa6773ddf9f3f477683149c6a2606cdcf237d81 Mon Sep 17 00:00:00 2001 From: HIRAKI Satoru Date: Sun, 28 Aug 2011 01:05:18 +0900 Subject: [PATCH 083/463] translate "Hoisting" in "Function" to ja --- doc/ja/function/scopes.md | 41 +++++++++++++++------------------------ 1 file changed, 16 insertions(+), 25 deletions(-) diff --git a/doc/ja/function/scopes.md b/doc/ja/function/scopes.md index 88d27066..016e6599 100644 --- a/doc/ja/function/scopes.md +++ b/doc/ja/function/scopes.md @@ -75,10 +75,9 @@ JavaScriptのローカル変数の為の唯一のソースは[function](#functio `foo`と`i`は、関数`test`のスコープ内のローカル変数ですが、`bar`の割り当ては同じ名前のグローバル変数で上書きされてしまいます。 -### Hoisting +### 巻き上げ -JavaScript **hoists** declarations. This means that both `var` statements and -`function` declarations will be moved to the top of their enclosing scope. +JavaScriptの**巻き上げ**宣言。この言葉の意味は`var`ステートメントと`function`宣言が、それらの外側のスコープに移動するというものです。 bar(); var bar = function() {}; @@ -97,16 +96,14 @@ JavaScript **hoists** declarations. This means that both `var` statements and } } -The above code gets transformed before any execution is started. JavaScript moves -the `var` statements as well as the `function` declarations to the top of the -nearest surrounding scope. +上記のコードは何も実行されないうちに変換されてしまいます。JavaScriptは`var`ステートメントと同じように、直近で囲んでいる`function`宣言を先頭に移動させます。 - // var statements got moved here - var bar, someValue; // default to 'undefined' + // varステートメントはここに移動する + var bar, someValue; // 'undefined'がデフォルト - // the function declartion got moved up too + // function宣言もここに移動する function test(data) { - var goo, i, e; // missing block scope moves these here + var goo, i, e; // 無くなったブロックスコープはこちらに移動する if (false) { goo = 1; @@ -118,36 +115,30 @@ nearest surrounding scope. } } - bar(); // fails with a TypeError since bar is still 'undefined' - someValue = 42; // assignments are not affected by hoisting + bar(); // barが'undefined'のままなので、Typeerrorで呼び出し失敗 + someValue = 42; // 割り当てすると巻き上げの影響を受けない bar = function() {}; test(); -Missing block scoping will not only move `var` statements out of loops and -their bodies, it will also make the results of certain `if` constructs -non-intuitive. +ブロックスコープの欠落はループ外の`var`ステートメントの移動だけでなく、その本体も移動させます。これはまた`if`が直感的じゃない結果になってしまいます。 -In the original code the `if` statement seemed to modify the *global -variable* `goo`, while actually it modifies the *local variable* - after hoisting -has been applied. +元のコードの中の`if`ステートメントは*グローバル変数*である`goo`も変更しているように見えますが、実際には -巻き上げが適用された後に- *ローカル変数*を変更しています。 -Without the knowledge about *hoisting*, below code might seem to raise a -`ReferenceError`. +*巻き上げ*についての知識がないと、下に挙げたコードは`ReferenceError`になるように見えます。 - // check whether SomeImportantThing has been initiliazed + // SomeImportantThingが初期化されているかチェックする if (!SomeImportantThing) { var SomeImportantThing = {}; } -But of course, the above works due to the fact that the `var` statement is being -moved to the top of the *global scope*. +しかし、勿論上記の動きは`val`ステートメントが*グローバルスコープ*の上に移動しているという事実に基づいています。 var SomeImportantThing; - // other code might initiliaze SomeImportantThing here, or not + // 他のコードがSomeImportantThingをここで初期化するかもしれないし、しないかもしれない - // make sure it's there + // SomeImportantThingがある事を確認してください if (!SomeImportantThing) { SomeImportantThing = {}; } From 8c4ecc09d29b0edf92309284e49e12406f9cb086 Mon Sep 17 00:00:00 2001 From: HIRAKI Satoru Date: Sun, 28 Aug 2011 01:16:54 +0900 Subject: [PATCH 084/463] translate "Name Resolution Order" in "Function" to ja --- doc/ja/function/scopes.md | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/doc/ja/function/scopes.md b/doc/ja/function/scopes.md index 016e6599..11537d74 100644 --- a/doc/ja/function/scopes.md +++ b/doc/ja/function/scopes.md @@ -143,24 +143,22 @@ JavaScriptの**巻き上げ**宣言。この言葉の意味は`var`ステート SomeImportantThing = {}; } -### Name Resolution Order +### 名前解決の順序 -All scopes in JavaScript, including the *global scope*, have the special name -[`this`](#function.this) defined in them, which refers to the *current object*. +JavaScriptの*グローバルスコープ*を含む、全てのスコープは、*現在のオブジェクト*を参照している特殊な名前[`this`](#function.this)を持っています。 -Function scopes also have the name [`arguments`](#function.arguments) defined in -them which contains the arguments that were passed to a function. +関数スコープはまた、関数を通過してきた引数を含んでいる[`arguments`](#function.arguments)という名前も持っています。 -For example, when trying to access a variable named `foo` inside the scope of a -function, JavaScript will lookup the name in the following order: +例として、関数の中で`foo`と命名された変数にアクセスしようとする場合を考えましょう。JavaScriptは以下の順番で、その名前を探索しようとします。 - 1. In case there is a `var foo` statement in the current scope use that. - 2. If one of the function parameters is named `foo` use that. - 3. If the function itself is called `foo` use that. - 4. Go to the next outer scope and start with **#1** again. + 1. `var foo`ステートメントが現在のスコープで使われている場合 + 2. `foo`という名前の関数パラメーターが存在するかどうか + 3. 関数それ自体が`foo`として呼ばれているかどうか + 4. 一つ外のスコープに行き、再度**#1**から始める + +> **注意:** `arguments`と呼ばれるパラメーターを持つという事は、デフォルトの`arguments` +> オブジェクトを生成するのを**阻害**します。 -> **Note:** Having a parameter called `arguments` will **prevent** the creation -> of the default `arguments` object. ### Namespaces From 42a9244aa4ffee12e39c62c2a138580aa180e21d Mon Sep 17 00:00:00 2001 From: HIRAKI Satoru Date: Sun, 28 Aug 2011 01:32:12 +0900 Subject: [PATCH 085/463] translate "Namespaces" in "Function" to ja --- doc/ja/function/scopes.md | 28 ++++++++++++---------------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/doc/ja/function/scopes.md b/doc/ja/function/scopes.md index 11537d74..28c153f0 100644 --- a/doc/ja/function/scopes.md +++ b/doc/ja/function/scopes.md @@ -160,34 +160,30 @@ JavaScriptの*グローバルスコープ*を含む、全てのスコープは > オブジェクトを生成するのを**阻害**します。 -### Namespaces +### 名前空間 -A common problem of having only one global namespace is the likeliness of running -into problems where variable names clash. In JavaScript, this problem can -easily be avoided with the help of *anonymous wrappers*. +一つしかグローバルの名前空間を持たない事による良くある問題は変数名の衝突による問題の起きる可能性です。JavaScriptでは、この問題を*匿名関数ラッパー*の助けで簡単に回避できます。 (function() { - // a self contained "namespace" - + // "名前空間"に自分を含む + window.foo = function() { - // an exposed closure + // 露出したクロージャ }; - })(); // execute the function immediately + })(); // 即座に関数を実行する -Unnamed functions are considered [expressions](#function.general); so in order to -being callable, they must first be evaluated. +無名関数は[expressions](#function.general)とみなされ、呼び出し可能になり最初に評価されます。 - ( // evaluate the function inside the paranthesis + ( // カッコ内の関数が評価される function() {} - ) // and return the function object - () // call the result of the evaluation + ) // 関数オブジェクトが返される + () // 評価の結果が呼び出される -There are other ways for evaluating and calling the function expression; which, -while different in syntax, do behave the exact same way. +関数式を評価し、呼び出す別の方法として構文は違いますが、同様の動作をするのが下記です。 - // Two other ways + // 2つの別の方法 +function(){}(); (function(){}()); From 411af79c279dae5f724e724f882d6b81d54f844c Mon Sep 17 00:00:00 2001 From: HIRAKI Satoru Date: Sun, 28 Aug 2011 01:37:18 +0900 Subject: [PATCH 086/463] translate "In Conclusion" in "Function" to ja --- doc/ja/function/scopes.md | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/doc/ja/function/scopes.md b/doc/ja/function/scopes.md index 28c153f0..451140f3 100644 --- a/doc/ja/function/scopes.md +++ b/doc/ja/function/scopes.md @@ -187,12 +187,9 @@ JavaScriptの*グローバルスコープ*を含む、全てのスコープは +function(){}(); (function(){}()); -### In Conclusion +### 終わりに -It is recommended to always use an *anonymous wrapper* for encapsulating code in -its own namespace. This does not only protect code against name clashes, it -also allows for better modularization of programs. +自身の名前空間にカプセル化する為に常に*匿名関数ラッパー*を使用する事を推奨します。これは、コードを名前衝突から守る為だけでなく、プログラムのより良いモジュール化の為でもあります。 -Additionally, the use of global variables is considered **bad practice**. **Any** -use of them indicates badly written code that is prone to errors and hard to maintain. +さらに、グローバル変数の使用は**悪い習慣**と考えられています。**一回**でもグローバル変数を使用するとエラーが発生しやすく、メンテナンスがしにくいコードになってしまいます。 From 20687b026f45a62501815e4726b6a80bd5da0bfb Mon Sep 17 00:00:00 2001 From: HIRAKI Satoru Date: Sun, 28 Aug 2011 13:35:37 +0900 Subject: [PATCH 087/463] translate "Array Iteration and Properties" in "Array" to ja --- doc/ja/array/general.md | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/doc/ja/array/general.md b/doc/ja/array/general.md index 7c8f07ab..b0cb3988 100644 --- a/doc/ja/array/general.md +++ b/doc/ja/array/general.md @@ -1,17 +1,11 @@ -## Array Iteration and Properties +## 配列の繰り返しとプロパティ -Although arrays in JavaScript are objects, there are no good reasons to use -the [`for in loop`](#object.forinloop) in for iteration on them. In fact there -are a number of good reasons **against** the use of `for in` on arrays. +JavaScriptの配列もまたオブジェクトですので[`for in ループ`](#object.forinloop)を配列の繰り返しで使用するような理由はありません。実際、配列に`for in`を使用**しない**為の正当な理由はたくさんあります。 -> **Note:** JavaScript arrays are **not** *associative arrays*. JavaScript only -> has [objects](#object.general) for mapping keys to values. And while associative -> arrays **preserve** order, objects **do not**. +> **注意:** JavaScriptの配列は*連想配列*では**ありません**。JavaScriptは[objects](#object.general)だけがキーバリューをマッピングするものです。 +> また、連想配列は順序を**保持**しますが、オブジェクトは**保持しません**。 -Since the `for in` loop enumerates all the properties that are on the prototype -chain and the only way to exclude those properties is to use -[`hasOwnProperty`](#object.hasownproperty), it is already up to **twenty times** -slower than a normal `for` loop. +`for in`ループはプロトタイプチェーン上の全てのプロパティを列挙するため、[`hasOwnProperty`](#object.hasownproperty)をそれらのプロパティの存在判定に使います。この為、通常の`for`ループよりも**20倍**遅くなります。 ### Iteration From ac908f936bda66f1b7dd00a087c9d49bb70366b1 Mon Sep 17 00:00:00 2001 From: HIRAKI Satoru Date: Sun, 11 Sep 2011 22:21:48 +0900 Subject: [PATCH 088/463] tranlate "Iteration" in "Array" to ja --- doc/ja/array/general.md | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/doc/ja/array/general.md b/doc/ja/array/general.md index b0cb3988..cbf6595e 100644 --- a/doc/ja/array/general.md +++ b/doc/ja/array/general.md @@ -7,26 +7,20 @@ JavaScriptの配列もまたオブジェクトですので[`for in ループ`](# `for in`ループはプロトタイプチェーン上の全てのプロパティを列挙するため、[`hasOwnProperty`](#object.hasownproperty)をそれらのプロパティの存在判定に使います。この為、通常の`for`ループよりも**20倍**遅くなります。 -### Iteration +### 繰り返し -In order to achieve the best performance when iterating over arrays, it is best -to use the classic `for` loop. +配列の要素を繰り返すとのに、最高のパフォーマンスを出したければ昔ながらの`for`ループを使うのが一番です。 var list = [1, 2, 3, 4, 5, ...... 100000000]; for(var i = 0, l = list.length; i < l; i++) { console.log(list[i]); } -There is one extra catch in the above example, that is the caching of the -length of the array via `l = list.length`. +上記の例では一つ余分に変数がありますが、それは配列の長さを取るための`l = list.length`の部分です。 -Although the `length` property is defined on the array itself, there is still an -overhead for doing the lookup on each iteration of the loop. And while recent -JavaScript engines **may** apply optimization in this case, there is no way of -telling whether the code will run on one of these newer engines or not. +また、`length`プロパティは配列自身に定義されていますが、ループのそれぞれの繰り返しで探索する為のオーバーヘッドがまだあります。最近のJavaScriptエンジンはこのような場合に最適化する**はず**です。新しいエンジンか古いエンジンで実行されるかどうかをコードが知る方法はありません。 -In fact, leaving out the caching may result in the loop being only **half as -fast** as with the cached length. +実際には、キャッシュを抜きにするとループの結果はキャッシュされたものに比べて、**半分だけ高速**になっている。 ### The `length` Property From 580fcd6d3b4df643489caeed7a605246e07cae94 Mon Sep 17 00:00:00 2001 From: HIRAKI Satoru Date: Sun, 11 Sep 2011 22:26:24 +0900 Subject: [PATCH 089/463] fix representation --- doc/ja/array/general.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/ja/array/general.md b/doc/ja/array/general.md index cbf6595e..9ef9c8f6 100644 --- a/doc/ja/array/general.md +++ b/doc/ja/array/general.md @@ -20,9 +20,9 @@ JavaScriptの配列もまたオブジェクトですので[`for in ループ`](# また、`length`プロパティは配列自身に定義されていますが、ループのそれぞれの繰り返しで探索する為のオーバーヘッドがまだあります。最近のJavaScriptエンジンはこのような場合に最適化する**はず**です。新しいエンジンか古いエンジンで実行されるかどうかをコードが知る方法はありません。 -実際には、キャッシュを抜きにするとループの結果はキャッシュされたものに比べて、**半分だけ高速**になっている。 +実際には、キャッシュを抜きにするとループの結果はキャッシュされたものに比べて、**半分だけ高速**になっています。 -### The `length` Property +### `length`プロパティ While the *getter* of the `length` property simply returns the number of elements that are contained in the array, the *setter* can be used to From 225d33878b15c4b80e5cfc30c66921827cc4077b Mon Sep 17 00:00:00 2001 From: HIRAKI Satoru Date: Mon, 12 Sep 2011 00:41:27 +0900 Subject: [PATCH 090/463] translate "The `length` Property" in "Array" to ja --- doc/ja/array/general.md | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/doc/ja/array/general.md b/doc/ja/array/general.md index 9ef9c8f6..61a159b0 100644 --- a/doc/ja/array/general.md +++ b/doc/ja/array/general.md @@ -24,9 +24,7 @@ JavaScriptの配列もまたオブジェクトですので[`for in ループ`](# ### `length`プロパティ -While the *getter* of the `length` property simply returns the number of -elements that are contained in the array, the *setter* can be used to -**truncate** the array. +`length`プロパティの*ゲッター*は単に配列に含まれる要素の数を返すだけにも関わらず、*セッター*は配列を**トランケート**する為にも使用できます。 var foo = [1, 2, 3, 4, 5, 6]; foo.length = 3; @@ -35,8 +33,7 @@ elements that are contained in the array, the *setter* can be used to foo.length = 6; foo; // [1, 2, 3] -Assigning a smaller length does truncate the array, but increasing the length -does not have any effect on the array. +より小さいlengthを割り当てると配列をトランケートしますが、lengthが大きくなっても配列には何も影響しません。 ### In Conclusion From 5036ba6a117a4a0de68ce5e2973cff559416f1f3 Mon Sep 17 00:00:00 2001 From: HIRAKI Satoru Date: Mon, 12 Sep 2011 00:51:19 +0900 Subject: [PATCH 091/463] translate "In Conclusion" in "Array" to ja --- doc/ja/array/general.md | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/doc/ja/array/general.md b/doc/ja/array/general.md index 61a159b0..c9331224 100644 --- a/doc/ja/array/general.md +++ b/doc/ja/array/general.md @@ -35,9 +35,7 @@ JavaScriptの配列もまたオブジェクトですので[`for in ループ`](# より小さいlengthを割り当てると配列をトランケートしますが、lengthが大きくなっても配列には何も影響しません。 -### In Conclusion +### 終わりに -For the best performance it is recommended to always use the plain `for` loop -and cache the `length` property. The use of `for in` on an array is a sign of -badly written code that is prone to bugs and bad performance. +最高のパフォーマンスの為には、常に`for`ループを使用し、`length`プロパティをキャッシュする事をお勧めします。`for in`ループを配列で使用するのは、バグや最低のパフォーマンスの傾向があるコードを書く前兆になります。 From d07447ec416b147d2c075abda86a2ca6d3f32e4b Mon Sep 17 00:00:00 2001 From: HIRAKI Satoru Date: Wed, 14 Sep 2011 01:47:05 +0900 Subject: [PATCH 092/463] translate "The `Array` Constructor" in "Array" to ja --- doc/ja/array/constructor.md | 26 +++++++++----------------- 1 file changed, 9 insertions(+), 17 deletions(-) diff --git a/doc/ja/array/constructor.md b/doc/ja/array/constructor.md index 763f55fb..82922119 100644 --- a/doc/ja/array/constructor.md +++ b/doc/ja/array/constructor.md @@ -1,29 +1,21 @@ -## The `Array` Constructor +## `Array`コンストラクター -Since the `Array` constructor is ambiguous in how it deals with its parameters, -it is highly recommended to always use the array literals - `[]` notation - -when creating new arrays. +`Array`コンストラクターはそのパラメーターの扱い方が曖昧なので、新しい配列を作る時には、常に配列リテラル - `[]`記法 - を使用する事を強くお勧めします。 - [1, 2, 3]; // Result: [1, 2, 3] - new Array(1, 2, 3); // Result: [1, 2, 3] + [1, 2, 3]; // 結果: [1, 2, 3] + new Array(1, 2, 3); // 結果: [1, 2, 3] [3]; // Result: [3] - new Array(3); // Result: [] - new Array('3') // Result: ['3'] + new Array(3); // 結果: [] + new Array('3') // 結果: ['3'] -In cases when there is only one argument passed to the `Array` constructor, -and that argument is a `Number`, the constructor will return a new *sparse* -array with the `length` property set to the value of the argument. It should be -noted that **only** the `length` property of the new array will be set this way, -the actual indexes of the array will not be initialized. +このケースの場合、`Array`コンストラクターに渡される引数は一つだけですが、その引数は`Number`になります。コンストラクターは、引数に値がセットされた`length`プロパティを伴った新しい*疎*配列を返します。特筆すべきなのは、新しい配列の`length`プロパティ**のみ**が、このようにセットされるという事です。実際の配列のインデックスは初期化されません。 var arr = new Array(3); arr[1]; // undefined - 1 in arr; // false, the index was not set + 1 in arr; // false, インデックスがセットされていない -The behavior of being able to set the length of the array upfront only comes in -handy in a few cases, like repeating a string, in which it avoids the use of a -`for loop` code. +配列の長さが先行してセットされるという振舞いは、いくつかの場合に便利です。例えば、文字の繰り返しや、`for loop`を使用したコードの回避などの場合です。 new Array(count + 1).join(stringToRepeat); From ea9e1ad9a9b056a38c82fd00a23ec283dd8abc60 Mon Sep 17 00:00:00 2001 From: HIRAKI Satoru Date: Wed, 14 Sep 2011 01:48:16 +0900 Subject: [PATCH 093/463] translate "In Conclusion" in "Array" to ja --- doc/ja/array/constructor.md | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/doc/ja/array/constructor.md b/doc/ja/array/constructor.md index 82922119..817808b7 100644 --- a/doc/ja/array/constructor.md +++ b/doc/ja/array/constructor.md @@ -19,9 +19,7 @@ new Array(count + 1).join(stringToRepeat); -### In Conclusion +### 終わりに -The use of the `Array` constructor should be avoided as much as possible. -Literals are definitely preferred. They are shorter and have a clearer syntax; -therefore, they also increase the readability of the code. +`Array`コンストラクターの使用は出来る限り避けてください。リテラルが当然望ましい形です。それらは、短かく明快な文法にもってるいる為に、コードの可読性を高めてくれます。 From b05a3be66af90480bf695a220604df3ff3401ae1 Mon Sep 17 00:00:00 2001 From: HIRAKI Satoru Date: Wed, 14 Sep 2011 02:04:37 +0900 Subject: [PATCH 094/463] translate "Equality and Comparisons" in "Array" to ja --- doc/ja/types/equality.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/ja/types/equality.md b/doc/ja/types/equality.md index a578b19c..a8421759 100644 --- a/doc/ja/types/equality.md +++ b/doc/ja/types/equality.md @@ -1,6 +1,6 @@ -## Equality and Comparisons +## 等価と比較 -JavaScript has two different ways of comparing the values of objects for equality. +JavaScriptはオブジェクトの値の等価の比較方法が2種類持っています。 ### The Equality Operator From 47ca4b022b49c43708005a22a73f389ff686f545 Mon Sep 17 00:00:00 2001 From: HIRAKI Satoru Date: Wed, 14 Sep 2011 02:18:47 +0900 Subject: [PATCH 095/463] translate "The Equality Operator" in "Array" to ja --- doc/ja/types/equality.md | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/doc/ja/types/equality.md b/doc/ja/types/equality.md index a8421759..df0a7b56 100644 --- a/doc/ja/types/equality.md +++ b/doc/ja/types/equality.md @@ -2,13 +2,12 @@ JavaScriptはオブジェクトの値の等価の比較方法が2種類持っています。 -### The Equality Operator +### 等価演算子 -The equality operator consists of two equal signs: `==` +等価演算子は2つのイコール記号: `==`から成っています。 + +JavaScriptは*弱い型付け*を特徴としています。これは等価演算子が比較をする際に型付けを**強制**するという意味です。 -JavaScript features *weak typing*. This means that the equality operator -**coerces** types in order to compare them. - "" == "0" // false 0 == "" // true 0 == "0" // true @@ -19,13 +18,9 @@ JavaScript features *weak typing*. This means that the equality operator null == undefined // true " \t\r\n" == 0 // true -The above table shows the results of the type coercion and it is the main reason -why the use of `==` is widely regarded as bad practice, it introduces hard to -track down bugs due to its complicated conversion rules. +上記の表では型強制の結果が表示されています。`==`の使用が一般に悪い習慣とみなされる大きな理由として、変換ルールが複雑な為、バグの追跡が困難になる事が挙げられます。 -Additionally there is also a performance impact when type coercion is in play; -for example, a string has to be converted to a number before it can be compared -to another number. +加えて、型強制が行なわれるとパフォーマンスにも影響してしまいます。例えば、文字列は他の数字と比較する前に数値に変換されなければなりません。 ### The Strict Equality Operator From 427d2d8f896ce288e908be18bc9c5d75f642ecf3 Mon Sep 17 00:00:00 2001 From: HIRAKI Satoru Date: Thu, 15 Sep 2011 01:45:03 +0900 Subject: [PATCH 096/463] translate "The Strict Equality Operator" in "type" to ja --- doc/ja/types/equality.md | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/doc/ja/types/equality.md b/doc/ja/types/equality.md index df0a7b56..f5576ebf 100644 --- a/doc/ja/types/equality.md +++ b/doc/ja/types/equality.md @@ -22,12 +22,11 @@ JavaScriptは*弱い型付け*を特徴としています。これは等価演 加えて、型強制が行なわれるとパフォーマンスにも影響してしまいます。例えば、文字列は他の数字と比較する前に数値に変換されなければなりません。 -### The Strict Equality Operator +### 厳密等価演算子 -The strict equality operator consists of **three** equal signs: `===` +厳密等価演算子は**3つ**のイコール記号:`===`で成っています。 -It works exactly like the normal equality operator, except that strict equality -operator does **not** perform type coercion between its operands. +これはオペランドの間で強制的な型変換が**実行されない**事を除けば、通常の等価演算子と同じように正確に動作します。 "" === "0" // false 0 === "" // false @@ -39,9 +38,7 @@ operator does **not** perform type coercion between its operands. null === undefined // false " \t\r\n" === 0 // false -The above results are a lot clearer and allow for early breakage of code. This -hardens code to a certain degree and also gives performance improvements in case -the operands are of different types. +上記の結果は、より明確でコードの早期破損を可能にします。これはある程度までコードを硬化させて、オペランドが別の型の場合にパフォーマンスが向上します。 ### Comparing Objects From 02c9091d44fe46583664ca61423d3c72f31326a8 Mon Sep 17 00:00:00 2001 From: Sergio Arbeo Date: Fri, 16 Sep 2011 15:04:30 +0300 Subject: [PATCH 097/463] Fix typo. declartion => declaration --- doc/en/function/scopes.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/en/function/scopes.md b/doc/en/function/scopes.md index 7ae5e4f5..ee11a653 100644 --- a/doc/en/function/scopes.md +++ b/doc/en/function/scopes.md @@ -122,7 +122,7 @@ nearest surrounding scope. // var statements got moved here var bar, someValue; // default to 'undefined' - // the function declartion got moved up too + // the function declaration got moved up too function test(data) { var goo, i, e; // missing block scope moves these here if (false) { From 8ba05acbbfbfb1e21d6f06b0a9a959f4e4d62c40 Mon Sep 17 00:00:00 2001 From: HIRAKI Satoru Date: Sun, 18 Sep 2011 18:55:15 +0900 Subject: [PATCH 098/463] translate "Comparing Objects" in "Array" to ja --- doc/ja/types/equality.md | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/doc/ja/types/equality.md b/doc/ja/types/equality.md index f5576ebf..1a9bce53 100644 --- a/doc/ja/types/equality.md +++ b/doc/ja/types/equality.md @@ -40,10 +40,9 @@ JavaScriptは*弱い型付け*を特徴としています。これは等価演 上記の結果は、より明確でコードの早期破損を可能にします。これはある程度までコードを硬化させて、オペランドが別の型の場合にパフォーマンスが向上します。 -### Comparing Objects +### オブジェクトの比較 -While both `==` and `===` are stated as **equality** operators, they behave -different when at least one of their operands happens to be an `Object`. +`==`と`===`は両方とも**等価**演算子とされていますが、そのオペランドの少なくとも一つが`Object`の場合は、両者は異なる動きをします。 {} === {}; // false new String('foo') === 'foo'; // false @@ -51,9 +50,7 @@ different when at least one of their operands happens to be an `Object`. var foo = {}; foo === foo; // true -Here both operators compare for **identity** and **not** equality; that is, they -will compare for the same **instance** of the object, much like `is` in Python -and pointer comparison in C. +これら2つの演算子は**同一性**と等価**ではない**事を比較しています。これは、これらの演算子はPythonの`is`演算子やCのポインター比較と同じように、同じオブジェクトの**インスタンス**を比較するという事になります。 ### In Conclusion From 5ccbfe5a1ddeb5cad1ec021287b988d4f560a51a Mon Sep 17 00:00:00 2001 From: HIRAKI Satoru Date: Sun, 18 Sep 2011 19:02:21 +0900 Subject: [PATCH 099/463] translate "In Conclusion" in "Array" to ja --- doc/ja/types/equality.md | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/doc/ja/types/equality.md b/doc/ja/types/equality.md index 1a9bce53..ea99d187 100644 --- a/doc/ja/types/equality.md +++ b/doc/ja/types/equality.md @@ -52,9 +52,7 @@ JavaScriptは*弱い型付け*を特徴としています。これは等価演 これら2つの演算子は**同一性**と等価**ではない**事を比較しています。これは、これらの演算子はPythonの`is`演算子やCのポインター比較と同じように、同じオブジェクトの**インスタンス**を比較するという事になります。 -### In Conclusion +### 終わりに -It is highly recommended to only use the **strict equality** operator. In cases -where types need to be coerced, it should be done [explicitly](#types.casting) -and not left to the language's complicated coercion rules. +**厳格等価**演算子だけを使用することを特に推奨します。型を強制的に型変換する場合は[explicitly](#types.casting)であるべきで、言語自体の複雑な変換ルールが残っているべきではありません。 From e642cdcc9d9990cd4497507988d4e50013d45db5 Mon Sep 17 00:00:00 2001 From: HIRAKI Satoru Date: Sun, 18 Sep 2011 22:00:20 +0900 Subject: [PATCH 100/463] translate "The `typeof` Operator" in 'Types' in ja --- doc/ja/types/typeof.md | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/doc/ja/types/typeof.md b/doc/ja/types/typeof.md index e4b28d7f..167837bb 100644 --- a/doc/ja/types/typeof.md +++ b/doc/ja/types/typeof.md @@ -1,17 +1,13 @@ -## The `typeof` Operator +## `typeof`演算子 -The `typeof` operator (together with -[`instanceof`](#types.instanceof)) is probably the biggest -design flaw of JavaScript, as it is near of being **completely broken**. +`typeof`演算子([`instanceof`](#types.instanceof)も同様です)は恐らくJavaScriptの最大の設計ミスです。**完全に壊れている**存在に近いものです。 -Although `instanceof` still has its limited uses, `typeof` really has only one -practical use case, which does **not** happen to be checking the type of an -object. +`instanceof`はまだ限られた用途で使用できますが、`typeof`は本当に使用できる実用的なケースはオブジェクトの型を調べるという起こら**ない**ケース一つしかありません。 -> **Note:** While `typeof` can also be called with a function like syntax -> i.e. `typeof(obj)`, this is not a function call. The two parenthesis will -> behave like normal and the return value will be used as the operand of the -> `typeof` operator. There is **no** `typeof` function. +> **注意点:** `typeof`も関数のような構文で呼ぶ事もできます。(例:`typeof(obj)`) +> これは関数呼び出しではありません。2つのカッコは通常と同じように +> `typeof`演算子のオペランドの値を返す振る舞いをします。 +> `typeof`関数は存在**しません**。 ### The JavaScript Type Table From 0febfd7bb238c3911e1ef39287c38911a16ccc0d Mon Sep 17 00:00:00 2001 From: XP1 Date: Tue, 20 Sep 2011 20:23:03 -0300 Subject: [PATCH 101/463] Fix grammar. --- doc/en/types/equality.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/en/types/equality.md b/doc/en/types/equality.md index a578b19c..4eadd5a0 100644 --- a/doc/en/types/equality.md +++ b/doc/en/types/equality.md @@ -51,7 +51,7 @@ the operands are of different types. ### Comparing Objects While both `==` and `===` are stated as **equality** operators, they behave -different when at least one of their operands happens to be an `Object`. +differently when at least one of their operands happens to be an `Object`. {} === {}; // false new String('foo') === 'foo'; // false @@ -59,7 +59,7 @@ different when at least one of their operands happens to be an `Object`. var foo = {}; foo === foo; // true -Here both operators compare for **identity** and **not** equality; that is, they +Here, both operators compare for **identity** and **not** equality; that is, they will compare for the same **instance** of the object, much like `is` in Python and pointer comparison in C. From ef2972ee5817ff036fbe9b7447dd2e323ef144fb Mon Sep 17 00:00:00 2001 From: XP1 Date: Tue, 20 Sep 2011 20:39:19 -0300 Subject: [PATCH 102/463] Fix grammar. --- doc/en/core/undefined.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/en/core/undefined.md b/doc/en/core/undefined.md index b29da3b4..584c1339 100644 --- a/doc/en/core/undefined.md +++ b/doc/en/core/undefined.md @@ -8,8 +8,8 @@ being `undefined`. `undefined` is a type with exactly one value: `undefined`. The language also defines a global variable that has the value of `undefined`, -this variable is also called `undefined`. But this variable is **not** a constant, -nor is it a keyword of the language. This means that its *value* can be easily +this variable is also called `undefined`. However, this variable is **neither** a constant +nor a keyword of the language. This means that its *value* can be easily overwritten. > **ES5 Note:** `undefined` in ECMAScript 5 is **no longer** *writable* in strict @@ -31,7 +31,7 @@ Since the global variable `undefined` only holds a copy of the actual *value* of `undefined`, assigning a new value to it does **not** change the value of the *type* `undefined`. -Still, in order to compare something against the value of `undefined` it is +Still, in order to compare something against the value of `undefined`, it is necessary to retrieve the value of `undefined` first. In order to protect code against a possible overwritten `undefined` variable, a From d4111e12430f8a964d9d780d39bfbb6f5d3047b1 Mon Sep 17 00:00:00 2001 From: XP1 Date: Tue, 20 Sep 2011 20:53:19 -0300 Subject: [PATCH 103/463] Fix comma splice. Remove extra comma. Fix subject-verb agreement. --- doc/en/object/general.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/en/object/general.md b/doc/en/object/general.md index cbad5f11..466d60ed 100644 --- a/doc/en/object/general.md +++ b/doc/en/object/general.md @@ -25,7 +25,7 @@ literals act as objects too. ### Objects as a Data Type -Objects in JavaScript can also be used as a [*Hashmap*][1], they mainly consist +Objects in JavaScript can also be used as a [*Hashmap*][1]; they mainly consist of named properties mapping to values. Using a object literal - `{}` notation - it is possible to create a @@ -40,7 +40,7 @@ has no [own properties](#object.hasownproperty) defined on it. ### Accessing Properties The properties of an object can be accessed in two ways, via either the dot -notation, or the square bracket notation. +notation or the square bracket notation. var foo = {name: 'Kitten'} foo.name; // kitten @@ -59,7 +59,7 @@ the use of property names that would otherwise lead to a syntax error. ### Deleting Properties The only way to actually remove a property from an object is to use the `delete` -operator; setting the property to `undefined` or `null` only remove the +operator; setting the property to `undefined` or `null` only removes the *value* associated with the property, but not the *key*. var obj = { From f3c8a30928a0f8228b9f6ac43e29077578fbb80f Mon Sep 17 00:00:00 2001 From: XP1 Date: Tue, 20 Sep 2011 20:57:28 -0300 Subject: [PATCH 104/463] Fix comma splice. Add commas. Fix incomplete sentence. --- doc/en/object/prototype.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/en/object/prototype.md b/doc/en/object/prototype.md index f780eba2..0a3b6d0c 100644 --- a/doc/en/object/prototype.md +++ b/doc/en/object/prototype.md @@ -1,11 +1,11 @@ ## The Prototype -JavaScript does not feature a classical inheritance model, instead it uses a +JavaScript does not feature a classical inheritance model; instead, it uses a *prototypal* one. While this is often considered to be one of JavaScript's weaknesses, the prototypal inheritance model is in fact more powerful than the classic model. -It is for example fairly trivial to build a classic model on top of it, while the +It is, for example, fairly trivial to build a classic model on top of it, while the other way around is a far more difficult task. Due to the fact that JavaScript is basically the only widely used language that @@ -71,7 +71,7 @@ hasn't found the specified property, it will return the value ### The Prototype Property While the prototype property is used by the language to build the prototype -chains, it is still possible to assign **any** given value to it. Although +chains, it is still possible to assign **any** given value to it. However, primitives will simply get ignored when assigned as a prototype. function Foo() {} From b37391ee0d66d834d174f3cccaabceca40790438 Mon Sep 17 00:00:00 2001 From: XP1 Date: Tue, 20 Sep 2011 20:58:53 -0300 Subject: [PATCH 105/463] Fix comma splices. --- doc/en/object/hasownproperty.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/en/object/hasownproperty.md b/doc/en/object/hasownproperty.md index 319a8801..576c50c6 100644 --- a/doc/en/object/hasownproperty.md +++ b/doc/en/object/hasownproperty.md @@ -21,7 +21,7 @@ does **not** traverse the prototype chain. foo.hasOwnProperty('bar'); // false foo.hasOwnProperty('goo'); // true -Only `hasOwnProperty` will give the correct and expected result, this is +Only `hasOwnProperty` will give the correct and expected result; this is essential when iterating over the properties of any object. There is **no** other way to exclude properties that are not defined on the object *itself*, but somewhere on its prototype chain. @@ -48,6 +48,6 @@ necessary to use an *external* `hasOwnProperty` in order to get correct results. When checking for the existence of a property on a object, `hasOwnProperty` is the **only** method of doing so. It is also recommended to make `hasOwnProperty` -part of **every** [`for in` loop](#object.forinloop), this will avoid errors from +part of **every** [`for in` loop](#object.forinloop); this will avoid errors from extended native [prototypes](#object.prototype). From d678b9bf87006fa79a643ba67508212e64f0e169 Mon Sep 17 00:00:00 2001 From: XP1 Date: Tue, 20 Sep 2011 21:02:25 -0300 Subject: [PATCH 106/463] Removed space before comma. Fix comma splice. Add comma. --- doc/en/object/forinloop.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/en/object/forinloop.md b/doc/en/object/forinloop.md index 30751ed9..cb776b36 100644 --- a/doc/en/object/forinloop.md +++ b/doc/en/object/forinloop.md @@ -16,7 +16,7 @@ chain when iterating over the properties of an object. } Since it is not possible to change the behavior of the `for in` loop itself, it -is necessary to filter out the unwanted properties inside the loop body , +is necessary to filter out the unwanted properties inside the loop body; this is done by using the [`hasOwnProperty`](#object.hasownproperty) method of `Object.prototype`. @@ -32,7 +32,7 @@ this is done by using the [`hasOwnProperty`](#object.hasownproperty) method of } } -This version is the only correct one to use. Due to the use of `hasOwnProperty` it +This version is the only correct one to use. Due to the use of `hasOwnProperty`, it will **only** print out `moo`. When `hasOwnProperty` is left out, the code is prone to errors in cases where the native prototypes - e.g. `Object.prototype` - have been extended. @@ -45,7 +45,7 @@ guaranteed to break. It is recommended to **always** use `hasOwnProperty`. Never should any assumptions be made about the environment the code is running in, or whether the -native prototypes have been extended or not. +native prototypes have been extended or not. [1]: http://www.prototypejs.org/ From 424214f0628f087437b61dfbce5ac1db4b749293 Mon Sep 17 00:00:00 2001 From: XP1 Date: Tue, 20 Sep 2011 21:04:38 -0300 Subject: [PATCH 107/463] Remove comma before "that". Add commas for introductory statements. --- doc/en/function/general.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/en/function/general.md b/doc/en/function/general.md index 64c9e0c9..7ca180f0 100644 --- a/doc/en/function/general.md +++ b/doc/en/function/general.md @@ -25,7 +25,7 @@ This example assigns the unnamed and *anonymous* function to the variable `foo`. foo(); // this raises a TypeError var foo = function() {}; -Due to the fact that `var` is a declaration, that hoists the variable name `foo` +Due to the fact that `var` is a declaration that hoists the variable name `foo` before the actual execution of the code starts, `foo` is already defined when the script gets executed. @@ -41,8 +41,8 @@ Another special case is the assignment of named functions. } bar(); // ReferenceError -Here `bar` is not available in the outer scope, since the function only gets -assigned to `foo`; however, inside of `bar` it is available. This is due to +Here, `bar` is not available in the outer scope, since the function only gets +assigned to `foo`; however, inside of `bar`, it is available. This is due to how [name resolution](#function.scopes) in JavaScript works, the name of the function is *always* made available in the local scope of the function itself. From 9c2277e02d043830df0e6a6db18016e5fa1a76f5 Mon Sep 17 00:00:00 2001 From: XP1 Date: Tue, 20 Sep 2011 21:10:17 -0300 Subject: [PATCH 108/463] Add commas for introductory statements. Fix comma splice. --- doc/en/function/this.md | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/doc/en/function/this.md b/doc/en/function/this.md index 85b11f0f..440900e8 100644 --- a/doc/en/function/this.md +++ b/doc/en/function/this.md @@ -15,7 +15,7 @@ When using `this` in global scope, it will simply refer to the *global* object. foo(); -Here `this` will again refer to the *global* object. +Here, `this` will again refer to the *global* object. > **ES5 Note:** In strict mode, the global case **no longer** exists. > `this` will instead have the value of `undefined` in that case. @@ -24,14 +24,14 @@ Here `this` will again refer to the *global* object. test.foo(); -In this example `this` will refer to `test`. +In this example, `this` will refer to `test`. ### Calling a Constructor new foo(); A function call that is preceded by the `new` keyword acts as -a [constructor](#function.constructors). Inside the function `this` will refer +a [constructor](#function.constructors). Inside the function, `this` will refer to a *newly created* `Object`. ### Explicit Setting of `this` @@ -56,7 +56,7 @@ inside of `foo` will be set to `bar`. ### Common Pitfalls While most of these cases make sense, the first one is to be considered another -mis-design of the language, as it **never** has any practical use. +mis-design of the language because it **never** has any practical use. Foo.method = function() { function test() { @@ -65,10 +65,10 @@ mis-design of the language, as it **never** has any practical use. test(); } -A common misconception is that `this` inside of `test` refers to `Foo`, while in -fact it **does not**. +A common misconception is that `this` inside of `test` refers to `Foo`; while in +fact, it **does not**. -In order to gain access to `Foo` from within `test` it is necessary to create a +In order to gain access to `Foo` from within `test`, it is necessary to create a local variable inside of `method` which refers to `Foo`. Foo.method = function() { @@ -85,17 +85,17 @@ be used to pass `this` values around. ### Assigning Methods -Another thing that does **not** work in JavaScript is function aliasing, that is, +Another thing that does **not** work in JavaScript is function aliasing, which is **assigning** a method to a variable. var test = someObject.methodTest; test(); -Due to the first case `test` now acts like a plain function call; therefore, +Due to the first case, `test` now acts like a plain function call; therefore, `this` inside it will no longer refer to `someObject`. -While the late binding of `this` might seem like a bad idea at first, it is in -fact what makes [prototypal inheritance](#object.prototype) work. +While the late binding of `this` might seem like a bad idea at first, in +fact, it is what makes [prototypal inheritance](#object.prototype) work. function Foo() {} Foo.prototype.method = function() {}; From dd3524b8cfcd197cc4e1025f3d6c9c6c885c9b2e Mon Sep 17 00:00:00 2001 From: XP1 Date: Tue, 20 Sep 2011 21:16:05 -0300 Subject: [PATCH 109/463] Clarify. Fix incomplete sentence. Split long sentence. Remove comma before "that". --- doc/en/function/closures.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/doc/en/function/closures.md b/doc/en/function/closures.md index 17554dcb..2e2a4ef6 100644 --- a/doc/en/function/closures.md +++ b/doc/en/function/closures.md @@ -1,8 +1,8 @@ ## Closures and References -One of JavaScript's most powerful features is the availability of *closures*, -this means that scopes **always** keep access to the outer scope they were -defined in. Since the only scoping that JavaScript has is +One of JavaScript's most powerful features is the availability of *closures*. +With closures, scopes **always** keep access to the outer scope, in which they +were defined. Since the only scoping that JavaScript has is [function scope](#function.scopes), all functions, by default, act as closures. ### Emulating private variables @@ -24,7 +24,7 @@ defined in. Since the only scoping that JavaScript has is foo.increment(); foo.get(); // 5 -Here, `Counter` returns **two** closures. The function `increment` as well as +Here, `Counter` returns **two** closures: the function `increment` as well as the function `get`. Both of these functions keep a **reference** to the scope of `Counter` and, therefore, always keep access to the `count` variable that was defined in that very scope. @@ -58,8 +58,8 @@ copying the value of the loops index variable. The above will **not** output the numbers `0` through `9`, but will simply print the number `10` ten times. -The *anonymous* function keeps a **reference** to `i` and at the time -`console.log` gets called, the `for loop` has already finished and the value of +The *anonymous* function keeps a **reference** to `i`. At the time +`console.log` gets called, the `for loop` has already finished, and the value of `i` as been set to `10`. In order to get the desired behavior, it is necessary to create a **copy** of @@ -84,8 +84,8 @@ argument and will receive a copy of the **value** of `i` as its parameter `e`. The anonymous function that gets passed to `setTimeout` now has a reference to `e`, whose value does **not** get changed by the loop. -There is another possible way of achieving this; that is to return a function -from the anonymous wrapper, that will then have the same behavior as the code +There is another possible way of achieving this, which is to return a function +from the anonymous wrapper that will then have the same behavior as the code above. for(var i = 0; i < 10; i++) { From 7a3b355f736e68e449c6d0db0633049239fd41c4 Mon Sep 17 00:00:00 2001 From: XP1 Date: Tue, 20 Sep 2011 21:18:52 -0300 Subject: [PATCH 110/463] Fix comma splices. Use hyphen. Add comma. --- doc/en/function/arguments.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/doc/en/function/arguments.md b/doc/en/function/arguments.md index 3d551ad5..1b219579 100644 --- a/doc/en/function/arguments.md +++ b/doc/en/function/arguments.md @@ -23,8 +23,8 @@ The code below will return a new `Array` containing all the elements of the Array.prototype.slice.call(arguments); -This conversion is **slow**, it is **not recommended** to use it in performance -critical sections of code. +Because this conversion is **slow**, it is **not recommended** to use it in +performance-critical sections of code. ### Passing Arguments @@ -59,7 +59,7 @@ wrappers. ### Formal Parameters and Arguments Indices The `arguments` object creates *getter* and *setter* functions for both its -properties as well as the function's formal parameters. +properties, as well as the function's formal parameters. As a result, changing the value of a formal parameter will also change the value of the corresponding property on the `arguments` object, and the other way around. @@ -105,8 +105,8 @@ modern JavaScript engines. That case is the use of `arguments.callee`. In the above code, `foo` can no longer be a subject to [inlining][1] since it needs to know about both itself and its caller. This not only defeats possible -performance gains that would arise from inlining, it also breaks encapsulation -since the function may now be dependent on a specific calling context. +performance gains that would arise from inlining, but it also breaks encapsulation +because the function may now be dependent on a specific calling context. It is **highly recommended** to **never** make use of `arguments.callee` or any of its properties. From be1968cbef36ee656a86c5231a4f5af738f7299b Mon Sep 17 00:00:00 2001 From: XP1 Date: Tue, 20 Sep 2011 21:21:03 -0300 Subject: [PATCH 111/463] Add comma. Use "which" instead of "that". Use "because". --- doc/en/function/constructors.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/en/function/constructors.md b/doc/en/function/constructors.md index ad90b028..a8e450a4 100644 --- a/doc/en/function/constructors.md +++ b/doc/en/function/constructors.md @@ -24,7 +24,7 @@ implicitly returns the value of `this` - the new object. The above calls `Foo` as constructor and sets the `prototype` of the newly created object to `Foo.prototype`. -In case of an explicit `return` statement the function returns the value +In case of an explicit `return` statement, the function returns the value specified that statement, **but only** if the return value is an `Object`. function Bar() { @@ -73,7 +73,7 @@ explicitly return a value. Bar(); Both calls to `Bar` return the exact same thing, a newly create object which -has a property called `method` on it, that is a +has a property called `method` on it, which is a [Closure](#function.closures). It is also to note that the call `new Bar()` does **not** affect the prototype @@ -86,7 +86,7 @@ not using the `new` keyword. ### Creating New Objects via Factories -An often made recommendation is to **not** use `new` since forgetting its use +An often made recommendation is to **not** use `new` because forgetting its use may lead to bugs. In order to create new object, one should rather use a factory and construct a From 9e0f603d1c91dc948d371b1ccf78a6b1897e37ca Mon Sep 17 00:00:00 2001 From: XP1 Date: Tue, 20 Sep 2011 21:32:20 -0300 Subject: [PATCH 112/463] Use "which" instead of "that". Fix joined independent clauses missing a comma. Use colon. Use hyphens for adjective. Add comma. Use introductory sentence. Use "the" article. Clarify dependent clauses. Use commas for introductory clauses. Fix comma splice. --- doc/en/function/scopes.md | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/doc/en/function/scopes.md b/doc/en/function/scopes.md index ee11a653..efb9d882 100644 --- a/doc/en/function/scopes.md +++ b/doc/en/function/scopes.md @@ -16,7 +16,7 @@ is in the language is *function scope*. > **not** as an object literal. This, in conjunction with > [automatic insertion of semicolons](#core.semicolon), can lead to subtle errors. -There are also no distinct namespaces in JavaScript, that means that everything +There are also no distinct namespaces in JavaScript, which means that everything gets defined in one *globally shared* namespace. Each time a variable is referenced, JavaScript will traverse upwards through all @@ -32,10 +32,10 @@ still has not found the requested name, it will raise a `ReferenceError`. var foo = '42' The above two scripts do **not** have the same effect. Script A defines a -variable called `foo` in the *global* scope and script B defines a `foo` in the +variable called `foo` in the *global* scope, and script B defines a `foo` in the *current* scope. -Again, that is **not** at all the *same effect*, not using `var` can have major +Again, that is **not** at all the *same effect*: not using `var` can have major implications. // global scope @@ -49,8 +49,8 @@ implications. Leaving out the `var` statement inside the function `test` will override the value of `foo`. While this might not seem like a big deal at first, having -thousands of lines of JavaScript and not using `var` will introduce horrible and -hard to track down bugs. +thousands of lines of JavaScript and not using `var` will introduce horrible, +hard-to-track-down bugs. // global scope var items = [/* some list */]; @@ -116,7 +116,7 @@ JavaScript **hoists** declarations. This means that both `var` statements and } The above code gets transformed before any execution is started. JavaScript moves -the `var` statements as well as the `function` declarations to the top of the +the `var` statements, as well as the `function` declarations to the top of the nearest surrounding scope. // var statements got moved here @@ -146,11 +146,11 @@ Missing block scoping will not only move `var` statements out of loops and their bodies, it will also make the results of certain `if` constructs non-intuitive. -In the original code the `if` statement seemed to modify the *global -variable* `goo`, while actually it modifies the *local variable* - after hoisting +In the original code, although the `if` statement seemed to modify the *global +variable* `goo`, it actually modifies the *local variable* - after hoisting has been applied. -Without the knowledge about *hoisting*, below code might seem to raise a +Without the knowledge about *hoisting*, the below code might seem to raise a `ReferenceError`. // check whether SomeImportantThing has been initiliazed @@ -173,18 +173,18 @@ moved to the top of the *global scope*. ### Name Resolution Order All scopes in JavaScript, including the *global scope*, have the special name -[`this`](#function.this) defined in them, which refers to the *current object*. +[`this`](#function.this), defined in them, which refers to the *current object*. -Function scopes also have the name [`arguments`](#function.arguments) defined in -them which contains the arguments that were passed to a function. +Function scopes also have the name [`arguments`](#function.arguments), defined in +them, which contains the arguments that were passed to a function. For example, when trying to access a variable named `foo` inside the scope of a function, JavaScript will lookup the name in the following order: - 1. In case there is a `var foo` statement in the current scope use that. - 2. If one of the function parameters is named `foo` use that. - 3. If the function itself is called `foo` use that. - 4. Go to the next outer scope and start with **#1** again. + 1. In case there is a `var foo` statement in the current scope, use that. + 2. If one of the function parameters is named `foo`, use that. + 3. If the function itself is called `foo`, use that. + 4. Go to the next outer scope, and start with **#1** again. > **Note:** Having a parameter called `arguments` will **prevent** the creation > of the default `arguments` object. @@ -223,7 +223,7 @@ while different in syntax, do behave the exact same way. ### In Conclusion It is recommended to always use an *anonymous wrapper* for encapsulating code in -its own namespace. This does not only protect code against name clashes, it +its own namespace. This does not only protect code against name clashes, but it also allows for better modularization of programs. Additionally, the use of global variables is considered **bad practice**. **Any** From 2558a27d8829240aaf4c14a0972ff87d3235d897 Mon Sep 17 00:00:00 2001 From: XP1 Date: Tue, 20 Sep 2011 21:35:29 -0300 Subject: [PATCH 113/463] Use comma for introductory clauses. Clarify introductory clause by repeating the first word. Use "which" instead of "that". --- doc/en/array/general.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/doc/en/array/general.md b/doc/en/array/general.md index 7c8f07ab..9f804d4c 100644 --- a/doc/en/array/general.md +++ b/doc/en/array/general.md @@ -1,15 +1,15 @@ ## Array Iteration and Properties Although arrays in JavaScript are objects, there are no good reasons to use -the [`for in loop`](#object.forinloop) in for iteration on them. In fact there +the [`for in loop`](#object.forinloop) in for iteration on them. In fact, there are a number of good reasons **against** the use of `for in` on arrays. > **Note:** JavaScript arrays are **not** *associative arrays*. JavaScript only > has [objects](#object.general) for mapping keys to values. And while associative > arrays **preserve** order, objects **do not**. -Since the `for in` loop enumerates all the properties that are on the prototype -chain and the only way to exclude those properties is to use +Because the `for in` loop enumerates all the properties that are on the prototype +chain and because the only way to exclude those properties is to use [`hasOwnProperty`](#object.hasownproperty), it is already up to **twenty times** slower than a normal `for` loop. @@ -23,7 +23,7 @@ to use the classic `for` loop. console.log(list[i]); } -There is one extra catch in the above example, that is the caching of the +There is one extra catch in the above example, which is the caching of the length of the array via `l = list.length`. Although the `length` property is defined on the array itself, there is still an @@ -52,7 +52,7 @@ does not have any effect on the array. ### In Conclusion -For the best performance it is recommended to always use the plain `for` loop +For the best performance, it is recommended to always use the plain `for` loop and cache the `length` property. The use of `for in` on an array is a sign of badly written code that is prone to bugs and bad performance. From 8449ded21e7a62e7e298bc6e5b6e9ae875d79594 Mon Sep 17 00:00:00 2001 From: XP1 Date: Tue, 20 Sep 2011 21:37:54 -0300 Subject: [PATCH 114/463] Clarify introductory clause. Fix comma splice. --- doc/en/array/constructor.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/en/array/constructor.md b/doc/en/array/constructor.md index 763f55fb..1d9abe18 100644 --- a/doc/en/array/constructor.md +++ b/doc/en/array/constructor.md @@ -11,10 +11,10 @@ when creating new arrays. new Array(3); // Result: [] new Array('3') // Result: ['3'] -In cases when there is only one argument passed to the `Array` constructor, -and that argument is a `Number`, the constructor will return a new *sparse* +In cases when there is only one argument passed to the `Array` constructor +and when that argument is a `Number`, the constructor will return a new *sparse* array with the `length` property set to the value of the argument. It should be -noted that **only** the `length` property of the new array will be set this way, +noted that **only** the `length` property of the new array will be set this way; the actual indexes of the array will not be initialized. var arr = new Array(3); From a89e6a883fb1242b2015c90690321c42b5eafda1 Mon Sep 17 00:00:00 2001 From: XP1 Date: Tue, 20 Sep 2011 21:40:38 -0300 Subject: [PATCH 115/463] Fix comma splice. Use hyphens for adjective. Use a comma for introductory clauses. Add period at the end of a sentence. --- doc/en/types/equality.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/doc/en/types/equality.md b/doc/en/types/equality.md index 4eadd5a0..5665917f 100644 --- a/doc/en/types/equality.md +++ b/doc/en/types/equality.md @@ -19,17 +19,17 @@ JavaScript features *weak typing*. This means that the equality operator null == undefined // true " \t\r\n" == 0 // true -The above table shows the results of the type coercion and it is the main reason -why the use of `==` is widely regarded as bad practice, it introduces hard to -track down bugs due to its complicated conversion rules. +The above table shows the results of the type coercion, and it is the main reason +why the use of `==` is widely regarded as bad practice. It introduces +hard-to-track-down bugs due to its complicated conversion rules. -Additionally there is also a performance impact when type coercion is in play; +Additionally, there is also a performance impact when type coercion is in play; for example, a string has to be converted to a number before it can be compared to another number. ### The Strict Equality Operator -The strict equality operator consists of **three** equal signs: `===` +The strict equality operator consists of **three** equal signs: `===`. It works exactly like the normal equality operator, except that strict equality operator does **not** perform type coercion between its operands. From 9b82ae6769619d22f79389f1a2c6ec1db7281e02 Mon Sep 17 00:00:00 2001 From: XP1 Date: Tue, 20 Sep 2011 21:43:22 -0300 Subject: [PATCH 116/463] Use a comma for introductory clauses. Remove comma before "that". Fix incomplete sentence. --- doc/en/types/typeof.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/en/types/typeof.md b/doc/en/types/typeof.md index e4b28d7f..00377db4 100644 --- a/doc/en/types/typeof.md +++ b/doc/en/types/typeof.md @@ -33,7 +33,7 @@ object. {} Object object new Object() Object object -In the above table *Type* refers to the value, that the `typeof` operator returns. +In the above table, *Type* refers to the value that the `typeof` operator returns. As can be clearly seen, this value is anything but consistent. The *Class* refers to the value of the internal `[[Class]]` property of an object. @@ -42,7 +42,7 @@ The *Class* refers to the value of the internal `[[Class]]` property of an objec > following strings. `Arguments`, `Array`, `Boolean`, `Date`, `Error`, > `Function`, `JSON`, `Math`, `Number`, `Object`, `RegExp`, `String`. -In order to retrieve the value of `[[Class]]` one has to make use of the +In order to retrieve the value of `[[Class]]`, one has to make use of the `toString` method of `Object.prototype`. ### The Class of an Object @@ -77,7 +77,7 @@ referencing it would result in a `ReferenceError`. This is the only thing ### In Conclusion In order to check the type of an object, it is highly recommended to use -`Object.prototype.toString`; as this is the only reliable way of doing so. +`Object.prototype.toString` because this is the only reliable way of doing so. As shown in the above type table, some return values of `typeof` are not defined in the specification; thus, they can differ across various implementations. From c98d89e247e81eacb2578a99e2cc0d4876962fc9 Mon Sep 17 00:00:00 2001 From: XP1 Date: Tue, 20 Sep 2011 21:46:39 -0300 Subject: [PATCH 117/463] Remove comma before "that". Fix verb expectations. Change "origin" to "originate". --- doc/en/types/instanceof.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/en/types/instanceof.md b/doc/en/types/instanceof.md index 8711331a..84251128 100644 --- a/doc/en/types/instanceof.md +++ b/doc/en/types/instanceof.md @@ -26,13 +26,13 @@ nearly as useless as the [typeof operator](#types.typeof). 'foo' instanceof String; // false 'foo' instanceof Object; // false -One important thing to note here is, that `instanceof` does not work on objects -that origin from different JavaScript contexts (e.g. different documents +One important thing to note here is that `instanceof` does not work on objects +that originate from different JavaScript contexts (e.g. different documents in a web browser), since their constructors will not be the exact same object. ### In Conclusion The `instanceof` operator should **only** be used when dealing with custom made -objects that origin from the same JavaScript context. Just like the +objects that originate from the same JavaScript context. Just like the [`typeof`](#types.typeof) operator, every other use of it should be **avoided**. From a3907080dfbaaf22dad47fc1ebfeba0bfe659f75 Mon Sep 17 00:00:00 2001 From: XP1 Date: Tue, 20 Sep 2011 21:48:42 -0300 Subject: [PATCH 118/463] Change "a" to "an". Use comma for introductory clauses. --- doc/en/types/casting.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/en/types/casting.md b/doc/en/types/casting.md index 15d84e74..34d6fd78 100644 --- a/doc/en/types/casting.md +++ b/doc/en/types/casting.md @@ -47,13 +47,13 @@ The best option is to cast to one of the three possible types **explicitly**. '' + 10 === '10'; // true -By prepending a empty string a value can easily be casted to a string. +By prepending an empty string, a value can easily be casted to a string. ### Casting to a Number +'10' === 10; // true -Using the **unary** plus operator it is possible to cast to a number. +Using the **unary** plus operator, it is possible to cast to a number. ### Casting to a Boolean From 1d8aaa99c795f956a6af68a3e48e30c81aae8f34 Mon Sep 17 00:00:00 2001 From: XP1 Date: Tue, 20 Sep 2011 21:53:56 -0300 Subject: [PATCH 119/463] Fix incomplete sentence. Fix run-on sentence. Fix comma splice. Remove repetitive clause. --- doc/en/core/eval.md | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/doc/en/core/eval.md b/doc/en/core/eval.md index ecf7ba90..160ba1f0 100644 --- a/doc/en/core/eval.md +++ b/doc/en/core/eval.md @@ -11,8 +11,8 @@ The `eval` function will execute a string of JavaScript code in the local scope. test(); // 3 foo; // 1 -But `eval` only executes in local scope when it is being called **directly** *and* -the name of the called function is actually `eval`. +However, `eval` only executes in the local scope when it is being called +**directly** *and* when the name of the called function is actually `eval`. var foo = 1; function test() { @@ -35,14 +35,13 @@ in the global scope since `eval` is not being called directly in that case. ### Security Issues -`eval` also is a security problem as it executes **any** code given to it, +`eval` also is a security problem. Because it executes **any** code given to it, it should **never** be used with strings of unknown or untrusted origins. ### In Conclusion -`eval` should never be used, any code that makes use of it is to be questioned in +`eval` should never be used. Any code that makes use of it is to be questioned in its workings, performance and security. In case something requires `eval` in -order to work, its design is to be questioned and should **not** be used in the -first place, a *better design* should be used, that does not require the use of -`eval`. +order to work, it should **not** be used in the first place. +A *better design* should be used, that does not require the use of `eval`. From 6d96eabd0b50a685cd2ec6fff379a2fb6e268cae Mon Sep 17 00:00:00 2001 From: XP1 Date: Tue, 20 Sep 2011 21:57:00 -0300 Subject: [PATCH 120/463] Fix comma splice. Remove comma before "that". Use comma for introductory clauses. --- doc/en/core/undefined.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/doc/en/core/undefined.md b/doc/en/core/undefined.md index 584c1339..d27761f0 100644 --- a/doc/en/core/undefined.md +++ b/doc/en/core/undefined.md @@ -7,7 +7,7 @@ being `undefined`. `undefined` is a type with exactly one value: `undefined`. -The language also defines a global variable that has the value of `undefined`, +The language also defines a global variable that has the value of `undefined`; this variable is also called `undefined`. However, this variable is **neither** a constant nor a keyword of the language. This means that its *value* can be easily overwritten. @@ -36,7 +36,7 @@ necessary to retrieve the value of `undefined` first. In order to protect code against a possible overwritten `undefined` variable, a common technique used is to add an additional parameter to an -[anonymous wrapper](#function.scopes), that gets no argument passed to it. +[anonymous wrapper](#function.scopes) that gets no argument passed to it. var undefined = 123; (function(something, foo, undefined) { @@ -55,8 +55,8 @@ wrapper. })('Hello World', 42); -The only difference being here, that this version results in 4 more bytes being -used in case it is minified and there is no other `var` statement inside the +The only difference here is that this version results in 4 more bytes being +used in case it is minified, and there is no other `var` statement inside the anonymous wrapper. ### Uses of `null` @@ -66,7 +66,7 @@ the sense of a traditional *null*, the actual `null` (both a literal and a type) is more or less just another data type. It is used in some JavaScript internals (like declaring the end of the -prototype chain by setting `Foo.prototype = null`), but in almost all cases it +prototype chain by setting `Foo.prototype = null`), but in almost all cases, it can be replaced by `undefined`. From 837a21f3f79365f42e52f952f4c220d4c8004c02 Mon Sep 17 00:00:00 2001 From: XP1 Date: Tue, 20 Sep 2011 22:00:22 -0300 Subject: [PATCH 121/463] Fix comma splices. Use comma for introductory clauses. --- doc/en/core/semicolon.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/doc/en/core/semicolon.md b/doc/en/core/semicolon.md index 61d74fd9..f03f7d82 100644 --- a/doc/en/core/semicolon.md +++ b/doc/en/core/semicolon.md @@ -1,10 +1,10 @@ ## Automatic Semicolon Insertion Although JavaScript has C style syntax, it does **not** enforce the use of -semicolons in the source code, it is possible to omit them. +semicolons in the source code, so it is possible to omit them. -But JavaScript is not a semicolon-less language, it in fact needs the -semicolons in order to understand the source code. Therefore the JavaScript +JavaScript is not a semicolon-less language. In fact, it needs the +semicolons in order to understand the source code. Therefore, the JavaScript parser **automatically** inserts them whenever it encounters a parse error due to a missing semicolon. @@ -19,7 +19,7 @@ Insertion happens, and the parser tries again. test() The automatic insertion of semicolon is considered to be one of **biggest** -design flaws in the language, as it *can* change the behavior of code. +design flaws in the language because it *can* change the behavior of code. ### How it Works @@ -87,7 +87,7 @@ Below is the result of the parser's "guessing" game. > which are followed by a new line, while this is not neccessarily the fault of > the automatic semicolon insertion, it can still be an unwanted side-effect. -The parser drastically changed the behavior of the code above, in certain cases +The parser drastically changed the behavior of the code above. In certain cases, it does the **wrong thing**. ### Leading Parenthesis @@ -106,9 +106,9 @@ the above will yield a `TypeError` stating that `undefined is not a function`. ### In Conclusion -It is highly recommended to **never** omit semicolons, it is also advocated to +It is highly recommended to **never** omit semicolons; it is also advocated to keep braces on the same line with their corresponding statements and to never omit them for one single-line `if` / `else` statements. Both of these measures will -not only improve the consistency of the code, they will also prevent the +not only improve the consistency of the code, but they will also prevent the JavaScript parser from changing its behavior. From 3bafb0a3ebae837f695a379f1ea10866a070271e Mon Sep 17 00:00:00 2001 From: XP1 Date: Tue, 20 Sep 2011 22:07:41 -0300 Subject: [PATCH 122/463] Use "which" instead of "that". Fix incomplete sentence. Use comma for introductory clauses. Add space after period. --- doc/en/other/timeouts.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/doc/en/other/timeouts.md b/doc/en/other/timeouts.md index d196a3b7..3a306bdd 100644 --- a/doc/en/other/timeouts.md +++ b/doc/en/other/timeouts.md @@ -19,7 +19,7 @@ gets executed might block the thread, it is by **no means** a safe bet that one will get the exact delay that was specified in the `setTimeout` call. The function that was passed as the first parameter will get called by the -*global object*, that means, that [`this`](#function.this) inside the called function +*global object*, which means that [`this`](#function.this) inside the called function refers to that very object. function Foo() { @@ -42,7 +42,7 @@ refers to that very object. ### Stacking Calls with `setInterval` While `setTimeout` only runs the function once, `setInterval` - as the name -suggests - will execute the function **every** `X` milliseconds. But its use is +suggests - will execute the function **every** `X` milliseconds, but its use is discouraged. When code that is being executed blocks the timeout call, `setInterval` will @@ -54,15 +54,15 @@ intervals, result in function calls stacking up. } setInterval(foo, 100); -In the above code `foo` will get called once and will then block for one second. +In the above code, `foo` will get called once and will then block for one second. -While `foo` blocks the code `setInterval` will still schedule further calls to +While `foo` blocks the code, `setInterval` will still schedule further calls to it. Now, when `foo` has finished, there will already be **ten** further calls to it waiting for execution. ### Dealing with Possible Blocking Code -The easiest as well as most controllable solution, is to use `setTimeout` within +The easiest solution, as well as most controllable solution, is to use `setTimeout` within the function itself. function foo(){ @@ -72,7 +72,7 @@ the function itself. foo(); Not only does this encapsulate the `setTimeout` call, but it also prevents the -stacking of calls and it gives additional control.`foo` itself can now decide +stacking of calls and it gives additional control. `foo` itself can now decide whether it wants to run again or not. ### Manually Clearing Timeouts @@ -86,7 +86,7 @@ the first place. ### Clearing all timeouts -As there is no built-in method for clearing all timeouts and/or intervals, +Because there is no built-in method for clearing all timeouts and/or intervals, it is necessary to use brute force in order to achieve this functionality. // clear "all" timeouts @@ -101,7 +101,7 @@ they can be cleared specifically. ### Hidden use of `eval` `setTimeout` and `setInterval` can also take a string as their first parameter. -This feature should **never** be used, since it internally makes use of `eval`. +This feature should **never** be used because it internally makes use of `eval`. > **Note:** Since the timeout functions are **not** specified by the ECMAScript > standard, the exact workings when a string is passed to them might differ in @@ -148,7 +148,7 @@ function that will get called by either of the timeout functions. to be supplied to the function that gets called. An *anonymous function* should be passed that then takes care of the actual call. -Further, the use of `setInterval` should be avoided since its scheduler is not +Furthermore, the use of `setInterval` should be avoided because its scheduler is not blocked by executing JavaScript. [1]: http://en.wikipedia.org/wiki/Document_Object_Model "Document Object Model" From 02ff4f618b2a566d20c45b1945cabc727c0a699f Mon Sep 17 00:00:00 2001 From: XP1 Date: Tue, 20 Sep 2011 22:09:53 -0300 Subject: [PATCH 123/463] Use a conjunction and comma. --- doc/en/intro/index.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/en/intro/index.md b/doc/en/intro/index.md index 6ddd7c71..134bca80 100644 --- a/doc/en/intro/index.md +++ b/doc/en/intro/index.md @@ -2,8 +2,8 @@ **JavaScript Garden** is a growing collection of documentation about the most quirky parts of the JavaScript programming language. It gives advice to -avoid common mistakes, subtle bugs, as well as performance issues and bad -practices that non-expert JavaScript programmers may encounter on their +avoid common mistakes and subtle bugs, as well as performance issues and bad +practices, that non-expert JavaScript programmers may encounter on their endeavours into the depths of the language. JavaScript Garden does **not** aim to teach you JavaScript. Former knowledge @@ -31,7 +31,7 @@ with a mirror at [JavaScriptGarden.info][8]. JavaScript Garden is published under the [MIT license][9] and hosted on [GitHub][10]. If you find errors or typos please [file an issue][11] or a pull request on the repository. You can also find us in the [JavaScript room][12] on -Stack Overflow chat. +Stack Overflow chat. [1]: https://developer.mozilla.org/en/JavaScript/Guide [2]: http://stackoverflow.com/ From 678e95812b08055303cdca56095b96c09c62cfbc Mon Sep 17 00:00:00 2001 From: HIRAKI Satoru Date: Sun, 25 Sep 2011 21:27:05 +0900 Subject: [PATCH 124/463] translate "The JavaScript Type Table" in "Types" to ja --- doc/ja/types/typeof.md | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/doc/ja/types/typeof.md b/doc/ja/types/typeof.md index 167837bb..e7485227 100644 --- a/doc/ja/types/typeof.md +++ b/doc/ja/types/typeof.md @@ -9,7 +9,7 @@ > `typeof`演算子のオペランドの値を返す振る舞いをします。 > `typeof`関数は存在**しません**。 -### The JavaScript Type Table +### JavaScript の型テーブル Value Class Type ------------------------------------- @@ -24,22 +24,20 @@ [1,2,3] Array object new Array(1, 2, 3) Array object new Function("") Function function - /abc/g RegExp object (function in Nitro/V8) - new RegExp("meow") RegExp object (function in Nitro/V8) + /abc/g RegExp object (Nitro/V8ではfunction) + new RegExp("meow") RegExp object (Nitro/V8ではfunction) {} Object object new Object() Object object -In the above table *Type* refers to the value, that the `typeof` operator returns. -As can be clearly seen, this value is anything but consistent. +上記のテーブルの*Type*は値を参照しており、`typeof`演算子が返ってきます。はっきりと分かるように、この値はどれでも一貫しています。 -The *Class* refers to the value of the internal `[[Class]]` property of an object. +*Class*はオブジェクト内部の`[[Class]]`プロパティの値を参照しています。 -> **From the Specification:** The value of `[[Class]]` can be one of the -> following strings. `Arguments`, `Array`, `Boolean`, `Date`, `Error`, +> **仕様より:** `[[Class]]`の値は以下の文字列のいずれかになります。 +> `Arguments`, `Array`, `Boolean`, `Date`, `Error`, > `Function`, `JSON`, `Math`, `Number`, `Object`, `RegExp`, `String`. -In order to retrieve the value of `[[Class]]` one has to make use of the -`toString` method of `Object.prototype`. +`[[Class]]`の値を取得する為に、`Object.prototype`メソッドの`toString`を使う事があります。 ### The Class of an Object From e9a55090192266ac368609a5b03322f4e9378b16 Mon Sep 17 00:00:00 2001 From: HIRAKI Satoru Date: Sun, 25 Sep 2011 21:58:19 +0900 Subject: [PATCH 125/463] translate "The Class of an Object" in "Types" to ja --- doc/ja/types/typeof.md | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/doc/ja/types/typeof.md b/doc/ja/types/typeof.md index e7485227..d67dc842 100644 --- a/doc/ja/types/typeof.md +++ b/doc/ja/types/typeof.md @@ -39,26 +39,22 @@ `[[Class]]`の値を取得する為に、`Object.prototype`メソッドの`toString`を使う事があります。 -### The Class of an Object +### オブジェクトのクラス -The specification gives exactly one way of accessing the `[[Class]]` value, -with the use of `Object.prototype.toString`. +仕様では`[[Class]]`の値にアクセスするためには`Object.prototype.toString`を使用した厳密な一つの方法が与えられています。 function is(type, obj) { var clas = Object.prototype.toString.call(obj).slice(8, -1); return obj !== undefined && obj !== null && clas === type; } - + is('String', 'test'); // true is('String', new String('test')); // true -In the above example, `Object.prototype.toString` gets called with the value of -[this](#function.this) being set to the object whose `[[Class]]` value should be -retrieved. +上記の例では[this](#function.this)の値と共に`Object.prototype.toString`が呼び出され`[[Class]]`の取得されている値がオブジェクトとして設定されます。 -> **ES5 Note:** For convenience the return value of `Object.prototype.toString` -> for both `null` and `undefined` was **changed** from `Object` to `Null` and -> `Undefined` in ECMAScript 5. +> **ES5での注意点:** 便宜上、ECMAScript 5では`Object.prototype.toString`の`null`と`undefined`は +> `Object`から`Null`と`Undefined`に**変更され**ました。 ### Testing for Undefined Variables From 843b9a7fb19fa05f6c4ea4d88a89bb5276f4e9f4 Mon Sep 17 00:00:00 2001 From: HIRAKI Satoru Date: Sun, 25 Sep 2011 22:39:36 +0900 Subject: [PATCH 126/463] translate "Testing for Undefined Variables" in "Types" to ja --- doc/ja/types/typeof.md | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/doc/ja/types/typeof.md b/doc/ja/types/typeof.md index d67dc842..8cbdf3e0 100644 --- a/doc/ja/types/typeof.md +++ b/doc/ja/types/typeof.md @@ -56,13 +56,11 @@ > **ES5での注意点:** 便宜上、ECMAScript 5では`Object.prototype.toString`の`null`と`undefined`は > `Object`から`Null`と`Undefined`に**変更され**ました。 -### Testing for Undefined Variables +### 未定義変数のテスト typeof foo !== 'undefined' -The above will check whether `foo` was actually declared or not; just -referencing it would result in a `ReferenceError`. This is the only thing -`typeof` is actually useful for. +上記では`foo`が実際に宣言されたかどうかを`ReferenceError`の結果を参照してチェックします。これは`typeof`が唯一実際に役に立つ場合です。 ### In Conclusion From 97a52d63865858e30ac539b817956522de67fd8a Mon Sep 17 00:00:00 2001 From: HIRAKI Satoru Date: Sun, 25 Sep 2011 22:46:39 +0900 Subject: [PATCH 127/463] form text --- doc/ja/types/typeof.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/doc/ja/types/typeof.md b/doc/ja/types/typeof.md index 8cbdf3e0..1dc68589 100644 --- a/doc/ja/types/typeof.md +++ b/doc/ja/types/typeof.md @@ -53,8 +53,10 @@ 上記の例では[this](#function.this)の値と共に`Object.prototype.toString`が呼び出され`[[Class]]`の取得されている値がオブジェクトとして設定されます。 -> **ES5での注意点:** 便宜上、ECMAScript 5では`Object.prototype.toString`の`null`と`undefined`は -> `Object`から`Null`と`Undefined`に**変更され**ました。 +> **ES5での注意点:** 便宜上、ECMAScript 5では +> `Object.prototype.toString`の +> `null`と`undefined`は`Object`から +> `Null`と`Undefined`に**変更され**ました。 ### 未定義変数のテスト From 4d659f8f7f2a19657efc24efdfad1bdcecf67da8 Mon Sep 17 00:00:00 2001 From: HIRAKI Satoru Date: Sun, 25 Sep 2011 23:10:39 +0900 Subject: [PATCH 128/463] translate "In Conclusion" in "Types" to ja --- doc/ja/types/typeof.md | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/doc/ja/types/typeof.md b/doc/ja/types/typeof.md index 1dc68589..8843c368 100644 --- a/doc/ja/types/typeof.md +++ b/doc/ja/types/typeof.md @@ -64,14 +64,8 @@ 上記では`foo`が実際に宣言されたかどうかを`ReferenceError`の結果を参照してチェックします。これは`typeof`が唯一実際に役に立つ場合です。 -### In Conclusion - -In order to check the type of an object, it is highly recommended to use -`Object.prototype.toString`; as this is the only reliable way of doing so. -As shown in the above type table, some return values of `typeof` are not defined -in the specification; thus, they can differ across various implementations. - -Unless checking whether a variable is defined, `typeof` should be avoided at -**all costs**. +### 終わりに +オブジェクトの型をチェックする為には、`Object.prototype.toString`を使用する事を強くお勧めします。これが唯一信頼できる方法だからです。上述の型テーブルでも分かるように、`typeof`の戻り値は仕様で定義されていないものを返します。よって、実装によって別の結果になる事があります。 +変数が定義されているかチェックしない限りは、`typeof`は**どんな事をしても**避けるべきです。 From 5eee4a896f1b435d527498e4d6bad0e02af19ec6 Mon Sep 17 00:00:00 2001 From: HIRAKI Satoru Date: Sun, 25 Sep 2011 23:51:35 +0900 Subject: [PATCH 129/463] translate "The `instanceof` Operator" in "Types" to ja --- doc/ja/types/instanceof.md | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/doc/ja/types/instanceof.md b/doc/ja/types/instanceof.md index 8711331a..0de57c9e 100644 --- a/doc/ja/types/instanceof.md +++ b/doc/ja/types/instanceof.md @@ -1,8 +1,6 @@ -## The `instanceof` Operator +## `instanceof`オペレーター -The `instanceof` operator compares the constructors of its two operands. It is -only useful when comparing custom made objects. Used on built-in types, it is -nearly as useless as the [typeof operator](#types.typeof). +`instanceof`オペレーターは2つのオペランドのコンストラクタを比較します。これはカスタムで作ったオブジェクトを比較する時にのみ有用です。組み込みの型に使用するのは[typeof operator](#types.typeof)を使用するのと同じくらい意味がありません。 ### Comparing Custom Objects From 3c7443f75c716204eafac9ae158bd0c2380b6520 Mon Sep 17 00:00:00 2001 From: HIRAKI Satoru Date: Mon, 26 Sep 2011 00:10:43 +0900 Subject: [PATCH 130/463] translate "Comparing Custom Objects" in "Types" to ja --- doc/ja/types/instanceof.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/ja/types/instanceof.md b/doc/ja/types/instanceof.md index 0de57c9e..1c1ff137 100644 --- a/doc/ja/types/instanceof.md +++ b/doc/ja/types/instanceof.md @@ -2,7 +2,7 @@ `instanceof`オペレーターは2つのオペランドのコンストラクタを比較します。これはカスタムで作ったオブジェクトを比較する時にのみ有用です。組み込みの型に使用するのは[typeof operator](#types.typeof)を使用するのと同じくらい意味がありません。 -### Comparing Custom Objects +### カスタムオブジェクトの比較 function Foo() {} function Bar() {} @@ -11,8 +11,8 @@ new Bar() instanceof Bar; // true new Bar() instanceof Foo; // true - // This just sets Bar.prototype to the function object Foo - // But not to an actual instance of Foo + // これは単に関数オブジェクトFooにBar.prototypeをセットしただけです。 + // しかし、実際のFooのインスタンスではありません。 Bar.prototype = Foo; new Bar() instanceof Foo; // false From 7e17fc6cec485d4ba694be7810a89f6c0a6ad9ed Mon Sep 17 00:00:00 2001 From: HIRAKI Satoru Date: Thu, 29 Sep 2011 02:18:47 +0900 Subject: [PATCH 131/463] translate "Using `instanceof` with Native Types" in "Types" to ja --- doc/ja/types/instanceof.md | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/doc/ja/types/instanceof.md b/doc/ja/types/instanceof.md index 1c1ff137..f3f6dc98 100644 --- a/doc/ja/types/instanceof.md +++ b/doc/ja/types/instanceof.md @@ -16,7 +16,7 @@ Bar.prototype = Foo; new Bar() instanceof Foo; // false -### Using `instanceof` with Native Types +### ネイティブ型で`instanceof`を使用する new String('foo') instanceof String; // true new String('foo') instanceof Object; // true @@ -24,9 +24,7 @@ 'foo' instanceof String; // false 'foo' instanceof Object; // false -One important thing to note here is, that `instanceof` does not work on objects -that origin from different JavaScript contexts (e.g. different documents -in a web browser), since their constructors will not be the exact same object. +ここで一つ重要な事は、この`instanceof`は異なるJavaScriptの文脈(例:ブラウザの異なるウィンドウ)では、そのコンストラクタが正確に同じオブジェクトになる訳では無いので、オリジナルのオブジェクトで動作しないという事です。 ### In Conclusion From b8b7eabd757c0978a8af31942e2bee8c1574c4fb Mon Sep 17 00:00:00 2001 From: HIRAKI Satoru Date: Thu, 29 Sep 2011 02:40:57 +0900 Subject: [PATCH 132/463] translate "In Conclusion" in "Types" to ja --- doc/ja/types/instanceof.md | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/doc/ja/types/instanceof.md b/doc/ja/types/instanceof.md index f3f6dc98..5dec8817 100644 --- a/doc/ja/types/instanceof.md +++ b/doc/ja/types/instanceof.md @@ -26,9 +26,6 @@ ここで一つ重要な事は、この`instanceof`は異なるJavaScriptの文脈(例:ブラウザの異なるウィンドウ)では、そのコンストラクタが正確に同じオブジェクトになる訳では無いので、オリジナルのオブジェクトで動作しないという事です。 -### In Conclusion - -The `instanceof` operator should **only** be used when dealing with custom made -objects that origin from the same JavaScript context. Just like the -[`typeof`](#types.typeof) operator, every other use of it should be **avoided**. +### 終わりに +`instanceof`オペレーターは同じJavaScriptのコンテキストが起源になっているカスタムメイドのオブジェクトを扱う場合**のみ**使うべきです。ちょうど[`typeof`](#types.typeof)オペレーターのように、その他での使用は**避けるべき**です。 From e7b639def32c93ff36103bb57e3659d6860205b4 Mon Sep 17 00:00:00 2001 From: HIRAKI Satoru Date: Thu, 29 Sep 2011 02:42:48 +0900 Subject: [PATCH 133/463] fix representation --- doc/ja/types/instanceof.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/ja/types/instanceof.md b/doc/ja/types/instanceof.md index 5dec8817..9efd399c 100644 --- a/doc/ja/types/instanceof.md +++ b/doc/ja/types/instanceof.md @@ -24,7 +24,7 @@ 'foo' instanceof String; // false 'foo' instanceof Object; // false -ここで一つ重要な事は、この`instanceof`は異なるJavaScriptの文脈(例:ブラウザの異なるウィンドウ)では、そのコンストラクタが正確に同じオブジェクトになる訳では無いので、オリジナルのオブジェクトで動作しないという事です。 +ここで一つ重要な事は、この`instanceof`は異なるJavaScriptのコンテキストが起源のオブジェクト(例:ブラウザの異なるウィンドウ)では、そのコンストラクタが正確に同じオブジェクトになる訳では無いので、同じオブジェクトとして動作しないという事です。 ### 終わりに From 03b779b4246343bdf2c6fec17ce93d1a49da983b Mon Sep 17 00:00:00 2001 From: Wang-Yue Date: Sat, 1 Oct 2011 00:29:15 -0400 Subject: [PATCH 134/463] modified: build.js update build.js to meet the current jade public api --- build.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/build.js b/build.js index 7fb93be0..36727aeb 100644 --- a/build.js +++ b/build.js @@ -164,10 +164,10 @@ var Garden = Class(function(options) { top: lang.navigation[0] }; - jade.renderFile(template, {locals: options}, function(err, html){ - if (err) throw err; - fs.writeFileSync(out, html); - }); + var jadefile = fs.readFileSync(template); + var jadetemplate = jade.compile (jadefile); + var html = jadetemplate(options); + fs.writeFileSync(out, html); this.log(' Done.'); } }, From 5dca6989fe34a0aa14605cafe808f5d56f278122 Mon Sep 17 00:00:00 2001 From: HIRAKI Satoru Date: Sun, 2 Oct 2011 02:54:59 +0900 Subject: [PATCH 135/463] translate "Type Casting" in "Types" to ja --- doc/ja/types/casting.md | 40 ++++++++++++++++++---------------------- 1 file changed, 18 insertions(+), 22 deletions(-) diff --git a/doc/ja/types/casting.md b/doc/ja/types/casting.md index 15d84e74..69595f7c 100644 --- a/doc/ja/types/casting.md +++ b/doc/ja/types/casting.md @@ -1,29 +1,25 @@ -## Type Casting - -JavaScript is a *weakly typed* language, so it will apply *type coercion* -**wherever** possible. - - // These are true - new Number(10) == 10; // Number.toString() is converted - // back to a number - - 10 == '10'; // Strings gets converted to Number - 10 == '+10 '; // More string madness - 10 == '010'; // And more - isNaN(null) == false; // null converts to 0 - // which of course is not NaN - - // These are false +## 型変換 + +JavaScriptは*弱い型付け*の言語なので、可能な**限り**に*型強制*が適用されます。 + + // これらはtrueです。 + new Number(10) == 10; // Number.toString()が変換される + // numberに戻る + + 10 == '10'; // StringsがNumberに変換される + 10 == '+10 '; // バカみたいに文字列を追加 + 10 == '010'; // もっともっと + isNaN(null) == false; // nullが0に変換される + // もちろんNaNではないです + + // これらはfalseです 10 == 010; 10 == '-10'; -> **ES5 Note:** Number literals that start with a `0` are interpreted as octal -> (Base 8). Octal support for these has been **removed** in ECMAScript 5 strict -> mode. +> **ES5での注意点:** `0`から始まるNumberリテラルは8進数(基数が8)として解釈されます。 +> このような8進数のサポートはECMAScript5のstrict modeでは**削除されました**。 -In order to avoid the above, use of the [strict equal operator](#types.equality) -is **highly** recommended. Although this avoids a lot of common pitfalls, there -are still many further issues that arise from JavaScript's weak typing system. +上記の自体を避ける為に、[strict equal operator](#types.equality)を使用する事を**強く**推奨します。また、これはたくさんある落し穴を避けますが、それでもまだJavaScriptの弱い型付けシステムから発生する色々な課題が残っています。 ### Constructors of Built-In Types From 918c19338fc91edc53cb3b8a2dbd1e655ba6d232 Mon Sep 17 00:00:00 2001 From: HIRAKI Satoru Date: Mon, 3 Oct 2011 00:48:45 +0900 Subject: [PATCH 136/463] translate "Constructors of Built-In Types" in "Types" to ja --- doc/ja/types/casting.md | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/doc/ja/types/casting.md b/doc/ja/types/casting.md index 69595f7c..5dbe560e 100644 --- a/doc/ja/types/casting.md +++ b/doc/ja/types/casting.md @@ -21,23 +21,19 @@ JavaScriptは*弱い型付け*の言語なので、可能な**限り**に*型強 上記の自体を避ける為に、[strict equal operator](#types.equality)を使用する事を**強く**推奨します。また、これはたくさんある落し穴を避けますが、それでもまだJavaScriptの弱い型付けシステムから発生する色々な課題が残っています。 -### Constructors of Built-In Types +### 組み込み型のコンストラクタ -The constructors of the built in types like `Number` and `String` behave -differently when being used with the `new` keyword and without it. +`Number`や`String`のような組み込み型のコンストラクタは、`new`キーワードの有無で振る舞いが違ってきます。 - new Number(10) === 10; // False, Object and Number - Number(10) === 10; // True, Number and Number - new Number(10) + 0 === 10; // True, due to implicit conversion + new Number(10) === 10; // False, ObjectとNumber + Number(10) === 10; // True, NumberとNumber + new Number(10) + 0 === 10; // True, 暗黙の型変換によります -Using a built-in type like `Number` as a constructor will create a new `Number` -object, but leaving out the `new` keyword will make the `Number` function behave -like a converter. +`Number`のような組み込み型をコンストラクタとして使うと、新しい`Number`オブジェクトが作られますが、`new`キーワードを除外すると`Number`関数がコンバーターのように振る舞います。 -In addition, having literals or non-object values in there will result in even -more type coercion. +加えて、リテラルかオブジェトではない値を持っていると、さらに型強制が多くなります。 -The best option is to cast to one of the three possible types **explicitly**. +最良のオプションは以下の3つの方法の内、1つで型を**明示**する事になります。 ### Casting to a String From 7bf431f8ae81851f11b737734af5f3df906e9a6b Mon Sep 17 00:00:00 2001 From: HIRAKI Satoru Date: Mon, 3 Oct 2011 00:52:04 +0900 Subject: [PATCH 137/463] add representation --- doc/ja/types/casting.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/ja/types/casting.md b/doc/ja/types/casting.md index 5dbe560e..6697a2a3 100644 --- a/doc/ja/types/casting.md +++ b/doc/ja/types/casting.md @@ -33,7 +33,7 @@ JavaScriptは*弱い型付け*の言語なので、可能な**限り**に*型強 加えて、リテラルかオブジェトではない値を持っていると、さらに型強制が多くなります。 -最良のオプションは以下の3つの方法の内、1つで型を**明示**する事になります。 +最良のオプションは以下の3つの方法の内、1つで型を**明示**してキャストする事になります。 ### Casting to a String From 0781d00f50694965e34af7a1665e0286682057d1 Mon Sep 17 00:00:00 2001 From: HIRAKI Satoru Date: Mon, 3 Oct 2011 00:54:45 +0900 Subject: [PATCH 138/463] translate "Casting to a String" in "Types" to ja --- doc/ja/types/casting.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/ja/types/casting.md b/doc/ja/types/casting.md index 6697a2a3..d4693281 100644 --- a/doc/ja/types/casting.md +++ b/doc/ja/types/casting.md @@ -35,11 +35,11 @@ JavaScriptは*弱い型付け*の言語なので、可能な**限り**に*型強 最良のオプションは以下の3つの方法の内、1つで型を**明示**してキャストする事になります。 -### Casting to a String +### Stringでキャストする '' + 10 === '10'; // true -By prepending a empty string a value can easily be casted to a string. +空の文字列の付加により値を簡単に文字列にキャストできます。 ### Casting to a Number From a7526c9c8edd0f7cd5f34fd988ef75cbbf9695e7 Mon Sep 17 00:00:00 2001 From: HIRAKI Satoru Date: Mon, 3 Oct 2011 00:57:23 +0900 Subject: [PATCH 139/463] translate "Casting to a Number" in "Types" to ja --- doc/ja/types/casting.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/ja/types/casting.md b/doc/ja/types/casting.md index d4693281..8b8b14da 100644 --- a/doc/ja/types/casting.md +++ b/doc/ja/types/casting.md @@ -41,11 +41,11 @@ JavaScriptは*弱い型付け*の言語なので、可能な**限り**に*型強 空の文字列の付加により値を簡単に文字列にキャストできます。 -### Casting to a Number +### Numberでキャストする +'10' === 10; // true -Using the **unary** plus operator it is possible to cast to a number. +**単項**プラスオペレーターを使うと数字にキャストする事が可能です。 ### Casting to a Boolean From fbe1dd72b5da7430bac23fc055d1c3a7938e2eb2 Mon Sep 17 00:00:00 2001 From: HIRAKI Satoru Date: Mon, 3 Oct 2011 01:04:54 +0900 Subject: [PATCH 140/463] translate "Casting to a Boolean" in "Types" to ja --- doc/ja/types/casting.md | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/doc/ja/types/casting.md b/doc/ja/types/casting.md index 8b8b14da..44446ea1 100644 --- a/doc/ja/types/casting.md +++ b/doc/ja/types/casting.md @@ -47,9 +47,9 @@ JavaScriptは*弱い型付け*の言語なので、可能な**限り**に*型強 **単項**プラスオペレーターを使うと数字にキャストする事が可能です。 -### Casting to a Boolean +### Booleanでキャストする -By using the **not** operator twice, a value can be converted a boolean. +**not**オペレーターを2回使うと、値はブーリアンに変換できます。 !!'foo'; // true !!''; // false @@ -58,5 +58,3 @@ By using the **not** operator twice, a value can be converted a boolean. !!'-1' // true !!{}; // true !!true; // true - - From 633aaf0b93d0247a9dfec21cf030fb2d61c3c1f5 Mon Sep 17 00:00:00 2001 From: HIRAKI Satoru Date: Tue, 4 Oct 2011 08:52:03 +0900 Subject: [PATCH 141/463] fix lint warnig --- build.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/build.js b/build.js index 36727aeb..50e9d0c5 100644 --- a/build.js +++ b/build.js @@ -1,5 +1,5 @@ var fs = require('fs'), - path = require('path'); + path = require('path'), jade = require('jade'), md = require('node-markdown'), Class = require('neko').Class; @@ -28,10 +28,10 @@ var Garden = Class(function(options) { if (that.loadIndex()) { that.languages[lang] = that.lang; - that.log(' Done.') + that.log(' Done.'); } else { - that.log(' Error: Could not find "index.json"!') + that.log(' Error: Could not find "index.json"!'); } } }); From d176cc6657a9d89070ce02bdfad6304a7afaf272 Mon Sep 17 00:00:00 2001 From: Nathan L Smith Date: Tue, 4 Oct 2011 09:51:47 -0500 Subject: [PATCH 142/463] add site/pl to gitignore Conflicts: site/pl/index.html --- .gitignore | 1 + site/pl/index.html | 1911 -------------------------------------------- 2 files changed, 1 insertion(+), 1911 deletions(-) delete mode 100644 site/pl/index.html diff --git a/.gitignore b/.gitignore index fecb262f..831db28d 100644 --- a/.gitignore +++ b/.gitignore @@ -8,6 +8,7 @@ /site/zh /site/en /site/fi +/site/pl /site/tr *.md~ *.src.md diff --git a/site/pl/index.html b/site/pl/index.html deleted file mode 100644 index 7542ba1d..00000000 --- a/site/pl/index.html +++ /dev/null @@ -1,1911 +0,0 @@ -JavaScript Garden -

Wstęp

JavaScript Garden jest rosnącą kolekcją dokumentów o najdziwniejszych -częściach języka JavaScript. Dokumentacja pomaga uniknąć najczęściej popełnianych -błędów, sybtelnych bugów, problemów wydajnościowych oraz złych praktyk, na które -niedoświadczeni programiści JavaScript mogą natrafić próbując poznać tajniki tego -języka.

- -

JavaScript Garden nie ma na celu nauczyć Cię języka JavaScript. Podstawowa -wiedza na temat języka jest wymagana do zrozumienia zagadnień poruszanych w tym -przewodniku. Aby nauczyć się podstaw jezyka JavaScript, odwiedź znakomity -przewodnik na stronach Mozilla Developer Network.

Licencja

JavaScript Garden jest publikowany w ramach licencji MIT i kod źródłowy znajduje -się na serwerze GitHub. Jeśli znajdziesz jakieś błędy lub literówek zgłoś proszę -problem lub rozwiąż go i zgloś pull request ze swojego repozytorium. -Możesz nas także znaleźć w pokoju JavaScript na chacie Stack Overflow.

Obiekty

Wykorzystanie obiektów i ich właściwości

Wszystko w JavaScripcie zachowuje sie jak obiekt, z dwoma wyjątkami -null oraz undefined.

- -
false.toString() // 'false'
-[1, 2, 3].toString(); // '1,2,3'
-
-function Foo(){}
-Foo.bar = 1;
-Foo.bar; // 1
-
- -

Popularnym błędem jest traktowanie literałów liczbowych jak obiektu. -Spowodowane jest to specyfiką parsera JavaScript, który interpretuje kropkę -po literale liczbowym jako rozdzielenie części całkowitej od części ułamkowej -liczby.

- -
2.toString(); // wyrzuca błąd SyntaxError
-
- -

Istnieje kilka rozwiązań, dzieki którym literał liczbowy będzie zachowywał się -jak obiekt.

- -
2..toString(); // druga kropka jest poprawnie rozpoznana
-2 .toString(); // zauważ, że pozostawiona jest spacja przed kropką
-(2).toString(); // 2 zostanie najpierw zewaluowane
-
- -

Obiekty jako typy danych

- -

Obiekty w języku JavaScript mogą być używana jako tablice asocjacyjne, -ponieważ obiekty składają się głównie z mapowań pomiędzy nazwanymi właściwościami (kluczami) -a wartościami dla tych atrybutów.

- -

Używając literału obiektu - notacji {} - istnieje możliwość stworzenia obiektu prostego. -Ten nowy obiekt bedzie dziedziczył z Object.prototype oraz -nie bedzie posiadał żadnych własnych właściwości.

- -
var foo = {}; // nowy, pusty obiekt
-
-// nowy obiekt z właściwością test o wartości 12
-var bar = {test: 12}; 
-
- -

Dostęp do właściwości

- -

Właściwości obiektu można uzyskać na dwa sposoby - poprzez notację z kropką -lub z nawiasami kwadratowymi.

- -
var foo = {name: 'Kitten'}
-foo.name; // kitten
-foo['name']; // kitten
-
-var get = 'name';
-foo[get]; // kitten
-
-foo.1234; // wyrzuca błąd SyntaxError
-foo['1234']; // działa, zwraca undefined
-
- -

Obie notacje są identyczne w swoim działaniu, z tą tylko różnicą, że notacja z nawiasami -kwadratowymi pozwala na dynamiczne dodawanie właściwości i nie prowadzi do wyrzucenia -błędu podczas odczytu nieistniejącej właściwości.

- -

Usuwanie właściwości

- -

Jedynym sposobem na faktycze usunięcie własności z obiektu jest użycie operatora -delete. Ustawienie własności na undefined lub null usunie tylko wartość -związaną z własnością, ale nie usunie to klucza (nazwy własności) z obiektu.

- -
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]);
-    }
-}
-
- -

Powyższy kod wypisuje dwie linie - bar undefined i foo null. Tylko własność baz -została usunięta i dlatego nie została wypisana.

- -

Notacja właściwości

- -
var test = {
-    'case': 'jestem zastrzeżonym słowem kluczowym, więc muszę być w cudzysłowie',
-    delete: 'tak samo jak ja' // wyrzuca błąd SyntaxError
-};
-
- -

Nazwy właściwości obiektu mogą być zarówno zapisane jako tekst (bez cudzysłowów -lub apostrofów) lub jako string (w cudzisłowach lub apostrofach). -Ze względu na kolejne niedociągnięcie w parserze JavaScript, -powyższy kod wyrzuci błąd SyntaxError dla implementacji JavaScript ponizej ECMAScript 5.

- -

Ten błąd wynika z faktu, że delete jest słowem kluczowym, dlatego musi zostać -zapisany jako string (z cudzysłowami lub apostrofami), aby zapewnić, że zostanie -to poprawnie zinterpretowane przez starsze silniki języka JavaScript.

Prototyp

JavaScript nie posiada klasycznego modelu dziedziczenia. Zamiast tego -dziedziczenie jest realizowane poprzez prototypy.

- -

Choć jest to często uważane za jedną ze słabości języka JavaScript, -prototypowy model dziedziczenia, jest w rzeczywistości potężniejszy od klasycznego -modelu. Na przykład stworzenia klasycznego modelu na podstawie modelu prototypowego -jest dość proste, podczas gdy zrobienie odwrotnego przekształcenie to o wiele trudniejsze zadanie.

- -

Ze względu na fakt, że w JavaScript jest w zasadzie jedynym powszechnie stosowanym -językiem, któy posiada prototypowy model dziedziczenia, dostosowanie się do różnic pomiędzy -tymi dwoma modelami wymaga trochę czasu.

- -

Pierwszą znaczącą różnicą jest to, że dziedziczenie w JavaScript odbywa się za pomocą -tak zwanych łańcuchów prototypów.

- - - -
function Foo() {
-    this.value = 42;
-}
-Foo.prototype = {
-    method: function() {}
-};
-
-function Bar() {}
-
-// Ustawienie prototypu Bar na nową instancję Foo
-Bar.prototype = new Foo();
-Bar.prototype.foo = 'Hello World';
-
-// Upewniamy się, że Bar jest ustawiony jako rzeczywisty konstruktor
-Bar.prototype.constructor = Bar;
-
-var test = new Bar() // tworzymy nową instancję Bar
-
-// The resulting prototype chain
-test [instance of Bar]
-    Bar.prototype [instance of Foo] 
-        { foo: 'Hello World' }
-        Foo.prototype
-            { method: ... }
-            Object.prototype
-                { toString: ... /* etc. */ }
-
- -

W powyższym przykładzie obiekt test będzie dziedziczył z obydwu, tj. -Bar.prototyp i Foo.prototyp, stąd będzie miał dostęp do funkcji method, -która była zdefiniowana w Foo. Ponadto obiekt będzie miał dostęp do -właściwości value, która jest jednyną instancją Foo i stała się jego prototypem. -Należy pamiętać, że new Bar nie tworzy nowej instancji Foo, -tylko wykorzystuje instancję, która jest przypisana do własności prototype. -Zatem Wszystkie instancje Bar będą dzieliły tą samą własność value.

- - - -

Wyszukiwanie własności

- -

Podczas dostępu do właściwości obiektu JavaScript przejdzie w górę łańcucha -prototypów, dopóki nie znajdzie właściwości bez nazwy.

- -

Gdy przeszukiwanie dotrze do końca (szczytu) łańcucha, mianowicie Object.prototype -i nadal nie znajdzie określonej właściwości, to zwróci wartość -undefined.

- -

Właściwość prototype

- -

Podczas gdy właściwość prototype jest używana przez język do budowania łańcucha -prototypów, istnieje możliwość przypisania do niej dowolnej wartości. Jednakże -prymitywne typy będą po prostu ignorowanie, jeżeli zostaną ustawione jako prototype.

- -
function Foo() {}
-Foo.prototype = 1; // nie ma wpływu
-
- -

Przypisywanie obiektów, jak pokazano w powyższym przykładzie, zadziała i pozwala -na dynamiczne tworzenie łańcuchów prototypów.

- -

Wydajność

- -

Czas wyszukiwania właściwości, które są na końcu łańcucha prototypów może mieć -negatywny wpływ na wydajność krytycznych części kodu. Dodatkowo, próba dostępu -do nieistniejącej właściwości zawsze spowoduje przeszukanie całego łańcucha prototypów.

- -

Również podczas iteracji po właściwościach obiektu -każda właściwość, która znajduje się w łańcuchu prototypów (niezależnie -na jakim znajduje się poziomie) zostanie wyliczona.

- -

Rozszerzanie natywnych prototypów

- -

Rozszerzanie Object.prototype lub innego prototypu wbudowanych typów jest jednym z -najczęściej nadużywanej częsci języka JavaScript.

- -

Technika ta nazywana jest monkey patching i łamie zasady enkapsulacji. -Mimo to jest szeroko rozpowszechniona w frameworkach takich jak Prototype. -Nie ma jednak dobrego powodu, aby zaśmiecać wbudowane typy poprzez wzbogacanie ich o -niestandardowe funkcjonalności.

- -

Jedynym dobrym powodem do rozszerzania wbudowanych prototypów jest portowanie
-funkcjonalności znajdujących sie w nowszych silnikach JavaScript, np. Array.forEach

- -

Wnioski

- -

Zanim przystąpi się do pisania skomplikowanego kodu korzystającego z dziedziczania,
-należy całkowicie zrozumieć prototypowy model dziedziczenia. Ponadto trzeba uważać -na długość łańcucha prototypów i w razie potrzeby zmniejszać ilość dziedziczeń, -aby uniknąć problemów z wydajnością. Natywne prototypy nigdy nie powinny być -rozszerzane, chyba że ze względu na wprowadzanie kompatybilności z nowszymi silnikami -JavaScript.

hasOwnProperty

W celu sprawdzenia, czy dana właściwość została zdefiniowana w tym obiekcie, a nie -w łańcuchu prototypów, niezbędne jest skorzystanie z metody -hasOwnProperty, której wszystkie obiekty dziedziczą z Object.prototype.

- - - -

hasOwnProperty jest jedyną metodą w języku JavaScript, która operuje na właściwościach -i nie przegląda całego łańcucha prototypów.

- -
// Zatrucie Object.prototype
-Object.prototype.bar = 1; 
-var foo = {goo: undefined};
-
-foo.bar; // 1
-'bar' in foo; // true
-
-foo.hasOwnProperty('bar'); // false
-foo.hasOwnProperty('goo'); // true
-
- -

Tylko hasOwnProperty da prawidłowy i oczekiwany rezultat. Jest to istotne podczas -iteracji po właściwościach obiektu. Nie ma innego sposobu na ominięcie -właściwości, która nie została zdefiniowana przez ten konkretny obiekt, -ale gdzieś indziej w łańcuchu prototypów.

- -

hasOwnProperty jako właściwość

- -

JavaScript nie chroni właściwości o nazwie hasOwnProperty, zatem istnieje -możliwość, że obiekt będzie posiadać tak nazwaną właściwość. Konieczne jest użycie -zewnętrznego hasOwnProperty, aby otrzymać poprawne rezultaty.

- -
var foo = {
-    hasOwnProperty: function() {
-        return false;
-    },
-    bar: 'Here be dragons'
-};
-
-foo.hasOwnProperty('bar'); // zawsze zwraca false
-
-// Została użyta metoda innego obiektu i wywołana z konkekstem 
-// `this` ustawionym na foo
-({}).hasOwnProperty.call(foo, 'bar'); // true
-
- -

Wnioski

- -

Jedyną metodą służącą do sprawdzenia istnienia jakiejś właściwości w konkretnym -obiekcie jest metoda hasOwnProperty. Zaleca się korzystać z hasOwnProperty w -każdej pętli for in. Pozwoli to uniknąć błędów pochodzących -z rozszerzonych natywnych prototypów.

Pętla for in

Podobnie jak operator in, pętla for in przeszukuje łańcuch prototypów -podczas iteracji po właściwościach obiektu.

- - - -
// Zatrucie Object.prototype
-Object.prototype.bar = 1;
-
-var foo = {moo: 2};
-for(var i in foo) {
-    console.log(i); // wyświetla obie właściwości: bar i moo
-}
-
- -

Ponieważ zmiana zachowania pętli for in nie jest możliwa, niezbędne -jest odfiltrowanie niechcianych właściwości wewnątrz ciała pętli, korzystając -z metody hasOwnProperty z Object.prototype.

- - - -

Filtrowania przy użyciu hasOwnProperty

- -
// foo z przykładu powyżej
-for(var i in foo) {
-    if (foo.hasOwnProperty(i)) {
-        console.log(i);
-    }
-}
-
- -

To jest jedyna poprawna wersja, której należy używać. Ze względu na użycie -hasOwnProperty zostanie wypisane jedynie moo. Gdy opuścimy hasOwnProperty, -kod będzie podatny na błędy, gdy natywne prototypy (np. Object.prototype) -zostaną rozszerzone.

- -

Prototype jest jednym z popularniejszych frameworków, które dokonują -takiego rozszerzenia. Używanie tego frameworku oraz nie stosowanie w pętli for in -metody hasOwnProperty gwarantuje błędy w wykonaniu.

- -

Wnioski

- -

Zaleca się, aby zawsze używać metody hasOwnProperty. Nigdy nie powinno się dokonywać -żadnych założeń na temat środowiska, w którym kod będzie wykonywany ani tego, czy -natywne prototypy zostały rozszerzone, czy nie.

Funkcje

Deklaracje funkcji i wyrażenia funkcyjne

Funcje w języku JavaScript są typami pierwszoklasowymi, co oznacza, że mogą -być przekazywane jak każda inna wartość. Jednym z typowych zastosowań tej cechy -jest przekazywanie anonimowej funkcji jako callback do innej, prawdopodobnie -asynchronicznej funkcji.

- -

Deklaracja funckcji

- -
function foo() {}
-
- -

Powyższa funkcja zostaje wyniesiona zanim program wystartuje. Dzięki temu -jest dostępna wszędzie w ramach zasięgu, w którym została zadeklarowana, -nawet, jeżeli ta funkcja została wywołana przed faktyczną definicją w kodzie źródłowym.

- -
foo(); // Działa ponieważ definicja funkcji została wyniesiona 
-       // na początek zasięgu przed uruchomieniem kodu
-function foo() {}
-
- -

Wyrażenie funkcyjne

- -
var foo = function() {};
-
- -

Ten przykład przypisuje nienazwaną i anonimową funkcję do zmiennej foo.

- -
foo; // 'undefined'
-foo(); // wyrzuca błąd TypeError
-var foo = function() {};
-
- -

Ze względu na fakt, że deklaracja var wynosi zmienną foo na początek zasięgu -zanim kod faktycznie zostanie uruchomiony, foo będzie zdefiniowane kiedy skrypt -będzie wykonywany.

- -

Ale ponieważ przypisania robione są dopiero podczas wykonania, wartość foo będzie -ustawiona na domyślną wartość undefined zanim powyższy kod -zostanie uruchomiony.

- -

Nazwane wyrażenia funkcyjne

- -

Kolejnym specjalnym przypadkiem jest przypisanie nazwanej funkcji.

- -
var foo = function bar() {
-    bar(); // Działa
-}
-bar(); // wyrzuca ReferenceError
-
- -

W zewnętrznym zakresie bar nie będzie dostępna, ponieważ funkcja zostaje -przypisana do foo, jednakże w wewnętrznym zakresie bar będzie dostępna. -Jest to spowodowane tym, jak działa rozwiązywanie nazw -w języku JavaScript. Nazwa funkcji jest zawsze dostępna w lokalnym -zakresie tej funkcji.

Jak działa this

JavaScript posiada inną koncepcję odnośnie tego na co wskazuje słowo kluczowe -this, niż większość innych języków programowania. Istnieje dokładnie -pięć różnych sytuacji, w których wartość this jest przypisana w języku JavaScript.

- -

JavaScript has a different concept of what the special name this refers to -than most other programming languages do. There are exactly five different -ways in which the value of this can be bound in the language.

- -

Zasięg globalny

- -
this;
-
- -

Używanie this w globalnym zasięgu, zwróci po prostu referencję do obiektu global.

- -

Wywołanie funkcji

- -
foo();
-
- -

Tutaj this również będzie wkazywało na obiekt global

- - - -

Wywoływanie metody

- -
test.foo(); 
-
- -

W tym przypadku this będzie wskazywało na test.

- -

Wywołanie konstruktora

- -
new foo(); 
-
- -

Wywołanie funkcji, które jest poprzedzone słowem kluczowym new, zachowuje się -jak konstruktor. Wewnątrz funkcji this będzie -wskazywało na nowo utworzony obiekt.

- -

Jawne ustawienie this

- -
function foo(a, b, c) {}
-
-var bar = {};
-foo.apply(bar, [1, 2, 3]); // tablica zostanie zamieniona w to co poniżej
-foo.call(bar, 1, 2, 3); // rezultat a = 1, b = 2, c = 3
-
- -

Używając metod call lub apply z prototypu Function.prototype, wartość this -wewnątrz wołanej funkcji zostanie jawnie ustawiona na pierwszy argument przekazany -podczas wywołania tych metod.

- -

Zatem w powyższym przykładzie przypadek Wywoływanie metody nie będzie miał -miejsca i this wewnątrz foo będzie wskazywać na bar.

- - - -

Częste pułapki

- -

Mimo iż Większość z tych przypadków ma sens, to pierwszy przypadek powinien być -traktorany jako błąd podczas projektowania języka i nigdy nie wykorzystywany -w praktyce.

- -
Foo.method = function() {
-    function test() {
-        // wewnątrz tej funkcji this wskazuje na obiekt global
-    }
-    test();
-}
-
- -

Powszechnym błędem jest myślenie, że this wewnątrz test wskazuje na Foo, -podczas gdy w rzeczywistości tak nie jest.

- -

Aby uzyskać dostęp do Foo wewnątrz test, niezbędne jest stworzenie wewnątrz -metody lokalnej zmiennej, która będzie wskazywała na Foo.

- -
Foo.method = function() {
-    var that = this;
-    function test() {
-        // Należy używać that zamiast this wewnątrz tej funkcji
-    }
-    test();
-}
-
- -

that jest zwykłą zmienną, ale jest to powszechnie stosowana konwencja otrzymywania
-wartości zewnętrznego this. W połączeniu z domknięciami(closures), -jest to sposób na przekazywanie wartości this wokół.

- -

Metody przypisywania

- -

Kolejną rzeczą, która nie działa w języku JavaScript, jest nadawanie aliasów -funkcjom, co oznacza przypisanie metody do zmiennej.

- -
var test = someObject.methodTest;
-test();
-
- -

Podobnie jak w pierwszym przypadku test zachowuje się jak wywołanie zwykłej -funkcji, a zatem wewnątrz funkcji this już nie będzie wskazywało someObject.

- -

Podczas gdy późne wiązanie this może się na początku wydawać złym pomysłem, -to w rzeczywistości jest to rzecz, która sprawia, że -dziedziczenie prototypowe działa.

- -
function Foo() {}
-Foo.prototype.method = function() {};
-
-function Bar() {}
-Bar.prototype = Foo.prototype;
-
-new Bar().method();
-
- -

Kiedy metoda method zostanie wywołana na instancji Bar, this będzie -wskazywało właśnie tę instancję.

Domknięcia i referencje

Jedną z najpotężniejszych funkcjonalności języka JavaScript są domknięcia. -Oznacza to że zasięg zawsze posiada dostęp do zewnętrznego zasięgu, w którym -został zdefiniowany. Ponieważ zasięg w JavaScript można definiować tylko poprzez -funckję, wszystkie funkcje domyślnie zachowują się jak domknięcia.

- -

Emulowanie prywatnych zmiennych

- -
function Counter(start) {
-    var count = start;
-    return {
-        increment: function() {
-            count++;
-        },
-
-        get: function() {
-            return count;
-        }
-    }
-}
-
-var foo = Counter(4);
-foo.increment();
-foo.get(); // 5
-
- -

Tutaj Counter zwraca dwa domknięcia: funkcję increment oraz funkcję get. -Obie te funkcje trzymają referencję do zasięgu Counter, a co za tym idzie -zawsze posiadają dostęp do zmiennej count tak, jakby ta zmienna była zdefiniowana -w zasięgu tych funkcji.

- -

Dlaczego zmienne prywatne działają?

- -

Ponieważ nie ma możliwości wskazania lub przypisania zasięgu w JavaScript, -nie istnieje sposób, aby uzyskać dostęp do zmiennej count z zewnątrz. -Wykorzystanie tych dwóch domknięć jest jedynym sposobem na interakcję z tą zmienną.

- -
var foo = new Counter(4);
-foo.hack = function() {
-    count = 1337;
-};
-
- -

Powyższy kod nie zmieni wartości zmiennej count wewnątrz zasięgu Counter, -ponieważ foo.hack nie została zadeklarowana wewnątrz tego konkretnego zasięgu. -Zamiast tego funkcja utworzy lub nadpisze globalną zmienną count.

- -

Domknięcia wewnątrz pętli

- -

Jednym z częstrzych błędów jest wykorzystywanie domknięć wewnątrz pętli, -aby wartość zmiennej po której odbywa się iteracja była kopiowana do -wewnętrznej funkcji.

- -
for(var i = 0; i < 10; i++) {
-    setTimeout(function() {
-        console.log(i);  
-    }, 1000);
-}
-
- -

Powyższy kod nie wypisze numerów od 0 do 9, ale wypisze -dziesięć razy liczbę 10.

- -

Anonimowa funkcja trzyma wskaźnik do zmiennej i i podczas uruchomienia -console.log, pętla for już zakończyła działanie i wartość zmiennej i -została ustawiona na 10.

- -

Aby otrzymać zamierzony efekt, niezbędne jest skopiowanie wartości -zmiennej i.

- -

Unikanie problemu z referencją

- -

Aby skopiować wartość zmiennej, po której iterujemy w pętli, należy skorzystać -z anonimowego wrappera.

- -
for(var i = 0; i < 10; i++) {
-    (function(e) {
-        setTimeout(function() {
-            console.log(e);  
-        }, 1000);
-    })(i);
-}
-
- -

Zewnętrzna anonimowa funkcja zostanie wywołana od razu z parametrem i -jako pierwszym argumentem oraz otrzyma kopię wartości zmiennej i jako -zmienną e.

- -

Anonimowa funkcja która zostaje przekazana do setTimeout teraz posiada -referencję do zmiennej e, która nie zostanie zmieniona przez pętle for.

- -

Istnieje jeszcze jeden sposób na osiągnięcie tego samego efektu. Należy zwrócic -fukcję z anonimowego wrappera, wówczas kod będzie zachowywał się jak ten -wcześniejszy.

- -
for(var i = 0; i < 10; i++) {
-    setTimeout((function(e) {
-        return function() {
-            console.log(e);
-        }
-    })(i), 1000)
-}
-

Obiekt arguments

Każdy zasięg funkcyjny w języku JavaScript ma dostęp do specjalnej zmiennej arguments. -Ta zmienna trzyma listę wszystkich argumentów przekazanych do funkcji.

- - - -

Obiekt arguments nie jest typu Array. Mimo że posiada pewne cechy -semantyki tablic - właściwość length - to w rzeczywistości nie dziedziczy -on z Array.prototype, tylko z Object.

- -

Ze względu na to, na obiekcie arguments nie można używać standardowych dla tablic metod, -takich jak push, pop czy slice. Mimo że iteracja przy pomocy -pętli for działa dobrze, to aby skorzystać ze standardowych metod tablicowych -należy skonwertować arguments do prawdziwego obiekt Array.

- -

Konwersja do tablicy

- -

Poniższy kod zwróci nowy obiekt Array zawierający wszystkie elementy -obiektu arguments.

- -
Array.prototype.slice.call(arguments);
-
- -

Jednakże konwersja ta jest wolna i nie jest zalecana w sekcjach, -które mają duży wpływ na wydajność.

- -

Przekazywanie argumentów

- -

Zalecany sposób przekazywania argumentów z jednej funkcji do następnej -wyglada następująco:

- -
function foo() {
-    bar.apply(null, arguments);
-}
-function bar(a, b, c) {
-    // do stuff here
-}
-
- -

Kolejną sztuczką jest użycie razem call i apply w celu stworzenia -szybkich i nieograniczonych wrapperów.

- -
function Foo() {}
-
-Foo.prototype.method = function(a, b, c) {
-    console.log(this, a, b, c);
-};
-
-// Stworzenie nieograniczoną wersję metody "method" 
-// która przyjmuje parametry: this, arg1, arg2...argN
-Foo.method = function() {
-
-    // Rezultat: Foo.prototype.method.call(this, arg1, arg2... argN)
-    Function.call.apply(Foo.prototype.method, arguments);
-};
-
- -

Parametry formalne i indeksy argumentów

- -

Obiekt arguments tworzy funkcje getter i setter nie tylko dla swoich -właściwości, ale również dla parametrów formalnych funkcji.

- -

W rezultacie zmiana wartości parametru formalnego zmieni również wartość -odpowiadającemu mu wpisowi w obiekcie arguments. Zachodzi to również w drugą stronę.

- -
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);
-
- -

Mity i prawdy o wydajności

- -

Obiekt arguments jest tworzony zawsze, z wyjątkiem dwóch przypadków, gdy -zmienna o takiej nazwie jest zdefiniowana wewnątrz funkcji lub jeden z parametrów -formalnych funkcji ma taką nazwę. Nie ma znaczenia czy obiekt arguments jest -używany czy nie.

- -

Zarówno gettery jak i settery są zawsze tworzone, zatem używanie ich nie ma -praktycznie żadnego wpływu na wydajność. Zwłaszcza w rzeczywistym kodzie, który -wykorzystuje coś więcej niż tylko prosty dostęp do właściwości obiektu arguments.

- - - -

Jednakże, istnieje jeden przypadek w którym wydajność drastycznie spada w -nowoczesnych silnikach JavaScript. Ten przypadek to wykorzystanie -arguments.callee.

- -
function foo() {
-    arguments.callee; // operowanie na obiekcie funkcji
-    arguments.callee.caller; // i obiekcie funkcji wywołującej
-}
-
-function bigLoop() {
-    for(var i = 0; i < 100000; i++) {
-        foo(); // Normalnie zostałaby wykorzystana metoda inline
-    }
-}
-
- -

W powyższym przykładzie foo nie może zostać wykorzystana metoda inline -ponieważ potrzebne są nie tylko informacje na własny temat ale również -na temat funkcji wywołującej. Takie użycie nie tylko uniemożliwia -inlining i korzyści z niego wynikające, ale też łamie zasady enkapsulacji, -ponieważ ta funkcja jest zależna od kontekstu w jakim została wywołana.

- -

Mocno zalecane jest aby nigdy nie korzystać z arguments.callee -i żadnej jej własności.

- -

Konstruktory

Konstruktory w JavaScript również wyglądają inaczej niż innych językach. Każde -wywołanie funkcji, które jest poprzedone słowem kluczowym new, zachowuje się -jak konstruktor.

- -

Wewnątrz konstruktora - wywoływanej fukcji - wartość this wskazuje na -nowo utworzony obiekt Object. Prototyp prototype tego -nowego obiektu będzie wskazywał na prototyp prototype obiektu fukcji, -która została wywołana jako konstruktor.

- -

Jeżeli wywołana funkcja nie posiada jawnej deklaracji return, wówczas -fukcja domyślnie zwraca wartość this - nowy obiekt.

- -
function Foo() {
-    this.bla = 1;
-}
-
-Foo.prototype.test = function() {
-    console.log(this.bla);
-};
-
-var test = new Foo();
-
- -

Powyżej wywołanya została funkcja Foo jako konstruktor oraz ustawia -nowo utworzonemu obiektowi właściwość prototype na Foo.prototype.

- -

W tym przypadku jawna deklaracja return w funkcji zwraca wartość -ustawioną w deklaracji, ale tylko jeżeli zwracaną wartością jest -obiekt Object.

- -
function Bar() {
-    return 2;
-}
-new Bar(); // nowy obiekt
-
-function Test() {
-    this.value = 2;
-
-    return {
-        foo: 1
-    };
-}
-new Test(); // zwrócony obiekt
-
- -

Jeżeli słowo kluczowe new zostanie pominięte, funkcja nie zwróci nowego -obiektu.

- -
function Foo() {
-    this.bla = 1; // zostanie ustawiona w obiekcie global
-}
-Foo(); // undefined
-
- -

Mimo że powyższy kod może zadziałać w pewnych przypadkach, w związku -z działaniem this w języku JavaScript, to jako -wartość thiszostanie wykorzystany obiekt global.

- -

Fabryki

- -

Aby móc ominąć słowo kluczowe new, konstruktor musi jawnie zwracać wartość.

- -
function Bar() {
-    var value = 1;
-    return {
-        method: function() {
-            return value;
-        }
-    }
-}
-Bar.prototype = {
-    foo: function() {}
-};
-
-new Bar();
-Bar();
-
- -

Oba wywołania Bar zwrócą tę samą rzecz, nowo utworzony obiekt, który posiada -właściwość nazwaną method i dla którego Bar jest Domknięciem.

- -

Należy również pamiętać, że wywołanie new Bar() nie ma wpływu na -prototyp zwróconego obiektu (prototypem będzie object.prototype a nie Bar.prototype). -Kiedy prototyp zostanie przypisany do nowo utworzonego obiektu, Bar nidgy -nie zwróci tego nowego obiektu Bar, tylko literał obiektu, który jest po -słowie kluczowym return.

- -

W powyższym przykładzie nie ma żadnej różnicy w działaniu pomiędzy użyciem -i nieużyciem słowa kluczowego new.

- -

Tworzenie nowych obiektów korzystając z fabryk

- -

Często zaleca się nie korzystać z operatora new, ponieważ zapominanie -o jego stosowaniu może prowadzić do błędów.

- -

W celu stworzenia nowego obiektu, powinno się używać fabryki i konstruować -nowy obiekt wewnątrz tej fabryki.

- -
function Foo() {
-    var obj = {};
-    obj.value = 'blub';
-
-    var private = 2;
-    obj.someMethod = function(value) {
-        this.value = value;
-    }
-
-    obj.getPrivate = function() {
-        return private;
-    }
-    return obj;
-}
-
- -

Mimo że powyższy kod jest odporny na brak słowa kluczowego new i ułatwia -korzystanie ze zmiennych prywatnych, to posiada -pewne wady. -While the above is robust against a missing new keyword and certainly makes -the use of private variables easier, it comes with some -downsides. - 1. Zużywa więcej pamięci, ponieważ tworzony obiekt nie współdzieli metod - poprzez prototyp. - 2. Aby móc dziedziczyć fabryka musi skopiować wszystkie metody z dziedziczonego - obiektu lub przypisać ten obiekt, z którego się dziedziczy, jako prototyp - do nowo utworzonego obiektu. - 3. Porzucenie łańcucha prototypów tylko ze względu na opuszczone słowo kluczowe - new jest sprzeczne z duchem języka.

- -

Wnioski

- -

Pominięcie słowa kluczowego new może prowadzić do błędów, ale na pewno nie -powinno to być powodem odrzucenia używania prototypów w ogóle. Sprowadza się to -do wyboru rozwiązania, które bardziej pasuje do potrzeb aplikacji. Szczególnie -ważne jest, aby wybrać określony styl tworzenia obiektów i trzymać się go.

Zasięg zmiennych i przestrzenie nazw

Mimo że JavaScript radzi sobie dobrze ze składnią opisującą dwa pasujące -nawiasy klamrowe jako blok, to jednak nie wspiera zasięgu blokowego. -Jedynym zasięgiem jaki istnieje w JavaScript jest zasięg funkcyjny.

- -
function test() { // definiuje zasięg (scope)
-    for(var i = 0; i < 10; i++) { // nie definiuje zasięgu (scope)
-        // count
-    }
-    console.log(i); // 10
-}
-
- - - -

W JavaScripcie nie ma również przestrzeni nazw, co oznacza, że wszystko jest -definiowane w jednej globalnie współdzielonej przestrzeni nazw.

- -

Z każdym odwołaniem do zmiennej, JavaScript przeszukuje w górę wszystkie zasięgi -dopóki nie znajdzie tej zmiennej. W przypadku, gdy przeszukiwanie dotrze do globalnego -zasięgu i nadal nie znajdzie żądanej nazwy, to wyrzuca błąd ReferenceError.

- -

Zmora globalnych zmiennych

- -
// script A
-foo = '42';
-
-// script B
-var foo = '42'
-
- -

Powyższe dwa skrypty nie dają tego samego efektu. Skrypt A definiuje zmienną -nazwaną foo w globalnym zasięgu, natomiast skrypt B definiuje foo -w aktualnym zasięgu.

- -

Jeszcze raz, to wcale nie daje tego samego efektu. Nie użycie var może mieć -poważne konsekwencje.

- -
// globalny zasięg
-var foo = 42;
-function test() {
-    // lokalny zasięg
-    foo = 21;
-}
-test();
-foo; // 21
-
- -

Pominięcie słowa var w deklaracji wewnątrz funkcji test nadpisze wartość -zmiennej globalnej foo. Mimo że nie wygląda to na początku na duży problem, -posiadanie wielu tysięcy linii kodu w JavaScript i nie korzystanie z var -wprowadzi straszne i trudne do wyśledzenia błędy.

- -
// globalny zasięg 
-var items = [/* jakaś lista */];
-for(var i = 0; i < 10; i++) {
-    subLoop();
-}
-
-function subLoop() {
-    // scope of subLoop
-    for(i = 0; i < 10; i++) { // brakuje słowa var w deklaracji
-        // do amazing stuff!
-    }
-}
-
- -

Zewnętrzna pętla zakończy działanie po pierwszym wywołaniu subLoop, ponieważ -subLoop nadpisuje wartość globalnej zmiennej i. Użycie var w drugiej pętli -for pozwoliłoby łatwo uniknąć problemu. Słowo kluczowe var nie powinno być -nigdy pominięte w deklaracji, chyba że pożądanym skutkiem jest wpłynięcie na -zewnętrzny zasięg.

- -

Lokalne zmienne

- -

Jedynym źródłem zmiennych lokalnych w JavaScripcie są parametry funkcji -oraz zmienne zadeklarowane poprzez deklaracje var wewnątrz funkcji.

- -
// globalny zasięg
-var foo = 1;
-var bar = 2;
-var i = 2;
-
-function test(i) {
-    // lokalny zasięg fukcji test
-    i = 5;
-
-    var foo = 3;
-    bar = 4;
-}
-test(10);
-
- -

Zmienne foo oraz i są lokalnymi zmiennymi wewnątrz zasiegu funkcji test, -natomiast przypisanie wartości do bar nadpisze zmienną globalną o tej samej nazwie.

- -

"Hoisting" - wywindowanie, podnoszenie

- -

JavaScript winduje deklaracje. Oznacza to, że zarówno deklaracja ze słowem -kluczowym var jak i deklaracje funkcji function zostaną przeniesione na -początek otaczającego zasięgu.

- -
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];
-    }
-}
-
- -

Powyższy kod zostanie przekształcony przed rozpoczęciem wykonania. JavaScript -przeniesie deklarację zmiennej var oraz deklarację funkcji function na szczyt -najbliższego zasięgu.

- -
// deklaracje var zostaną przeniesione tutaj
-var bar, someValue; // ustawione domyślnie na 'undefined'
-
-// deklaracje funkcji zostaną również przeniesione na górę
-function test(data) {
-    var goo, i, e; // brak blokowego zasięgu spowoduje przeniesienie tutaj
-    if (false) {
-        goo = 1;
-
-    } else {
-        goo = 2;
-    }
-    for(i = 0; i < 100; i++) {
-        e = data[i];
-    }
-}
-
-bar(); // powoduje błąd TypeError ponieważ bar jest nadal 'undefined'
-someValue = 42; // przypisania nie zostają zmienione przez 'hoisting'
-bar = function() {};
-
-test();
-
- -

Brak blokowego zasięgu nie tylko przeniesie deklaracje var poza ciało pętli, -ale również spowoduje, że niektóre porównania if staną się nieintuicyjne.

- -

W oryginalnym kodzie instrukcja warunkowa if zdaje się modyfikować zmienną -globalną goo, podczas gdy faktycznie modyfikuje ona zmienną lokalną - po tym -jak zostało zastosowane windowanie (hoisting).

- -

Bez wiedzy na temat podnoszenia (hoistingu), poniższy kod może sprawiać wrażenie, -że zobaczymy błąd ReferenceError.

- -
// sprawdz czy SomeImportantThing zostało zainicjalizowane
-if (!SomeImportantThing) {
-    var SomeImportantThing = {};
-}
-
- -

Oczywiście powyższy kod działa ze względu na fakt, że deklaracja var zostanie -przeniesiona na początek globalnego zasięgu.

- -
var SomeImportantThing;
-
-// inny kod który może ale nie musi zainicjalizować SomeImportantThing
-
-// upewnienie sie, że SomeImportantThing zostało zainicjalizowane
-if (!SomeImportantThing) {
-    SomeImportantThing = {};
-}
-
- -

Kolejność rozwiązywania nazw

- -

Wszystkie zasięgi w JavaScripcie, włączając globalny zasięg, posiadają -zdefiniowaną wewnątrz specjalną nazwę this, która wskazuje -na aktualny obiekt.

- -

Zasięg funkcyjny posiada również zdefiniowaną wewnętrznie nazwę -arguments, która zawiera listę argumentów przekazaną do -funkcji.

- -

Na przykład, kiedy próbujemy odczytać zmienną foo wewnątrz zasięgu funkcji, -JavaScript będzie szukać nazwy w określonej kolejności: - 1. Jeżeli wewnątrz aktualnego zasięgu znajduje się deklaracja var foo skorzystaj z niej. - 2. Jeżeli jeden z parametrów fukcji został nazwany foo użyj go. - 3. Jeżeli fukcja została nazwana foo skorzystaj z tego. - 4. Przejdz do zewnętrznego zasięgu i przejdz do kroku #1.

- - - -

Przestrzenie nazw

- -

Powszechnym problemem posiadania tylko jednej globalnej przestrzeni nazw jest -prawdopodobieństwo wystąpienia kolizji nazw. W JavaScripcie, można łatwo uniknąć -tego problemu korzystając z anonimowych wrapperów.

- -
(function() {
-    // autonomiczna "przestrzeń nazw"
-
-    window.foo = function() {
-        // wyeksponowane domkniecie (closure)
-    };
-
-})(); // natychmiastowe wykonanie funkcji
-
- -

Anonimowe funkcje są rozpoznane jako wyrażenia, więc -aby mogły zostać wywołane muszą zostać zewaluowane.

- -
( // zewaluowanie funkcji znajdującej się wewnątrz nawiasów
-function() {}
-) // zwrócenie obiektu funkcji
-() // wywołanie rezultatu ewaluacji
-
- -

Istnieją inne sposoby aby zewaluować i wykonać wyrażenie funkcyjne. Mimo że -mają inną składnię, zachowują się dokładnie tak samo.

- -
// Trzy inne sposoby
-!function(){}();
-+function(){}();
-(function(){}());
-
- -

Wnioski

- -

Zaleca się, aby zawsze używać anonimowych wrapperów do hermetyzacji kodu wewnątrz -jego własnej przestrzeni nazw. To nie tylko chroni kod przed kolizją nazw, ale -również wprowadza lepszą modularyzację programów.

- -

Ponadto, stosowanie zmiennych globalnych jest uznawane za złą praktykę. -Wykorzystanie zmiennych globalnych wskazuje na źle napisany kod, który -jest podatny na błędy i trudny do utrzymania.

Tablice

Iterowanie po tablicach oraz właściwościach tablic

Mimo że tablice w JavaScript są obiektami, nie ma dobrych powodów aby używać -pętli for in do iteracji po nich. W rzeczywstości istnieje -wiele dobrych powodów przeciwko wykorzystaniu for in na tablicach.

- - - -

Ponieważ pętla for in wylicza wszystkie właściwości, które są wewnątrz -łańcucha prototypów i jedynym sposobem aby wykluczyć te właściwości jest użycie -hasOwnProperty, ale wówczas pętla staje się -dwadzieście razy wolniejsza od normalnej pętli for.

- -

Iteracja

- -

W celu osiągnięcia najlepszej wydajności podczas iteracji po tablicach należy -użyć klasycznej pętli for.

- -
var list = [1, 2, 3, 4, 5, ...... 100000000];
-for(var i = 0, l = list.length; i < l; i++) {
-    console.log(list[i]);
-}
-
- -

W powyższym przykładzie jest jeszcze jeden dodatkowy haczyk. Jest to zbuforowanie -długości tablicy poprzez l = list.length.

- -

Mimo że właściwość length jest zdefiniowana wewnątrz tablicy, istnieje nadal -dodatkowy koszt na wyszukiwanie tej właściwości przy każdej iteracji w pętli. -Chociaż najnowsze silniki JavaScript mogą zastosować w tym -przypadku optymalizację. Nie ma jednak możliwość ustalenia czy kod będzie wykonywany w jednym -z tych nowych silników, czy też nie.

- -

W rzeczywistości pominięcie buforowania długości tablicy może spowodować, że pętla -będzie tylko w połowie tak szybka jak ta z buforowaniem długości.

- -

Właściwość length

- -

Mimo, że getter właściwości length zwraca po prostu liczbę elementów, które są -zawarte w tablicy, to setter może być użyty do skracania tablicy.

- -
var foo = [1, 2, 3, 4, 5, 6];
-foo.length = 3;
-foo; // [1, 2, 3]
-
-foo.length = 6;
-foo; // [1, 2, 3]
-
- -

Przypisanie mniejszej długości spowoduje skrócenie tablicy, ale zwiększenie wartości -length nie ma żadnego wpływu na tablicę.

- -

Wnioski

- -

Aby uzyskać najlepszą wydajność zaleca się, aby zawsze używać zwykłej pętli for -i zbuforowanie właściwości length. Korzystanie z pętli for in na tablicy jest -oznaką źle napisanego kodu, który jest podatny na błędy i ma słabą wydajność.

Konstruktor Array

Zaleca się zawsze korzystać z literału tablicy - notacja [] - podczas tworzenia -nowych tablic, ponieważ konstruktor Array niejednoznacznie interpretuje -przekazane do niego parametry.

- -
[1, 2, 3]; // Rezultat: [1, 2, 3]
-new Array(1, 2, 3); // Rezultat: [1, 2, 3]
-
-[3]; // Rezultat: [3]
-new Array(3); // Rezultat: []
-new Array('3') // Rezultat: ['3']
-
- -

W przypadku gdy tylko jeden argument zostanie przekazany do kostruktora Array i -ten argument jest typu Number, konstruktor zwróci nową dziwną tablicę -z ustawioną właściwością length na wartość przekazaną jako argument. Należy -zauważyć, że tylko właściwość length zostanie ustawiona w ten sposób. -Rzeczywiste indeksy w tej tablicy nie zostaną zainicjalizowane.

- -
var arr = new Array(3);
-arr[1]; // undefined
-1 in arr; // zwraca false, indeks nie został ustawiony
-
- -

Możliwość ustalenia z góry długości tablicy jest użyteczna tylko w kilku -przypadkach, jak np. powtarzanie ciągu znaków, w którym unika się stosowania -pętli for.

- -
// count - ilosc powtorzen
-// stringToRepeat - ciąg znaków do powtórzenia 
-new Array(count + 1).join(stringToRepeat); 
-
- -

Wnioski

- -

W miarę możliwości należy unikać używania konstruktora Array. Literały są -zdecydowanie lepszym rozwiązaniem. Są krótsze i mają bardziej precyzyjną składnię. -Zwiększają również czytelność kodu.

Typy

Równość i porównania

JavaScript posiada dwa różne sposoby równościowego porównywania obiektów.

- -

Operator równości

- -

Operator równości składa się z dwóch znaków "równa się": ==

- -

JavaScript jest słabo typowanym językiem. Oznacza to, że operator równości -konwertuje typy (dokonuje koercji), aby wykonać porównanie.

- -
""           ==   "0"           // false
-0            ==   ""            // true
-0            ==   "0"           // true
-false        ==   "false"       // false
-false        ==   "0"           // true
-false        ==   undefined     // false
-false        ==   null          // false
-null         ==   undefined     // true
-" \t\r\n"    ==   0             // true
-
- -

Powyższa tabela przedstawia wyniki koercji typów. Nieprzewidywalne wyniki -porównania są głównym powodem, że stosowanie == jest powszechnie uważane za złą -praktykę. Skomplikowane reguły konwersji są powodem trudnych do wyśledzenia błędów.

- -

Ponadto koercja ma również wpływ na wydajność, Na przykład gdy typ String musi zostać -przekształcony na typ Number przed porównaniem z drugą liczbą.

- -

Operator ścisłej równości

- -

Operator ścisłej równości składa się z trzech znaków "równa się": ===

- -

Działa on dokładnie tak jak normalny operator równości, z jednym wyjątkiem - nie -dokonuje koercji typów przed porównaniem.

- -
""           ===   "0"           // false
-0            ===   ""            // false
-0            ===   "0"           // false
-false        ===   "false"       // false
-false        ===   "0"           // false
-false        ===   undefined     // false
-false        ===   null          // false
-null         ===   undefined     // false
-" \t\r\n"    ===   0             // false
-
- -

Powyższe rezultaty są o wiele bardziej przejrzyste. Powoduje to "ustatycznienie" -języka do pewnego stopnia oraz pozwala na wprowadzenie optymalizacji porównań -obiektów o różnych typach.

- -

Porównywanie obiektów

- -

Mimo że oba operatory == i === nazywane są operatorami równościowymi, -to zachowują się różnie, gdy jednym z operandów jest obiekt typu Object.

- -
{} === {};                   // false
-new String('foo') === 'foo'; // false
-new Number(10) === 10;       // false
-var foo = {};
-foo === foo;                 // true
-
- -

Oba operatory porównują toższmość a nie równość, czyli będą porównywać czy -jeden i drugi operand jest tą samą instancją obiektu (podobnie jak operator -is w Pythonie i porównanie wskaźników w C).

- -

Wnioski

- -

Zaleca się, aby używać tylko operatora ścisłej równości. W sytuacjach gdy -potrzebna jest koercja (porównanie obiektów różnych typów), konwersja powinna -być dokonana jawnie, a nie pozostawiona trudnym regułom koercji -obowiązującym w języku.

Operator typeof

Operator typeof (razem z operatorem instanceof) jest -prawdopodobnie najwiekszą wadą konstrukcji języka JavaScript. Posiada on praktycznie
-same wady.

- -

Mimo że instanceof ma swoje wady to nadal ma ograniczone zastosowanie w praktyce, -natomiast typeof ma tylko jeden praktyczny przypadek użycia, który na dodatek -nie jest związany z sprawdzaniem typu obiektu.

- - - -

Tablica typów JavaScript

- -
Wartość             Klasa      Typ
--------------------------------------
-"foo"               String     string
-new String("foo")   String     object
-1.2                 Number     number
-new Number(1.2)     Number     object
-true                Boolean    boolean
-new Boolean(true)   Boolean    object
-new Date()          Date       object
-new Error()         Error      object
-[1,2,3]             Array      object
-new Array(1, 2, 3)  Array      object
-new Function("")    Function   function
-/abc/g              RegExp     object (function w Nitro i V8)
-new RegExp("meow")  RegExp     object (function w Nitro i V8)
-{}                  Object     object
-new Object()        Object     object
-
- -

W powyższej tabeli Typ odnosi się do wartości zwracanej przez operator typeof. -Wyraźnie widać, że zwracane wartości w ogóle nie są spójne.

- -

Klasa odnosi sie do wartości wewnętrznej właściwości [[Class]] obiektu.

- - - -

W celu uzyskania wartości właściwości [[Class]] trzeba skorzystać z metody -toString z Object.prototype.

- -

Klasa obiektu

- -

Specyfikacja zawiera dokładnie jeden sposób dostepu do wartości [[Class]], -wykorzystując Object.prototype.toString.

- -
function is(type, obj) {
-    var clas = Object.prototype.toString.call(obj).slice(8, -1);
-    return obj !== undefined && obj !== null && clas === type;
-}
-
-is('String', 'test'); // true
-is('String', new String('test')); // true
-
- -

Powyższy przykład wywołuje Object.prototype.toString z wartością -this ustawioną na obiekt, dla której wartość właściwości -[[Class]] ma zostać odczytana.

- - - -

Testowanie niezdefiniowania zmiennej

- -
typeof foo !== 'undefined'
-
- -

Powyższy kod sprawdza czy foo została faktycznie zadeklarowana czy też nie. -Próba odwołania się do zmiennej spowodowała by wyrzucenie błędu ReferenceError. -Jest to jedyne praktyczne wykorzystanie operatora typeof.

- -

Wnioski

- -

W celu sprawdzenia typu obiektu zalecane jest skorzystanie z -Object.prototype.toString, ponieważ jest to jedyny wiarygodny sposób. Jak -pokazano w powyższej tabeli typów, niektóre wartości zwracane przez typeof nie -są zdefiniowane w specyfikacji, co za tym idzie mogą się różnić w różnych -implementacjach.

- -

O ile nie operator typeof nie jest użyty do sprawdzania czy zmienna została -zdefiniowana, powinien być unikany jeśli to tylko możliwe.

Operator instanceof

Operator instanceof porównuje konstruktory obiektów przekazanych jako operendy. -Jest on użyteczny jedynie do porównywania obiektów utworzonych klas. Stosowanie -go na wbudowanych typach jest praktycznie tak samo bezużyteczne, jak operatora -typeof.

- -

Porównywanie obiektów utworzonych klas

- -
function Foo() {}
-function Bar() {}
-Bar.prototype = new Foo();
-
-new Bar() instanceof Bar; // true
-new Bar() instanceof Foo; // true
-
-// poniżej kod który przypisuje do Bar.prototype obiekt funkcji Foo
-// a nie faktyczną instancję Foo
-Bar.prototype = Foo;
-new Bar() instanceof Foo; // false
-
- -

Stosowanie instanceof na natywnych typach

- -
new String('foo') instanceof String; // true
-new String('foo') instanceof Object; // true
-
-'foo' instanceof String; // false
-'foo' instanceof Object; // false
-
- -

Jedną ważną rzeczą, którą należy zauważyć jest to, że instanceof nie zadziała -na obiektach, które pochodzą z różnych kontekstów JavaScript (np. z różnych -dokumentów wewnątrz przeglądarki), ponieważ ich konstruktory nie będą tymi -samymi obiektami.

- -

Wnioski

- -

Operator instanceof powinien być używany wyłącznie podczas korzystania z obiektów -klas utworzonych, które były zdefiniowane w tym samym kontekscie JavaScriptowym. -Podobnie jak operator typeof, należy unikać korzystania -z tego operatora w innych sytuacjach.

Rzutowanie typów

JavaScript jest językiem słabo typowanym. Co za tym idzie, będzie stosować koercję -typów gdziekolwiek jest to możliwe.

- -
// te zwracają true
-new Number(10) == 10; // Number.toString() zostanie przekształcone
-                      // z powrotem do liczby
-
-10 == '10';           // stringi zostaną przekształcone do typu Number
-10 == '+10 ';         // kolejne wariacje
-10 == '010';          // i następne
-isNaN(null) == false; // null zostanie przekształcony do 0
-                      // który oczywiście nie jest NaN
-
-// poniższe zwracają false
-10 == 010;
-10 == '-10';
-
- - - -

Aby uniknąć powyższych problemów, należy koniecznie korzystać ze -ściełego operatora równości. Mimo, że pozwala to uniknąć wiele -typowych problemów to nadal istnieje wiele innych, które powstają na bazie słabego -typowania języka JavaScript.

- -

Konstruktory typów wbudowanych

- -

Konstruktory typów wbudowanych, takich jak Number lub String, zachowują się -inaczej kiedy są poprzedzone słowem kluczowym new a inaczej kiedy nie są.

- -
new Number(10) === 10;     // False, Object i Number
-Number(10) === 10;         // True, Number i Number
-new Number(10) + 0 === 10; // True, ponieważ dokonano jawnej konwersji
-
- -

Korzystanie z wbudowanych typów jak Number jako konstruktora tworzy nowy obiekt -typu Number, natomiast opuszczenie słowa kluczowego new powoduje, że funkcja -Number zachowuje się jak konwerter.

- -

Ponadto, użycie literałów lub wartości nieobiektowych zaowocuje jeszcze większą -ilością rzutowań (koercją) typów.

- -

Najlepszym rozwiązaniem jest jawne rzutowanie do jednego z trzech typów.

- -

Rzutowanie do typu String

- -
'' + 10 === '10'; // true
-
- -

Konkatenacja pustego stringu i wartości powoduje rzutowanie do typu String.

- -

Rzutowanie do typu Number

- -
+'10' === 10; // true
-
- -

Zastosowanie unarnego operatora + spowoduje rzutowanie do typu Number.

- -

Rzutowanie do typu Boolean

- -

Używając dwukrotnie operatora negacji, dowolna wartość może zostać zrzutowana -do typu Boolean

- -
!!'foo';   // true
-!!'';      // false
-!!'0';     // true
-!!'1';     // true
-!!'-1'     // true
-!!{};      // true
-!!true;    // true
-

Jądro

Dlaczego nie należy używać eval?

Funkcja eval uruchomi podany string jako kod JavaScript w lokalnym zasięgu (scopie).

- -
var foo = 1;
-function test() {
-    var foo = 2;
-    eval('foo = 3');
-    return foo;
-}
-test(); // 3
-foo; // 1
-
- -

Niestaty, eval zostanie wykonana w lokalnym zasięgu tylko wtedy, gdy zostanie wywołana -bezpośrednio i nazwa wywoływanej funkcji równa sie eval.

- -
var foo = 1;
-function test() {
-    var foo = 2;
-    var bar = eval;
-    bar('foo = 3');
-    return foo;
-}
-test(); // 2
-foo; // 3
-
- -

Należy unikać stosowania eval o ile to tylko możliwe. W 99.9% przypadków można -osiągnąć ten sam efekt nie używając eval.

- -

eval w przebraniu

- -

Funkcje wykonywane po upływie czasu setTimeout i setInterval -mogą przyjąć string jako pierwszy argument. String ten zawsze będzie wykonywany -w globalnym zasięgu, ponieważ funkcja eval jest w tym wypadku wywoływana pośrednio.

- -

Problemy z bezpieczeństwem

- -

Funkcja eval jest również problematyczna od strony bezpieczeństwa, ponieważ -wykonuje każdy kod, który zostanie do niej przekazany i nigdy nie należy -jej używać na stringach nieznanego lub niezaufanego pochodzenia.

- -

Wnioski

- -

Funkcja eval nie powinna być w ogóle używana. Każdy kod, który jej używa -powinien zostać sprawdzony pod względem działania, wydajności i bezpieczeństwa. -W przypadku gdy użycie eval jest niezbędne do działania, wówczas taki kod -należy ponownie przemyśleć i ulepszyć aby nie wymagał użycia eval.

undefined i null

JavaScript ma dwie różne wartości dla pustych wartości, bardziej użyteczną -z tych dwóch jest undefined.

- -

Wartość undefined

- -

undefined jest typem z dokładnie jedną wartością: undefined.

- -

Język również definiuje globalną zmienną, która ma wartość undefined - zmienna -ta jest nazwana undefined. Jednakże jest to zmienna a nie stała, czy słowo -kluczowe. Oznacza to, że możliwe jest nadpisanie wartości tej zmiennej.

- - - -

Kilka przykładów kiedy wartość undefined jest zwracana:

- -
    -
  • dostęp do (niemodyfikowalnej) zmiennej globalnej undefined,
  • -
  • wyjście z funkcji, która nie ma deklaracji return,
  • -
  • deklaracja return, która nic jawnie nie zwraca,
  • -
  • poszukiwanie nieistniejącej właściwości,
  • -
  • parametr funkcji, który nie został jawnie przekazany podczas wywołania funkcji,
  • -
  • wszystko czemu została przypisana wartość undefined.
  • -
- -

Obsługa przypadku zmiany wartości undefined

- -

Ponieważ globalna zmienna undefined zawiera tylko kopię prawdziwej wartości typu -undefined, przypisanie nowej wartości do tej zmiennej nie zmienia wartości -typu undefined.

- -

Jednak aby porównać coś z wartością undefined, trzeba odczytać wartość undefined.

- -

Aby uchronić swój kod przed możliwym nadpisaniem zmiennej undefined, korzysta -się z powszechnej techniki dodania dodatkowego parametru do -anonimowego wrappera, do którego nie zostanie przekazany -argument.

- -
var undefined = 123;
-(function(something, foo, undefined) {
-    // undefined o lokalnym zasięgu znowu 
-    // odnosi się do poprawnej wartości
-
-})('Hello World', 42);
-
- -

Kolejnym sposobem na osiągnięcie tego samego efektu jest użycie deklaracji zmiennej -wewnątrz wrappera.

- -
var undefined = 123;
-(function(something, foo) {
-    var undefined;
-    ...
-
-})('Hello World', 42);
-
- -

Jedyną różnicą pomiędzy tymi sposobami są dodatkowe 4 bajty przeznaczone na słowo -kluczowe var i spację po nim.

- -

Zastosowanie null

- -

Podczas gdy undefined w kontekście języka jest używany jak null w sensie -tradycyjnych języków, null w JavaScript (jako literał i jako typ) jest po -prostu kolejnym typem danych.

- -

Jest wykorzystywany we wnętrzu JavaScript (np. deklaracji końca łańcucha prototypów -poprzez ustawienie Foo.prototype = null), ale prawie w każdym przypadku można go -zastąpić przez undefined.

Automatyczne wstawianie średnika

Mimo że JavaScript ma składnię podobną do języka C, to nie wymusza stosowania -średników w kodzie źródłowym. Istnieje możliwość ich pominięcia.

- -

JavaScript nie jest językiem bez średników, tak na prawdę potrzebuje -średników aby zinterpretować kod źródłowy. Jednakże parser JavaScript -automatycznie wstawia średniki o ile napotka błąd parsowania związany z -brakiem średnika.

- -
var foo = function() {
-} // błąd parsowania, oczekiwany był w tym miejscu średnik
-test()
-
- -

Parser dodaje średnik, i próbuje jeszcze raz sparsować skrypt.

- -
var foo = function() {
-}; // bez błędu parser kontynuuje
-test()
-
- -

Automatyczne wstawianie średników jest uważane za jeden z największych błędów -konstrukcji języka, ponieważ może ono zmienić zachowanie kodu.

- -

Jak działa wstawianie

- -

Kod poniżej nie ma żadnych średników, więc parser zdecyduje, w których miejscach -je wstawi.

- -
(function(window, undefined) {
-    function test(options) {
-        log('testing!')
-
-        (options.list || []).forEach(function(i) {
-
-        })
-
-        options.value.test(
-            'long string to pass here',
-            'and another long string to pass'
-        )
-
-        return
-        {
-            foo: function() {}
-        }
-    }
-    window.test = test
-
-})(window)
-
-(function(window) {
-    window.someLibrary = {}
-
-})(window)
-
- -

Poniżej znajduje się rezultat "zgadywania" parsera.

- -
(function(window, undefined) {
-    function test(options) {
-
-        // Nie wstaniony średnik, linie zostały połączone
-        log('testing!')(options.list || []).forEach(function(i) {
-
-        }); // <- wstawiony
-
-        options.value.test(
-            'long string to pass here',
-            'and another long string to pass'
-        ); // <- wstawiony
-
-        return; // <- wstawiony, psując deklarację return
-        { // potraktowane jako definicja bloku
-
-            // etykieta oraz pojedyncze wyrażenie
-            foo: function() {} 
-        }; // <- wstawiony
-    }
-    window.test = test; // <- wstawiony
-
-// Kolejna połączona linia
-})(window)(function(window) {
-    window.someLibrary = {}; // <- wstawiony
-
-})(window); //<- wstawiony
-
- - - -

Parser drastycznie zmienił działanie powyższego kodu. W niektórych przypadkach -zmienił go źle.

- -

Nawiasy

- -

W przypadku, gdy w następnej linii znajduje się nawias, parser nie wstawi -średnika.

- -
log('testing!')
-(options.list || []).forEach(function(i) {})
-
- -

Kod ten zostanie zmieniony w poniższą linię.

- -
log('testing!')(options.list || []).forEach(function(i) {})
-
- -

Jest bardzo prawdopodobne, że log nie zwróci fukcji. Co za tym idzie -powyższy kod wyrzuci błąd TypeError oznajmując, że undefined is not a -function - undefined nie jest funkcją.

- -

Wnioski

- -

Zaleca się, aby nigdy nie pomijać średników, pozostawiać nawias otwierający -w tej samej linii co odpowiadająca mu definicja i nigdy nie pozostawiać deklaracji -if / else bez nawiasów - nawet, jeżeli są jednolinijkowe. Wszystkie te uwagi nie -tylko pomagają poprawić spójność kodu, ale też zapobiegają zmianie działania -kodu przez parser JavaScript.

Inne

setTimeout i setInterval

Ponieważ JavaScript jest asynchroniczny, istnieje możliwość zaplanowania wykonania -funkcji przy użyciu funkcji setTimeout i setInterval. -Since JavaScript is asynchronous, it is possible to schedule the execution of a -function by using the setTimeout and setInterval functions.

- - - -
function foo() {}
-var id = setTimeout(foo, 1000); // zwraca liczbę typu Number > 0
-
- -

Powyższe wywołanie setTimeout zwraca ID budzika i planuje wywołanie foo za -około tysiąc milisekund. foo zostanie wykonana dokładnie jeden raz.

- -

Nie ma pewności, że kod zaplanowany do wykonania wykona się dokładnie po -upłynięciu zadanego czasu podanego jako parametr do setTimeout, ponieważ zależy -to od dokładności zegara w silniku JavaScript, który wykonuje kod oraz od tego, -że inny kawałek kodu może zablokować wątek, ponieważ JavaScript jest tylko -jednowątkowy.

- -

Funkcja, która została przekazana jako pierwszy parametr zostanie wykonana w -globalnym zasięgu, co oznacza, że this wewnątrz tej funkcji -będzie wskazywać na obiekt global.

- -
function Foo() {
-    this.value = 42;
-    this.method = function() {
-        // this wskazuje na obiekt global
-        console.log(this.value); // wypisze undefined
-    };
-    setTimeout(this.method, 500);
-}
-new Foo();
-
- - - -

Kolejkowanie wywołań z setInterval

- -

Podczas gdy setTimeout wywołuje podaną funkcję tylko raz, setInterval - -jak wskazuje nazwa - będzie wykonywać funkcję w odstępach czasowych co X -milisekund. Jednakże korzystanie z tej funkcji jest odradzane.

- -

Kiedy wykonywany kod zablokuje możliwość uruchomienia zaplanowanej funkcji, -setInterval będzie próbować uruchamiać daną funkcję, co będzie powodować -kolejkowanie wykonania tej samej funkcji kilkukrotnie. Może się to zdażyć -szczególnie przy krótkim interwale.

- -
function foo(){
-    // coś co blokuje wykonanie na 1 sekundę 
-}
-setInterval(foo, 100);
-
- -

W powyższym kodzie kod foo zostanie wywołany tylko raz i zablokuje wywołanie na -jedną sekundę.

- -

Podczas, gdy funkcja foo blokuje wykonanie, setInterval będzie planować kolejne -wywołania foo. W momencie, gdy pierwsze wywołanie foo się zakończy, -w kolejce do wywołania będzie już czekało kolejne dziesięć wywołań tej funkcji.

- -

Radzenie sobie z możliwymi blokadami

- -

Najprostszą, jak również najbardziej kontrolowaną sytuacją, jest użycie setTimeout -wewnątrz wywoływanej funkcji.

- -
function foo(){
-    // coś co blokuje wykonanie na 1 sekundę
-    setTimeout(foo, 100);
-}
-foo();
-
- -

Powyższy kod nie tylko hermetyzuje wywołanie setTimeout, ale też zapobiega -kolejkowaniu wywołań funkcji i daje dodatkową kontrolę. W tym przypadku funkcja -foo może zdecydować czy powinna się wywołać ponownie, czy też nie.

- -

Ręczne usuwanie budzików

- -

Usuwanie budzików i interwałów dokonywane jest przez przekazanie odpowiedniego ID -do clearTimeout lub clearInterval, w zależności z jakiej funkcji zostało -zwrócone ID.

- -
var id = setTimeout(foo, 1000);
-clearTimeout(id);
-
- -

Usuwanie wszystkich budzików

- -

Ponieważ nie istnieje wbudowana metoda usuwania wszystkich budzików i/lub -interwałów, do osiągnięcia tego efektu konieczne jest użycie metody 'brute force'.

- -
// usunięcie "wszystkich" budzików 
-for(var i = 1; i < 1000; i++) {
-    clearTimeout(i);
-}
-
- -

Nadal mogą istnieć jakieś budziki, na które powyższy kawałek kodu nie zadziała. -Ponieważ ID było z innego przedziału, zamiast korzystania z metody brute force, -zaleca się śledzić wszystkie numery ID budzików, aby można je było usunąć.

- -

Ukryte wykorzystanie eval

- -

Do setTimeout i setInterval można również przekazać string jako pierwszy -parametr zamiast obiektu funkcji, jednakże nigdy nie należy korzystać z tej -możliwości, ponieważ wewnętrznie setTimeout i setInterval wykorzystują eval.

- - - -
function foo() {
-    // zostanie wykonane 
-}
-
-function bar() {
-    function foo() {
-        // nigdy nie zostanie wywołane
-    }
-    setTimeout('foo()', 1000);
-}
-bar();
-
- -

Ponieważ eval nie zostało wywołane w tym przypadku wprost, to -string przekazany do setTimeout zostanie uruchomiony w zasięgu globalnym. -Co za tym idzie, lokalna zmienna foo z zasięgu bar nie zostanie użyta.

- -

Kolejnym zaleceniem jest niestosowanie stringów do przekazywania argumentów -do funkcji, która ma zostać wywołana przez budzik.

- -
function foo(a, b, c) {}
-
-// NIGDY nie należy tak robić 
-setTimeout('foo(1,2, 3)', 1000)
-
-// zamiast tego należy skorzystać z anonimowej funkcji
-setTimeout(function() {
-    foo(a, b, c);
-}, 1000)
-
- - - -

Wnioski

- -

Nigdy nie należy przekazywać stringu jako parametru do setTimeout lub -setInterval. Jest to wyraźną oznaką bardzo złego kodu. Jeżeli potrzebne jest -przekazanie argumentów do funkcji, należy skorzystać z anonimowej funkcji i -wewnątrz niej dokonać przekazania argumentów.

- -

Ponadto, należy unikać korzystania z setInterval, ponieważ planista może -zablokować wykonanie JavaScriptu.

\ No newline at end of file From d62ef392d41ea66201865a3a35c52a7955efd858 Mon Sep 17 00:00:00 2001 From: HIRAKI Satoru Date: Tue, 4 Oct 2011 19:57:49 +0900 Subject: [PATCH 143/463] translate "Why Not to Use `eval`" in "Core" to ja --- doc/ja/core/eval.md | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/doc/ja/core/eval.md b/doc/ja/core/eval.md index ecf7ba90..83e18d51 100644 --- a/doc/ja/core/eval.md +++ b/doc/ja/core/eval.md @@ -1,6 +1,6 @@ -## Why Not to Use `eval` +## なぜ、`eval`を使ってはいけないのか -The `eval` function will execute a string of JavaScript code in the local scope. +`eval`関数はローカルスコープ中のJavaScriptコードの文字列を実行します。 var foo = 1; function test() { @@ -11,8 +11,7 @@ The `eval` function will execute a string of JavaScript code in the local scope. test(); // 3 foo; // 1 -But `eval` only executes in local scope when it is being called **directly** *and* -the name of the called function is actually `eval`. +しかし、`eval`は**直接**ローカルスコープから呼ばれて、*かつ*呼んだ関数の名前が実際の`eval`でないと実行しません。 var foo = 1; function test() { @@ -24,9 +23,8 @@ the name of the called function is actually `eval`. test(); // 2 foo; // 3 -The use of `eval` should be avoided at **all costs**. 99.9% of its "uses" can be -achieved **without** it. - +`eval`の使用は**全てのコスト**を払ってでも回避するべきです。その「使用法」の99.9%で、これ**無し**でも実装できます。 + ### `eval` in Disguise The [timeout functions](#other.timeouts) `setTimeout` and `setInterval` can both From 70f5ad76b222b1d21d21dc24eeb8308b4881ce0f Mon Sep 17 00:00:00 2001 From: HIRAKI Satoru Date: Wed, 5 Oct 2011 15:09:10 +0900 Subject: [PATCH 144/463] remove "site/pl" because merge from master --- .gitignore | 1 - 1 file changed, 1 deletion(-) diff --git a/.gitignore b/.gitignore index bb7b0b6e..ff4e6c39 100644 --- a/.gitignore +++ b/.gitignore @@ -10,7 +10,6 @@ /site/fi /site/pl /site/tr -/site/pl /site/ja *.md~ *.src.md From 6a1267a956e60846e9b26fa24d9787c1a5f7c362 Mon Sep 17 00:00:00 2001 From: HIRAKI Satoru Date: Fri, 7 Oct 2011 01:14:15 +0900 Subject: [PATCH 145/463] translate "`eval` in Disguise" in "Core" to ja --- doc/ja/core/eval.md | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/doc/ja/core/eval.md b/doc/ja/core/eval.md index 83e18d51..7f8e5f19 100644 --- a/doc/ja/core/eval.md +++ b/doc/ja/core/eval.md @@ -25,11 +25,9 @@ `eval`の使用は**全てのコスト**を払ってでも回避するべきです。その「使用法」の99.9%で、これ**無し**でも実装できます。 -### `eval` in Disguise +### 偽装された`eval` -The [timeout functions](#other.timeouts) `setTimeout` and `setInterval` can both -take a string as their first argument. This string will **always** get executed -in the global scope since `eval` is not being called directly in that case. +[timeout functions](#other.timeouts)である`setTimeout`と`setInterval`はどちらも最初の引数として文字列を取る事ができます。この文字列は`eval`がこの場合直接呼ばれていないので、**常に**グローバルスコープで実行されてしまいます。 ### Security Issues From b30583434b9b4d4a815a3a8f0bec189757469231 Mon Sep 17 00:00:00 2001 From: HIRAKI Satoru Date: Fri, 7 Oct 2011 01:17:25 +0900 Subject: [PATCH 146/463] translate in "Security Issues" in "Core" to ja --- doc/ja/core/eval.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/doc/ja/core/eval.md b/doc/ja/core/eval.md index 7f8e5f19..21e80f84 100644 --- a/doc/ja/core/eval.md +++ b/doc/ja/core/eval.md @@ -29,10 +29,9 @@ [timeout functions](#other.timeouts)である`setTimeout`と`setInterval`はどちらも最初の引数として文字列を取る事ができます。この文字列は`eval`がこの場合直接呼ばれていないので、**常に**グローバルスコープで実行されてしまいます。 -### Security Issues +### セキュリティの問題 -`eval` also is a security problem as it executes **any** code given to it, -it should **never** be used with strings of unknown or untrusted origins. +`eval`はまたセキュリティの問題もあります。なぜなら、**どんな**コードを与えられても実行してしまうからで、**絶対**に不明または信頼できない発行元の文字列は使ってはいけません。 ### In Conclusion From 7679822b4d033bf91fe70c77fecbcb534341ddc8 Mon Sep 17 00:00:00 2001 From: HIRAKI Satoru Date: Fri, 7 Oct 2011 01:21:48 +0900 Subject: [PATCH 147/463] translate "In Conclusion" in "Core" to ja --- doc/ja/core/eval.md | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/doc/ja/core/eval.md b/doc/ja/core/eval.md index 21e80f84..846d32c1 100644 --- a/doc/ja/core/eval.md +++ b/doc/ja/core/eval.md @@ -33,11 +33,7 @@ `eval`はまたセキュリティの問題もあります。なぜなら、**どんな**コードを与えられても実行してしまうからで、**絶対**に不明または信頼できない発行元の文字列は使ってはいけません。 -### In Conclusion +### 終わりに -`eval` should never be used, any code that makes use of it is to be questioned in -its workings, performance and security. In case something requires `eval` in -order to work, its design is to be questioned and should **not** be used in the -first place, a *better design* should be used, that does not require the use of -`eval`. +`eval`は絶対に使用しないでください。これを使用しているどんなコードも、その働き、パフォーマンスやセキュリティについて問われてしまいます。`eval`が必要な場合でも、最初の段階で使用**しない**でください。*より良いデザイン*を使用するべきで、それには`eval`を使う必要性はありません。 From 66d98dd5a3f9d69a8e3d2fca783a35d902173c39 Mon Sep 17 00:00:00 2001 From: Changwoo Park Date: Sun, 9 Oct 2011 18:19:01 +0900 Subject: [PATCH 148/463] [ko] Init files for ko --- doc/ko/array/constructor.md | 35 +++++ doc/ko/array/general.md | 58 ++++++++ doc/ko/core/delete.md | 87 ++++++++++++ doc/ko/core/eval.md | 47 +++++++ doc/ko/core/semicolon.md | 114 ++++++++++++++++ doc/ko/core/undefined.md | 72 ++++++++++ doc/ko/function/arguments.md | 119 ++++++++++++++++ doc/ko/function/closures.md | 98 ++++++++++++++ doc/ko/function/constructors.md | 128 ++++++++++++++++++ doc/ko/function/general.md | 48 +++++++ doc/ko/function/scopes.md | 231 ++++++++++++++++++++++++++++++++ doc/ko/function/this.md | 111 +++++++++++++++ doc/ko/index.json | 69 ++++++++++ doc/ko/intro/index.md | 47 +++++++ doc/ko/object/forinloop.md | 51 +++++++ doc/ko/object/general.md | 99 ++++++++++++++ doc/ko/object/hasownproperty.md | 53 ++++++++ doc/ko/object/prototype.md | 116 ++++++++++++++++ doc/ko/other/timeouts.md | 155 +++++++++++++++++++++ doc/ko/types/casting.md | 70 ++++++++++ doc/ko/types/equality.md | 71 ++++++++++ doc/ko/types/instanceof.md | 38 ++++++ doc/ko/types/typeof.md | 87 ++++++++++++ doc/language.json | 2 +- 24 files changed, 2005 insertions(+), 1 deletion(-) create mode 100644 doc/ko/array/constructor.md create mode 100644 doc/ko/array/general.md create mode 100644 doc/ko/core/delete.md create mode 100644 doc/ko/core/eval.md create mode 100644 doc/ko/core/semicolon.md create mode 100644 doc/ko/core/undefined.md create mode 100644 doc/ko/function/arguments.md create mode 100644 doc/ko/function/closures.md create mode 100644 doc/ko/function/constructors.md create mode 100644 doc/ko/function/general.md create mode 100644 doc/ko/function/scopes.md create mode 100644 doc/ko/function/this.md create mode 100644 doc/ko/index.json create mode 100644 doc/ko/intro/index.md create mode 100644 doc/ko/object/forinloop.md create mode 100644 doc/ko/object/general.md create mode 100644 doc/ko/object/hasownproperty.md create mode 100644 doc/ko/object/prototype.md create mode 100644 doc/ko/other/timeouts.md create mode 100644 doc/ko/types/casting.md create mode 100644 doc/ko/types/equality.md create mode 100644 doc/ko/types/instanceof.md create mode 100644 doc/ko/types/typeof.md diff --git a/doc/ko/array/constructor.md b/doc/ko/array/constructor.md new file mode 100644 index 00000000..1d9abe18 --- /dev/null +++ b/doc/ko/array/constructor.md @@ -0,0 +1,35 @@ +## The `Array` Constructor + +Since the `Array` constructor is ambiguous in how it deals with its parameters, +it is highly recommended to always use the array literals - `[]` notation - +when creating new arrays. + + [1, 2, 3]; // Result: [1, 2, 3] + new Array(1, 2, 3); // Result: [1, 2, 3] + + [3]; // Result: [3] + new Array(3); // Result: [] + new Array('3') // Result: ['3'] + +In cases when there is only one argument passed to the `Array` constructor +and when that argument is a `Number`, the constructor will return a new *sparse* +array with the `length` property set to the value of the argument. It should be +noted that **only** the `length` property of the new array will be set this way; +the actual indexes of the array will not be initialized. + + var arr = new Array(3); + arr[1]; // undefined + 1 in arr; // false, the index was not set + +The behavior of being able to set the length of the array upfront only comes in +handy in a few cases, like repeating a string, in which it avoids the use of a +`for loop` code. + + new Array(count + 1).join(stringToRepeat); + +### In Conclusion + +The use of the `Array` constructor should be avoided as much as possible. +Literals are definitely preferred. They are shorter and have a clearer syntax; +therefore, they also increase the readability of the code. + diff --git a/doc/ko/array/general.md b/doc/ko/array/general.md new file mode 100644 index 00000000..9f804d4c --- /dev/null +++ b/doc/ko/array/general.md @@ -0,0 +1,58 @@ +## Array Iteration and Properties + +Although arrays in JavaScript are objects, there are no good reasons to use +the [`for in loop`](#object.forinloop) in for iteration on them. In fact, there +are a number of good reasons **against** the use of `for in` on arrays. + +> **Note:** JavaScript arrays are **not** *associative arrays*. JavaScript only +> has [objects](#object.general) for mapping keys to values. And while associative +> arrays **preserve** order, objects **do not**. + +Because the `for in` loop enumerates all the properties that are on the prototype +chain and because the only way to exclude those properties is to use +[`hasOwnProperty`](#object.hasownproperty), it is already up to **twenty times** +slower than a normal `for` loop. + +### Iteration + +In order to achieve the best performance when iterating over arrays, it is best +to use the classic `for` loop. + + var list = [1, 2, 3, 4, 5, ...... 100000000]; + for(var i = 0, l = list.length; i < l; i++) { + console.log(list[i]); + } + +There is one extra catch in the above example, which is the caching of the +length of the array via `l = list.length`. + +Although the `length` property is defined on the array itself, there is still an +overhead for doing the lookup on each iteration of the loop. And while recent +JavaScript engines **may** apply optimization in this case, there is no way of +telling whether the code will run on one of these newer engines or not. + +In fact, leaving out the caching may result in the loop being only **half as +fast** as with the cached length. + +### The `length` Property + +While the *getter* of the `length` property simply returns the number of +elements that are contained in the array, the *setter* can be used to +**truncate** the array. + + var foo = [1, 2, 3, 4, 5, 6]; + foo.length = 3; + foo; // [1, 2, 3] + + foo.length = 6; + foo; // [1, 2, 3] + +Assigning a smaller length does truncate the array, but increasing the length +does not have any effect on the array. + +### In Conclusion + +For the best performance, it is recommended to always use the plain `for` loop +and cache the `length` property. The use of `for in` on an array is a sign of +badly written code that is prone to bugs and bad performance. + diff --git a/doc/ko/core/delete.md b/doc/ko/core/delete.md new file mode 100644 index 00000000..37a12816 --- /dev/null +++ b/doc/ko/core/delete.md @@ -0,0 +1,87 @@ +## The `delete` Operator + +In short, it's *impossible* to delete global variables, functions and some other +stuff in JavaScript which have a `DontDelete` attribute set. + +### Global code and Function code + +When a variable or a function is defined in a global +or a [function scope](#function.scopes) it is a property of either +Activation object or Global object. Such properties have a set of attributes, +one of these is `DontDelete`. Variable and function declarations in global +and function code always create properties with `DontDelete`, therefore +cannot be deleted. + + // global variable: + var a = 1; // DontDelete is set + delete a; // false + a; // 1 + + // normal function: + function f() {} // DontDelete is set + delete f; // false + typeof f; // "function" + + // reassigning doesn't help: + f = 1; + delete f; // false + f; // 1 + +### Explicit properties + +There are things which can be deleted normally: these are explicitly set +properties. + + // explicitly set property: + var obj = {x: 1}; + obj.y = 2; + delete obj.x; // true + delete obj.y; // true + obj.x; // undefined + obj.y; // undefined + +In the example above `obj.x` and `obj.y` can be deleted because they have no +`DontDelete` atribute. That's why an example below works too. + + // this works fine, except for IE: + var GLOBAL_OBJECT = this; + GLOBAL_OBJECT.a = 1; + a === GLOBAL_OBJECT.a; // true - just a global var + delete GLOBAL_OBJECT.a; // true + GLOBAL_OBJECT.a; // undefined + +Here we use a trick to delete `a`. [`this`](#function.this) here refers +to the Global object and we explicitly declare variable `a` as it's property +which allows us to delete it. + +IE (at least 6-8) has some bugs, so code above doesn't work. + +### Function arguments and built-ins + +Functions' normal arguments, [`arguments` object](#function.arguments) +and built-in properties also have `DontDelete` set. + + // function arguments and properties: + (function (x) { + + delete arguments; // false + typeof arguments; // "object" + + delete x; // false + x; // 1 + + function f(){} + delete f.length; // false + typeof f.length; // "number" + + })(1); + +### Host objects + +Behaviour of `delete` operator can be unpredictable for hosted objects. Due to +specification, host objects are allowed to implement any kind of behavior. + +### In conclusion + +`delete` operator often has an unexpected behaviour and can be safely used +only for dealing with explicitly set properties on normal objects. diff --git a/doc/ko/core/eval.md b/doc/ko/core/eval.md new file mode 100644 index 00000000..160ba1f0 --- /dev/null +++ b/doc/ko/core/eval.md @@ -0,0 +1,47 @@ +## Why Not to Use `eval` + +The `eval` function will execute a string of JavaScript code in the local scope. + + var foo = 1; + function test() { + var foo = 2; + eval('foo = 3'); + return foo; + } + test(); // 3 + foo; // 1 + +However, `eval` only executes in the local scope when it is being called +**directly** *and* when the name of the called function is actually `eval`. + + var foo = 1; + function test() { + var foo = 2; + var bar = eval; + bar('foo = 3'); + return foo; + } + test(); // 2 + foo; // 3 + +The use of `eval` should be avoided at **all costs**. 99.9% of its "uses" can be +achieved **without** it. + +### `eval` in Disguise + +The [timeout functions](#other.timeouts) `setTimeout` and `setInterval` can both +take a string as their first argument. This string will **always** get executed +in the global scope since `eval` is not being called directly in that case. + +### Security Issues + +`eval` also is a security problem. Because it executes **any** code given to it, +it should **never** be used with strings of unknown or untrusted origins. + +### In Conclusion + +`eval` should never be used. Any code that makes use of it is to be questioned in +its workings, performance and security. In case something requires `eval` in +order to work, it should **not** be used in the first place. +A *better design* should be used, that does not require the use of `eval`. + diff --git a/doc/ko/core/semicolon.md b/doc/ko/core/semicolon.md new file mode 100644 index 00000000..f03f7d82 --- /dev/null +++ b/doc/ko/core/semicolon.md @@ -0,0 +1,114 @@ +## Automatic Semicolon Insertion + +Although JavaScript has C style syntax, it does **not** enforce the use of +semicolons in the source code, so it is possible to omit them. + +JavaScript is not a semicolon-less language. In fact, it needs the +semicolons in order to understand the source code. Therefore, the JavaScript +parser **automatically** inserts them whenever it encounters a parse +error due to a missing semicolon. + + var foo = function() { + } // parse error, semicolon expected + test() + +Insertion happens, and the parser tries again. + + var foo = function() { + }; // no error, parser continues + test() + +The automatic insertion of semicolon is considered to be one of **biggest** +design flaws in the language because it *can* change the behavior of code. + +### How it Works + +The code below has no semicolons in it, so it is up to the parser to decide where +to insert them. + + (function(window, undefined) { + function test(options) { + log('testing!') + + (options.list || []).forEach(function(i) { + + }) + + options.value.test( + 'long string to pass here', + 'and another long string to pass' + ) + + return + { + foo: function() {} + } + } + window.test = test + + })(window) + + (function(window) { + window.someLibrary = {} + + })(window) + +Below is the result of the parser's "guessing" game. + + (function(window, undefined) { + function test(options) { + + // Not inserted, lines got merged + log('testing!')(options.list || []).forEach(function(i) { + + }); // <- inserted + + options.value.test( + 'long string to pass here', + 'and another long string to pass' + ); // <- inserted + + return; // <- inserted, breaks the return statement + { // treated as a block + + // a label and a single expression statement + foo: function() {} + }; // <- inserted + } + window.test = test; // <- inserted + + // The lines got merged again + })(window)(function(window) { + window.someLibrary = {}; // <- inserted + + })(window); //<- inserted + +> **Note:** The JavaScript parser does not "correctly" handle return statements +> which are followed by a new line, while this is not neccessarily the fault of +> the automatic semicolon insertion, it can still be an unwanted side-effect. + +The parser drastically changed the behavior of the code above. In certain cases, +it does the **wrong thing**. + +### Leading Parenthesis + +In case of a leading parenthesis, the parser will **not** insert a semicolon. + + log('testing!') + (options.list || []).forEach(function(i) {}) + +This code gets transformed into one line. + + log('testing!')(options.list || []).forEach(function(i) {}) + +Chances are **very** high that `log` does **not** return a function; therefore, +the above will yield a `TypeError` stating that `undefined is not a function`. + +### In Conclusion + +It is highly recommended to **never** omit semicolons; it is also advocated to +keep braces on the same line with their corresponding statements and to never omit +them for one single-line `if` / `else` statements. Both of these measures will +not only improve the consistency of the code, but they will also prevent the +JavaScript parser from changing its behavior. + diff --git a/doc/ko/core/undefined.md b/doc/ko/core/undefined.md new file mode 100644 index 00000000..d27761f0 --- /dev/null +++ b/doc/ko/core/undefined.md @@ -0,0 +1,72 @@ +## `undefined` and `null` + +JavaScript has two distinct values for `nothing`, the more useful of these two +being `undefined`. + +### The Value `undefined` + +`undefined` is a type with exactly one value: `undefined`. + +The language also defines a global variable that has the value of `undefined`; +this variable is also called `undefined`. However, this variable is **neither** a constant +nor a keyword of the language. This means that its *value* can be easily +overwritten. + +> **ES5 Note:** `undefined` in ECMAScript 5 is **no longer** *writable* in strict +> mode, but its name can still be shadowed by for example a function with the name +> `undefined`. + +Some examples for when the value `undefined` is returned: + + - Accessing the (unmodified) global variable `undefined`. + - Implicit returns of functions due to missing `return` statements. + - `return` statements which do not explicitly return anything. + - Lookups of non-existent properties. + - Function parameters which do not had any explicit value passed. + - Anything that has been set to the value of `undefined`. + +### Handling Changes to the Value of `undefined` + +Since the global variable `undefined` only holds a copy of the actual *value* of +`undefined`, assigning a new value to it does **not** change the value of the +*type* `undefined`. + +Still, in order to compare something against the value of `undefined`, it is +necessary to retrieve the value of `undefined` first. + +In order to protect code against a possible overwritten `undefined` variable, a +common technique used is to add an additional parameter to an +[anonymous wrapper](#function.scopes) that gets no argument passed to it. + + var undefined = 123; + (function(something, foo, undefined) { + // undefined in the local scope does + // now again refer to the value + + })('Hello World', 42); + +Another way to achieve the same effect would be to use a declaration inside the +wrapper. + + var undefined = 123; + (function(something, foo) { + var undefined; + ... + + })('Hello World', 42); + +The only difference here is that this version results in 4 more bytes being +used in case it is minified, and there is no other `var` statement inside the +anonymous wrapper. + +### Uses of `null` + +While `undefined` in the context of the JavaScript language is mostly used in +the sense of a traditional *null*, the actual `null` (both a literal and a type) +is more or less just another data type. + +It is used in some JavaScript internals (like declaring the end of the +prototype chain by setting `Foo.prototype = null`), but in almost all cases, it +can be replaced by `undefined`. + + diff --git a/doc/ko/function/arguments.md b/doc/ko/function/arguments.md new file mode 100644 index 00000000..37f3a634 --- /dev/null +++ b/doc/ko/function/arguments.md @@ -0,0 +1,119 @@ +## The `arguments` Object + +Every function scope in JavaScript can access the special variable `arguments`. +This variable holds a list of all the arguments that were passed to the function. + +> **Note:** In case `arguments` has already been defined inside the function's +> scope either via a `var` statement or being the name of a formal parameter, +> the `arguments` object will not be created. + +The `arguments` object is **not** an `Array`. While it has some of the +semantics of an array - namely the `length` property - it does not inherit from +`Array.prototype` and is in fact an `Object`. + +Due to this, it is **not** possible to use standard array methods like `push`, +`pop` or `slice` on `arguments`. While iteration with a plain `for` loop works +just fine, it is necessary to convert it to a real `Array` in order to use the +standard `Array` methods on it. + +### Converting to an Array + +The code below will return a new `Array` containing all the elements of the +`arguments` object. + + Array.prototype.slice.call(arguments); + +Because this conversion is **slow**, it is **not recommended** to use it in +performance-critical sections of code. + +### Passing Arguments + +The following is the recommended way of passing arguments from one function to +another. + + function foo() { + bar.apply(null, arguments); + } + function bar(a, b, c) { + // do stuff here + } + +Another trick is to use both `call` and `apply` together to create fast, unbound +wrappers. + + function Foo() {} + + Foo.prototype.method = function(a, b, c) { + console.log(this, a, b, c); + }; + + // Create an unbound version of "method" + // It takes the parameters: this, arg1, arg2...argN + Foo.method = function() { + + // Result: Foo.prototype.method.call(this, arg1, arg2... argN) + Function.call.apply(Foo.prototype.method, arguments); + }; + + +### Formal Parameters and Arguments Indices + +The `arguments` object creates *getter* and *setter* functions for both its +properties, as well as the function's formal parameters. + +As a result, changing the value of a formal parameter will also change the value +of the corresponding property on the `arguments` object, and the other way around. + + 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); + +### Performance Myths and Truths + +The `arguments` object is always created with the only two exceptions being the +cases where it is declared as a name inside of a function or one of its formal +parameters. It does not matter whether it is used or not. + +Both *getters* and *setters* are **always** created; thus, using it has nearly +no performance impact at all, especially not in real world code where there is +more than a simple access to the `arguments` object's properties. + +> **ES5 Note:** These *getters* and *setters* are not created in strict mode. + +However, there is one case which will drastically reduce the performance in +modern JavaScript engines. That case is the use of `arguments.callee`. + + function foo() { + arguments.callee; // do something with this function object + arguments.callee.caller; // and the calling function object + } + + function bigLoop() { + for(var i = 0; i < 100000; i++) { + foo(); // Would normally be inlined... + } + } + +In the above code, `foo` can no longer be a subject to [inlining][1] since it +needs to know about both itself and its caller. This not only defeats possible +performance gains that would arise from inlining, but it also breaks encapsulation +because the function may now be dependent on a specific calling context. + +It is **highly recommended** to **never** make use of `arguments.callee` or any of +its properties. + +> **ES5 Note:** In strict mode, `arguments.callee` will throw a `TypeError` since +> its use has been deprecated. + +[1]: http://en.wikipedia.org/wiki/Inlining + + diff --git a/doc/ko/function/closures.md b/doc/ko/function/closures.md new file mode 100644 index 00000000..2e2a4ef6 --- /dev/null +++ b/doc/ko/function/closures.md @@ -0,0 +1,98 @@ +## Closures and References + +One of JavaScript's most powerful features is the availability of *closures*. +With closures, scopes **always** keep access to the outer scope, in which they +were defined. Since the only scoping that JavaScript has is +[function scope](#function.scopes), all functions, by default, act as closures. + +### Emulating private variables + + function Counter(start) { + var count = start; + return { + increment: function() { + count++; + }, + + get: function() { + return count; + } + } + } + + var foo = Counter(4); + foo.increment(); + foo.get(); // 5 + +Here, `Counter` returns **two** closures: the function `increment` as well as +the function `get`. Both of these functions keep a **reference** to the scope of +`Counter` and, therefore, always keep access to the `count` variable that was +defined in that very scope. + +### Why Private Variables Work + +Since it is not possible to reference or assign scopes in JavaScript, there is +**no** way of accessing the variable `count` from the outside. The only way to +interact with it is via the two closures. + + var foo = new Counter(4); + foo.hack = function() { + count = 1337; + }; + +The above code will **not** change the variable `count` in the scope of `Counter`, +since `foo.hack` was not defined in **that** scope. It will instead create - or +override - the *global* variable `count`. + +### Closures Inside Loops + +One often made mistake is to use closures inside of loops, as if they were +copying the value of the loops index variable. + + for(var i = 0; i < 10; i++) { + setTimeout(function() { + console.log(i); + }, 1000); + } + +The above will **not** output the numbers `0` through `9`, but will simply print +the number `10` ten times. + +The *anonymous* function keeps a **reference** to `i`. At the time +`console.log` gets called, the `for loop` has already finished, and the value of +`i` as been set to `10`. + +In order to get the desired behavior, it is necessary to create a **copy** of +the value of `i`. + +### Avoiding the Reference Problem + +In order to copy the value of the loop's index variable, it is best to use an +[anonymous wrapper](#function.scopes). + + for(var i = 0; i < 10; i++) { + (function(e) { + setTimeout(function() { + console.log(e); + }, 1000); + })(i); + } + +The anonymous outer function gets called immediately with `i` as its first +argument and will receive a copy of the **value** of `i` as its parameter `e`. + +The anonymous function that gets passed to `setTimeout` now has a reference to +`e`, whose value does **not** get changed by the loop. + +There is another possible way of achieving this, which is to return a function +from the anonymous wrapper that will then have the same behavior as the code +above. + + for(var i = 0; i < 10; i++) { + setTimeout((function(e) { + return function() { + console.log(e); + } + })(i), 1000) + } + diff --git a/doc/ko/function/constructors.md b/doc/ko/function/constructors.md new file mode 100644 index 00000000..a8e450a4 --- /dev/null +++ b/doc/ko/function/constructors.md @@ -0,0 +1,128 @@ +## Constructors + +Constructors in JavaScript are yet again different from many other languages. Any +function call that is preceded by the `new` keyword acts as a constructor. + +Inside the constructor - the called function - the value of `this` refers to a +newly created `Object`. The [`prototype`](#object.prototype) of this **new** +object is set to the `prototype` of the function object that was invoked as the +constructor. + +If the function that was called has no explicit `return` statement, then it +implicitly returns the value of `this` - the new object. + + function Foo() { + this.bla = 1; + } + + Foo.prototype.test = function() { + console.log(this.bla); + }; + + var test = new Foo(); + +The above calls `Foo` as constructor and sets the `prototype` of the newly +created object to `Foo.prototype`. + +In case of an explicit `return` statement, the function returns the value +specified that statement, **but only** if the return value is an `Object`. + + function Bar() { + return 2; + } + new Bar(); // a new object + + function Test() { + this.value = 2; + + return { + foo: 1 + }; + } + new Test(); // the returned object + +When the `new` keyword is omitted, the function will **not** return a new object. + + function Foo() { + this.bla = 1; // gets set on the global object + } + Foo(); // undefined + +While the above example might still appear to work in some cases, due to the +workings of [`this`](#function.this) in JavaScript, it will use the +*global object* as the value of `this`. + +### Factories + +In order to be able to omit the `new` keyword, the constructor function has to +explicitly return a value. + + function Bar() { + var value = 1; + return { + method: function() { + return value; + } + } + } + Bar.prototype = { + foo: function() {} + }; + + new Bar(); + Bar(); + +Both calls to `Bar` return the exact same thing, a newly create object which +has a property called `method` on it, which is a +[Closure](#function.closures). + +It is also to note that the call `new Bar()` does **not** affect the prototype +of the returned object. While the prototype will be set on the newly created +object, `Bar` never returns that new object. + +In the above example, there is no functional difference between using and +not using the `new` keyword. + + +### Creating New Objects via Factories + +An often made recommendation is to **not** use `new` because forgetting its use +may lead to bugs. + +In order to create new object, one should rather use a factory and construct a +new object inside of that factory. + + function Foo() { + var obj = {}; + obj.value = 'blub'; + + var private = 2; + obj.someMethod = function(value) { + this.value = value; + } + + obj.getPrivate = function() { + return private; + } + return obj; + } + +While the above is robust against a missing `new` keyword and certainly makes +the use of [private variables](#function.closures) easier, it comes with some +downsides. + + 1. It uses more memory since the created objects do **not** share the methods + on a prototype. + 2. In order to inherit the factory needs to copy all the methods from another + object or put that object on the prototype of the new object. + 3. Dropping the prototype chain just because of a left out `new` keyword + somehow goes against the spirit of the language. + +### In Conclusion + +While omitting the `new` keyword might lead to bugs, it is certainly **not** a +reason to drop the use of prototypes altogether. In the end it comes down to +which solution is better suited for the needs of the application, it is +especially important to choose a specific style of object creation **and stick** +with it. + diff --git a/doc/ko/function/general.md b/doc/ko/function/general.md new file mode 100644 index 00000000..7ca180f0 --- /dev/null +++ b/doc/ko/function/general.md @@ -0,0 +1,48 @@ +## Function Declarations and Expressions + +Functions in JavaScript are first class objects. That means they can be +passed around like any other value. One common use of this feature is to pass +an *anonymous function* as a callback to another, possibly asynchronous function. + +### The `function` Declaration + + function foo() {} + +The above function gets [hoisted](#function.scopes) before the execution of the +program starts; thus, it is available *everywhere* in the scope it was *defined* +in, even if called before the actual definition in the source. + + foo(); // Works because foo was created before this code runs + function foo() {} + +### The `function` Expression + + var foo = function() {}; + +This example assigns the unnamed and *anonymous* function to the variable `foo`. + + foo; // 'undefined' + foo(); // this raises a TypeError + var foo = function() {}; + +Due to the fact that `var` is a declaration that hoists the variable name `foo` +before the actual execution of the code starts, `foo` is already defined when +the script gets executed. + +But since assignments only happen at runtime, the value of `foo` will default +to [undefined](#core.undefined) before the corresponding code is executed. + +### Named Function Expression + +Another special case is the assignment of named functions. + + var foo = function bar() { + bar(); // Works + } + bar(); // ReferenceError + +Here, `bar` is not available in the outer scope, since the function only gets +assigned to `foo`; however, inside of `bar`, it is available. This is due to +how [name resolution](#function.scopes) in JavaScript works, the name of the +function is *always* made available in the local scope of the function itself. + diff --git a/doc/ko/function/scopes.md b/doc/ko/function/scopes.md new file mode 100644 index 00000000..efb9d882 --- /dev/null +++ b/doc/ko/function/scopes.md @@ -0,0 +1,231 @@ +## Scopes and Namespaces + +Although JavaScript deals fine with the syntax of two matching curly +braces for blocks, it does **not** support block scope; hence, all that is left +is in the language is *function scope*. + + function test() { // a scope + for(var i = 0; i < 10; i++) { // not a scope + // count + } + console.log(i); // 10 + } + +> **Note:** When not used in an assignment, return statement or as a function +> argument, the `{...}` notation will get interpreted as a block statement and +> **not** as an object literal. This, in conjunction with +> [automatic insertion of semicolons](#core.semicolon), can lead to subtle errors. + +There are also no distinct namespaces in JavaScript, which means that everything +gets defined in one *globally shared* namespace. + +Each time a variable is referenced, JavaScript will traverse upwards through all +the scopes until it finds it. In the case that it reaches the global scope and +still has not found the requested name, it will raise a `ReferenceError`. + +### The Bane of Global Variables + + // script A + foo = '42'; + + // script B + var foo = '42' + +The above two scripts do **not** have the same effect. Script A defines a +variable called `foo` in the *global* scope, and script B defines a `foo` in the +*current* scope. + +Again, that is **not** at all the *same effect*: not using `var` can have major +implications. + + // global scope + var foo = 42; + function test() { + // local scope + foo = 21; + } + test(); + foo; // 21 + +Leaving out the `var` statement inside the function `test` will override the +value of `foo`. While this might not seem like a big deal at first, having +thousands of lines of JavaScript and not using `var` will introduce horrible, +hard-to-track-down bugs. + + // global scope + var items = [/* some list */]; + for(var i = 0; i < 10; i++) { + subLoop(); + } + + function subLoop() { + // scope of subLoop + for(i = 0; i < 10; i++) { // missing var statement + // do amazing stuff! + } + } + +The outer loop will terminate after the first call to `subLoop`, since `subLoop` +overwrites the global value of `i`. Using a `var` for the second `for` loop would +have easily avoided this error. The `var` statement should **never** be left out +unless the *desired effect* is to affect the outer scope. + +### Local Variables + +The only source for local variables in JavaScript are +[function](#function.general) parameters and variables that were declared via the +`var` statement. + + // global scope + var foo = 1; + var bar = 2; + var i = 2; + + function test(i) { + // local scope of the function test + i = 5; + + var foo = 3; + bar = 4; + } + test(10); + +While `foo` and `i` are local variables inside the scope of the function `test`, +the assignment of `bar` will override the global variable with the same name. + +### Hoisting + +JavaScript **hoists** declarations. This means that both `var` statements and +`function` declarations will be moved to the top of their enclosing scope. + + 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]; + } + } + +The above code gets transformed before any execution is started. JavaScript moves +the `var` statements, as well as the `function` declarations to the top of the +nearest surrounding scope. + + // var statements got moved here + var bar, someValue; // default to 'undefined' + + // the function declaration got moved up too + function test(data) { + var goo, i, e; // missing block scope moves these here + if (false) { + goo = 1; + + } else { + goo = 2; + } + for(i = 0; i < 100; i++) { + e = data[i]; + } + } + + bar(); // fails with a TypeError since bar is still 'undefined' + someValue = 42; // assignments are not affected by hoisting + bar = function() {}; + + test(); + +Missing block scoping will not only move `var` statements out of loops and +their bodies, it will also make the results of certain `if` constructs +non-intuitive. + +In the original code, although the `if` statement seemed to modify the *global +variable* `goo`, it actually modifies the *local variable* - after hoisting +has been applied. + +Without the knowledge about *hoisting*, the below code might seem to raise a +`ReferenceError`. + + // check whether SomeImportantThing has been initiliazed + if (!SomeImportantThing) { + var SomeImportantThing = {}; + } + +But of course, the above works due to the fact that the `var` statement is being +moved to the top of the *global scope*. + + var SomeImportantThing; + + // other code might initiliaze SomeImportantThing here, or not + + // make sure it's there + if (!SomeImportantThing) { + SomeImportantThing = {}; + } + +### Name Resolution Order + +All scopes in JavaScript, including the *global scope*, have the special name +[`this`](#function.this), defined in them, which refers to the *current object*. + +Function scopes also have the name [`arguments`](#function.arguments), defined in +them, which contains the arguments that were passed to a function. + +For example, when trying to access a variable named `foo` inside the scope of a +function, JavaScript will lookup the name in the following order: + + 1. In case there is a `var foo` statement in the current scope, use that. + 2. If one of the function parameters is named `foo`, use that. + 3. If the function itself is called `foo`, use that. + 4. Go to the next outer scope, and start with **#1** again. + +> **Note:** Having a parameter called `arguments` will **prevent** the creation +> of the default `arguments` object. + +### Namespaces + +A common problem of having only one global namespace is the likeliness of running +into problems where variable names clash. In JavaScript, this problem can +easily be avoided with the help of *anonymous wrappers*. + + (function() { + // a self contained "namespace" + + window.foo = function() { + // an exposed closure + }; + + })(); // execute the function immediately + + +Unnamed functions are considered [expressions](#function.general); so in order to +being callable, they must first be evaluated. + + ( // evaluate the function inside the paranthesis + function() {} + ) // and return the function object + () // call the result of the evaluation + +There are other ways for evaluating and calling the function expression; which, +while different in syntax, do behave the exact same way. + + // Two other ways + +function(){}(); + (function(){}()); + +### In Conclusion + +It is recommended to always use an *anonymous wrapper* for encapsulating code in +its own namespace. This does not only protect code against name clashes, but it +also allows for better modularization of programs. + +Additionally, the use of global variables is considered **bad practice**. **Any** +use of them indicates badly written code that is prone to errors and hard to maintain. + diff --git a/doc/ko/function/this.md b/doc/ko/function/this.md new file mode 100644 index 00000000..440900e8 --- /dev/null +++ b/doc/ko/function/this.md @@ -0,0 +1,111 @@ +## How `this` Works + +JavaScript has a different concept of what the special name `this` refers to +than most other programming languages do. There are exactly **five** different +ways in which the value of `this` can be bound in the language. + +### The Global Scope + + this; + +When using `this` in global scope, it will simply refer to the *global* object. + + +### Calling a Function + + foo(); + +Here, `this` will again refer to the *global* object. + +> **ES5 Note:** In strict mode, the global case **no longer** exists. +> `this` will instead have the value of `undefined` in that case. + +### Calling a Method + + test.foo(); + +In this example, `this` will refer to `test`. + +### Calling a Constructor + + new foo(); + +A function call that is preceded by the `new` keyword acts as +a [constructor](#function.constructors). Inside the function, `this` will refer +to a *newly created* `Object`. + +### Explicit Setting of `this` + + function foo(a, b, c) {} + + var bar = {}; + foo.apply(bar, [1, 2, 3]); // array will expand to the below + foo.call(bar, 1, 2, 3); // results in a = 1, b = 2, c = 3 + +When using the `call` or `apply` methods of `Function.prototype`, the value of +`this` inside the called function gets **explicitly set** to the first argument +of the corresponding function call. + +As a result, the above example the *method case* does **not** apply, and `this` +inside of `foo` will be set to `bar`. + +> **Note:** `this` **cannot** be used to refer to the object inside of an `Object` +> literal. So `var obj = {me: this}` will **not** result in `me` referring to +> `obj`, since `this` only gets bound by one of the five listed cases. + +### Common Pitfalls + +While most of these cases make sense, the first one is to be considered another +mis-design of the language because it **never** has any practical use. + + Foo.method = function() { + function test() { + // this is set to the global object + } + test(); + } + +A common misconception is that `this` inside of `test` refers to `Foo`; while in +fact, it **does not**. + +In order to gain access to `Foo` from within `test`, it is necessary to create a +local variable inside of `method` which refers to `Foo`. + + Foo.method = function() { + var that = this; + function test() { + // Use that instead of this here + } + test(); + } + +`that` is just a normal variable name, but it is commonly used for the reference to an +outer `this`. In combination with [closures](#function.closures), it can also +be used to pass `this` values around. + +### Assigning Methods + +Another thing that does **not** work in JavaScript is function aliasing, which is +**assigning** a method to a variable. + + var test = someObject.methodTest; + test(); + +Due to the first case, `test` now acts like a plain function call; therefore, +`this` inside it will no longer refer to `someObject`. + +While the late binding of `this` might seem like a bad idea at first, in +fact, it is what makes [prototypal inheritance](#object.prototype) work. + + function Foo() {} + Foo.prototype.method = function() {}; + + function Bar() {} + Bar.prototype = Foo.prototype; + + new Bar().method(); + +When `method` gets called on a instance of `Bar`, `this` will now refer to that +very instance. + + diff --git a/doc/ko/index.json b/doc/ko/index.json new file mode 100644 index 00000000..bffcbf2c --- /dev/null +++ b/doc/ko/index.json @@ -0,0 +1,69 @@ +{ + "title": "JavaScript Garden", + "langTitle": "JavaScript Garden in English", + "description": "A Guide to JavaScript's Quirks and Flaws.", + "sections": [ + { + "title": "Intro", + "dir": "intro", + "articles": [] + }, + { + "title": "Objects", + "dir": "object", + "articles": [ + "general", + "prototype", + "hasownproperty", + "forinloop" + ] + }, + { + "title": "Functions", + "dir": "function", + "articles": [ + "general", + "this", + "closures", + "arguments", + "constructors", + "scopes" + ] + }, + { + "title": "Arrays", + "dir": "array", + "articles": [ + "general", + "constructor" + ] + }, + { + "title": "Types", + "dir": "types", + "articles": [ + "equality", + "typeof", + "instanceof", + "casting" + ] + }, + { + "title": "Core", + "dir": "core", + "articles": [ + "eval", + "undefined", + "semicolon", + "delete" + ] + }, + { + "title": "Other", + "dir": "other", + "articles": [ + "timeouts" + ] + } + ] +} diff --git a/doc/ko/intro/index.md b/doc/ko/intro/index.md new file mode 100644 index 00000000..134bca80 --- /dev/null +++ b/doc/ko/intro/index.md @@ -0,0 +1,47 @@ +## Intro + +**JavaScript Garden** is a growing collection of documentation about the most +quirky parts of the JavaScript programming language. It gives advice to +avoid common mistakes and subtle bugs, as well as performance issues and bad +practices, that non-expert JavaScript programmers may encounter on their +endeavours into the depths of the language. + +JavaScript Garden does **not** aim to teach you JavaScript. Former knowledge +of the language is strongly recommended in order to understand the topics covered +in this guide. In order to learn the basics of the language, please head over to +the excellent [guide][1] on the Mozilla Developer Network. + +## The Authors + +This guide is the work of two lovely [Stack Overflow][2] users, [Ivo Wetzel][3] +(Writing) and [Zhang Yi Jiang][4] (Design). + +## Contributors + + - [Caio Romão][5] (Spelling corrections) + - [Andreas Blixt][6] (Language corrections) + +## Hosting + +JavaScript Garden is hosted on GitHub, but [Cramer Development][7] supports us +with a mirror at [JavaScriptGarden.info][8]. + +## License + +JavaScript Garden is published under the [MIT license][9] and hosted on +[GitHub][10]. If you find errors or typos please [file an issue][11] or a pull +request on the repository. You can also find us in the [JavaScript room][12] on +Stack Overflow chat. + +[1]: https://developer.mozilla.org/en/JavaScript/Guide +[2]: http://stackoverflow.com/ +[3]: http://stackoverflow.com/users/170224/ivo-wetzel +[4]: http://stackoverflow.com/users/313758/yi-jiang +[5]: https://github.com/caio +[6]: https://github.com/blixt +[7]: http://cramerdev.com/ +[8]: http://javascriptgarden.info/ +[9]: https://github.com/BonsaiDen/JavaScript-Garden/blob/next/LICENSE +[10]: https://github.com/BonsaiDen/JavaScript-Garden +[11]: https://github.com/BonsaiDen/JavaScript-Garden/issues +[12]: http://chat.stackoverflow.com/rooms/17/javascript diff --git a/doc/ko/object/forinloop.md b/doc/ko/object/forinloop.md new file mode 100644 index 00000000..cb776b36 --- /dev/null +++ b/doc/ko/object/forinloop.md @@ -0,0 +1,51 @@ +## The `for in` Loop + +Just like the `in` operator, the `for in` loop also traverses the prototype +chain when iterating over the properties of an object. + +> **Note:** The `for in` loop will **not** iterate over any properties that +> have their `enumerable` attribute set to `false`; for example, the `length` +> property of an array. + + // Poisoning Object.prototype + Object.prototype.bar = 1; + + var foo = {moo: 2}; + for(var i in foo) { + console.log(i); // prints both bar and moo + } + +Since it is not possible to change the behavior of the `for in` loop itself, it +is necessary to filter out the unwanted properties inside the loop body; +this is done by using the [`hasOwnProperty`](#object.hasownproperty) method of +`Object.prototype`. + +> **Note:** Since the `for in` always traverses the complete prototype chain, it +> will get slower with each additional layer of inheritance added to an object. + +### Using `hasOwnProperty` for Filtering + + // still the foo from above + for(var i in foo) { + if (foo.hasOwnProperty(i)) { + console.log(i); + } + } + +This version is the only correct one to use. Due to the use of `hasOwnProperty`, it +will **only** print out `moo`. When `hasOwnProperty` is left out, the code is +prone to errors in cases where the native prototypes - e.g. `Object.prototype` - +have been extended. + +One widely used framework which does this is [Prototype][1]. When this +framework is included, `for in` loops that do not use `hasOwnProperty` are +guaranteed to break. + +### In Conclusion + +It is recommended to **always** use `hasOwnProperty`. Never should any +assumptions be made about the environment the code is running in, or whether the +native prototypes have been extended or not. + +[1]: http://www.prototypejs.org/ + diff --git a/doc/ko/object/general.md b/doc/ko/object/general.md new file mode 100644 index 00000000..bc52f1f7 --- /dev/null +++ b/doc/ko/object/general.md @@ -0,0 +1,99 @@ +## Object Usage and Properties + +Everything in JavaScript acts like an object, with the only two exceptions being +[`null`](#core.undefined) and [`undefined`](#core.undefined). + + false.toString() // 'false' + [1, 2, 3].toString(); // '1,2,3' + + function Foo(){} + Foo.bar = 1; + Foo.bar; // 1 + +A common misconception is that number literals cannot be used as +objects. That is because a flaw in JavaScript's parser tries to parse the *dot +notation* on a number as a floating point literal. + + 2.toString(); // raises SyntaxError + +There are a couple of workarounds which can be used in order make number +literals act as objects too. + + 2..toString(); // the second point is correctly recognized + 2 .toString(); // note the space left to the dot + (2).toString(); // 2 is evaluated first + +### Objects as a Data Type + +Objects in JavaScript can also be used as a [*Hashmap*][1]; they mainly consist +of named properties mapping to values. + +Using a object literal - `{}` notation - it is possible to create a +plain object. This new object [inherits](#object.prototype) from `Object.prototype` and +has no [own properties](#object.hasownproperty) defined on it. + + var foo = {}; // a new empty object + + // a new object with a property called 'test' with value 12 + var bar = {test: 12}; + +### Accessing Properties + +The properties of an object can be accessed in two ways, via either the dot +notation or the square bracket notation. + + var foo = {name: 'Kitten'} + foo.name; // kitten + foo['name']; // kitten + + var get = 'name'; + foo[get]; // kitten + + foo.1234; // SyntaxError + foo['1234']; // works + +Both notations are identical in their workings, with the only difference being that +the square bracket notation allows for dynamic setting of properties, as well as +the use of property names that would otherwise lead to a syntax error. + +### Deleting Properties + +The only way to actually remove a property from an object is to use the `delete` +operator; setting the property to `undefined` or `null` only removes the +*value* associated with the property, but not the *key*. + + 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]); + } + } + +The above outputs both `bar undefined` and `foo null` - only `baz` was +removed and is therefore missing from the output. + +### Notation of Keys + + var test = { + 'case': 'I am a keyword, so I must be notated as a string', + delete: 'I am a keyword, so me too' // raises SyntaxError + }; + +Object properties can be both notated as plain characters and as strings. Due to +another mis-design in JavaScript's parser, the above will throw +a `SyntaxError` prior to ECMAScript 5. + +This error arises from the fact that `delete` is a *keyword*; therefore, it must be +notated as a *string literal* to ensure that it will be correctly interpreted by +older JavaScript engines. + +[1]: http://en.wikipedia.org/wiki/Hashmap + diff --git a/doc/ko/object/hasownproperty.md b/doc/ko/object/hasownproperty.md new file mode 100644 index 00000000..576c50c6 --- /dev/null +++ b/doc/ko/object/hasownproperty.md @@ -0,0 +1,53 @@ +## `hasOwnProperty` + +In order to check whether a object has a property defined on *itself* and **not** +somewhere on its [prototype chain](#object.prototype), it is necessary to use the +`hasOwnProperty` method which all objects inherit from `Object.prototype`. + +> **Note:** It is **not** enough to check whether a property is `undefined`. The +> property might very well exist, but its value just happens to be set to +> `undefined`. + +`hasOwnProperty` is the only thing in JavaScript which deals with properties and +does **not** traverse the prototype chain. + + // Poisoning Object.prototype + Object.prototype.bar = 1; + var foo = {goo: undefined}; + + foo.bar; // 1 + 'bar' in foo; // true + + foo.hasOwnProperty('bar'); // false + foo.hasOwnProperty('goo'); // true + +Only `hasOwnProperty` will give the correct and expected result; this is +essential when iterating over the properties of any object. There is **no** other +way to exclude properties that are not defined on the object *itself*, but +somewhere on its prototype chain. + +### `hasOwnProperty` as a Property + +JavaScript does **not** protect the property name `hasOwnProperty`; thus, if the +possibility exists that an object might have a property with this name, it is +necessary to use an *external* `hasOwnProperty` in order to get correct results. + + var foo = { + hasOwnProperty: function() { + return false; + }, + bar: 'Here be dragons' + }; + + foo.hasOwnProperty('bar'); // always returns false + + // Use another Object's hasOwnProperty and call it with 'this' set to foo + ({}).hasOwnProperty.call(foo, 'bar'); // true + +### In Conclusion + +When checking for the existence of a property on a object, `hasOwnProperty` is +the **only** method of doing so. It is also recommended to make `hasOwnProperty` +part of **every** [`for in` loop](#object.forinloop); this will avoid errors from +extended native [prototypes](#object.prototype). + diff --git a/doc/ko/object/prototype.md b/doc/ko/object/prototype.md new file mode 100644 index 00000000..0a3b6d0c --- /dev/null +++ b/doc/ko/object/prototype.md @@ -0,0 +1,116 @@ +## The Prototype + +JavaScript does not feature a classical inheritance model; instead, it uses a +*prototypal* one. + +While this is often considered to be one of JavaScript's weaknesses, the +prototypal inheritance model is in fact more powerful than the classic model. +It is, for example, fairly trivial to build a classic model on top of it, while the +other way around is a far more difficult task. + +Due to the fact that JavaScript is basically the only widely used language that +features prototypal inheritance, it takes some time to adjust to the +differences between the two models. + +The first major difference is that inheritance in JavaScript is done by using so +called *prototype chains*. + +> **Note:** Simply using `Bar.prototype = Foo.prototype` will result in both objects +> sharing the **same** prototype. Therefore, changes to either object's prototype +> will affect the prototype of the other as well, which in most cases is not the +> desired effect. + + function Foo() { + this.value = 42; + } + Foo.prototype = { + method: function() {} + }; + + function Bar() {} + + // Set Bar's prototype to a new instance of Foo + Bar.prototype = new Foo(); + Bar.prototype.foo = 'Hello World'; + + // Make sure to list Bar as the actual constructor + Bar.prototype.constructor = Bar; + + var test = new Bar() // create a new bar instance + + // The resulting prototype chain + test [instance of Bar] + Bar.prototype [instance of Foo] + { foo: 'Hello World' } + Foo.prototype + { method: ... } + Object.prototype + { toString: ... /* etc. */ } + +In the above, the object `test` will inherit from both `Bar.prototype` and +`Foo.prototype`; hence, it will have access to the function `method` that was +defined on `Foo`. It will also have access to the property `value` of the +**one** `Foo` instance that is its prototype. It is important to note that `new +Bar()` does **not** create a new `Foo` instance, but reuses the one assigned to +its prototype; thus, all `Bar` instances will share the **same** `value` property. + +> **Note:** Do **not** use `Bar.prototype = Foo`, since it will not point to +> the prototype of `Foo` but rather to the function object `Foo`. So the +> prototype chain will go over `Function.prototype` and not `Foo.prototype`; +> therefore, `method` will not be on the prototype chain. + +### Property Lookup + +When accessing the properties of an object, JavaScript will traverse the +prototype chain **upwards** until it finds a property with the requested name. + +When it reaches the top of the chain - namely `Object.prototype` - and still +hasn't found the specified property, it will return the value +[undefined](#core.undefined) instead. + +### The Prototype Property + +While the prototype property is used by the language to build the prototype +chains, it is still possible to assign **any** given value to it. However, +primitives will simply get ignored when assigned as a prototype. + + function Foo() {} + Foo.prototype = 1; // no effect + +Assigning objects, as shown in the example above, will work, and allows for dynamic +creation of prototype chains. + +### Performance + +The lookup time for properties that are high up on the prototype chain can have a +negative impact on performance critical sections of code. Additionally, trying to +access non-existent properties will always traverse the full prototype chain. + +Also, when [iterating](#object.forinloop) over the properties of an object +**every** property that is on the prototype chain will get enumerated. + +### Extension of Native Prototypes + +One mis-feature that is often used is to extend `Object.prototype` or one of the +other built in prototypes. + +This technique is called [monkey patching][1] and breaks *encapsulation*. While +used by widely spread frameworks such as [Prototype][2], there is still no good +reason for cluttering built-in types with additional *non-standard* functionality. + +The **only** good reason for extending a built-in prototype is to backport +the features of newer JavaScript engines; for example, +[`Array.forEach`][3]. + +### In Conclusion + +It is a **must** to understand the prototypal inheritance model completely +before writing complex code which makes use of it. Also, watch the length of +the prototype chains and break them up if necessary to avoid possible +performance issues. Further, the native prototypes should **never** be extended +unless it is for the sake of compatibility with newer JavaScript features. + +[1]: http://en.wikipedia.org/wiki/Monkey_patch +[2]: http://prototypejs.org/ +[3]: https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/forEach + diff --git a/doc/ko/other/timeouts.md b/doc/ko/other/timeouts.md new file mode 100644 index 00000000..3a306bdd --- /dev/null +++ b/doc/ko/other/timeouts.md @@ -0,0 +1,155 @@ +### `setTimeout` and `setInterval` + +Since JavaScript is asynchronous, it is possible to schedule the execution of a +function by using the `setTimeout` and `setInterval` functions. + +> **Note:** Timeouts are **not** part of the ECMAScript Standard. They are +> implemented as part of the [DOM][1]. + + function foo() {} + var id = setTimeout(foo, 1000); // returns a Number > 0 + +When `setTimeout` gets called, it will return the ID of the timeout and schedule +`foo` to run in **approximately** one thousand milliseconds in the future. +`foo` will then get executed exactly **once**. + +Depending on the timer resolution of the JavaScript engine that is running the +code, as well as the fact that JavaScript is single threaded and other code that +gets executed might block the thread, it is by **no means** a safe bet that one +will get the exact delay that was specified in the `setTimeout` call. + +The function that was passed as the first parameter will get called by the +*global object*, which means that [`this`](#function.this) inside the called function +refers to that very object. + + function Foo() { + this.value = 42; + this.method = function() { + // this refers to the global object + console.log(this.value); // will log undefined + }; + setTimeout(this.method, 500); + } + new Foo(); + + +> **Note:** As `setTimeout` takes a **function object** as its first parameter, an +> often made mistake is to use `setTimeout(foo(), 1000)`, which will use the +> **return value** of the call `foo` and **not** `foo`. This is, most of the time, +> a silent error, since when the function returns `undefined` `setTimeout` will +> **not** raise any error. + +### Stacking Calls with `setInterval` + +While `setTimeout` only runs the function once, `setInterval` - as the name +suggests - will execute the function **every** `X` milliseconds, but its use is +discouraged. + +When code that is being executed blocks the timeout call, `setInterval` will +still issue more calls to the specified function. This can, especially with small +intervals, result in function calls stacking up. + + function foo(){ + // something that blocks for 1 second + } + setInterval(foo, 100); + +In the above code, `foo` will get called once and will then block for one second. + +While `foo` blocks the code, `setInterval` will still schedule further calls to +it. Now, when `foo` has finished, there will already be **ten** further calls to +it waiting for execution. + +### Dealing with Possible Blocking Code + +The easiest solution, as well as most controllable solution, is to use `setTimeout` within +the function itself. + + function foo(){ + // something that blocks for 1 second + setTimeout(foo, 100); + } + foo(); + +Not only does this encapsulate the `setTimeout` call, but it also prevents the +stacking of calls and it gives additional control. `foo` itself can now decide +whether it wants to run again or not. + +### Manually Clearing Timeouts + +Clearing timeouts and intervals works by passing the respective ID to +`clearTimeout` or `clearInterval`, depending which `set` function was used in +the first place. + + var id = setTimeout(foo, 1000); + clearTimeout(id); + +### Clearing all timeouts + +Because there is no built-in method for clearing all timeouts and/or intervals, +it is necessary to use brute force in order to achieve this functionality. + + // clear "all" timeouts + for(var i = 1; i < 1000; i++) { + clearTimeout(i); + } + +There might still be timeouts that are unaffected by this arbitrary number; +therefore, is is instead recommended to keep track of all the timeout IDs, so +they can be cleared specifically. + +### Hidden use of `eval` + +`setTimeout` and `setInterval` can also take a string as their first parameter. +This feature should **never** be used because it internally makes use of `eval`. + +> **Note:** Since the timeout functions are **not** specified by the ECMAScript +> standard, the exact workings when a string is passed to them might differ in +> various JavaScript implementations. For example, Microsoft's JScript makes use of +> the `Function` constructor in place of `eval`. + + function foo() { + // will get called + } + + function bar() { + function foo() { + // never gets called + } + setTimeout('foo()', 1000); + } + bar(); + +Since `eval` is not getting called [directly](#core.eval) in this case, the string +passed to `setTimeout` will get executed in the *global scope*; thus, it will +not use the local variable `foo` from the scope of `bar`. + +It is further recommended to **not** use a string for passing arguments to the +function that will get called by either of the timeout functions. + + function foo(a, b, c) {} + + // NEVER use this + setTimeout('foo(1,2, 3)', 1000) + + // Instead use an anonymous function + setTimeout(function() { + foo(a, b, c); + }, 1000) + +> **Note:** While it is also possible to use the syntax +> `setTimeout(foo, 1000, a, b, c)`, it is not recommended, as its use may lead +> to subtle errors when used with [methods](#function.this). + +### In Conclusion + +**Never** should a string be used as the parameter of `setTimeout` or +`setInterval`. It is a clear sign of **really** bad code, when arguments need +to be supplied to the function that gets called. An *anonymous function* should +be passed that then takes care of the actual call. + +Furthermore, the use of `setInterval` should be avoided because its scheduler is not +blocked by executing JavaScript. + +[1]: http://en.wikipedia.org/wiki/Document_Object_Model "Document Object Model" + diff --git a/doc/ko/types/casting.md b/doc/ko/types/casting.md new file mode 100644 index 00000000..34d6fd78 --- /dev/null +++ b/doc/ko/types/casting.md @@ -0,0 +1,70 @@ +## Type Casting + +JavaScript is a *weakly typed* language, so it will apply *type coercion* +**wherever** possible. + + // These are true + new Number(10) == 10; // Number.toString() is converted + // back to a number + + 10 == '10'; // Strings gets converted to Number + 10 == '+10 '; // More string madness + 10 == '010'; // And more + isNaN(null) == false; // null converts to 0 + // which of course is not NaN + + // These are false + 10 == 010; + 10 == '-10'; + +> **ES5 Note:** Number literals that start with a `0` are interpreted as octal +> (Base 8). Octal support for these has been **removed** in ECMAScript 5 strict +> mode. + +In order to avoid the above, use of the [strict equal operator](#types.equality) +is **highly** recommended. Although this avoids a lot of common pitfalls, there +are still many further issues that arise from JavaScript's weak typing system. + +### Constructors of Built-In Types + +The constructors of the built in types like `Number` and `String` behave +differently when being used with the `new` keyword and without it. + + new Number(10) === 10; // False, Object and Number + Number(10) === 10; // True, Number and Number + new Number(10) + 0 === 10; // True, due to implicit conversion + +Using a built-in type like `Number` as a constructor will create a new `Number` +object, but leaving out the `new` keyword will make the `Number` function behave +like a converter. + +In addition, having literals or non-object values in there will result in even +more type coercion. + +The best option is to cast to one of the three possible types **explicitly**. + +### Casting to a String + + '' + 10 === '10'; // true + +By prepending an empty string, a value can easily be casted to a string. + +### Casting to a Number + + +'10' === 10; // true + +Using the **unary** plus operator, it is possible to cast to a number. + +### Casting to a Boolean + +By using the **not** operator twice, a value can be converted a boolean. + + !!'foo'; // true + !!''; // false + !!'0'; // true + !!'1'; // true + !!'-1' // true + !!{}; // true + !!true; // true + + diff --git a/doc/ko/types/equality.md b/doc/ko/types/equality.md new file mode 100644 index 00000000..5665917f --- /dev/null +++ b/doc/ko/types/equality.md @@ -0,0 +1,71 @@ +## Equality and Comparisons + +JavaScript has two different ways of comparing the values of objects for equality. + +### The Equality Operator + +The equality operator consists of two equal signs: `==` + +JavaScript features *weak typing*. This means that the equality operator +**coerces** types in order to compare them. + + "" == "0" // false + 0 == "" // true + 0 == "0" // true + false == "false" // false + false == "0" // true + false == undefined // false + false == null // false + null == undefined // true + " \t\r\n" == 0 // true + +The above table shows the results of the type coercion, and it is the main reason +why the use of `==` is widely regarded as bad practice. It introduces +hard-to-track-down bugs due to its complicated conversion rules. + +Additionally, there is also a performance impact when type coercion is in play; +for example, a string has to be converted to a number before it can be compared +to another number. + +### The Strict Equality Operator + +The strict equality operator consists of **three** equal signs: `===`. + +It works exactly like the normal equality operator, except that strict equality +operator does **not** perform type coercion between its operands. + + "" === "0" // false + 0 === "" // false + 0 === "0" // false + false === "false" // false + false === "0" // false + false === undefined // false + false === null // false + null === undefined // false + " \t\r\n" === 0 // false + +The above results are a lot clearer and allow for early breakage of code. This +hardens code to a certain degree and also gives performance improvements in case +the operands are of different types. + +### Comparing Objects + +While both `==` and `===` are stated as **equality** operators, they behave +differently when at least one of their operands happens to be an `Object`. + + {} === {}; // false + new String('foo') === 'foo'; // false + new Number(10) === 10; // false + var foo = {}; + foo === foo; // true + +Here, both operators compare for **identity** and **not** equality; that is, they +will compare for the same **instance** of the object, much like `is` in Python +and pointer comparison in C. + +### In Conclusion + +It is highly recommended to only use the **strict equality** operator. In cases +where types need to be coerced, it should be done [explicitly](#types.casting) +and not left to the language's complicated coercion rules. + diff --git a/doc/ko/types/instanceof.md b/doc/ko/types/instanceof.md new file mode 100644 index 00000000..84251128 --- /dev/null +++ b/doc/ko/types/instanceof.md @@ -0,0 +1,38 @@ +## The `instanceof` Operator + +The `instanceof` operator compares the constructors of its two operands. It is +only useful when comparing custom made objects. Used on built-in types, it is +nearly as useless as the [typeof operator](#types.typeof). + +### Comparing Custom Objects + + function Foo() {} + function Bar() {} + Bar.prototype = new Foo(); + + new Bar() instanceof Bar; // true + new Bar() instanceof Foo; // true + + // This just sets Bar.prototype to the function object Foo + // But not to an actual instance of Foo + Bar.prototype = Foo; + new Bar() instanceof Foo; // false + +### Using `instanceof` with Native Types + + new String('foo') instanceof String; // true + new String('foo') instanceof Object; // true + + 'foo' instanceof String; // false + 'foo' instanceof Object; // false + +One important thing to note here is that `instanceof` does not work on objects +that originate from different JavaScript contexts (e.g. different documents +in a web browser), since their constructors will not be the exact same object. + +### In Conclusion + +The `instanceof` operator should **only** be used when dealing with custom made +objects that originate from the same JavaScript context. Just like the +[`typeof`](#types.typeof) operator, every other use of it should be **avoided**. + diff --git a/doc/ko/types/typeof.md b/doc/ko/types/typeof.md new file mode 100644 index 00000000..00377db4 --- /dev/null +++ b/doc/ko/types/typeof.md @@ -0,0 +1,87 @@ +## The `typeof` Operator + +The `typeof` operator (together with +[`instanceof`](#types.instanceof)) is probably the biggest +design flaw of JavaScript, as it is near of being **completely broken**. + +Although `instanceof` still has its limited uses, `typeof` really has only one +practical use case, which does **not** happen to be checking the type of an +object. + +> **Note:** While `typeof` can also be called with a function like syntax +> i.e. `typeof(obj)`, this is not a function call. The two parenthesis will +> behave like normal and the return value will be used as the operand of the +> `typeof` operator. There is **no** `typeof` function. + +### The JavaScript Type Table + + Value Class Type + ------------------------------------- + "foo" String string + new String("foo") String object + 1.2 Number number + new Number(1.2) Number object + true Boolean boolean + new Boolean(true) Boolean object + new Date() Date object + new Error() Error object + [1,2,3] Array object + new Array(1, 2, 3) Array object + new Function("") Function function + /abc/g RegExp object (function in Nitro/V8) + new RegExp("meow") RegExp object (function in Nitro/V8) + {} Object object + new Object() Object object + +In the above table, *Type* refers to the value that the `typeof` operator returns. +As can be clearly seen, this value is anything but consistent. + +The *Class* refers to the value of the internal `[[Class]]` property of an object. + +> **From the Specification:** The value of `[[Class]]` can be one of the +> following strings. `Arguments`, `Array`, `Boolean`, `Date`, `Error`, +> `Function`, `JSON`, `Math`, `Number`, `Object`, `RegExp`, `String`. + +In order to retrieve the value of `[[Class]]`, one has to make use of the +`toString` method of `Object.prototype`. + +### The Class of an Object + +The specification gives exactly one way of accessing the `[[Class]]` value, +with the use of `Object.prototype.toString`. + + function is(type, obj) { + var clas = Object.prototype.toString.call(obj).slice(8, -1); + return obj !== undefined && obj !== null && clas === type; + } + + is('String', 'test'); // true + is('String', new String('test')); // true + +In the above example, `Object.prototype.toString` gets called with the value of +[this](#function.this) being set to the object whose `[[Class]]` value should be +retrieved. + +> **ES5 Note:** For convenience the return value of `Object.prototype.toString` +> for both `null` and `undefined` was **changed** from `Object` to `Null` and +> `Undefined` in ECMAScript 5. + +### Testing for Undefined Variables + + typeof foo !== 'undefined' + +The above will check whether `foo` was actually declared or not; just +referencing it would result in a `ReferenceError`. This is the only thing +`typeof` is actually useful for. + +### In Conclusion + +In order to check the type of an object, it is highly recommended to use +`Object.prototype.toString` because this is the only reliable way of doing so. +As shown in the above type table, some return values of `typeof` are not defined +in the specification; thus, they can differ across various implementations. + +Unless checking whether a variable is defined, `typeof` should be avoided at +**all costs**. + + diff --git a/doc/language.json b/doc/language.json index 1c1bdffc..d79c4298 100644 --- a/doc/language.json +++ b/doc/language.json @@ -1,5 +1,5 @@ { "default": "en", - "listed": ["en", "fi", "ru", "zh", "tr", "pl"] + "listed": ["en", "fi", "ru", "zh", "tr", "pl", "ko"] } From 8ce511f0c2dcda8f308695a073b2c405e1f04278 Mon Sep 17 00:00:00 2001 From: HIRAKI Satoru Date: Mon, 10 Oct 2011 17:49:15 +0900 Subject: [PATCH 149/463] translate "`undefined` and `null`" in "Core" to ja --- doc/ja/core/undefined.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/doc/ja/core/undefined.md b/doc/ja/core/undefined.md index b29da3b4..fd954379 100644 --- a/doc/ja/core/undefined.md +++ b/doc/ja/core/undefined.md @@ -1,7 +1,6 @@ -## `undefined` and `null` +## `undefined`と`null` -JavaScript has two distinct values for `nothing`, the more useful of these two -being `undefined`. +JavaScriptは`nothing`を表す2つの別個の値を持っています。`undefined`はこれら2つの内より便利な存在です。 ### The Value `undefined` From 5876a505a7617b7279fa8fd88b6b106f44ac2b0a Mon Sep 17 00:00:00 2001 From: HIRAKI Satoru Date: Mon, 10 Oct 2011 20:24:23 +0900 Subject: [PATCH 150/463] translate "The Value `undefined`" in "Core" to ja --- doc/ja/core/undefined.md | 28 ++++++++++++---------------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/doc/ja/core/undefined.md b/doc/ja/core/undefined.md index fd954379..a22f4fbd 100644 --- a/doc/ja/core/undefined.md +++ b/doc/ja/core/undefined.md @@ -2,27 +2,23 @@ JavaScriptは`nothing`を表す2つの別個の値を持っています。`undefined`はこれら2つの内より便利な存在です。 -### The Value `undefined` +### `undefined`の値 -`undefined` is a type with exactly one value: `undefined`. +`undefined`はただ1つの値`undefined`を持つ型です。 -The language also defines a global variable that has the value of `undefined`, -this variable is also called `undefined`. But this variable is **not** a constant, -nor is it a keyword of the language. This means that its *value* can be easily -overwritten. +この言語はまた、`undefined`の値を持つグローバル変数を定義しています。この値もまた`undefined`と呼ばれています。しかし、この変数は **どちらも** 言語のキーワードではなく、定数です。この事はこの*値*は簡単に上書きされてしまうという事になります。 -> **ES5 Note:** `undefined` in ECMAScript 5 is **no longer** *writable* in strict -> mode, but its name can still be shadowed by for example a function with the name -> `undefined`. +> **ES5での注意点:** ECMAScript 5での`undefined`は **もはや** strict modeでは *書き変えられない* +> ようになっています。しかし、この名前は`undefined`という名前の関数の例に痕跡が見られるだけです。 -Some examples for when the value `undefined` is returned: +`undefined`が帰される時の例をいくつか挙げます。 - - Accessing the (unmodified) global variable `undefined`. - - Implicit returns of functions due to missing `return` statements. - - `return` statements which do not explicitly return anything. - - Lookups of non-existent properties. - - Function parameters which do not had any explicit value passed. - - Anything that has been set to the value of `undefined`. + - (未定義の)グローバル変数`undefined`にアクセスした時 + - `return`文が無い為に、暗黙のうちに関数が返された時 + - 何も返されない`return`がある時 + - 存在しないプロパティを探索する時 + - 関数のパラメーターで明示的な値が何も無い時 + - 全ての`undefined`が設定された値 ### Handling Changes to the Value of `undefined` From d0a59c75b9654758371d5f1bb1939f88a9a38e50 Mon Sep 17 00:00:00 2001 From: HIRAKI Satoru Date: Mon, 10 Oct 2011 22:14:18 +0900 Subject: [PATCH 151/463] translate "Handling Changes to the Value of `undefined`" in "Core" to ja --- doc/ja/core/undefined.md | 24 ++++++++---------------- 1 file changed, 8 insertions(+), 16 deletions(-) diff --git a/doc/ja/core/undefined.md b/doc/ja/core/undefined.md index a22f4fbd..4ee6668d 100644 --- a/doc/ja/core/undefined.md +++ b/doc/ja/core/undefined.md @@ -20,28 +20,22 @@ JavaScriptは`nothing`を表す2つの別個の値を持っています。`undef - 関数のパラメーターで明示的な値が何も無い時 - 全ての`undefined`が設定された値 -### Handling Changes to the Value of `undefined` +### `undefined`の値に変更する処理 -Since the global variable `undefined` only holds a copy of the actual *value* of -`undefined`, assigning a new value to it does **not** change the value of the -*type* `undefined`. +グローバル変数`undefined`のみが実際の`undefined`の*値*のコピーを保持するので、これに新しい値を代入しても`undefined`の*型* の値が変更される事は**ありません**。 -Still, in order to compare something against the value of `undefined` it is -necessary to retrieve the value of `undefined` first. +まだ、`undefined`の値に対して何かしらの比較をしないといけない場合は、最初に`undefined`の値を取得する必要があります。 -In order to protect code against a possible overwritten `undefined` variable, a -common technique used is to add an additional parameter to an -[anonymous wrapper](#function.scopes), that gets no argument passed to it. +コードの`undefined`の変数の上書きを可能な限りしないよう保護する為には、一般的なテクニックとして[anonymous wrapper](#function.scopes)の引数にパラメーターを追加するというものがあります。 var undefined = 123; (function(something, foo, undefined) { - // undefined in the local scope does - // now again refer to the value + // ローカルスコープではundefined。 + // ここで値に対して参照がされる })('Hello World', 42); -Another way to achieve the same effect would be to use a declaration inside the -wrapper. +同じ効果を得る事ができる別の方法として、ラッパーの内部での宣言を使うものがあります。 var undefined = 123; (function(something, foo) { @@ -50,9 +44,7 @@ wrapper. })('Hello World', 42); -The only difference being here, that this version results in 4 more bytes being -used in case it is minified and there is no other `var` statement inside the -anonymous wrapper. +これらの唯一の違いは、こちらのバージョンの方が4バイト余計に短縮できるという物です。また、他に`var`ステートメントは匿名ラッパーの中にはありません。 ### Uses of `null` From c474577b26fb77677eb5e8bec1b80815142ace13 Mon Sep 17 00:00:00 2001 From: HIRAKI Satoru Date: Tue, 11 Oct 2011 01:15:00 +0900 Subject: [PATCH 152/463] translate "Uses of `null`" in "Core" to ja --- doc/ja/core/undefined.md | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/doc/ja/core/undefined.md b/doc/ja/core/undefined.md index 4ee6668d..9d6949f3 100644 --- a/doc/ja/core/undefined.md +++ b/doc/ja/core/undefined.md @@ -46,14 +46,8 @@ JavaScriptは`nothing`を表す2つの別個の値を持っています。`undef これらの唯一の違いは、こちらのバージョンの方が4バイト余計に短縮できるという物です。また、他に`var`ステートメントは匿名ラッパーの中にはありません。 -### Uses of `null` - -While `undefined` in the context of the JavaScript language is mostly used in -the sense of a traditional *null*, the actual `null` (both a literal and a type) -is more or less just another data type. - -It is used in some JavaScript internals (like declaring the end of the -prototype chain by setting `Foo.prototype = null`), but in almost all cases it -can be replaced by `undefined`. +### `null`の使用 +JavaScriptというプログラム言語のコンテキストの中では、`undefined`は主に伝統的な意味での*null*の意味で使用される事が多いです。実際の`null`(リテラルも型も両方)は多かれ少なかれ、単なるデータ型です。 +それはJavaScriptの内部でいくつか使われています(プロトタイプチェーンの終わりに`Foo.prototype = null`という宣言をするようなもの)が、ほとんど全てのケースで、`undefined`に置き替える事が可能です。 From 47ba6a742a3286d0feda55781a1a3e9fadb9f095 Mon Sep 17 00:00:00 2001 From: HIRAKI Satoru Date: Tue, 18 Oct 2011 02:42:26 +0900 Subject: [PATCH 153/463] translate "Automatic Semicolon Insertion" in "Core" to ja --- doc/ja/core/semicolon.md | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/doc/ja/core/semicolon.md b/doc/ja/core/semicolon.md index 61d74fd9..2e89dafc 100644 --- a/doc/ja/core/semicolon.md +++ b/doc/ja/core/semicolon.md @@ -1,25 +1,20 @@ -## Automatic Semicolon Insertion +## セミコロン自動挿入 -Although JavaScript has C style syntax, it does **not** enforce the use of -semicolons in the source code, it is possible to omit them. +JavaScriptはC言語スタイルのシンタックスを持っていますが、これはソースコードの中でセミコロンの使用を強制している事には**ならない**ので、これらを省略する事も可能です。 -But JavaScript is not a semicolon-less language, it in fact needs the -semicolons in order to understand the source code. Therefore the JavaScript -parser **automatically** inserts them whenever it encounters a parse -error due to a missing semicolon. +JavaScriptはセミコロン無しの言語ではありません。実際に、ソースコードを理解する為にもセミコロンは必要になります。ですので、JavaScriptのパーサーはセミコロンが無い事によるパースエラーを検出する度に、**自動的**にセミコロンを挿入します。 var foo = function() { - } // parse error, semicolon expected + } // セミコロンが入っている事が期待されるので、パースエラーになる test() -Insertion happens, and the parser tries again. +挿入が起こると、パーサーはもう一度パースします。 var foo = function() { - }; // no error, parser continues + }; // エラーが無いので、パーサーは次の解析をする test() -The automatic insertion of semicolon is considered to be one of **biggest** -design flaws in the language, as it *can* change the behavior of code. +セミコロンの自動挿入は、コードの振る舞いを変えられる為に、言語の**最大**の欠陥の内の一つと考えられています。 ### How it Works From 89b5dd7a7bf0e90d9f745f8660a44b0b8cd892fe Mon Sep 17 00:00:00 2001 From: HIRAKI Satoru Date: Thu, 20 Oct 2011 01:56:27 +0900 Subject: [PATCH 154/463] translage "How it Works" in "Core" to ja --- doc/ja/core/semicolon.md | 34 ++++++++++++++++------------------ 1 file changed, 16 insertions(+), 18 deletions(-) diff --git a/doc/ja/core/semicolon.md b/doc/ja/core/semicolon.md index 2e89dafc..2dc476c2 100644 --- a/doc/ja/core/semicolon.md +++ b/doc/ja/core/semicolon.md @@ -16,10 +16,9 @@ JavaScriptはセミコロン無しの言語ではありません。実際に、 セミコロンの自動挿入は、コードの振る舞いを変えられる為に、言語の**最大**の欠陥の内の一つと考えられています。 -### How it Works +### どのように動くか -The code below has no semicolons in it, so it is up to the parser to decide where -to insert them. +以下のコードはセミコロン無いので、パーサーはどこに挿入するか決めなくてはなりません。 (function(window, undefined) { function test(options) { @@ -48,42 +47,41 @@ to insert them. })(window) -Below is the result of the parser's "guessing" game. +下記がパーサーの「推測」ゲームの結果になります。 (function(window, undefined) { function test(options) { - // Not inserted, lines got merged + // 行がマージされて、挿入されない log('testing!')(options.list || []).forEach(function(i) { - }); // <- inserted + }); // <- 挿入 options.value.test( 'long string to pass here', 'and another long string to pass' - ); // <- inserted + ); // <- 挿入 return; // <- inserted, breaks the return statement - { // treated as a block + { // ブロックとして扱われる // a label and a single expression statement foo: function() {} - }; // <- inserted + }; // <- 挿入 } - window.test = test; // <- inserted + window.test = test; // <- 挿入 - // The lines got merged again + // 再度行がマージされる })(window)(function(window) { - window.someLibrary = {}; // <- inserted + window.someLibrary = {}; // <- 挿入 - })(window); //<- inserted + })(window); //<- 挿入 -> **Note:** The JavaScript parser does not "correctly" handle return statements -> which are followed by a new line, while this is not neccessarily the fault of -> the automatic semicolon insertion, it can still be an unwanted side-effect. +> **注意点:** JavaScriptパーサーは新しい行のreturn文を「正しく」返してはいないですが、 +> これは必要という訳では無いので自動セミコロン挿入の障害になります。 +> このお陰で不必要な副作用を無くす事にもなります。 -The parser drastically changed the behavior of the code above, in certain cases -it does the **wrong thing**. +パーサーは上記のコードの振舞いを劇的に変化させます。あるケースにおいては、**間違っている事**にもなってしまいます。 ### Leading Parenthesis From d5c068e36e0a3cbe494b9af73f3f718224ebddf8 Mon Sep 17 00:00:00 2001 From: HIRAKI Satoru Date: Thu, 20 Oct 2011 02:02:14 +0900 Subject: [PATCH 155/463] translate "Leading Parenthesis" in "Core" to ja --- doc/ja/core/semicolon.md | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/doc/ja/core/semicolon.md b/doc/ja/core/semicolon.md index 2dc476c2..a697cbe9 100644 --- a/doc/ja/core/semicolon.md +++ b/doc/ja/core/semicolon.md @@ -83,19 +83,18 @@ JavaScriptはセミコロン無しの言語ではありません。実際に、 パーサーは上記のコードの振舞いを劇的に変化させます。あるケースにおいては、**間違っている事**にもなってしまいます。 -### Leading Parenthesis +### 先頭の括弧 -In case of a leading parenthesis, the parser will **not** insert a semicolon. +先頭に括弧がある場合、パーサーはセミコロンを挿入**しません**。 log('testing!') (options.list || []).forEach(function(i) {}) -This code gets transformed into one line. +このコードは1つの行に変形します。 log('testing!')(options.list || []).forEach(function(i) {}) -Chances are **very** high that `log` does **not** return a function; therefore, -the above will yield a `TypeError` stating that `undefined is not a function`. +`log`が関数を返さ**ない**確率は**とても**高いです。しかし、上記では`undefined is not a function`という`TypeError`が繰り返されます。 ### In Conclusion From 2013516f59001a12f2724d997fdb6b1d5b8cccc9 Mon Sep 17 00:00:00 2001 From: HIRAKI Satoru Date: Thu, 20 Oct 2011 02:09:02 +0900 Subject: [PATCH 156/463] translate "In Conclusion" in "Core" to ja --- doc/ja/core/semicolon.md | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/doc/ja/core/semicolon.md b/doc/ja/core/semicolon.md index a697cbe9..f7d7c07d 100644 --- a/doc/ja/core/semicolon.md +++ b/doc/ja/core/semicolon.md @@ -96,11 +96,6 @@ JavaScriptはセミコロン無しの言語ではありません。実際に、 `log`が関数を返さ**ない**確率は**とても**高いです。しかし、上記では`undefined is not a function`という`TypeError`が繰り返されます。 -### In Conclusion - -It is highly recommended to **never** omit semicolons, it is also advocated to -keep braces on the same line with their corresponding statements and to never omit -them for one single-line `if` / `else` statements. Both of these measures will -not only improve the consistency of the code, they will also prevent the -JavaScript parser from changing its behavior. +### 終わりに +セミコロンを省略するのは**絶対**にお勧めしません。この事はまた括弧をその終端と一緒の行に書く事が推奨されてますし、1つの`if`や`else`文を絶対に省略してはなりません。これら両方の処理がコードの整合性を高めてくれる上、JavaScriptパーサーの振舞いを変えてしまうのを防いでくれるでしょう。 From 9bab686e0408ce2b6a9bfbe7696a81404304dd96 Mon Sep 17 00:00:00 2001 From: HIRAKI Satoru Date: Sun, 23 Oct 2011 20:31:10 +0900 Subject: [PATCH 157/463] translate "`setTimeout` and `setInterval`" in "Others" to ja --- doc/ja/other/timeouts.md | 38 +++++++++++++++----------------------- 1 file changed, 15 insertions(+), 23 deletions(-) diff --git a/doc/ja/other/timeouts.md b/doc/ja/other/timeouts.md index d196a3b7..9c80c28d 100644 --- a/doc/ja/other/timeouts.md +++ b/doc/ja/other/timeouts.md @@ -1,43 +1,35 @@ -### `setTimeout` and `setInterval` +### `setTimeout`と`setInterval` -Since JavaScript is asynchronous, it is possible to schedule the execution of a -function by using the `setTimeout` and `setInterval` functions. +JavaScriptは非同期なので、`setTimeout`と`setInterval`関数を使ってある関数の実行のスケジュールを決める事が可能です。 -> **Note:** Timeouts are **not** part of the ECMAScript Standard. They are -> implemented as part of the [DOM][1]. +> **注意点:** タイムアウトはECMAScript標準の一部では**ありません**。 +> これらは[DOM][1]の一部として実装されています。 function foo() {} - var id = setTimeout(foo, 1000); // returns a Number > 0 + var id = setTimeout(foo, 1000); // Number > 0を返す -When `setTimeout` gets called, it will return the ID of the timeout and schedule -`foo` to run in **approximately** one thousand milliseconds in the future. -`foo` will then get executed exactly **once**. +`setTimeout`が呼ばれた時に、タイムアウトのIDと`foo`この先の**おおよそ**1000msに実行するスケジュールを返します。`foo`は正確に**1度**だけ実行されます。 -Depending on the timer resolution of the JavaScript engine that is running the -code, as well as the fact that JavaScript is single threaded and other code that -gets executed might block the thread, it is by **no means** a safe bet that one -will get the exact delay that was specified in the `setTimeout` call. +コードが実行されているJavaScriptエンジンのタイマー分解能によって決まります。この事実はJavaScriptがシングルスレッドのなので、他のスレッドでの実行を妨害してしまう事があるかもしれません。これは、`setTimeout`の呼び出しにより指定された正確なディレイで実行するという確実な賭けという**意味ではありません**。 -The function that was passed as the first parameter will get called by the -*global object*, that means, that [`this`](#function.this) inside the called function -refers to that very object. +第一パラメーターを渡された関数は*グローバルオブジェクト*によって呼び出されます。これは呼び出された関数の内部で[`this`](#functionis)がまさにこのオブジェクトを参照しているという事になります。 function Foo() { this.value = 42; this.method = function() { - // this refers to the global object - console.log(this.value); // will log undefined + // これはグローバルオブジェクトを参照しています + console.log(this.value); // undefinedを記録するはずです }; setTimeout(this.method, 500); } new Foo(); -> **Note:** As `setTimeout` takes a **function object** as its first parameter, an -> often made mistake is to use `setTimeout(foo(), 1000)`, which will use the -> **return value** of the call `foo` and **not** `foo`. This is, most of the time, -> a silent error, since when the function returns `undefined` `setTimeout` will -> **not** raise any error. +> **注意点:** `setTimeout`は**関数オブジェクト**を第一引数に取ります。 +> 良く間違えてしまう使い方として`setTimeout(foo(), 1000)`というものがあります。 +> `foo`と`foo`**以外**の呼び出しに対する**戻り値**としてしまいます。これは、大体において、 +> 関数が`undefined`になる為に表に出ないエラーになるでしょう。`setTimeout`はどんな +> エラーも発生`させません`。 ### Stacking Calls with `setInterval` From fb7c165d3e6ef912dea74c277e6c70639edd0efd Mon Sep 17 00:00:00 2001 From: Changwoo Park Date: Wed, 26 Oct 2011 02:18:34 +0900 Subject: [PATCH 158/463] [ko] merge all Squashed commit of the following: commit 2ce9cfae13db7723d0def834bd1274daf88d71e3 Author: Changwoo Park Date: Tue Oct 25 22:42:17 2011 +0900 [ko] correction commit 30f5d7b4d10fadec11327f5a5869bf13a0525865 Author: Changwoo Park Date: Fri Oct 21 19:14:25 2011 +0900 [ko] types first draft ect commit 4f6cacb4af0b2251d6fdba78301e84262d10f2c1 Author: Changwoo Park Date: Thu Oct 20 02:48:14 2011 +0900 [ko] first draft. --- doc/ko/array/constructor.md | 25 ++--- doc/ko/array/general.md | 45 +++------ doc/ko/core/delete.md | 65 +++++------- doc/ko/core/eval.md | 29 ++---- doc/ko/core/semicolon.md | 73 ++++++-------- doc/ko/core/undefined.md | 68 +++++-------- doc/ko/function/arguments.md | 87 ++++++----------- doc/ko/function/closures.md | 55 ++++------- doc/ko/function/constructors.md | 76 +++++---------- doc/ko/function/general.md | 35 +++---- doc/ko/function/scopes.md | 168 ++++++++++++-------------------- doc/ko/function/this.md | 82 ++++++---------- doc/ko/intro/index.md | 36 +++---- doc/ko/object/forinloop.md | 45 +++------ doc/ko/object/general.md | 74 ++++++-------- doc/ko/object/hasownproperty.md | 37 +++---- doc/ko/object/prototype.md | 95 ++++++------------ doc/ko/other/timeouts.md | 116 +++++++--------------- doc/ko/types/casting.md | 68 ++++++------- doc/ko/types/equality.md | 48 ++++----- doc/ko/types/instanceof.md | 25 ++--- doc/ko/types/typeof.md | 58 ++++------- 22 files changed, 491 insertions(+), 919 deletions(-) diff --git a/doc/ko/array/constructor.md b/doc/ko/array/constructor.md index 1d9abe18..5297fc73 100644 --- a/doc/ko/array/constructor.md +++ b/doc/ko/array/constructor.md @@ -1,8 +1,6 @@ -## The `Array` Constructor +## `Array` 생성자 -Since the `Array` constructor is ambiguous in how it deals with its parameters, -it is highly recommended to always use the array literals - `[]` notation - -when creating new arrays. +`Array` 생성자가 파라미터를 처리하는 방법은 모호하기 때문에 항상 `[]` 노테이션으로 Array를 만들어야 한다. [1, 2, 3]; // Result: [1, 2, 3] new Array(1, 2, 3); // Result: [1, 2, 3] @@ -11,25 +9,16 @@ when creating new arrays. new Array(3); // Result: [] new Array('3') // Result: ['3'] -In cases when there is only one argument passed to the `Array` constructor -and when that argument is a `Number`, the constructor will return a new *sparse* -array with the `length` property set to the value of the argument. It should be -noted that **only** the `length` property of the new array will be set this way; -the actual indexes of the array will not be initialized. +`Array` 생성자에 인자로 숫자 하나를 넘기면 생성자는 `length`가 그 숫자인 텅 빈 `Array` 하나를 반환한다. 생성자는 **오직** `length` 프로퍼티에 할당하기만 하고 실제 `Array`는 초기화하지 않는다는 것을 기억해야 한다. var arr = new Array(3); arr[1]; // undefined - 1 in arr; // false, the index was not set + 1 in arr; // false, 이 인덱스는 초기화되지 않음. -The behavior of being able to set the length of the array upfront only comes in -handy in a few cases, like repeating a string, in which it avoids the use of a -`for loop` code. +Array의 length 프로퍼티에 숫자를 할당해주는 이 기능이 유용할 때도 있긴 있다. `for loop`을 사용하지 않고 스트링을 더하는 경우가 그렇다. new Array(count + 1).join(stringToRepeat); -### In Conclusion - -The use of the `Array` constructor should be avoided as much as possible. -Literals are definitely preferred. They are shorter and have a clearer syntax; -therefore, they also increase the readability of the code. +### 결론 +`Array` 생성자는 가능하면 사용하지 말아야 한다. `[]` 노테이션이 더 알맞다. 더 간략하고 명확하기 때문에 보기도 좋다. diff --git a/doc/ko/array/general.md b/doc/ko/array/general.md index 9f804d4c..69214a15 100644 --- a/doc/ko/array/general.md +++ b/doc/ko/array/general.md @@ -1,44 +1,29 @@ -## Array Iteration and Properties +## Array Iteration과 프로퍼티 -Although arrays in JavaScript are objects, there are no good reasons to use -the [`for in loop`](#object.forinloop) in for iteration on them. In fact, there -are a number of good reasons **against** the use of `for in` on arrays. +JavaScript에서는 Array도 객체지만 Iterate를 할 때 [`for in`](#object.forinloop)을 사용해서 좋을 게 없다. -> **Note:** JavaScript arrays are **not** *associative arrays*. JavaScript only -> has [objects](#object.general) for mapping keys to values. And while associative -> arrays **preserve** order, objects **do not**. +> **Note:** JavaScript의 Array는 *Associative Array*가 **아니다**. JavaScript [객체](#object.general)는 key/value만 mapping 할 뿐이다. Associative Array는 순서를 보장하지만, 객체는 보장하지 않는다. -Because the `for in` loop enumerates all the properties that are on the prototype -chain and because the only way to exclude those properties is to use -[`hasOwnProperty`](#object.hasownproperty), it is already up to **twenty times** -slower than a normal `for` loop. +`for in`은 프로토타입 체인에 있는 프로퍼티를 모두 훑는(enumerate) 데다가 객체 자신의 프로퍼티만 훑으려면 [`hasOwnProperty`](#object.hasownproperty)를 사용해야 하기 때문에 `for`보다 20배 느리다. ### Iteration -In order to achieve the best performance when iterating over arrays, it is best -to use the classic `for` loop. +Array를 Iterate 할 때에는 구식인 `for`를 사용하는 것이 가장 빠르다. var list = [1, 2, 3, 4, 5, ...... 100000000]; for(var i = 0, l = list.length; i < l; i++) { console.log(list[i]); } -There is one extra catch in the above example, which is the caching of the -length of the array via `l = list.length`. +위 예제에서 꼭 기억해야 하는 것은 `l = list.length`로 Array의 length 값을 캐시 했다는 것이다. -Although the `length` property is defined on the array itself, there is still an -overhead for doing the lookup on each iteration of the loop. And while recent -JavaScript engines **may** apply optimization in this case, there is no way of -telling whether the code will run on one of these newer engines or not. +Array에 있는 `length` 프로퍼티를 iterate마다 사용하는 것은 좀 부담스럽다. 최신 JavaScript 엔진은 이 일을 알아서 처리하기도 하지만 코드가 새 엔진에서 실행되도록 보장할 방법이 없다. -In fact, leaving out the caching may result in the loop being only **half as -fast** as with the cached length. +실제로 캐시 하지 않으면 성능이 반으로 줄어든다. -### The `length` Property +### `length` 프로퍼티 -While the *getter* of the `length` property simply returns the number of -elements that are contained in the array, the *setter* can be used to -**truncate** the array. +`length` 프로퍼티의 *getter*는 단순히 Array 안에 있는 엘리먼트의 개수를 반환하고 *setter*는 할당한 수로 Array를 잘라 버린다. var foo = [1, 2, 3, 4, 5, 6]; foo.length = 3; @@ -47,12 +32,8 @@ elements that are contained in the array, the *setter* can be used to foo.length = 6; foo; // [1, 2, 3] -Assigning a smaller length does truncate the array, but increasing the length -does not have any effect on the array. +현재 크기보다 더 작은 값을 할당하면 Array를 자르지만, 현재 크기보다 더 큰 값을 할당하면 아무것도 하지 않는다. -### In Conclusion - -For the best performance, it is recommended to always use the plain `for` loop -and cache the `length` property. The use of `for in` on an array is a sign of -badly written code that is prone to bugs and bad performance. +### 결론 +최적의 성능을 위해서 `for`를 사용하고 `length` 프로퍼티 값을 캐시 하길 바란다. Array에 `for in`을 사용하면 성능도 떨어지고 버그 나기도 쉽다. diff --git a/doc/ko/core/delete.md b/doc/ko/core/delete.md index 37a12816..eefa5b5b 100644 --- a/doc/ko/core/delete.md +++ b/doc/ko/core/delete.md @@ -1,38 +1,31 @@ -## The `delete` Operator +## `delete` -In short, it's *impossible* to delete global variables, functions and some other -stuff in JavaScript which have a `DontDelete` attribute set. +간단히 말해서 global 변수, 함수, 등은 `DontDelete` 속성이기 때문에 삭제 못 한다. -### Global code and Function code +### 글로벌 코드와 함수 코드 -When a variable or a function is defined in a global -or a [function scope](#function.scopes) it is a property of either -Activation object or Global object. Such properties have a set of attributes, -one of these is `DontDelete`. Variable and function declarations in global -and function code always create properties with `DontDelete`, therefore -cannot be deleted. +Global이나 Function scope에 정의된 함수나 변수는 모두 Activation 객체나 Global 객체의 프로퍼티다. 이 프로퍼티는 모두 `DontDelete`속성을 가진다. Global이나 Function 코드에서 변수나 함수의 정의하면 항상 `DontDelete` 프로퍼티로 만들어진다. 그러니까 삭제할 수 없다: - // global variable: - var a = 1; // DontDelete is set + // 글로벌 변수: + var a = 1; // DontDelete가 설정된다. delete a; // false a; // 1 - // normal function: - function f() {} // DontDelete is set + // 함수: + function f() {} // DontDelete가 설정된다. delete f; // false typeof f; // "function" - // reassigning doesn't help: + // 다시 할당해도 삭제할 수 없다: f = 1; delete f; // false f; // 1 -### Explicit properties +### Explicit 프로퍼티 -There are things which can be deleted normally: these are explicitly set -properties. +다음 예제에서 만드는 property는 정상적으로 지워진다. 이런 걸 Explicit 프로퍼티라고 부른다: - // explicitly set property: + // Explicit 프로퍼티를 만든다: var obj = {x: 1}; obj.y = 2; delete obj.x; // true @@ -40,28 +33,24 @@ properties. obj.x; // undefined obj.y; // undefined -In the example above `obj.x` and `obj.y` can be deleted because they have no -`DontDelete` atribute. That's why an example below works too. +`obj.x`와 `obj.y`는 `DontDelete` 속성이 아녀서 삭제된다. 그러나 다음과 같은 코드도 잘 동작하기 때문에 헷갈린다.: - // this works fine, except for IE: + // IE를 빼고 잘 동작한다.: var GLOBAL_OBJECT = this; GLOBAL_OBJECT.a = 1; - a === GLOBAL_OBJECT.a; // true - just a global var + a === GLOBAL_OBJECT.a; // true - 진짜 글로벌 변순지 확인하는 것 delete GLOBAL_OBJECT.a; // true GLOBAL_OBJECT.a; // undefined -Here we use a trick to delete `a`. [`this`](#function.this) here refers -to the Global object and we explicitly declare variable `a` as it's property -which allows us to delete it. +[`this`](#function.this)가 글로벌 객체를 가리키는 것을 이용해서 명시적으로 프로퍼티 `a`를 선언하면 삭제할 수 있다. 이런 꼼수가 가능하다. -IE (at least 6-8) has some bugs, so code above doesn't work. +IE (적어도 6-8)는 버그가 있어서 안 된다. -### Function arguments and built-ins +### arguments와 함수의 기본 프로퍼티 -Functions' normal arguments, [`arguments` object](#function.arguments) -and built-in properties also have `DontDelete` set. +함수의 [`arguments` 객체](#function.arguments)와 built-in 프로퍼티도 `DontDelete` 속성이다. - // function arguments and properties: + // 함수의 arguments와 프로퍼티: (function (x) { delete arguments; // false @@ -76,12 +65,12 @@ and built-in properties also have `DontDelete` set. })(1); -### Host objects - -Behaviour of `delete` operator can be unpredictable for hosted objects. Due to -specification, host objects are allowed to implement any kind of behavior. +### Host 객체 + +(역주, Host 객체들은 document같은 DOM 객체를 말한다.) + +Host 객체를 delete하면 어떻게 될지 알 수 없다. 어떻게 Host 객체를 delete해야 하는지 표준에 정의되지 않았다. -### In conclusion +### 결론 -`delete` operator often has an unexpected behaviour and can be safely used -only for dealing with explicitly set properties on normal objects. +`delete` 연산자는 엉뚱하게 동작할 때가 잦다. 명시적으로 정의한 일반 객체의 프로퍼티만 delete하는 것이 안전하다. diff --git a/doc/ko/core/eval.md b/doc/ko/core/eval.md index 160ba1f0..9e5cf1b8 100644 --- a/doc/ko/core/eval.md +++ b/doc/ko/core/eval.md @@ -1,6 +1,6 @@ -## Why Not to Use `eval` +## 왜 `eval`을 사용하면 안 될까? -The `eval` function will execute a string of JavaScript code in the local scope. +`eval` 함수는 스트링으로 된 JavaScript 코드를 로컬 스콥에서 실행한다. var foo = 1; function test() { @@ -11,8 +11,7 @@ The `eval` function will execute a string of JavaScript code in the local scope. test(); // 3 foo; // 1 -However, `eval` only executes in the local scope when it is being called -**directly** *and* when the name of the called function is actually `eval`. +`eval`을 `eval`이라는 이름으로 **직접** 직행할 때에만 로컬 스콥에서 실행된다. var foo = 1; function test() { @@ -24,24 +23,16 @@ However, `eval` only executes in the local scope when it is being called test(); // 2 foo; // 3 -The use of `eval` should be avoided at **all costs**. 99.9% of its "uses" can be -achieved **without** it. - -### `eval` in Disguise +어쨌든 `eval`은 사용하지 말아야 한다. eval을 사용하는 경우의 99.9%는 사실 eval이 필요 없다. -The [timeout functions](#other.timeouts) `setTimeout` and `setInterval` can both -take a string as their first argument. This string will **always** get executed -in the global scope since `eval` is not being called directly in that case. +### 가짜 `eval` -### Security Issues +[timeout functions](#other.timeouts)인 `setTimeout`과 `setInterval`은 첫 번째 인자로 스트링을 입력받을 수 있다. 이 경우에는 `eval`을 직접 호출하는 것이 아녀서 항상 global scope에서 실행된다. -`eval` also is a security problem. Because it executes **any** code given to it, -it should **never** be used with strings of unknown or untrusted origins. +### 보안 이슈 -### In Conclusion +`eval`은 보안 문제도 있다. 단순히 **모든** 코드를 실행하기 때문에 신뢰하지 못하는 코드가 **절대로** 포함되지 않도록 주의해야 한다. -`eval` should never be used. Any code that makes use of it is to be questioned in -its workings, performance and security. In case something requires `eval` in -order to work, it should **not** be used in the first place. -A *better design* should be used, that does not require the use of `eval`. +### 결론 +`eval`은 사용하지 않는 게 좋다. `eval`을 사용하는 모든 코드는 성능, 보안, 버그의 문제를 일으킬 수 있다. 만약 `eval`이 필요해지면 *설계를 변경*하여 `eval`이 필요 없게 만들어야 한다. diff --git a/doc/ko/core/semicolon.md b/doc/ko/core/semicolon.md index f03f7d82..723ff2d4 100644 --- a/doc/ko/core/semicolon.md +++ b/doc/ko/core/semicolon.md @@ -1,30 +1,24 @@ -## Automatic Semicolon Insertion +## 세미콜론을 자동으로 삽입해준다. -Although JavaScript has C style syntax, it does **not** enforce the use of -semicolons in the source code, so it is possible to omit them. +JavaScript는 C와 문법이 비슷하지만, 꼭 코드에 semicolon을 사용하도록 강제하지 않는다. 그래서 생략할 수 있다. -JavaScript is not a semicolon-less language. In fact, it needs the -semicolons in order to understand the source code. Therefore, the JavaScript -parser **automatically** inserts them whenever it encounters a parse -error due to a missing semicolon. +사실 JavaScript는 semicolon이 꼭 있어야 하고 없으면 이해하지 못한다. 그래서 JavaScript 파서는 semicolon이 없으면 **자동으로** semicolon을 추가한다. var foo = function() { - } // parse error, semicolon expected + } // 세미콜론이 없으니 에러 난다. test() -Insertion happens, and the parser tries again. +파서는 세미콜론을 삽입하고 다시 시도한다. var foo = function() { - }; // no error, parser continues + }; // 에러가 없어짐. test() -The automatic insertion of semicolon is considered to be one of **biggest** -design flaws in the language because it *can* change the behavior of code. +JavaScript에서 세미콜론을 자동으로 삽입한 것은 **대표적인** 설계 오류 중 하나다. 세미콜론 유무에 따라 *전혀* 다른 코드가 될 수 있다. -### How it Works +### 어떻게 다를까? -The code below has no semicolons in it, so it is up to the parser to decide where -to insert them. +코드에 세미콜론이 없으면 파서가 어디에 넣을지 결정한다. (function(window, undefined) { function test(options) { @@ -53,62 +47,53 @@ to insert them. })(window) -Below is the result of the parser's "guessing" game. +파서는 다음과 같이 삽입한다. (function(window, undefined) { function test(options) { - // Not inserted, lines got merged + // 세미콜론을 넣는 것이 아니라 줄을 합친다. log('testing!')(options.list || []).forEach(function(i) { - }); // <- inserted + }); // <- 여기 options.value.test( 'long string to pass here', 'and another long string to pass' - ); // <- inserted + ); // <- 여기 - return; // <- inserted, breaks the return statement - { // treated as a block + return; // <- 여기에 넣어서 그냥 반환시킨다. + { // 파서는 단순 블럭이라고 생각하고 - // a label and a single expression statement + // 단순한 레이블과 함수 foo: function() {} - }; // <- inserted + }; // <- 여기 } - window.test = test; // <- inserted + window.test = test; // <- 여기 - // The lines got merged again + // 이 줄도 합쳐진다. })(window)(function(window) { - window.someLibrary = {}; // <- inserted + window.someLibrary = {}; // <- 여기 - })(window); //<- inserted + })(window); //<- 여기에 파서는 세미콜론을 넣는다. -> **Note:** The JavaScript parser does not "correctly" handle return statements -> which are followed by a new line, while this is not neccessarily the fault of -> the automatic semicolon insertion, it can still be an unwanted side-effect. +> **주의:** JavaScript 파서는 new line 문자가 뒤따라 오는 return 구문을 제대로 처리하지 못한다. 자동으로 세미콜론을 넣는 것 자체의 문제는 아니지만 어쨌든 여전히 문제로 남아있다. -The parser drastically changed the behavior of the code above. In certain cases, -it does the **wrong thing**. +파서는 완전히 다른 코드로 만들어 버린다. 이것은 **오류**다. -### Leading Parenthesis +### Parenthesis -In case of a leading parenthesis, the parser will **not** insert a semicolon. +세미콜론 없이 괄호가 붙어 있으면 파서는 세미콜론을 넣지 않는다. log('testing!') (options.list || []).forEach(function(i) {}) -This code gets transformed into one line. +파서는 다음과 같이 코드를 바꾼다. log('testing!')(options.list || []).forEach(function(i) {}) -Chances are **very** high that `log` does **not** return a function; therefore, -the above will yield a `TypeError` stating that `undefined is not a function`. +`log` 함수가 함수를 반환할 가능성은 거의 없다. 아마도 `undefined is not a function`이라는 `TypeError`가 발생할 거다. -### In Conclusion - -It is highly recommended to **never** omit semicolons; it is also advocated to -keep braces on the same line with their corresponding statements and to never omit -them for one single-line `if` / `else` statements. Both of these measures will -not only improve the consistency of the code, but they will also prevent the -JavaScript parser from changing its behavior. +### 결론 +세미콜론은 반드시 사용해야 한다. 그리고 `{}`도 생략하지 않고 꼭 사용하는 것이 좋다. 한 줄밖에 안 되는 `if` / `else` 블럭에서도 꼭 사용해야 한다. 이 두 가지 규칙을 잘 지키면 JavaScript 파서가 잘못 해석하는 일을 미리 방지하고 코드도 튼튼해진다. diff --git a/doc/ko/core/undefined.md b/doc/ko/core/undefined.md index d27761f0..7f4c9c05 100644 --- a/doc/ko/core/undefined.md +++ b/doc/ko/core/undefined.md @@ -1,52 +1,40 @@ -## `undefined` and `null` +## `undefined`와 `null` -JavaScript has two distinct values for `nothing`, the more useful of these two -being `undefined`. +JavaScript는 `nothing`을 두 가지로 표현할 수 있고 그중 `undefined`가 더 유용하다. -### The Value `undefined` +### `undefined`도 변수 -`undefined` is a type with exactly one value: `undefined`. +`undefined`는 `undefined`라는 값을 가지는 데이터 형식이다. -The language also defines a global variable that has the value of `undefined`; -this variable is also called `undefined`. However, this variable is **neither** a constant -nor a keyword of the language. This means that its *value* can be easily -overwritten. +`undefined`는 상수도 아니고 JavaScript의 키워드도 아니다. 그냥 `undefined`라는 이름의 글로벌 변수이고 이 변수에는 `undefined`라고 할당돼 있다. 그래서 이 글로벌 변수의 값을 쉽게 바꿀 수 있다. -> **ES5 Note:** `undefined` in ECMAScript 5 is **no longer** *writable* in strict -> mode, but its name can still be shadowed by for example a function with the name -> `undefined`. +> **ES5 Note:** ECMAScript 5의 strict 모드에서는 `undefined`를 더는 바꿀 수 없도록 했다. 하지만 `undefined`라는 함수를 만들면 여전히 할당할 수 있다. -Some examples for when the value `undefined` is returned: +`undefined` 값이 반환될 때: - - Accessing the (unmodified) global variable `undefined`. - - Implicit returns of functions due to missing `return` statements. - - `return` statements which do not explicitly return anything. - - Lookups of non-existent properties. - - Function parameters which do not had any explicit value passed. - - Anything that has been set to the value of `undefined`. + - global 변수 `undefined`에 접근할 때. + - `return` 구문이 없는 함수는 `undefined`를 반환함. + - `return` 구문으로 아무것도 반환하지 않을 때. + - 없는 프로퍼티를 찾을 때. + - 함수 인자가 생략될 때. + - `undefined`가 할당된 모든 것. -### Handling Changes to the Value of `undefined` +### `undefined`가 바뀔 때를 대비하기 -Since the global variable `undefined` only holds a copy of the actual *value* of -`undefined`, assigning a new value to it does **not** change the value of the -*type* `undefined`. +global 변수 `undefined`는 `undefined`라는 객체를 가리키는 것뿐이기 때문에 새로운 값을 할당한다고 해도 `undefined`의 값 자체가 바뀌는 것이 아니다. -Still, in order to compare something against the value of `undefined`, it is -necessary to retrieve the value of `undefined` first. +그래서 `undefined`와 비교하려면 먼저 `undefined`의 값을 찾아와야 한다. -In order to protect code against a possible overwritten `undefined` variable, a -common technique used is to add an additional parameter to an -[anonymous wrapper](#function.scopes) that gets no argument passed to it. +보통 `undefined` 변수가 바뀌어 있을 때를 대비해서 undefined라는 변수를 인자로 받는 [anonymous wrapper](#function.scopes)로 감싸고 아무런 인자를 넘기지 않는 꼼수를 사용한다. var undefined = 123; (function(something, foo, undefined) { - // undefined in the local scope does - // now again refer to the value + // 로컬 스콥에 undefined를 만들어서 + // 원래 값을 가리키도록 했다. })('Hello World', 42); -Another way to achieve the same effect would be to use a declaration inside the -wrapper. +wrapper 안에서 변수를 새로 정의하는 방법으로도 같은 효과를 볼 수 있다. var undefined = 123; (function(something, foo) { @@ -55,18 +43,10 @@ wrapper. })('Hello World', 42); -The only difference here is that this version results in 4 more bytes being -used in case it is minified, and there is no other `var` statement inside the -anonymous wrapper. +이 두 방법의 차이는 minified했을 때 4바이트만큼 차이 난다는 것과 한쪽은 wrapper 안에 var 구문이 없다는 것밖에 없다. -### Uses of `null` - -While `undefined` in the context of the JavaScript language is mostly used in -the sense of a traditional *null*, the actual `null` (both a literal and a type) -is more or less just another data type. - -It is used in some JavaScript internals (like declaring the end of the -prototype chain by setting `Foo.prototype = null`), but in almost all cases, it -can be replaced by `undefined`. +### `Null` 객체의 용도 +JavaScript 언어에서는 `undefined`를 다른 언어에서 *null*을 사용하듯이 쓰고 진짜 `null`은 그냥 다른 데이터 타입 중 하나일 뿐이다. +JavaScript 내부적인 곳에 사용하는 경우가 아니면 null 대신 `undefined`를 사용해도 된다(`Foo.prototype = null`같이 프로토타입 체인을 끊을 때는 null을 사용한다). diff --git a/doc/ko/function/arguments.md b/doc/ko/function/arguments.md index 37f3a634..e6f5a553 100644 --- a/doc/ko/function/arguments.md +++ b/doc/ko/function/arguments.md @@ -1,45 +1,33 @@ -## The `arguments` Object +## `arguments` 객체 -Every function scope in JavaScript can access the special variable `arguments`. -This variable holds a list of all the arguments that were passed to the function. +JavaScript의 모든 Function Scope에는 `arguments`라는 특별한 변수가 있다. 이 변수는 함수에 넘겨진 모든 인자에 대한 정보가 담겨 있다. -> **Note:** In case `arguments` has already been defined inside the function's -> scope either via a `var` statement or being the name of a formal parameter, -> the `arguments` object will not be created. +> **Note:** `arguments` 변수는 함수 안에서 다시 정의할 수 없다. `var` 구문이나 파라미터에 `arguments`라는 이름으로 변수를 정의해도 변수가 재정의되지 않는다. -The `arguments` object is **not** an `Array`. While it has some of the -semantics of an array - namely the `length` property - it does not inherit from -`Array.prototype` and is in fact an `Object`. +`length` 프로퍼티도 있고 대체로 Array와 비슷하게 생겼지만 Array.prototype을 상속받지 않았다. `arguments` 객체는 `Array`가 아니다. -Due to this, it is **not** possible to use standard array methods like `push`, -`pop` or `slice` on `arguments`. While iteration with a plain `for` loop works -just fine, it is necessary to convert it to a real `Array` in order to use the -standard `Array` methods on it. +그래서 `arguments`에는 `push`, `pop`, `slice`같은 표준 메소드가 없다. `for`로 하는 iteration은 원래 잘되지만 `Array`의 메소드를 이용하려면 `arguments`를 Array로 변환해야 한다. -### Converting to an Array +### Array로 변환하기 -The code below will return a new `Array` containing all the elements of the -`arguments` object. +다음 코드는 arguments에 있는 객체를 새로운 Array에 담아 반환한다. Array.prototype.slice.call(arguments); -Because this conversion is **slow**, it is **not recommended** to use it in -performance-critical sections of code. +이 변환 과정은 **느리기** 때문에 성능이 중요한 부분에 사용하는 것은 **별로 바람직하지** 못 하다. -### Passing Arguments +### arguemnts 객체 넘기기 -The following is the recommended way of passing arguments from one function to -another. +어떤 함수에서 다른 함수로 arguments 객체를 넘길 때에는 다음과 같이 하는 것이 좋다. function foo() { bar.apply(null, arguments); } function bar(a, b, c) { - // do stuff here + // 내곡동에 땅이라도 산다. } -Another trick is to use both `call` and `apply` together to create fast, unbound -wrappers. +`call`과 `apply`를 함께 사용하여 unbound wrapper도 쉽게 만들 수 있다. function Foo() {} @@ -47,22 +35,19 @@ wrappers. console.log(this, a, b, c); }; - // Create an unbound version of "method" - // It takes the parameters: this, arg1, arg2...argN + // "method"의 unbound 버전 + // 이 함수의 인자: this, arg1, arg2...argN Foo.method = function() { - // Result: Foo.prototype.method.call(this, arg1, arg2... argN) + // 결과: Foo.prototype.method.call(this, arg1, arg2... argN) Function.call.apply(Foo.prototype.method, arguments); }; +### 파라미터로 선언한 것과 arguments 객체 인덱스 -### Formal Parameters and Arguments Indices +`arguments` 객체의 프로퍼티와 파라미터는 모두 *getter*와 *setter*가 만들어진다. -The `arguments` object creates *getter* and *setter* functions for both its -properties, as well as the function's formal parameters. - -As a result, changing the value of a formal parameter will also change the value -of the corresponding property on the `arguments` object, and the other way around. +그래서 파라미터의 값이나 `arguments` 객체의 프로퍼티 중 하나를 바꾸면 같이 바뀐다. function foo(a, b, c) { arguments[0] = 2; @@ -77,43 +62,31 @@ of the corresponding property on the `arguments` object, and the other way aroun } foo(1, 2, 3); -### Performance Myths and Truths +### 성능에 대한 진실과 오해. -The `arguments` object is always created with the only two exceptions being the -cases where it is declared as a name inside of a function or one of its formal -parameters. It does not matter whether it is used or not. +`arguments`라는 이름의 변수를 함수 안에 정의하거나 파라미터로 정의해도 `arguments` 객체는 만들어진다. -Both *getters* and *setters* are **always** created; thus, using it has nearly -no performance impact at all, especially not in real world code where there is -more than a simple access to the `arguments` object's properties. +getter*와 *setter*는 항상 생성되기 때문에 getter/setter를 사용하는 것은 성능에 별 영향을 끼치지 않는다. 단순히 `arguments` 객체의 프로퍼티에 접근하는 수준이 아닌 실제 코드에서도 그렇다. -> **ES5 Note:** These *getters* and *setters* are not created in strict mode. +> **ES5 Note:** strict 모드에서는 *getter*와 *setter*가 생성되지 않는다. -However, there is one case which will drastically reduce the performance in -modern JavaScript engines. That case is the use of `arguments.callee`. +그러나 예외도 있다. 최신 JavaScript 엔진에서 `arguments.callee`를 사용하면 성능이 확 떨어진다. function foo() { - arguments.callee; // do something with this function object - arguments.callee.caller; // and the calling function object + arguments.callee; // 이 함수를 가리킨다. + arguments.callee.caller; // 이 함수를 호출한 함수를 가리킨다. } function bigLoop() { for(var i = 0; i < 100000; i++) { - foo(); // Would normally be inlined... + foo(); // 원래 인라인 돼야 하는디... } } -In the above code, `foo` can no longer be a subject to [inlining][1] since it -needs to know about both itself and its caller. This not only defeats possible -performance gains that would arise from inlining, but it also breaks encapsulation -because the function may now be dependent on a specific calling context. - -It is **highly recommended** to **never** make use of `arguments.callee` or any of -its properties. - -> **ES5 Note:** In strict mode, `arguments.callee` will throw a `TypeError` since -> its use has been deprecated. +이 코드에서 callee와 caller를 알아야 하기 때문에 `foo`는 더는 [inlining][1]되지 않는다. 이렇게 쓰면 inlining이 주는 성능상 장점을 포기해야 하는데다가 함수가 호출되는 상황(calling context)에 의존하게 돼 버려서 encapsulation도 해친다. -[1]: http://en.wikipedia.org/wiki/Inlining +`arguments.callee`와 그 프로퍼티들은 **절대** 사용하지 말아야 한다. +> **ES5 Note:** strict 모드에서 `arguments.callee`는 deprecated됐기 때문에 사용하면 `TypeError`가 난다. +[1]: http://en.wikipedia.org/wiki/Inlining \ No newline at end of file diff --git a/doc/ko/function/closures.md b/doc/ko/function/closures.md index 2e2a4ef6..24dcf25e 100644 --- a/doc/ko/function/closures.md +++ b/doc/ko/function/closures.md @@ -1,11 +1,8 @@ -## Closures and References +## Closure와 Reference -One of JavaScript's most powerful features is the availability of *closures*. -With closures, scopes **always** keep access to the outer scope, in which they -were defined. Since the only scoping that JavaScript has is -[function scope](#function.scopes), all functions, by default, act as closures. +JavaScript가 두드러지는 점 중의 하나가 *Closure*를 사용할 수 있다는 것이다. Closure는 항상 그 Closure를 만든 외부 Scope에 접근할 수 있다. JavaScript에서 Scope을 만들려면 [function Scope](#function.Scopes)을 사용하는 방법뿐이기 때문에 기본적으로 모든 함수는 Closure다. -### Emulating private variables +### private 변수 function Counter(start) { var count = start; @@ -24,30 +21,22 @@ were defined. Since the only scoping that JavaScript has is foo.increment(); foo.get(); // 5 -Here, `Counter` returns **two** closures: the function `increment` as well as -the function `get`. Both of these functions keep a **reference** to the scope of -`Counter` and, therefore, always keep access to the `count` variable that was -defined in that very scope. +`Counter`는 `increment` closure와 `get` closure를 두 개 반환한다. 이 두 closure는 `Counter` Scope에 대한 **reference**를 유지하고 있기 때문에 그 Scope에 있는 count 변수에 계속 접근할 수 있다. -### Why Private Variables Work +### Private 변수가 진짜 맞나? -Since it is not possible to reference or assign scopes in JavaScript, there is -**no** way of accessing the variable `count` from the outside. The only way to -interact with it is via the two closures. +JavaScript에서 Scope을 어딘가에 할당하거나 저장해두는 것이 불가능해서 Scope 밖에서 count 변수에 직접 접근할 방법은 없다. 꼭 Scope 안에서 정의한 두 closure를 통해서만 접근할 수 있다. var foo = new Counter(4); foo.hack = function() { count = 1337; }; -The above code will **not** change the variable `count` in the scope of `Counter`, -since `foo.hack` was not defined in **that** scope. It will instead create - or -override - the *global* variable `count`. +이 코드의 count는 `Counter` Scope의 변수 count가 아니다. `foo.hack`은 그 Scope 안에 정의되지 않았기 때문에 이 `count`는 *Global* 변수를 사용하는 것이다. -### Closures Inside Loops +### Loop에서 Closure 사용하기 -One often made mistake is to use closures inside of loops, as if they were -copying the value of the loops index variable. +많은 사람은 Loop에서 closure를 사용할 때 자주 index 변수를 잘못 사용한다. for(var i = 0; i < 10; i++) { setTimeout(function() { @@ -55,20 +44,15 @@ copying the value of the loops index variable. }, 1000); } -The above will **not** output the numbers `0` through `9`, but will simply print -the number `10` ten times. +이 코드는 `0`부터 `9`까지의 수를 출력하지 않고 `10`만 열 번 출력한다. -The *anonymous* function keeps a **reference** to `i`. At the time -`console.log` gets called, the `for loop` has already finished, and the value of -`i` as been set to `10`. +이 *anonymous* function은 변수 `i`에 대한 참조를 저장했다가 `console.log`가 호출되는 시점에 `i`의 값을 사용한다. `console.log`가 호출되는 시점은 `for loop`이 이미 끝난 상태라서 `i` 값은 10이다. -In order to get the desired behavior, it is necessary to create a **copy** of -the value of `i`. +기대한 결과를 얻으려면 `i` 값을 복사해 두어야 한다. -### Avoiding the Reference Problem +### 이 Reference 문제 해결하기 -In order to copy the value of the loop's index variable, it is best to use an -[anonymous wrapper](#function.scopes). +[anonymous wrapper](#function.Scopes)로 index 값을 복사하는 것이 좋다. for(var i = 0; i < 10; i++) { (function(e) { @@ -78,15 +62,11 @@ In order to copy the value of the loop's index variable, it is best to use an })(i); } -The anonymous outer function gets called immediately with `i` as its first -argument and will receive a copy of the **value** of `i` as its parameter `e`. +이 anonymous function의 인자로 `i`를 넘기면 이 함수의 파라미터 e에 i의 **값**이 복사된다. -The anonymous function that gets passed to `setTimeout` now has a reference to -`e`, whose value does **not** get changed by the loop. +이 `setTimeout`는 anonymous function 파라미터인 `e`에 대한 참조를 갖게 되고 `e`는 loop의 상태에 따라 변하지 않는다. -There is another possible way of achieving this, which is to return a function -from the anonymous wrapper that will then have the same behavior as the code -above. +함수를 반환하는 anonymous wrapper를 이용하는 방법도 있다. 다음 코드는 위 코드와 같다. for(var i = 0; i < 10; i++) { setTimeout((function(e) { @@ -95,4 +75,3 @@ above. } })(i), 1000) } - diff --git a/doc/ko/function/constructors.md b/doc/ko/function/constructors.md index a8e450a4..9ee49f57 100644 --- a/doc/ko/function/constructors.md +++ b/doc/ko/function/constructors.md @@ -1,15 +1,10 @@ -## Constructors +## 생성자 -Constructors in JavaScript are yet again different from many other languages. Any -function call that is preceded by the `new` keyword acts as a constructor. +JavaScript에서 생성자는 다른 언어들과 다르게 `new` 키워드로 호출되는 함수가 생성자다. -Inside the constructor - the called function - the value of `this` refers to a -newly created `Object`. The [`prototype`](#object.prototype) of this **new** -object is set to the `prototype` of the function object that was invoked as the -constructor. +어쨌든 생성자로 호출된 함수의 this는 막 만들어진 객체를 참조한다. **막 만든** 객체의 [`prototype`](#object.prototype)에는 생성자의 prototype이 할당된다. -If the function that was called has no explicit `return` statement, then it -implicitly returns the value of `this` - the new object. +생성자에 `return` 구문이 없으면 this가 가리키는 객체를 반환한다. function Foo() { this.bla = 1; @@ -21,16 +16,14 @@ implicitly returns the value of `this` - the new object. var test = new Foo(); -The above calls `Foo` as constructor and sets the `prototype` of the newly -created object to `Foo.prototype`. +`new` 키워드가 실행되는 시점에 `Foo`를 생성자로 호출하고 `Foo.prototype`을 새 객체의 prototype에 할당한다. -In case of an explicit `return` statement, the function returns the value -specified that statement, **but only** if the return value is an `Object`. +생성자에 `return` 구문이 있고 literal이 아니라 `객체`를 반환하면 그 객체가 반환된다. function Bar() { return 2; } - new Bar(); // a new object + new Bar(); // 새 객체를 만들어 반환 function Test() { this.value = 2; @@ -39,23 +32,20 @@ specified that statement, **but only** if the return value is an `Object`. foo: 1 }; } - new Test(); // the returned object + new Test(); // 명시한 객체를 반환 -When the `new` keyword is omitted, the function will **not** return a new object. +new 키워드가 없으면 그 함수는 객체를 반환하지 않는다. function Foo() { this.bla = 1; // gets set on the global object } Foo(); // undefined -While the above example might still appear to work in some cases, due to the -workings of [`this`](#function.this) in JavaScript, it will use the -*global object* as the value of `this`. +이 함수는 그때그때 다르게 동작하지만 보통 [`this`](#function.this)의 규칙에 따라 `this`의 값으로 *Global 객체*가 사용된다.:w -### Factories +### 팩토리 -In order to be able to omit the `new` keyword, the constructor function has to -explicitly return a value. +생성자가 객체를 반환하면 `new` 키워드를 생략할 수 있다. function Bar() { var value = 1; @@ -72,25 +62,17 @@ explicitly return a value. new Bar(); Bar(); -Both calls to `Bar` return the exact same thing, a newly create object which -has a property called `method` on it, which is a -[Closure](#function.closures). +new 키워드가 있으나 없으니 `Bar` 생성자는 똑같이 동작한다. [Closure](#function.closures)가 할당된 method 프로퍼티가 있는 객체를 만들어 반환한다. -It is also to note that the call `new Bar()` does **not** affect the prototype -of the returned object. While the prototype will be set on the newly created -object, `Bar` never returns that new object. +`new Bar()`는 반환된 객체의 prototype 프로퍼티에 아무런 영향을 주지 않는다. 객체를 반환하지 않는 생성자로 만들어지는 경우에만 객체의 prototype이 생성자의 것으로 할당된다. -In the above example, there is no functional difference between using and -not using the `new` keyword. +그러니까 이 예제에서 `new` 키워드의 유무는 아무 차이가 없다. +### 팩토리로 객체 만들기 -### Creating New Objects via Factories +`new` 키워들 빼먹었을 때 버그가 생긴다는 이유로 **아예 new를 사용하지 말 것**을 권하기도 한다. -An often made recommendation is to **not** use `new` because forgetting its use -may lead to bugs. - -In order to create new object, one should rather use a factory and construct a -new object inside of that factory. +이를 위해서 객체를 만들고 반환해주는 팩토리를 사용할 수 있다. function Foo() { var obj = {}; @@ -107,22 +89,12 @@ new object inside of that factory. return obj; } -While the above is robust against a missing `new` keyword and certainly makes -the use of [private variables](#function.closures) easier, it comes with some -downsides. - - 1. It uses more memory since the created objects do **not** share the methods - on a prototype. - 2. In order to inherit the factory needs to copy all the methods from another - object or put that object on the prototype of the new object. - 3. Dropping the prototype chain just because of a left out `new` keyword - somehow goes against the spirit of the language. +`new` 키워드가 없어도 괜찮고 [private 변수](#function.closures)를 사용하기도 쉽다. 그렇지만, 단점도 있다. -### In Conclusion + 1. prototype으로 메소드를 공유하지 않으므로 메모리를 좀 더 사용한다. + 2. 팩토리를 상속하려면 모든 메소드를 복사하거나 객체의 prototype에 객체를 할당해 주어야 한다. + 3. `new` 키워드를 누락시켜서 prototype chain을 끊어버리는 것은 아무래도 언어의 의도에 어긋난다. -While omitting the `new` keyword might lead to bugs, it is certainly **not** a -reason to drop the use of prototypes altogether. In the end it comes down to -which solution is better suited for the needs of the application, it is -especially important to choose a specific style of object creation **and stick** -with it. +### 결론 +`new` 키워가 생략되면 버그가 생길 수 있지만 그렇다고 prototype을 사용하지 않을 이유가 되지 않는다. 애플리케이션에 맞는 방법을 선택하는 것이 나을 거고 어떤 방법이든 **엄격하고 한결같이* 지켜야 한다. diff --git a/doc/ko/function/general.md b/doc/ko/function/general.md index 7ca180f0..8786f7fc 100644 --- a/doc/ko/function/general.md +++ b/doc/ko/function/general.md @@ -1,48 +1,37 @@ ## Function Declarations and Expressions -Functions in JavaScript are first class objects. That means they can be -passed around like any other value. One common use of this feature is to pass -an *anonymous function* as a callback to another, possibly asynchronous function. +JavaScript의 function은 first class object라서 일반 객체처럼 취급될 수 있다. 그래서 익명 함수를 비동기 함수의 callback 같은 거로 넘길 수 있다. -### The `function` Declaration +### `function` Declaration function foo() {} -The above function gets [hoisted](#function.scopes) before the execution of the -program starts; thus, it is available *everywhere* in the scope it was *defined* -in, even if called before the actual definition in the source. +코드를 실행하기 전에 이 함수 [hoist](#function.Scopes)되기 때문에 해당 Scope 어디에서나 이 함수를 호출할 수 있다. 심지어 함수를 정의하기 전에 호출해도 된다. - foo(); // Works because foo was created before this code runs + foo(); // 이 코드가 실행되기 전에 foo가 만들어져서 잘 호출된다. function foo() {} -### The `function` Expression +### `function` Expression var foo = function() {}; -This example assigns the unnamed and *anonymous* function to the variable `foo`. +`foo` 변수에 *익명* 함수를 할당하는 예를 보자. foo; // 'undefined' - foo(); // this raises a TypeError + foo(); // TypeError가 난다. var foo = function() {}; -Due to the fact that `var` is a declaration that hoists the variable name `foo` -before the actual execution of the code starts, `foo` is already defined when -the script gets executed. +JavaScript가 hoist하는 것은 `var`로 선언하는 부분뿐이기 때문에 코드가 실행하기 전에 `foo` 변수는 정의된다. -But since assignments only happen at runtime, the value of `foo` will default -to [undefined](#core.undefined) before the corresponding code is executed. +그러나 할당은 런타임에만 가능한 일이라 할당하는 코드가 실행될 때까지 `foo`변수는 기본 값인 [undefined](#core.undefined)다. ### Named Function Expression -Another special case is the assignment of named functions. +named function을 할당하는 경우는 조금 특이하다. var foo = function bar() { - bar(); // Works + bar(); // 된다. } bar(); // ReferenceError -Here, `bar` is not available in the outer scope, since the function only gets -assigned to `foo`; however, inside of `bar`, it is available. This is due to -how [name resolution](#function.scopes) in JavaScript works, the name of the -function is *always* made available in the local scope of the function itself. - +function 밖에서 `bar`를 사용할 수 없지만, function 안에서는 사용할 수 있다. JavaScript가 [이름을 찾는 방법](#function.Scopes)이 있는데 function Scope에서는 항상 그 함수의 이름을 사용할 수 있다. diff --git a/doc/ko/function/scopes.md b/doc/ko/function/scopes.md index efb9d882..f957359d 100644 --- a/doc/ko/function/scopes.md +++ b/doc/ko/function/scopes.md @@ -1,29 +1,21 @@ -## Scopes and Namespaces +## Scope과 Namespace -Although JavaScript deals fine with the syntax of two matching curly -braces for blocks, it does **not** support block scope; hence, all that is left -is in the language is *function scope*. +JavaScript는 '{}' Block이 배배 꼬여 있어도 문법적으로는 잘 처리하지만, Block Scope은 지원하지 않는다. 그래서 JavaScript에서는 항상 *Function Scope*을 사용한다. - function test() { // a scope - for(var i = 0; i < 10; i++) { // not a scope + function test() { // Scope + for(var i = 0; i < 10; i++) { // Scope이 아님 // count } console.log(i); // 10 } -> **Note:** When not used in an assignment, return statement or as a function -> argument, the `{...}` notation will get interpreted as a block statement and -> **not** as an object literal. This, in conjunction with -> [automatic insertion of semicolons](#core.semicolon), can lead to subtle errors. +> **Note:** 할당할 때, 반환할 때, 함수 인자에서 사용되는 것을 제외하면 `{...}`는 모두 객체 리터럴이 아니라 Block 구문으로 해석된다. 그래서 [세미콜론을 자동으로 넣어주면](#core.semicolon) 에러가 생길 수 있다. -There are also no distinct namespaces in JavaScript, which means that everything -gets defined in one *globally shared* namespace. +그리고 JavaScript에는 namespace 개념이 없어서 *항상 공유하는* namepace가 하나 있는 거다. -Each time a variable is referenced, JavaScript will traverse upwards through all -the scopes until it finds it. In the case that it reaches the global scope and -still has not found the requested name, it will raise a `ReferenceError`. +변수를 사용할 때마다 JavaScript는 아는 Scope을 상위방향으로 찾는다. Global Scope에까지 해당 변수를 찾지 못하면 `ReferenceError`가 난다. -### The Bane of Global Variables +### Global 변수의 지옥. // script A foo = '42'; @@ -31,58 +23,47 @@ still has not found the requested name, it will raise a `ReferenceError`. // script B var foo = '42' -The above two scripts do **not** have the same effect. Script A defines a -variable called `foo` in the *global* scope, and script B defines a `foo` in the -*current* scope. +이 두 스크립트는 다르다. Script A는 *Global* Scope에 `foo`라는 변수를 정의하는 것이고 Script B는 *현* Scope에 변수 `foo`를 정의하는 것이다. -Again, that is **not** at all the *same effect*: not using `var` can have major -implications. +다시 말하지만, 이 둘은 전혀 다르고 `var`가 없는 것이 중요한 의미가 있다. - // global scope + // Global Scope var foo = 42; function test() { - // local scope + // local Scope foo = 21; } test(); foo; // 21 -Leaving out the `var` statement inside the function `test` will override the -value of `foo`. While this might not seem like a big deal at first, having -thousands of lines of JavaScript and not using `var` will introduce horrible, -hard-to-track-down bugs. - - // global scope +함수에서 `var` 구문을 빼버리면 Global Scope의 `foo`의 값을 바꿔버린다. '뭐 이게 뭐가 문제야'라고 생각될 수 있지만 수천 줄인 JavaScript 코드에서 `var`를 빼먹어서 생긴 버그를 해결하는 것은 정말 어렵다. + + // Global Scope var items = [/* some list */]; for(var i = 0; i < 10; i++) { subLoop(); } function subLoop() { - // scope of subLoop - for(i = 0; i < 10; i++) { // missing var statement - // do amazing stuff! + // Scope of subLoop + for(i = 0; i < 10; i++) { // var가 없다. + // 내가 for문도 하는데... } } - -The outer loop will terminate after the first call to `subLoop`, since `subLoop` -overwrites the global value of `i`. Using a `var` for the second `for` loop would -have easily avoided this error. The `var` statement should **never** be left out -unless the *desired effect* is to affect the outer scope. -### Local Variables +subLoop이 Global 변수 `i`의 값을 변경해버리기 때문에 외부 Loop은 `subLoop`을 한번 호출하고 나면 종료된다. 두 번째 `for` Loop에 `var`를 사용하여 `i`를 정의하면 이 문제는 생기지 않는다. 외부 Scope의 변수를 사용하는 것이 아니라면 `var`를 꼭 넣어야 한다. + +### 로컬 변수 -The only source for local variables in JavaScript are -[function](#function.general) parameters and variables that were declared via the -`var` statement. +JavaScript에서 로컬 변수를 정의하는 방법은 [함수 파라미터](#function.general)와 `var`로 정의한 변수뿐이다. - // global scope + // Global Scope var foo = 1; var bar = 2; var i = 2; function test(i) { - // local scope of the function test + // test 함수의 local Scope i = 5; var foo = 3; @@ -90,13 +71,11 @@ The only source for local variables in JavaScript are } test(10); -While `foo` and `i` are local variables inside the scope of the function `test`, -the assignment of `bar` will override the global variable with the same name. +`foo`, `i`는 `test` Function Scope에 있는 로컬 변수라서 Global의 `foo`, `i` 값은 바뀌지 않는다. 하지만 `bar`는 Global 변수이기 때문에 Global의 `bar` 값이 변경된다. ### Hoisting -JavaScript **hoists** declarations. This means that both `var` statements and -`function` declarations will be moved to the top of their enclosing scope. +JavaScript는 선언문을 모두 **Hoist**한다. Hoist는 `var` 구문이나 `function`을 선언문을 해당 Scope의 가장 처음으로 옮기는 것을 말한다. bar(); var bar = function() {}; @@ -115,16 +94,14 @@ JavaScript **hoists** declarations. This means that both `var` statements and } } -The above code gets transformed before any execution is started. JavaScript moves -the `var` statements, as well as the `function` declarations to the top of the -nearest surrounding scope. +코드를 본격적으로 실행하기 전에 JavaScript는 `var` 구문과 `function` 선언문을 해당 Scope의 상위로 옮긴다. - // var statements got moved here + // var 구문이 여기로 옮겨짐. var bar, someValue; // default to 'undefined' - // the function declaration got moved up too + // function 선언문도 여기로 옮겨짐 function test(data) { - var goo, i, e; // missing block scope moves these here + var goo, i, e; // Block Scope은 없으므로 local 변수들은 여기로 옮겨짐 if (false) { goo = 1; @@ -136,96 +113,77 @@ nearest surrounding scope. } } - bar(); // fails with a TypeError since bar is still 'undefined' - someValue = 42; // assignments are not affected by hoisting + bar(); // bar()가 아직 'undefined'이기 때문에 TypeError가 남 + someValue = 42; // Hoisting은 할당문까지 옮기지 않는다. bar = function() {}; test(); -Missing block scoping will not only move `var` statements out of loops and -their bodies, it will also make the results of certain `if` constructs -non-intuitive. +Block Scope이 없으므로 Loop이나 if의 Block 안에 있는 `var` 구문들까지도 모두 Function Scope의 앞쪽으로 옮겨진다. 그래서 `if` Block의 결과는 좀 이상해진다. -In the original code, although the `if` statement seemed to modify the *global -variable* `goo`, it actually modifies the *local variable* - after hoisting -has been applied. +원래 코드에서 `if` Block은 *Global 변수* `goo`를 바꾸는 것처럼 보였지만 Hoisting 후에는 *local 변수*를 바꾼다. -Without the knowledge about *hoisting*, the below code might seem to raise a -`ReferenceError`. +*Hoisting*을 모르면 다음과 같은 코드는 `ReferenceError`가 날 것으로 생각할 것이다. - // check whether SomeImportantThing has been initiliazed + // SomeImportantThing이 초기화됐는지 검사한다. if (!SomeImportantThing) { var SomeImportantThing = {}; } -But of course, the above works due to the fact that the `var` statement is being -moved to the top of the *global scope*. +`var` 구문은 *Global Scope* 상단으로 옮겨지기 때문에 이 코드는 잘 동작한다. var SomeImportantThing; - // other code might initiliaze SomeImportantThing here, or not + // SomeImportantThing을 여기서 초기화하거나 말거나... - // make sure it's there + // SomeImportantThing는 선언돼 있다. if (!SomeImportantThing) { SomeImportantThing = {}; } -### Name Resolution Order - -All scopes in JavaScript, including the *global scope*, have the special name -[`this`](#function.this), defined in them, which refers to the *current object*. +### 이름 찾는 순서 -Function scopes also have the name [`arguments`](#function.arguments), defined in -them, which contains the arguments that were passed to a function. +JavaScript의 모든 Scope은 *현 객체*를 가리키는 [`this`](#function.this)를 가지고 있다. *Global Scope*에도 this가 있다. -For example, when trying to access a variable named `foo` inside the scope of a -function, JavaScript will lookup the name in the following order: +Function Scope에는 [`arguments`](#function.arguments)라는 변수가 하나 더 있다. 이 변수는 함수에 넘겨진 인자들이 담겨 있다. - 1. In case there is a `var foo` statement in the current scope, use that. - 2. If one of the function parameters is named `foo`, use that. - 3. If the function itself is called `foo`, use that. - 4. Go to the next outer scope, and start with **#1** again. +예를 들어 Function Scope에서 `foo`라는 변수에 접근할 때 JavaScript는 다음과 같은 순서로 찾는다. -> **Note:** Having a parameter called `arguments` will **prevent** the creation -> of the default `arguments` object. + 1. 해당 Scope에서 `var foo` 구문으로 선언된 것을 찾는다. + 2. 함수 파라미터에서 `foo`라는 것을 찾는다. + 3. 해당 함수 이름이 `foo`인지 찾는다. + 4. 상위 Scope으로 있는지 확인하고 있으면 **#1**부터 다시 한다. + +> **Note:** `arguments`라는 파라미터가 있으면 Function의 기본 객체인 `arguments`가 생성되지 않는다. -### Namespaces +### Namespace -A common problem of having only one global namespace is the likeliness of running -into problems where variable names clash. In JavaScript, this problem can -easily be avoided with the help of *anonymous wrappers*. +JavaScript에서는 Global namespace 하나밖에 없어서 변수 이름이 중복되는 문제가 발생하기 쉽다. *Anonymous Wrappers*가 있어서 쉽게 피해갈 수 있다. (function() { - // a self contained "namespace" + // 일종의 namespace라고 할 수 있다. window.foo = function() { - // an exposed closure + // 이 Closure는 Global Scope에 노출된다. }; - })(); // execute the function immediately + })(); // 함수를 정의하자마자 실행한다. +Unnamed Function은 [expressions](#function.general)이기 때문에 호출되려면 먼저 Evaluate돼야 한다. -Unnamed functions are considered [expressions](#function.general); so in order to -being callable, they must first be evaluated. - - ( // evaluate the function inside the paranthesis + ( // 소괄호 안에 있는 것을 먼저 Evaluate한다. function() {} - ) // and return the function object - () // call the result of the evaluation + ) // 그리고 Function 객체를 반환한다. + () // Evaluation된 결과를 호출한다. -There are other ways for evaluating and calling the function expression; which, -while different in syntax, do behave the exact same way. +같은 표기법이 두 가지 더 있다. 문법은 다르지만 똑같다. - // Two other ways + // 두 가지 다른 방법 +function(){}(); (function(){}()); -### In Conclusion - -It is recommended to always use an *anonymous wrapper* for encapsulating code in -its own namespace. This does not only protect code against name clashes, but it -also allows for better modularization of programs. +### 결론 -Additionally, the use of global variables is considered **bad practice**. **Any** -use of them indicates badly written code that is prone to errors and hard to maintain. +코드를 캡슐화할 때는 늘 *Anonymous Wrapper*로 namespace를 만들어 사용해야 한다. 이 Wrapper는 이름이 중복되는 것을 막아 주고 더 쉽게 모듈화할 수 있도록 해준다. +그리고 Global 변수를 사용하는 것은 악질 습관이다. 이유야 어쨌든 에러 나기 쉽고 관리하기 어렵다. diff --git a/doc/ko/function/this.md b/doc/ko/function/this.md index 440900e8..37a6a801 100644 --- a/doc/ko/function/this.md +++ b/doc/ko/function/this.md @@ -1,101 +1,82 @@ -## How `this` Works +## `this` -JavaScript has a different concept of what the special name `this` refers to -than most other programming languages do. There are exactly **five** different -ways in which the value of `this` can be bound in the language. +다른 프로그래밍 언어에서 `this`가 가리키는 것과 JavaScript에서 `this`가 가리키는 것과는 좀 다르다. `this`가 가리킬 수 있는 객체는 정확히 5종류나 된다. -### The Global Scope +### Global Scope에서 this; -When using `this` in global scope, it will simply refer to the *global* object. +Global scope에서도 this가 사용될 수 있고 이때에는 *Global* 객체를 가리킨다. - -### Calling a Function +### 함수를 호출할 때 foo(); -Here, `this` will again refer to the *global* object. +이때에도 `this`는 *Global* 객체를 가리킨다. -> **ES5 Note:** In strict mode, the global case **no longer** exists. -> `this` will instead have the value of `undefined` in that case. +> **ES5 Note:** strict 모드에서는 더는 Global 객체를 가리키지 않고 대신 `undefined`를 가리킨다. -### Calling a Method +### 메소드로 호출할 때 test.foo(); -In this example, `this` will refer to `test`. +이 경우에는 `this`가 `test`를 가리킨다. -### Calling a Constructor +### 생성자를 호출할 때 new foo(); -A function call that is preceded by the `new` keyword acts as -a [constructor](#function.constructors). Inside the function, `this` will refer -to a *newly created* `Object`. +`new` 키워드로 [생성자](#function.constructors)를 실행시키는 경우에 이 생성자 안에서 `this`는 새로 만들어진 객체를 가리킨다. -### Explicit Setting of `this` +### `this`가 가리키는 객체 정해주기. function foo(a, b, c) {} - + var bar = {}; - foo.apply(bar, [1, 2, 3]); // array will expand to the below - foo.call(bar, 1, 2, 3); // results in a = 1, b = 2, c = 3 + foo.apply(bar, [1, 2, 3]); // a = 1, b = 2, c = 3으로 넘어간다. + foo.call(bar, 1, 2, 3); // 이것도... -When using the `call` or `apply` methods of `Function.prototype`, the value of -`this` inside the called function gets **explicitly set** to the first argument -of the corresponding function call. +`Function.prototype`의 `call`이나 `apply` 메소드를 호출하면 `this`가 무엇을 가리킬지 *정해줄 수 있다*. 호출할 때 첫 번째 인자로 `this`가 가리켜야 할 객체를 넘겨준다. -As a result, the above example the *method case* does **not** apply, and `this` -inside of `foo` will be set to `bar`. +그래서 `foo` Function 안에서 `this`는 위에서 설명했던 객체 중 하나를 가리키는 것이 아니라 `bar`를 가리킨다. -> **Note:** `this` **cannot** be used to refer to the object inside of an `Object` -> literal. So `var obj = {me: this}` will **not** result in `me` referring to -> `obj`, since `this` only gets bound by one of the five listed cases. +> **Note:** 객체 리터럴에서 this는 그 객체를 가리키지 않는다. 예를 들어 `var obj= {me:this}`에서 `me`가 `obj`를 가리키는 것이 아니라 위에 설명한 5가지 객체 중 하나를 가리킨다. -### Common Pitfalls +### 대표적인 결점 -While most of these cases make sense, the first one is to be considered another -mis-design of the language because it **never** has any practical use. +`this`가 Global 객체를 가리키는 것도 잘못 설계된 부분 중 하나다. 괜찮아 보이지만 실제로는 전혀 사용하지 않는다. Foo.method = function() { function test() { - // this is set to the global object + // 여기에서 this는 Global 객체를 가리킨다. } test(); } -A common misconception is that `this` inside of `test` refers to `Foo`; while in -fact, it **does not**. +`test` 에서 `this`가 `Foo`를 가리킬 것으로 생각할 테지만 틀렸다. 실제로는 그렇지 않다. -In order to gain access to `Foo` from within `test`, it is necessary to create a -local variable inside of `method` which refers to `Foo`. +`test`에서 `Foo`에 접근하려면 method에 로컬 변수를 하나 만들고 `Foo`를 가리키게 하여야 한다. Foo.method = function() { var that = this; function test() { - // Use that instead of this here + // 여기에서 this 대신에 that을 사용하여 Foo에 접근한다. } test(); } -`that` is just a normal variable name, but it is commonly used for the reference to an -outer `this`. In combination with [closures](#function.closures), it can also -be used to pass `this` values around. +`that`은 this에 접근하기 위해 만든 변수다. [closures](#function.closures)와 함께 `this`의 값을 넘기는 데 사용할 수 있다. -### Assigning Methods +### Method할당 하기 -Another thing that does **not** work in JavaScript is function aliasing, which is -**assigning** a method to a variable. +메소드를 변수에 *할당*해 버리기 때문에 Function Aliasing은 JavaScript에서 안된다. var test = someObject.methodTest; test(); -Due to the first case, `test` now acts like a plain function call; therefore, -`this` inside it will no longer refer to `someObject`. +`test`는 다른 함수를 호출하는 것과 다름없어서 `this`가 someObject를 가리키지 않는다. -While the late binding of `this` might seem like a bad idea at first, in -fact, it is what makes [prototypal inheritance](#object.prototype) work. +처음에는 `this`를 늦게 바인딩하는 것이 나쁜 아이디어라고 생각할 수도 있지만, 이 점이 실제로 [prototypal inheritance](#object.prototype)를 가능케 해준다. function Foo() {} Foo.prototype.method = function() {}; @@ -105,7 +86,4 @@ fact, it is what makes [prototypal inheritance](#object.prototype) work. new Bar().method(); -When `method` gets called on a instance of `Bar`, `this` will now refer to that -very instance. - - +`Bar` 인스턴스에서 `method`를 호출하면 `method`에서 `this`는 바로 그 인스턴스를 가리킨다. diff --git a/doc/ko/intro/index.md b/doc/ko/intro/index.md index 134bca80..dd885f40 100644 --- a/doc/ko/intro/index.md +++ b/doc/ko/intro/index.md @@ -1,37 +1,25 @@ ## Intro -**JavaScript Garden** is a growing collection of documentation about the most -quirky parts of the JavaScript programming language. It gives advice to -avoid common mistakes and subtle bugs, as well as performance issues and bad -practices, that non-expert JavaScript programmers may encounter on their -endeavours into the depths of the language. +**JavaScript Garden**은 JavaScript 언어의 핵심에 대한 글을 모은 것이다. 이 글은 초보자들이 JavaScript 익히면서 자주 겪는 실수, 미묘한 버그, 성능 이슈, 나쁜 습관들 줄일 수 있도록 도와줄 것이다. -JavaScript Garden does **not** aim to teach you JavaScript. Former knowledge -of the language is strongly recommended in order to understand the topics covered -in this guide. In order to learn the basics of the language, please head over to -the excellent [guide][1] on the Mozilla Developer Network. +JavaScript Garden은 단순히 JavaScript를 설명하려 만들지 않았다. 그래서 이 글에서 설명하는 주제들을 이해하려면 반드시 언어에 대한 기본 지식이 필요하다. 먼저 Mozilla Developer Network에 있는 [문서][1]로 JavaScript 언어를 공부하기 바란다. -## The Authors +## 저자들 -This guide is the work of two lovely [Stack Overflow][2] users, [Ivo Wetzel][3] -(Writing) and [Zhang Yi Jiang][4] (Design). +이 글은 [Stack Overflow][2]에서 사랑받는 두 사람 [Ivo Wetzel][3]과 [Zhang Yi Jiang][4]의 작품이다. Ivo Wetzel이 글을 썼고 Zhang Yi jiang이 디자인을 맡았다. -## Contributors +## 기여자들 - - [Caio Romão][5] (Spelling corrections) - - [Andreas Blixt][6] (Language corrections) + - [Caio Romão][5] (철자 교정) + - [Andreas Blixt][6] (언어 교정) -## Hosting +## 호스팅 -JavaScript Garden is hosted on GitHub, but [Cramer Development][7] supports us -with a mirror at [JavaScriptGarden.info][8]. +JavaScript Garden은 Github에서 호스팅하고 있고 [Cramer Development][7]가 [JavaScriptGarden.info][8]에서 미러링해주고 있다. -## License +## 저작권 -JavaScript Garden is published under the [MIT license][9] and hosted on -[GitHub][10]. If you find errors or typos please [file an issue][11] or a pull -request on the repository. You can also find us in the [JavaScript room][12] on -Stack Overflow chat. +JavaScript Garden은 [MIT license][9]를 따르고 [GitHub][10]에서 호스팅하고 있다. 문제를 발견하면 [이슈를 보고][11]하거나 수정해서 Pull Request를 하라. 아니면 Stack Overflow 채팅 사이트의 [Javascript room][12]에서 우리를 찾아도 된다. [1]: https://developer.mozilla.org/en/JavaScript/Guide [2]: http://stackoverflow.com/ @@ -44,4 +32,4 @@ Stack Overflow chat. [9]: https://github.com/BonsaiDen/JavaScript-Garden/blob/next/LICENSE [10]: https://github.com/BonsaiDen/JavaScript-Garden [11]: https://github.com/BonsaiDen/JavaScript-Garden/issues -[12]: http://chat.stackoverflow.com/rooms/17/javascript +[12]: http://chat.stackoverflow.com/rooms/17/javascript \ No newline at end of file diff --git a/doc/ko/object/forinloop.md b/doc/ko/object/forinloop.md index cb776b36..26687e1b 100644 --- a/doc/ko/object/forinloop.md +++ b/doc/ko/object/forinloop.md @@ -1,51 +1,36 @@ -## The `for in` Loop +## `for in` Loop -Just like the `in` operator, the `for in` loop also traverses the prototype -chain when iterating over the properties of an object. +`in` 연산자와 마찬가지로 `for in`도 객체의 프로퍼티뿐만 아니라 프로토타입 체인까지 traverse 한다. -> **Note:** The `for in` loop will **not** iterate over any properties that -> have their `enumerable` attribute set to `false`; for example, the `length` -> property of an array. - - // Poisoning Object.prototype +> **Note:** `for in`은 Array의 `length`처럼 `enumerable` 속성이 `false`인 프로퍼티는 iterate 하지 않는다. + + // 원래는 Object.prototype을 바꾸면 안 된다. Object.prototype.bar = 1; var foo = {moo: 2}; for(var i in foo) { - console.log(i); // prints both bar and moo + console.log(i); // bar와 moo 둘 다 출력한다. } -Since it is not possible to change the behavior of the `for in` loop itself, it -is necessary to filter out the unwanted properties inside the loop body; -this is done by using the [`hasOwnProperty`](#object.hasownproperty) method of -`Object.prototype`. +선택적으로 iterate 하려면 `for in`은 바꿀 수 없으니까 loop 바디에서 하는 수밖에 없다. `Object.prototype`의 [`hasOwnProperty`](#object.hasownproperty)메소드를 사용하면 객체의 프로퍼티만 골라낼 수 있다. -> **Note:** Since the `for in` always traverses the complete prototype chain, it -> will get slower with each additional layer of inheritance added to an object. +> **Note:** `for in`은 프로토타입 체인을 모두 traverse 한다. 그래서 상속할 때마다 더 느려진다. -### Using `hasOwnProperty` for Filtering +### `hasOwnProperty`로 필터링 하기 - // still the foo from above + // 위의 예제에 이어서 for(var i in foo) { if (foo.hasOwnProperty(i)) { console.log(i); } } -This version is the only correct one to use. Due to the use of `hasOwnProperty`, it -will **only** print out `moo`. When `hasOwnProperty` is left out, the code is -prone to errors in cases where the native prototypes - e.g. `Object.prototype` - -have been extended. - -One widely used framework which does this is [Prototype][1]. When this -framework is included, `for in` loops that do not use `hasOwnProperty` are -guaranteed to break. +실무에 사용할 작정이라면 이렇게 써야 옳다. `hasOwnProperty` 때문에 **오직** `moo`만 출력된다. `hasOwnProperty`가 없으면 `Object.prototype`같은 네이티브 프로토타입이 확장될 때 에러 날 수 있다. -### In Conclusion +네이티브 프로토타입을 확장하는 [Proptotype 라이브러리][1]을 사용할 때 `hasOwnProperty`가 없는 `for in` loop은 꼭 문제가 발생한다. -It is recommended to **always** use `hasOwnProperty`. Never should any -assumptions be made about the environment the code is running in, or whether the -native prototypes have been extended or not. +### 결론 -[1]: http://www.prototypejs.org/ +`hasOwnProperty`는 항상 사용해야 한다. 실제로 코드가 동작할 환경에서 네이티브 프로토타입의 확장 여부에 대해 어떠한 가정도 하지 말아야 한다. +[1]: http://www.prototypejs.org/ \ No newline at end of file diff --git a/doc/ko/object/general.md b/doc/ko/object/general.md index bc52f1f7..0db98e14 100644 --- a/doc/ko/object/general.md +++ b/doc/ko/object/general.md @@ -1,66 +1,55 @@ -## Object Usage and Properties +## 객체와 프로퍼티 -Everything in JavaScript acts like an object, with the only two exceptions being -[`null`](#core.undefined) and [`undefined`](#core.undefined). +JavaScript에서 [`null`](#core.undefined)과 [`undefined`](#core.undefined)를 제외한 모든 것은 객체다. false.toString() // 'false' [1, 2, 3].toString(); // '1,2,3' - + function Foo(){} Foo.bar = 1; Foo.bar; // 1 -A common misconception is that number literals cannot be used as -objects. That is because a flaw in JavaScript's parser tries to parse the *dot -notation* on a number as a floating point literal. +숫자 리터럴은 객체가 아니라는 오해가 있는데 단지 JavaScript 파서의 문제일 뿐이다. JavaScript 파서는 숫자에 *Dot Notation*이 들어가면 오류라고 생각한다. - 2.toString(); // raises SyntaxError + 2.toString(); // SyntaxError가 난다. -There are a couple of workarounds which can be used in order make number -literals act as objects too. +하지만, 숫자를 객체로 인식하는 꼼수가 몇 가지 있다. - 2..toString(); // the second point is correctly recognized - 2 .toString(); // note the space left to the dot - (2).toString(); // 2 is evaluated first + 2..toString(); // 두 번째 점은 잘 된다. + 2 .toString(); // 왼쪽 공백이 있으면 잘 된다. + (2).toString(); // 2를 먼저 해석한다. -### Objects as a Data Type +### Object 타입 -Objects in JavaScript can also be used as a [*Hashmap*][1]; they mainly consist -of named properties mapping to values. +JavaScript 객체는 name/value 쌍으로 된 프로퍼티로 구성되기 때문에 [*Hashmap*][1]으로도 사용할 수 있다. -Using a object literal - `{}` notation - it is possible to create a -plain object. This new object [inherits](#object.prototype) from `Object.prototype` and -has no [own properties](#object.hasownproperty) defined on it. +객체 리터럴인 Object Notation으로 객체를 만들면 `Object.prototype`을 상속받고 [프로퍼티를 하나도 가지지 않은](#object.hasownproperty) 객체가 만들어진다. - var foo = {}; // a new empty object + var foo = {}; // 깨끗한 새 객체를 만든다. - // a new object with a property called 'test' with value 12 + // 값이 12인 'test' 프로퍼티가 있는 객체를 만든다. var bar = {test: 12}; -### Accessing Properties +### 프로퍼티 + +객체의 프로퍼티는 Dot Notation이나 Square Bracket Notation으로 접근할 수 있다. -The properties of an object can be accessed in two ways, via either the dot -notation or the square bracket notation. - var foo = {name: 'Kitten'} foo.name; // kitten foo['name']; // kitten - + var get = 'name'; foo[get]; // kitten - + foo.1234; // SyntaxError foo['1234']; // works -Both notations are identical in their workings, with the only difference being that -the square bracket notation allows for dynamic setting of properties, as well as -the use of property names that would otherwise lead to a syntax error. -### Deleting Properties +'[]'은 프로퍼티를 동적으로 할당할 수 있고 변수 이름 규칙에도 구애받지 않는다. 그렇지만, 두 가지 방법은 근본적으로 서로 똑같다. -The only way to actually remove a property from an object is to use the `delete` -operator; setting the property to `undefined` or `null` only removes the -*value* associated with the property, but not the *key*. +### 프로퍼티 삭제 + +객체의 프로퍼티를 삭제하는 방법은 `delete`를 사용하는 것뿐이다. 프로퍼티에 `undefined`나 `null`을 할당하는 것은 프로퍼티를 삭제하는 것이 아니라 프로퍼티에 할당된 *value*만 지우고 *key*는 그대로 두는 것이다. var obj = { bar: 1, @@ -77,23 +66,18 @@ operator; setting the property to `undefined` or `null` only removes the } } -The above outputs both `bar undefined` and `foo null` - only `baz` was -removed and is therefore missing from the output. + +`baz`만 제거했기 때문에 `bar undefined`와 `foo null`은 출력되고 `baz`와 관련된 것은 출력되지 않는다. ### Notation of Keys var test = { 'case': 'I am a keyword, so I must be notated as a string', - delete: 'I am a keyword, so me too' // raises SyntaxError + delete: 'I am a keyword, so me too' // SyntaxError가 난다. }; -Object properties can be both notated as plain characters and as strings. Due to -another mis-design in JavaScript's parser, the above will throw -a `SyntaxError` prior to ECMAScript 5. - -This error arises from the fact that `delete` is a *keyword*; therefore, it must be -notated as a *string literal* to ensure that it will be correctly interpreted by -older JavaScript engines. +프로퍼티의 key에 문자열이나 스트링을 사용할 수 있다. 이 부분도 JavaScript 파서가 좀 잘못 설계된 거다. ECMAScript 5 이전에는 `SystaxError`가 났었다. -[1]: http://en.wikipedia.org/wiki/Hashmap +이 에러는 `delete`가 키워드이기 때문에 발생하는 것이다. key를 스트링 리터럴로 정의하면 JavaScript 엔진은 언제나 잘 해석한다. +[1]: http://en.wikipedia.org/wiki/Hashmap \ No newline at end of file diff --git a/doc/ko/object/hasownproperty.md b/doc/ko/object/hasownproperty.md index 576c50c6..d1437f47 100644 --- a/doc/ko/object/hasownproperty.md +++ b/doc/ko/object/hasownproperty.md @@ -1,17 +1,13 @@ ## `hasOwnProperty` -In order to check whether a object has a property defined on *itself* and **not** -somewhere on its [prototype chain](#object.prototype), it is necessary to use the -`hasOwnProperty` method which all objects inherit from `Object.prototype`. +어떤 프로퍼티가 해당 객체 자신의 것인지 아니면 [프로토타입 체인](#object.prototype)에 있는 것인지 확인하려면 `Object.prototype`을 상속받은 `hasOwnProperty` 메소드를 사용해야 한다. -> **Note:** It is **not** enough to check whether a property is `undefined`. The -> property might very well exist, but its value just happens to be set to -> `undefined`. +> **Note:** 이 메소드로는 프로퍼티의 값이 `undefined`인지 확인할 수 없다. 프로퍼티가 존재해도 그 값은 `undefined`일 수 있다. -`hasOwnProperty` is the only thing in JavaScript which deals with properties and -does **not** traverse the prototype chain. +프로토타입 체인을 traverse 하지 않으려면 `hasOwnProperty`를 사용하는 방법밖에 없다. - // Poisoning Object.prototype + + // Object.prototype을 더럽힌다. Object.prototype.bar = 1; var foo = {goo: undefined}; @@ -21,16 +17,11 @@ does **not** traverse the prototype chain. foo.hasOwnProperty('bar'); // false foo.hasOwnProperty('goo'); // true -Only `hasOwnProperty` will give the correct and expected result; this is -essential when iterating over the properties of any object. There is **no** other -way to exclude properties that are not defined on the object *itself*, but -somewhere on its prototype chain. +프로퍼티의 존재 여부를 확인하는 방법은 `hasOwnProperty` 메소드 뿐이다. 이 메소드는 프로토타입 체인의 프로퍼티말고 해당 객체의 프로퍼티만 iterate 할 때 유용하다. 객체 자체의 프로퍼티와 프로토타입 체인 어딘가에 있는 프로퍼티를 골라 주는 다른 방법은 없다. -### `hasOwnProperty` as a Property +### `hasOwnProperty`도 프로퍼티 -JavaScript does **not** protect the property name `hasOwnProperty`; thus, if the -possibility exists that an object might have a property with this name, it is -necessary to use an *external* `hasOwnProperty` in order to get correct results. +JavaScript는 `hasOwnProperty` 프로퍼티 역시 보호하지 않는다. 그래서 객체에 `hasOwnProperty` 프로퍼티가 있으면 다른 객체의 `hasOwnProperty` 메소드를 빌려 사용해야 한다. var foo = { hasOwnProperty: function() { @@ -39,15 +30,11 @@ necessary to use an *external* `hasOwnProperty` in order to get correct results. bar: 'Here be dragons' }; - foo.hasOwnProperty('bar'); // always returns false + foo.hasOwnProperty('bar'); // 항상 false를 반환한다. - // Use another Object's hasOwnProperty and call it with 'this' set to foo + // 다른 객체의 hasOwnProperty를 사용하여 foo 객체의 프로퍼티 유무를 확인한다. ({}).hasOwnProperty.call(foo, 'bar'); // true -### In Conclusion - -When checking for the existence of a property on a object, `hasOwnProperty` is -the **only** method of doing so. It is also recommended to make `hasOwnProperty` -part of **every** [`for in` loop](#object.forinloop); this will avoid errors from -extended native [prototypes](#object.prototype). +### 결론 +객체에 프로퍼티가 있는지 `hasOwnProperty`로만 확인할 수 있다. [`for in` loop](#object.forinloop)은 항상 `hasOwnProperty`와 함께 사용하길 권장한다. 네이티브 객체의 [프로토타입](#object.prototype)이 확장하는 사태가 일어나도 안전하게 지켜준다. \ No newline at end of file diff --git a/doc/ko/object/prototype.md b/doc/ko/object/prototype.md index 0a3b6d0c..feb69086 100644 --- a/doc/ko/object/prototype.md +++ b/doc/ko/object/prototype.md @@ -1,24 +1,14 @@ -## The Prototype +## Prototype -JavaScript does not feature a classical inheritance model; instead, it uses a -*prototypal* one. +Javascript는 클래스 스타일의 상속 모델을 사용하지 않고 *프로토타입* 스타일의 상속 모델을 사용한다. -While this is often considered to be one of JavaScript's weaknesses, the -prototypal inheritance model is in fact more powerful than the classic model. -It is, for example, fairly trivial to build a classic model on top of it, while the -other way around is a far more difficult task. +'이 점이 JavaScript의 약점이다.'라고 말하는 사람들도 있지만 실제로는 prototypal inheritance 모델이 훨씬 더 강력하다. 왜냐하면, 프로토타입 모델에서 클래스 모델을 흉내 내기는 매우 쉽지만, 반대로 클래스 모델에서 프로토타입 모델을 흉내 내기란 너무 어렵다. -Due to the fact that JavaScript is basically the only widely used language that -features prototypal inheritance, it takes some time to adjust to the -differences between the two models. +실제로 prototypal inheritance 모델을 채용한 언어 중에서 JavaScript만큼 널리 사용되는 언어는 없었기 때문에 너무 늦게 두 모델의 차이점이 정리된 감도 있다. -The first major difference is that inheritance in JavaScript is done by using so -called *prototype chains*. +JavaScript는 *프로토타입 체인*이라는 것으로 상속을 구현한다. -> **Note:** Simply using `Bar.prototype = Foo.prototype` will result in both objects -> sharing the **same** prototype. Therefore, changes to either object's prototype -> will affect the prototype of the other as well, which in most cases is not the -> desired effect. +> **Note:** 간단히 말해서 `Bar.prototype = Foo.prototype`은 두 객체가 **하나의 프로토타입**을 공유하는 것이다. 그래서 한 객체의 프로토타입을 변경하면 그 프로토타입 객체를 사용하는 다른 객체에도 영향을 끼친다. 대부분은 나쁜 결과로 이어진다. function Foo() { this.value = 42; @@ -29,16 +19,16 @@ called *prototype chains*. function Bar() {} - // Set Bar's prototype to a new instance of Foo + // Foo의 인스턴스를 만들어 Bar의 prototype에 할당한다. Bar.prototype = new Foo(); Bar.prototype.foo = 'Hello World'; - // Make sure to list Bar as the actual constructor + // Bar function을 생성자로 만들고 Bar.prototype.constructor = Bar; - var test = new Bar() // create a new bar instance + var test = new Bar() // bar 인스턴스를 만든다. - // The resulting prototype chain + // 결과적으로 만들어진 프로토타입 체인은 다음과 같다. test [instance of Bar] Bar.prototype [instance of Foo] { foo: 'Hello World' } @@ -47,70 +37,43 @@ called *prototype chains*. Object.prototype { toString: ... /* etc. */ } -In the above, the object `test` will inherit from both `Bar.prototype` and -`Foo.prototype`; hence, it will have access to the function `method` that was -defined on `Foo`. It will also have access to the property `value` of the -**one** `Foo` instance that is its prototype. It is important to note that `new -Bar()` does **not** create a new `Foo` instance, but reuses the one assigned to -its prototype; thus, all `Bar` instances will share the **same** `value` property. +`Bar.prototype`과 `Foo.prototype`을 둘 다 상속받았기 때문에 `test` 객체는 Foo에 정의한 `method` 함수에 접근할 수 있다. 프로토타입 체인에 있는 `Foo` 인스턴스의 `value` 프로퍼티도 사용할 수 있다. `new Bar()`를 해도 `Foo` 인스턴스는 새로 만들어지지 않고 Bar의 prototype에 있는 것을 재사용한다. 그래서 모든 Bar 인스턴스의 `value` 프로퍼티에 들어 있는 객체는 전부 **같은 객체다**. -> **Note:** Do **not** use `Bar.prototype = Foo`, since it will not point to -> the prototype of `Foo` but rather to the function object `Foo`. So the -> prototype chain will go over `Function.prototype` and not `Foo.prototype`; -> therefore, `method` will not be on the prototype chain. +> **Note:** `Bar.prototype = Foo`라고 하는 것은 `Foo`의 prototype을 가리키는 것이 아니라 Foo라는 function의 prototype을 가리키는 것이다. 그래서 프로토타입 체인에 `Foo.prototype` 대신 `Function.prototype`이 들어서는 것이기 때문에 `method` 프로퍼티는 못 찾는다. -### Property Lookup +### 프로토타입 찾기 -When accessing the properties of an object, JavaScript will traverse the -prototype chain **upwards** until it finds a property with the requested name. +객체의 프로퍼티에 접근을 시도하면 JavaScript는 해당 이름의 프로퍼티를 찾을 때까지 위쪽으로 프로토타입 체인을 뒤진다. -When it reaches the top of the chain - namely `Object.prototype` - and still -hasn't found the specified property, it will return the value -[undefined](#core.undefined) instead. +체인의 끝까지 찾았는데도(보통은 `Object.prototype`임) 발견하지 못하면 [undefined](#core.undefined)를 반환한다. -### The Prototype Property +### prototype 프로퍼티 -While the prototype property is used by the language to build the prototype -chains, it is still possible to assign **any** given value to it. However, -primitives will simply get ignored when assigned as a prototype. +prototype 프로퍼티는 프로토타입 체인을 만드는 데 사용하고 어떤 거라도 할당할 수 있지만, primitive 값을 할당하면 무시된다. function Foo() {} - Foo.prototype = 1; // no effect + Foo.prototype = 1; // 무시됨 -Assigning objects, as shown in the example above, will work, and allows for dynamic -creation of prototype chains. +객체를 할당하면 프로토타입 체인이 동적으로 잘 만들어진다. -### Performance +### 성능 -The lookup time for properties that are high up on the prototype chain can have a -negative impact on performance critical sections of code. Additionally, trying to -access non-existent properties will always traverse the full prototype chain. +성능이 중요한 부분에서는 프로토타입 체인을 따라 프로퍼티를 찾는 것이 부담일 수 있다. 게다가 없는 프로퍼티에 접근하면 항상 프로토타입 체인 전체를 뒤진다. -Also, when [iterating](#object.forinloop) over the properties of an object -**every** property that is on the prototype chain will get enumerated. +객체를 [iterating](#object.forinloop)하면 프로토타입 체인에 있는 **모든** 프로퍼티가 나열된다. -### Extension of Native Prototypes +### 네이티브 프로토타입의 확장 -One mis-feature that is often used is to extend `Object.prototype` or one of the -other built in prototypes. +JavaScript에서는 `Object.prototype`같이 네이티브 객체들의 프로토타입도 확장할 수 있지만, 이것도 잘못 설계됐다. -This technique is called [monkey patching][1] and breaks *encapsulation*. While -used by widely spread frameworks such as [Prototype][2], there is still no good -reason for cluttering built-in types with additional *non-standard* functionality. +이것을 [monkey patching][1]라고 부르는데 *캡슐화*를 망친다. 굉장히 많이 사용하는 [Prototype][2]도 굳이 기본 타입에 표준도 아닌 것들을 추가하는 이유를 아직 설명하지 못하고 있다. -The **only** good reason for extending a built-in prototype is to backport -the features of newer JavaScript engines; for example, -[`Array.forEach`][3]. +기본 타입을 확장해야 하는 경우도 하나 있다. [`Array.forEach`][3]같이 새 JavaScript 엔진에 추가된 기능을 위한 backport를 만들 때는 유용하다. -### In Conclusion +### 결론 -It is a **must** to understand the prototypal inheritance model completely -before writing complex code which makes use of it. Also, watch the length of -the prototype chains and break them up if necessary to avoid possible -performance issues. Further, the native prototypes should **never** be extended -unless it is for the sake of compatibility with newer JavaScript features. +prototypal inheritance 모델을 사용하는 코드를 작성하기 전에는 이 모델을 완벽하게 이해해야 한다. 프로토타입 체인과 관련된 성능 문제로 고생하지 않으려면 프로토타입 체인의 길이에 주의하고 너무 길지 않게 적당히 끊어줘야 한다. JavaScript의 새 기능에 대한 호환성을 유지하려는 경우를 제외하고 절대로 네이티브 프로토타입을 확장하면 안 된다. [1]: http://en.wikipedia.org/wiki/Monkey_patch [2]: http://prototypejs.org/ -[3]: https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/forEach - +[3]: https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/forEach \ No newline at end of file diff --git a/doc/ko/other/timeouts.md b/doc/ko/other/timeouts.md index 3a306bdd..582a77f9 100644 --- a/doc/ko/other/timeouts.md +++ b/doc/ko/other/timeouts.md @@ -1,69 +1,48 @@ -### `setTimeout` and `setInterval` +### `setTimeout`과 `setInterval` -Since JavaScript is asynchronous, it is possible to schedule the execution of a -function by using the `setTimeout` and `setInterval` functions. +JavaScript는 비동기이기 때문에 `setTimeout`과 `setInterval` 로 함수의 실행 순서를 조절할 수 있다. -> **Note:** Timeouts are **not** part of the ECMAScript Standard. They are -> implemented as part of the [DOM][1]. +> **Note:** Timeout은 ECMAScript 표준이 아니라 [DOM][1]때문에 구현됐다. function foo() {} - var id = setTimeout(foo, 1000); // returns a Number > 0 + var id = setTimeout(foo, 1000); // 0보다 큰 수를 반환한다. -When `setTimeout` gets called, it will return the ID of the timeout and schedule -`foo` to run in **approximately** one thousand milliseconds in the future. -`foo` will then get executed exactly **once**. +`setTimeout`을 호출하면 timeout의 ID를 반환하고 **대충** 1,000밀리 초 후에 `foo`를 실행시킨다. `foo`는 **딱 한 번만** 실행된다. -Depending on the timer resolution of the JavaScript engine that is running the -code, as well as the fact that JavaScript is single threaded and other code that -gets executed might block the thread, it is by **no means** a safe bet that one -will get the exact delay that was specified in the `setTimeout` call. +JavaScript 엔진의 단위 시간(timer resolution)에 따라서 코드를 실행시키고 단일 쓰레드인 JavaScript를 특정 코드가 블록 시켜 버릴 수도 있기 때문에 `setTimeout`으로 코드가 실행돼야 할 시간을 정해줘도 **정확하게 그 시간에 실행되지 않는다.**. -The function that was passed as the first parameter will get called by the -*global object*, which means that [`this`](#function.this) inside the called function -refers to that very object. +첫 번째 인자로 넘긴 함수가 실행될 때 컨텍스트인 [`this`](#function.this)는 *글로벌* 객체를 가리킨다. function Foo() { this.value = 42; this.method = function() { - // this refers to the global object - console.log(this.value); // will log undefined + // this는 global 객체를 가리키기 때문에 + console.log(this.value); // undefined를 출력한다. }; setTimeout(this.method, 500); } new Foo(); +> **Note:** `setTimeout`의 첫 번째 파라미터에 **함수** 객체를 넘겨야 하는 데 `setTimeout(foo(), 1000)`처럼 함수의 실행 결과를 넘기는 실수를 저지를 때가 잦다. 이럴 때 `setTimeout`은 그냥 `undefined`를 반환할 뿐이지 에러를 발생시키지 않는다. -> **Note:** As `setTimeout` takes a **function object** as its first parameter, an -> often made mistake is to use `setTimeout(foo(), 1000)`, which will use the -> **return value** of the call `foo` and **not** `foo`. This is, most of the time, -> a silent error, since when the function returns `undefined` `setTimeout` will -> **not** raise any error. +### `setInterval`은 계속 함수 호출을 쌓는다(Stacking). -### Stacking Calls with `setInterval` +`setTimeout`은 딱 한 번 함수를 호출하지만 `setInterval`은 이름처럼 **지정한 시간마다** 함수를 실행해 준다. 이 `setInterval`은 별로다. -While `setTimeout` only runs the function once, `setInterval` - as the name -suggests - will execute the function **every** `X` milliseconds, but its use is -discouraged. - -When code that is being executed blocks the timeout call, `setInterval` will -still issue more calls to the specified function. This can, especially with small -intervals, result in function calls stacking up. +만약 실행하는 코드가 일정시간 동안 블럭되도 `setInterval`은 계속 함수를 호출시키려 든다. 특히 주기가 짧으면 밀리기 쉬워서 함수 호출은 계속 쌓일 수 있다. function foo(){ - // something that blocks for 1 second + // 1초 동안 블럭함. } setInterval(foo, 100); -In the above code, `foo` will get called once and will then block for one second. +`foo`는 단순히 호출될 때마다 1초 동안 블럭하는 함수다. -While `foo` blocks the code, `setInterval` will still schedule further calls to -it. Now, when `foo` has finished, there will already be **ten** further calls to -it waiting for execution. +`foo`가 블럭해도 `setInterval`은 계속 함수 호출을 쌓는다. `foo`의 첫 번째 호출이 끝나도 *10번* 이상의 함수 호출이 쌓여 대기하고 있다. -### Dealing with Possible Blocking Code +### 오래 걸리는 코드 다루기 -The easiest solution, as well as most controllable solution, is to use `setTimeout` within -the function itself. +`setTimeout` 으로 함수 자신을 호출하는 방법으로 해결하기가 가장 쉽다. function foo(){ // something that blocks for 1 second @@ -71,85 +50,64 @@ the function itself. } foo(); -Not only does this encapsulate the `setTimeout` call, but it also prevents the -stacking of calls and it gives additional control. `foo` itself can now decide -whether it wants to run again or not. +함수 호출이 쌓이지도 않을 뿐만 아니라 `setTimeout` 호출을 해당 함수 안에서 관리하고 `foo` 함수에서 계속 실행할지 말지 조절할 수도 있다. -### Manually Clearing Timeouts +### Timeout 없애기 -Clearing timeouts and intervals works by passing the respective ID to -`clearTimeout` or `clearInterval`, depending which `set` function was used in -the first place. +`clearTimeout`과 `clearInterval` 함수로 setTimeout과 setInterval로 등록한 timeout과 interval을 삭제할 수 있다. `set` 함수들이 반환한 id를 저장했다가 `clear` 함수를 호출하여 삭제한다. var id = setTimeout(foo, 1000); clearTimeout(id); -### Clearing all timeouts +### timeout을 전부 없애기 -Because there is no built-in method for clearing all timeouts and/or intervals, -it is necessary to use brute force in order to achieve this functionality. +등록한 timeout과 interval을 한꺼번에 삭제하는 메소드는 없다. 구현해서 사용해야 한다. // clear "all" timeouts for(var i = 1; i < 1000; i++) { clearTimeout(i); } -There might still be timeouts that are unaffected by this arbitrary number; -therefore, is is instead recommended to keep track of all the timeout IDs, so -they can be cleared specifically. +Id가 1부터 1000 사이에 있는 timeout들을 삭제했지만, 그 외의 것은 아직 남아있다. 완벽하게 구현하려면 만들어진 timeout id를 모두 저장했다가 삭제해야 한다. -### Hidden use of `eval` +### 숨겨진 `eval` -`setTimeout` and `setInterval` can also take a string as their first parameter. -This feature should **never** be used because it internally makes use of `eval`. +`setTimeout`과 `setInterval`의 첫 파라미터에 스트링도 넘길 수 있다. 그렇지만, 내부적으로 `eval`을 사용하는 것이기 때문에 절대 사용하지 말아야 한다. -> **Note:** Since the timeout functions are **not** specified by the ECMAScript -> standard, the exact workings when a string is passed to them might differ in -> various JavaScript implementations. For example, Microsoft's JScript makes use of -> the `Function` constructor in place of `eval`. +> **Note:** timeout 함수는 ECMAScript 표준이 아녀서 첫 인자가 스트링 타입일 때에는 JavaScript 구현체마다 다르게 동작한다. 예를 들어, Microsoft의 JScript는 `eval`이 아니라 `Function` 생성자를 사용한다. function foo() { - // will get called + // 이게 호출됨 } function bar() { function foo() { - // never gets called + // 이것은 절대 호출 안 됨 } setTimeout('foo()', 1000); } bar(); -Since `eval` is not getting called [directly](#core.eval) in this case, the string -passed to `setTimeout` will get executed in the *global scope*; thus, it will -not use the local variable `foo` from the scope of `bar`. +이 경우 `eval`이 [그냥(directly)](#core.eval) 호출되는 것이 아니다. `setTimeout`에 넘겨진 스트링은 *global* scope에서 실행되기 때문에 `bar`의 로컬 함수 `foo`가 실행되는 것이 아니라 *global* scope의 `foo`가 실행된다. -It is further recommended to **not** use a string for passing arguments to the -function that will get called by either of the timeout functions. +함수에 파라미터를 넘겨야 하면 스트링을 사용하지 말아야 한다. function foo(a, b, c) {} - // NEVER use this + // 절대 사용하면 안 됨 setTimeout('foo(1,2, 3)', 1000) - // Instead use an anonymous function + // 대신 익명 함수를 사용하는 게 좋다. setTimeout(function() { foo(a, b, c); }, 1000) -> **Note:** While it is also possible to use the syntax -> `setTimeout(foo, 1000, a, b, c)`, it is not recommended, as its use may lead -> to subtle errors when used with [methods](#function.this). +> **Note:** `setTimeout(foo, 1000, a, b, c)`처럼 사용하는 것도 가능하지만, 이것도 권장하지 않는다. 메소드를 사용할 때 미묘한 에러가 날 수 있다. -### In Conclusion +### 결론 -**Never** should a string be used as the parameter of `setTimeout` or -`setInterval`. It is a clear sign of **really** bad code, when arguments need -to be supplied to the function that gets called. An *anonymous function* should -be passed that then takes care of the actual call. +`setTimeout`과 `setInterval`의 파라미터로 스트링은 절대 사용하지 말아야 한다. 핸들러 함수에 인자를 넘겨야 하는 경우도 **분명히** 탈 난다. *익명 함수*을 사용해서 호출해야 한다. -Furthermore, the use of `setInterval` should be avoided because its scheduler is not -blocked by executing JavaScript. +그리고 `setInterval`은 해당 핸들러가 블럭되든 말든 상관하지 않기 때문에 사용하면 안 된다. [1]: http://en.wikipedia.org/wiki/Document_Object_Model "Document Object Model" - diff --git a/doc/ko/types/casting.md b/doc/ko/types/casting.md index 34d6fd78..99328ebb 100644 --- a/doc/ko/types/casting.md +++ b/doc/ko/types/casting.md @@ -1,63 +1,53 @@ ## Type Casting -JavaScript is a *weakly typed* language, so it will apply *type coercion* -**wherever** possible. - - // These are true - new Number(10) == 10; // Number.toString() is converted - // back to a number - - 10 == '10'; // Strings gets converted to Number - 10 == '+10 '; // More string madness - 10 == '010'; // And more - isNaN(null) == false; // null converts to 0 - // which of course is not NaN - - // These are false +JavaScript는 weak typing 언어이기 때문에 필요할 때마다 알아서 타입을 변환한다. + + // 다음은 모두 true + new Number(10) == 10; // Number.toString()이 호출되고 + // 다시 Number로 변환된다. + + 10 == '10'; // 스트링은 Number로 변환된다. + 10 == '+10 '; // 이상한 스트링 + 10 == '010'; // 엉뚱한 스트링 + isNaN(null) == false; // null은 NaN이 아녀서 0으로 변환된다. + + // 다음은 모두 false 10 == 010; 10 == '-10'; -> **ES5 Note:** Number literals that start with a `0` are interpreted as octal -> (Base 8). Octal support for these has been **removed** in ECMAScript 5 strict -> mode. +> **ES5 Note:** `0`으로 시작하는 숫자 리터럴은 8진수다. 하지만, ECMAScript 5의 strict 모드에서는 더는 8진수로 해석하지 않는다. -In order to avoid the above, use of the [strict equal operator](#types.equality) -is **highly** recommended. Although this avoids a lot of common pitfalls, there -are still many further issues that arise from JavaScript's weak typing system. +이런 문제들은 [strict equal operator](#types.equality)로 **미리 방지해야** 한다. 이 operator로 JavaScript의 많은 결점을 보완할 수 있지만, 아직도 weak typing 시스템 때문에 생기는 문제가 많다. -### Constructors of Built-In Types +### 기본 타입 생성자 -The constructors of the built in types like `Number` and `String` behave -differently when being used with the `new` keyword and without it. +`Number`나 `String` 같은 기본 타입들의 생성자는 `new` 키워드가 있을 때와 없을 때 다르게 동작한다. - new Number(10) === 10; // False, Object and Number - Number(10) === 10; // True, Number and Number - new Number(10) + 0 === 10; // True, due to implicit conversion + new Number(10) === 10; // False, Object와 Number + Number(10) === 10; // True, Number와 Number + new Number(10) + 0 === 10; // True, 타입을 자동으로 변환해주기 때문에 -Using a built-in type like `Number` as a constructor will create a new `Number` -object, but leaving out the `new` keyword will make the `Number` function behave -like a converter. +`new` 키워드와 함께 `Number` 같은 기본 타입의 생성자를 호출하면 객체를 생성하지만 `new` 없이 호출하면 형 변환만 시킨다. -In addition, having literals or non-object values in there will result in even -more type coercion. +그리고 객체가 아니라 단순히 값이나 리터럴을 사용하면 타입 변환이 더 많이 일어난다. -The best option is to cast to one of the three possible types **explicitly**. +가능한 정확하게 타입을 변환해주는 것이 최선이다. -### Casting to a String +### 스트링으로 변환하기 '' + 10 === '10'; // true -By prepending an empty string, a value can easily be casted to a string. +숫자를 빈 스트링과 더하면 쉽게 스트링으로 변환된다. -### Casting to a Number +### 숫자로 변환하기 +'10' === 10; // true -Using the **unary** plus operator, it is possible to cast to a number. +`+` 연산자만 앞에 붙여주면 스트링을 쉽게 숫자로 변환할 수 있다. -### Casting to a Boolean +### Boolean으로 변환하기 -By using the **not** operator twice, a value can be converted a boolean. +'!' 연산자를 두 번 사용하면 쉽게 Boolean으로 변환할 수 있다. !!'foo'; // true !!''; // false @@ -66,5 +56,3 @@ By using the **not** operator twice, a value can be converted a boolean. !!'-1' // true !!{}; // true !!true; // true - - diff --git a/doc/ko/types/equality.md b/doc/ko/types/equality.md index 5665917f..3be20fbe 100644 --- a/doc/ko/types/equality.md +++ b/doc/ko/types/equality.md @@ -1,14 +1,13 @@ -## Equality and Comparisons +## 객체 비교하기 -JavaScript has two different ways of comparing the values of objects for equality. +JavaScript에서 객체를 비교하는 방법은 두 가지다. -### The Equality Operator +### Equality Operator -The equality operator consists of two equal signs: `==` +`==`가 equality operator이다. + +JavaScript는 weak typing을 따르기 때문에 equality operator가 비교할 때 두 객체의 자료형을 **강제로** 변환한다. -JavaScript features *weak typing*. This means that the equality operator -**coerces** types in order to compare them. - "" == "0" // false 0 == "" // true 0 == "0" // true @@ -19,20 +18,15 @@ JavaScript features *weak typing*. This means that the equality operator null == undefined // true " \t\r\n" == 0 // true -The above table shows the results of the type coercion, and it is the main reason -why the use of `==` is widely regarded as bad practice. It introduces -hard-to-track-down bugs due to its complicated conversion rules. +이 표는 왜 Equality Operator를 사용하면 안 되는지를 보여준다. 이 복잡한 변환 규칙은 실제로 골치 아픈 버그를 만들어 낸다. -Additionally, there is also a performance impact when type coercion is in play; -for example, a string has to be converted to a number before it can be compared -to another number. +게다가 강제로 타입을 변환하는 것은 성능 문제도 일으킨다. 예를 들어 스트링과 숫자를 비교하려면 반드시 숫자로 변환해야 한다. -### The Strict Equality Operator +### Strict Equality Operator -The strict equality operator consists of **three** equal signs: `===`. +Strict Equality Operator는 `===`이다. -It works exactly like the normal equality operator, except that strict equality -operator does **not** perform type coercion between its operands. +강제로 타입을 변환하지 않는 것을 제외하고는 Equality Operator와 똑같다. "" === "0" // false 0 === "" // false @@ -44,14 +38,11 @@ operator does **not** perform type coercion between its operands. null === undefined // false " \t\r\n" === 0 // false -The above results are a lot clearer and allow for early breakage of code. This -hardens code to a certain degree and also gives performance improvements in case -the operands are of different types. +이 결과가 훨씬 명확하고 문제를 빨리 발견할 수 있게 해준다. 이 Operator를 사용하면 코드가 좀 더 튼튼하고 비교하는 두 객체의 타입이 다르면 성능도 빠르다. -### Comparing Objects +### 객체 비교하기 -While both `==` and `===` are stated as **equality** operators, they behave -differently when at least one of their operands happens to be an `Object`. +`==`와 `===`는 둘 다 **Equality** Operator지만 비교하는 객체 중 적어도 한 개가 Object 타입일 때에는 다르게 동작한다. {} === {}; // false new String('foo') === 'foo'; // false @@ -59,13 +50,8 @@ differently when at least one of their operands happens to be an `Object`. var foo = {}; foo === foo; // true -Here, both operators compare for **identity** and **not** equality; that is, they -will compare for the same **instance** of the object, much like `is` in Python -and pointer comparison in C. - -### In Conclusion +두 Operator 모두 **같은 객체(identity)**인지 비교하는 것이지 객체의 값이 같은지 비교하는 것이 아니다. C에서 포인터를 비교하거나 Python의 is처럼 같은 인스턴스인지 비교하는 것이다. -It is highly recommended to only use the **strict equality** operator. In cases -where types need to be coerced, it should be done [explicitly](#types.casting) -and not left to the language's complicated coercion rules. +### 결론 +반드시 **Strict Equality Operator**를 사용해야 한다. 비교하기 위해서 꼭 타입 변환이 필요하면 언어의 복잡한 변환 규칙에 맡기지 말고 꼭 명시적으로 변환하고 나서 비교해야 한다. \ No newline at end of file diff --git a/doc/ko/types/instanceof.md b/doc/ko/types/instanceof.md index 84251128..560f4435 100644 --- a/doc/ko/types/instanceof.md +++ b/doc/ko/types/instanceof.md @@ -1,10 +1,8 @@ -## The `instanceof` Operator +## `instanceof` -The `instanceof` operator compares the constructors of its two operands. It is -only useful when comparing custom made objects. Used on built-in types, it is -nearly as useless as the [typeof operator](#types.typeof). +`instanceof`는 두 객체의 생성자를 비교하는 것이고 직접 만든 타입의 객체를 비교할 때 유용하다. 기본 타입만 생각하면 이 연산자는 [typeof](#types.typeof)처럼 거의 쓸모 없다. -### Comparing Custom Objects +### 직접 만든 타입의 객체를 `intanceof`로 비교하기 function Foo() {} function Bar() {} @@ -13,12 +11,12 @@ nearly as useless as the [typeof operator](#types.typeof). new Bar() instanceof Bar; // true new Bar() instanceof Foo; // true - // This just sets Bar.prototype to the function object Foo - // But not to an actual instance of Foo + // Bar.prototype에 function 객체인 Foo를 할당하면 + // Bar의 인스턴스는 Foo의 인스턴스가 아니다. Bar.prototype = Foo; new Bar() instanceof Foo; // false -### Using `instanceof` with Native Types +### 기본 타입 객체를 `intanceof`로 비교하기 new String('foo') instanceof String; // true new String('foo') instanceof Object; // true @@ -26,13 +24,8 @@ nearly as useless as the [typeof operator](#types.typeof). 'foo' instanceof String; // false 'foo' instanceof Object; // false -One important thing to note here is that `instanceof` does not work on objects -that originate from different JavaScript contexts (e.g. different documents -in a web browser), since their constructors will not be the exact same object. +JavaScript 컨텍스트마다(웹 브라우저의 도큐먼트 같은) 객체의 생성자는 다를 수밖에 없어서 `instanceof`는 다른 JavaScript 컨텍스트에 있는(웹 브라우저의 다른 도큐먼트에 있는) 객체와는 비교할 수 없다. -### In Conclusion - -The `instanceof` operator should **only** be used when dealing with custom made -objects that originate from the same JavaScript context. Just like the -[`typeof`](#types.typeof) operator, every other use of it should be **avoided**. +### 결론 +`instanceof`는 한 JavaScript 컨텍스트 내에서 사용자가 만든 타입의 객체를 비교할 때에만 유용하다. [`typeof`](#types.typeof)처럼 다른 목적으로는 사용하지 않는 것이 좋다. diff --git a/doc/ko/types/typeof.md b/doc/ko/types/typeof.md index 00377db4..aed2e210 100644 --- a/doc/ko/types/typeof.md +++ b/doc/ko/types/typeof.md @@ -1,19 +1,12 @@ -## The `typeof` Operator +## `typeof` -The `typeof` operator (together with -[`instanceof`](#types.instanceof)) is probably the biggest -design flaw of JavaScript, as it is near of being **completely broken**. +`typeof`도 [`instanceof`](#types.instanceof)와 함께 JavaScript에서 치명적으로 잘못 설계된 부분이다. 이건 정말 아무짝에 쓸모없다. -Although `instanceof` still has its limited uses, `typeof` really has only one -practical use case, which does **not** happen to be checking the type of an -object. +`instanceof`는 그래도 쓸 데가 좀 있었는데 `typeof`는 딱 한 군데에만 써먹을 수 있다. 객체의 타입을 검사할 일이 없다. -> **Note:** While `typeof` can also be called with a function like syntax -> i.e. `typeof(obj)`, this is not a function call. The two parenthesis will -> behave like normal and the return value will be used as the operand of the -> `typeof` operator. There is **no** `typeof` function. +> **Note:** `typeof`는 함수처럼 `typeof(obj)`로 사용할 수 있다. 하지만, 이것은 함수를 호출하는 것이 아니라 단순히 `()`안의 값이 반환되고 `typeof`가 적용되는 것이다. `typeof`라는 함수는 **없다**. -### The JavaScript Type Table +### JavaScript 타입 표 Value Class Type ------------------------------------- @@ -33,22 +26,17 @@ object. {} Object object new Object() Object object -In the above table, *Type* refers to the value that the `typeof` operator returns. -As can be clearly seen, this value is anything but consistent. +이 표에서 *Type*은 `typeof`가 반환하는 값이다. 표에서 본 것처럼 이 값은 계속 쓸모없다. -The *Class* refers to the value of the internal `[[Class]]` property of an object. +Class는 객체 내부에 있는 `[[Class]]` 프로퍼티의 값이다. -> **From the Specification:** The value of `[[Class]]` can be one of the -> following strings. `Arguments`, `Array`, `Boolean`, `Date`, `Error`, -> `Function`, `JSON`, `Math`, `Number`, `Object`, `RegExp`, `String`. +> **표준**에는 `[[Class]]`의 값은 `Arguments`, `Array`, `Boolean`, `Date`, `Error`, `Function`, `JSON`, `Math`, `Number`, `Object`, `RegExp`, `String`중 하나라고 나와있다. -In order to retrieve the value of `[[Class]]`, one has to make use of the -`toString` method of `Object.prototype`. +`[[Class]]`의 값을 가져다 쓰려면 `Object.prototype`의 `toString` 메소드를 사용해야 한다. -### The Class of an Object +### 객체의 클래스 -The specification gives exactly one way of accessing the `[[Class]]` value, -with the use of `Object.prototype.toString`. +표준에 의하면 `[[Class]]` 값을 얻는 방법은 `Object.prototype.toString`하나뿐이다. function is(type, obj) { var clas = Object.prototype.toString.call(obj).slice(8, -1); @@ -58,30 +46,18 @@ with the use of `Object.prototype.toString`. is('String', 'test'); // true is('String', new String('test')); // true -In the above example, `Object.prototype.toString` gets called with the value of -[this](#function.this) being set to the object whose `[[Class]]` value should be -retrieved. +`Object.prototype.toString`은 [this](#function.this)의 `[[Class]]` 값을 가져오는 것이니까 this를 obj로 바꾸어 사용한다. -> **ES5 Note:** For convenience the return value of `Object.prototype.toString` -> for both `null` and `undefined` was **changed** from `Object` to `Null` and -> `Undefined` in ECMAScript 5. +> **ES5 Note:** ECMAScript 5에서 `Object.prototype.toString`의 컨텍스트가 `null`과 `undefined`일 때 `Object`가 아니라 각각 `Null`과 `Undefined`를 반환하도록 수정됐다. -### Testing for Undefined Variables +### 변수가 Undefined인지 확인하기 typeof foo !== 'undefined' -The above will check whether `foo` was actually declared or not; just -referencing it would result in a `ReferenceError`. This is the only thing -`typeof` is actually useful for. +이것은 `foo`가 정의됐는지 아닌지를 확인해준다. 정의되지 않은 변수에 접근하면 `ReferenceError` 나는데 이것을 방지할 수 있다. `typeof`가 유용한 건 이때뿐이다. ### In Conclusion -In order to check the type of an object, it is highly recommended to use -`Object.prototype.toString` because this is the only reliable way of doing so. -As shown in the above type table, some return values of `typeof` are not defined -in the specification; thus, they can differ across various implementations. - -Unless checking whether a variable is defined, `typeof` should be avoided at -**all costs**. - +객체의 타입을 검사하려면 `Object.prototype.toString`를 사용해야 한다. 다른 방법은 신뢰할 수 없다. 위 표에서 보여준 것처럼 typeof가 반환하는 값은 표준에 나와 있지 않기 때문에 구현마다 다르다. +변수가 정의됐는지 확인할 때는 빼고 **목숨을 걸고** `typeof`를 못 사용하게 해야 한다. From 97794ccad8b5e0ff1670fbbdfcea7376daa3b5da Mon Sep 17 00:00:00 2001 From: Changwoo Park Date: Wed, 26 Oct 2011 02:26:45 +0900 Subject: [PATCH 159/463] [ko] typing correction. --- doc/ko/core/delete.md | 8 ++++---- doc/ko/core/eval.md | 4 ++-- doc/ko/core/undefined.md | 4 ++-- doc/ko/function/closures.md | 4 ++-- doc/ko/function/general.md | 9 +++++---- doc/ko/function/scopes.md | 6 +++--- doc/ko/function/this.md | 4 ++-- doc/ko/other/timeouts.md | 6 +++--- 8 files changed, 23 insertions(+), 22 deletions(-) diff --git a/doc/ko/core/delete.md b/doc/ko/core/delete.md index eefa5b5b..0effdd10 100644 --- a/doc/ko/core/delete.md +++ b/doc/ko/core/delete.md @@ -2,11 +2,11 @@ 간단히 말해서 global 변수, 함수, 등은 `DontDelete` 속성이기 때문에 삭제 못 한다. -### 글로벌 코드와 함수 코드 +### Global 코드와 함수 코드 Global이나 Function scope에 정의된 함수나 변수는 모두 Activation 객체나 Global 객체의 프로퍼티다. 이 프로퍼티는 모두 `DontDelete`속성을 가진다. Global이나 Function 코드에서 변수나 함수의 정의하면 항상 `DontDelete` 프로퍼티로 만들어진다. 그러니까 삭제할 수 없다: - // 글로벌 변수: + // Global 변수: var a = 1; // DontDelete가 설정된다. delete a; // false a; // 1 @@ -38,11 +38,11 @@ Global이나 Function scope에 정의된 함수나 변수는 모두 Activation // IE를 빼고 잘 동작한다.: var GLOBAL_OBJECT = this; GLOBAL_OBJECT.a = 1; - a === GLOBAL_OBJECT.a; // true - 진짜 글로벌 변순지 확인하는 것 + a === GLOBAL_OBJECT.a; // true - 진짜 Global 변순지 확인하는 것 delete GLOBAL_OBJECT.a; // true GLOBAL_OBJECT.a; // undefined -[`this`](#function.this)가 글로벌 객체를 가리키는 것을 이용해서 명시적으로 프로퍼티 `a`를 선언하면 삭제할 수 있다. 이런 꼼수가 가능하다. +[`this`](#function.this)가 Global 객체를 가리키는 것을 이용해서 명시적으로 프로퍼티 `a`를 선언하면 삭제할 수 있다. 이런 꼼수가 가능하다. IE (적어도 6-8)는 버그가 있어서 안 된다. diff --git a/doc/ko/core/eval.md b/doc/ko/core/eval.md index 9e5cf1b8..f366401c 100644 --- a/doc/ko/core/eval.md +++ b/doc/ko/core/eval.md @@ -1,6 +1,6 @@ ## 왜 `eval`을 사용하면 안 될까? -`eval` 함수는 스트링으로 된 JavaScript 코드를 로컬 스콥에서 실행한다. +`eval` 함수는 스트링으로 된 JavaScript 코드를 Local Scope에서 실행한다. var foo = 1; function test() { @@ -11,7 +11,7 @@ test(); // 3 foo; // 1 -`eval`을 `eval`이라는 이름으로 **직접** 직행할 때에만 로컬 스콥에서 실행된다. +`eval`을 `eval`이라는 이름으로 **직접** 직행할 때에만 Local Scope에서 실행된다. var foo = 1; function test() { diff --git a/doc/ko/core/undefined.md b/doc/ko/core/undefined.md index 7f4c9c05..c66078ad 100644 --- a/doc/ko/core/undefined.md +++ b/doc/ko/core/undefined.md @@ -6,7 +6,7 @@ JavaScript는 `nothing`을 두 가지로 표현할 수 있고 그중 `undefined` `undefined`는 `undefined`라는 값을 가지는 데이터 형식이다. -`undefined`는 상수도 아니고 JavaScript의 키워드도 아니다. 그냥 `undefined`라는 이름의 글로벌 변수이고 이 변수에는 `undefined`라고 할당돼 있다. 그래서 이 글로벌 변수의 값을 쉽게 바꿀 수 있다. +`undefined`는 상수도 아니고 JavaScript의 키워드도 아니다. 그냥 `undefined`라는 이름의 Global 변수이고 이 변수에는 `undefined`라고 할당돼 있다. 그래서 이 Global 변수의 값을 쉽게 바꿀 수 있다. > **ES5 Note:** ECMAScript 5의 strict 모드에서는 `undefined`를 더는 바꿀 수 없도록 했다. 하지만 `undefined`라는 함수를 만들면 여전히 할당할 수 있다. @@ -29,7 +29,7 @@ global 변수 `undefined`는 `undefined`라는 객체를 가리키는 것뿐이 var undefined = 123; (function(something, foo, undefined) { - // 로컬 스콥에 undefined를 만들어서 + // Local Scope에 undefined를 만들어서 // 원래 값을 가리키도록 했다. })('Hello World', 42); diff --git a/doc/ko/function/closures.md b/doc/ko/function/closures.md index 24dcf25e..c9b7e989 100644 --- a/doc/ko/function/closures.md +++ b/doc/ko/function/closures.md @@ -1,6 +1,6 @@ ## Closure와 Reference -JavaScript가 두드러지는 점 중의 하나가 *Closure*를 사용할 수 있다는 것이다. Closure는 항상 그 Closure를 만든 외부 Scope에 접근할 수 있다. JavaScript에서 Scope을 만들려면 [function Scope](#function.Scopes)을 사용하는 방법뿐이기 때문에 기본적으로 모든 함수는 Closure다. +JavaScript가 두드러지는 점 중의 하나가 *Closure*를 사용할 수 있다는 것이다. Closure는 항상 그 Closure를 만든 외부 Scope에 접근할 수 있다. JavaScript에서 Scope을 만들려면 [function Scope](#function.scopes)을 사용하는 방법뿐이기 때문에 기본적으로 모든 함수는 Closure다. ### private 변수 @@ -52,7 +52,7 @@ JavaScript에서 Scope을 어딘가에 할당하거나 저장해두는 것이 ### 이 Reference 문제 해결하기 -[anonymous wrapper](#function.Scopes)로 index 값을 복사하는 것이 좋다. +[anonymous wrapper](#function.scopes)로 index 값을 복사하는 것이 좋다. for(var i = 0; i < 10; i++) { (function(e) { diff --git a/doc/ko/function/general.md b/doc/ko/function/general.md index 8786f7fc..54401b08 100644 --- a/doc/ko/function/general.md +++ b/doc/ko/function/general.md @@ -1,12 +1,12 @@ ## Function Declarations and Expressions -JavaScript의 function은 first class object라서 일반 객체처럼 취급될 수 있다. 그래서 익명 함수를 비동기 함수의 callback 같은 거로 넘길 수 있다. +JavaScript의 Function은 first class object라서 일반 객체처럼 취급될 수 있다. 그래서 익명 함수를 비동기 함수의 callback 같은 거로 넘길 수 있다. ### `function` Declaration function foo() {} -코드를 실행하기 전에 이 함수 [hoist](#function.Scopes)되기 때문에 해당 Scope 어디에서나 이 함수를 호출할 수 있다. 심지어 함수를 정의하기 전에 호출해도 된다. +코드를 실행하기 전에 이 함수 [hoist](#function.scopes)되기 때문에 해당 Scope 어디에서나 이 함수를 호출할 수 있다. 심지어 함수를 정의하기 전에 호출해도 된다. foo(); // 이 코드가 실행되기 전에 foo가 만들어져서 잘 호출된다. function foo() {} @@ -27,11 +27,12 @@ JavaScript가 hoist하는 것은 `var`로 선언하는 부분뿐이기 때문에 ### Named Function Expression -named function을 할당하는 경우는 조금 특이하다. +Named Function을 할당하는 경우는 조금 특이하다. var foo = function bar() { bar(); // 된다. } bar(); // ReferenceError -function 밖에서 `bar`를 사용할 수 없지만, function 안에서는 사용할 수 있다. JavaScript가 [이름을 찾는 방법](#function.Scopes)이 있는데 function Scope에서는 항상 그 함수의 이름을 사용할 수 있다. +함수 밖에서 `bar`를 사용할 수 없지만, 함수 안에서는 사용할 수 있다. JavaScript가 [이름을 찾는 방법](#function.scopes)이 있는데 function Scope에서는 항상 그 함수의 이름을 사용할 수 있다. + diff --git a/doc/ko/function/scopes.md b/doc/ko/function/scopes.md index f957359d..c72c49c5 100644 --- a/doc/ko/function/scopes.md +++ b/doc/ko/function/scopes.md @@ -53,9 +53,9 @@ JavaScript는 '{}' Block이 배배 꼬여 있어도 문법적으로는 잘 처 subLoop이 Global 변수 `i`의 값을 변경해버리기 때문에 외부 Loop은 `subLoop`을 한번 호출하고 나면 종료된다. 두 번째 `for` Loop에 `var`를 사용하여 `i`를 정의하면 이 문제는 생기지 않는다. 외부 Scope의 변수를 사용하는 것이 아니라면 `var`를 꼭 넣어야 한다. -### 로컬 변수 +### Local 변수 -JavaScript에서 로컬 변수를 정의하는 방법은 [함수 파라미터](#function.general)와 `var`로 정의한 변수뿐이다. +JavaScript에서 Local 변수를 정의하는 방법은 [함수 파라미터](#function.general)와 `var`로 정의한 변수뿐이다. // Global Scope var foo = 1; @@ -71,7 +71,7 @@ JavaScript에서 로컬 변수를 정의하는 방법은 [함수 파라미터](# } test(10); -`foo`, `i`는 `test` Function Scope에 있는 로컬 변수라서 Global의 `foo`, `i` 값은 바뀌지 않는다. 하지만 `bar`는 Global 변수이기 때문에 Global의 `bar` 값이 변경된다. +`foo`, `i`는 `test` Function Scope에 있는 Local 변수라서 Global의 `foo`, `i` 값은 바뀌지 않는다. 하지만 `bar`는 Global 변수이기 때문에 Global의 `bar` 값이 변경된다. ### Hoisting diff --git a/doc/ko/function/this.md b/doc/ko/function/this.md index 37a6a801..ddc18692 100644 --- a/doc/ko/function/this.md +++ b/doc/ko/function/this.md @@ -6,7 +6,7 @@ this; -Global scope에서도 this가 사용될 수 있고 이때에는 *Global* 객체를 가리킨다. +Global Scope에서도 this가 사용될 수 있고 이때에는 *Global* 객체를 가리킨다. ### 함수를 호출할 때 @@ -55,7 +55,7 @@ Global scope에서도 this가 사용될 수 있고 이때에는 *Global* 객체 `test` 에서 `this`가 `Foo`를 가리킬 것으로 생각할 테지만 틀렸다. 실제로는 그렇지 않다. -`test`에서 `Foo`에 접근하려면 method에 로컬 변수를 하나 만들고 `Foo`를 가리키게 하여야 한다. +`test`에서 `Foo`에 접근하려면 method에 Local 변수를 하나 만들고 `Foo`를 가리키게 하여야 한다. Foo.method = function() { var that = this; diff --git a/doc/ko/other/timeouts.md b/doc/ko/other/timeouts.md index 582a77f9..e2d627a9 100644 --- a/doc/ko/other/timeouts.md +++ b/doc/ko/other/timeouts.md @@ -11,12 +11,12 @@ JavaScript는 비동기이기 때문에 `setTimeout`과 `setInterval` 로 함수 JavaScript 엔진의 단위 시간(timer resolution)에 따라서 코드를 실행시키고 단일 쓰레드인 JavaScript를 특정 코드가 블록 시켜 버릴 수도 있기 때문에 `setTimeout`으로 코드가 실행돼야 할 시간을 정해줘도 **정확하게 그 시간에 실행되지 않는다.**. -첫 번째 인자로 넘긴 함수가 실행될 때 컨텍스트인 [`this`](#function.this)는 *글로벌* 객체를 가리킨다. +첫 번째 인자로 넘긴 함수가 실행될 때 컨텍스트인 [`this`](#function.this)는 *Global* 객체를 가리킨다. function Foo() { this.value = 42; this.method = function() { - // this는 global 객체를 가리키기 때문에 + // this는 Global 객체를 가리키기 때문에 console.log(this.value); // undefined를 출력한다. }; setTimeout(this.method, 500); @@ -88,7 +88,7 @@ Id가 1부터 1000 사이에 있는 timeout들을 삭제했지만, 그 외의 } bar(); -이 경우 `eval`이 [그냥(directly)](#core.eval) 호출되는 것이 아니다. `setTimeout`에 넘겨진 스트링은 *global* scope에서 실행되기 때문에 `bar`의 로컬 함수 `foo`가 실행되는 것이 아니라 *global* scope의 `foo`가 실행된다. +이 경우 `eval`이 [그냥(directly)](#core.eval) 호출되는 것이 아니다. `setTimeout`에 넘겨진 스트링은 *Global* Scope에서 실행되기 때문에 `bar`의 Local 함수 `foo`가 실행되는 것이 아니라 *Global* Scope의 `foo`가 실행된다. 함수에 파라미터를 넘겨야 하면 스트링을 사용하지 말아야 한다. From f400e6265cdfb4f74fc3c669f711095fa3e59cc0 Mon Sep 17 00:00:00 2001 From: Changwoo Park Date: Wed, 26 Oct 2011 02:39:35 +0900 Subject: [PATCH 160/463] [ko] add translator info --- doc/ko/intro/index.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/doc/ko/intro/index.md b/doc/ko/intro/index.md index dd885f40..2f04336b 100644 --- a/doc/ko/intro/index.md +++ b/doc/ko/intro/index.md @@ -13,6 +13,11 @@ JavaScript Garden은 단순히 JavaScript를 설명하려 만들지 않았다. - [Caio Romão][5] (철자 교정) - [Andreas Blixt][6] (언어 교정) +## 번역 + - [박창우][] + +[박창우]: https://github.com/pismute + ## 호스팅 JavaScript Garden은 Github에서 호스팅하고 있고 [Cramer Development][7]가 [JavaScriptGarden.info][8]에서 미러링해주고 있다. @@ -32,4 +37,4 @@ JavaScript Garden은 [MIT license][9]를 따르고 [GitHub][10]에서 호스팅 [9]: https://github.com/BonsaiDen/JavaScript-Garden/blob/next/LICENSE [10]: https://github.com/BonsaiDen/JavaScript-Garden [11]: https://github.com/BonsaiDen/JavaScript-Garden/issues -[12]: http://chat.stackoverflow.com/rooms/17/javascript \ No newline at end of file +[12]: http://chat.stackoverflow.com/rooms/17/javascript From 39f0b9f1fe5a810b0bd2574b5bf06741d40a4143 Mon Sep 17 00:00:00 2001 From: Changwoo Park Date: Wed, 26 Oct 2011 02:52:50 +0900 Subject: [PATCH 161/463] [ko] translate index --- doc/ko/index.json | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/doc/ko/index.json b/doc/ko/index.json index bffcbf2c..3e3930a1 100644 --- a/doc/ko/index.json +++ b/doc/ko/index.json @@ -1,15 +1,15 @@ { "title": "JavaScript Garden", - "langTitle": "JavaScript Garden in English", + "langTitle": "JavaScript Garden", "description": "A Guide to JavaScript's Quirks and Flaws.", "sections": [ { - "title": "Intro", + "title": "소개", "dir": "intro", "articles": [] }, { - "title": "Objects", + "title": "객체", "dir": "object", "articles": [ "general", @@ -19,7 +19,7 @@ ] }, { - "title": "Functions", + "title": "함수", "dir": "function", "articles": [ "general", @@ -31,7 +31,7 @@ ] }, { - "title": "Arrays", + "title": "Array", "dir": "array", "articles": [ "general", @@ -39,7 +39,7 @@ ] }, { - "title": "Types", + "title": "타입", "dir": "types", "articles": [ "equality", @@ -49,7 +49,7 @@ ] }, { - "title": "Core", + "title": "핵심", "dir": "core", "articles": [ "eval", @@ -59,7 +59,7 @@ ] }, { - "title": "Other", + "title": "기타", "dir": "other", "articles": [ "timeouts" From e9bfa4e48a4d90a8f0c9da93a69b9a822cbf0a56 Mon Sep 17 00:00:00 2001 From: HIRAKI Satoru Date: Mon, 31 Oct 2011 23:14:16 +0900 Subject: [PATCH 162/463] translate "Stacking Calls with `setInterval`" in "Ohters" to ja --- doc/ja/other/timeouts.md | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/doc/ja/other/timeouts.md b/doc/ja/other/timeouts.md index 9c80c28d..2399c476 100644 --- a/doc/ja/other/timeouts.md +++ b/doc/ja/other/timeouts.md @@ -31,26 +31,20 @@ JavaScriptは非同期なので、`setTimeout`と`setInterval`関数を使って > 関数が`undefined`になる為に表に出ないエラーになるでしょう。`setTimeout`はどんな > エラーも発生`させません`。 -### Stacking Calls with `setInterval` +### `setInterval`でスタッキングコール -While `setTimeout` only runs the function once, `setInterval` - as the name -suggests - will execute the function **every** `X` milliseconds. But its use is -discouraged. +`setTimeout`は関数を一度だけ実行します。`setInterval` - 名前が示すように - **毎回**`X`ミリ秒毎に関数を実行しますが、この使用は推奨されていません。 -When code that is being executed blocks the timeout call, `setInterval` will -still issue more calls to the specified function. This can, especially with small -intervals, result in function calls stacking up. +コードがタイムアウト呼び出しブロックで実行される時に、`setInterval`は指定された関数を呼び出します。これは、特に小さい間隔で、関数の結果をスタックに積む事ができます。 function foo(){ - // something that blocks for 1 second + // 1秒おきにブロックの何かを実行 } setInterval(foo, 100); -In the above code `foo` will get called once and will then block for one second. +上記のコードでは、`foo`が1回呼び出されて、1秒ブロックされます。 -While `foo` blocks the code `setInterval` will still schedule further calls to -it. Now, when `foo` has finished, there will already be **ten** further calls to -it waiting for execution. +`foo`がコードをブロックしている間、`setInterval`は呼び出される予定を確保しています。`foo`が完了した瞬間に、実行を待っている間に**10回**以上呼び出されている事になります。 ### Dealing with Possible Blocking Code From 80a65ff046d014648b93cb166c7c00590f92650b Mon Sep 17 00:00:00 2001 From: HIRAKI Satoru Date: Tue, 8 Nov 2011 02:08:39 +0900 Subject: [PATCH 163/463] translate "Dealing with Possible Blocking Code" in "Others" to ja --- doc/ja/other/timeouts.md | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/doc/ja/other/timeouts.md b/doc/ja/other/timeouts.md index 2399c476..2eceefeb 100644 --- a/doc/ja/other/timeouts.md +++ b/doc/ja/other/timeouts.md @@ -46,20 +46,17 @@ JavaScriptは非同期なので、`setTimeout`と`setInterval`関数を使って `foo`がコードをブロックしている間、`setInterval`は呼び出される予定を確保しています。`foo`が完了した瞬間に、実行を待っている間に**10回**以上呼び出されている事になります。 -### Dealing with Possible Blocking Code +### ブロッキング可能なコードの取り扱い -The easiest as well as most controllable solution, is to use `setTimeout` within -the function itself. +簡単かつ、一番コントロール可能な解決法として、関数自体の中で`setTimeout`を使うという方法があります。 function foo(){ - // something that blocks for 1 second + // 1秒ブロックする何か setTimeout(foo, 100); } foo(); -Not only does this encapsulate the `setTimeout` call, but it also prevents the -stacking of calls and it gives additional control.`foo` itself can now decide -whether it wants to run again or not. +このカプセル化は`setTimeout`の呼び出しだけでなく、呼び出しのスタッキングを防止してより詳細なコントロールが出来ます。`foo`それ自身が今や、再度実行するかしないかを決める事が出来るのです。 ### Manually Clearing Timeouts From bcb31de1ae2919eb22524059139859e54afda2a3 Mon Sep 17 00:00:00 2001 From: HIRAKI Satoru Date: Tue, 8 Nov 2011 02:14:10 +0900 Subject: [PATCH 164/463] translate "Manually Clearing Timeouts" in "Others" to ja --- doc/ja/other/timeouts.md | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/doc/ja/other/timeouts.md b/doc/ja/other/timeouts.md index 2eceefeb..5ca1c6b7 100644 --- a/doc/ja/other/timeouts.md +++ b/doc/ja/other/timeouts.md @@ -58,11 +58,9 @@ JavaScriptは非同期なので、`setTimeout`と`setInterval`関数を使って このカプセル化は`setTimeout`の呼び出しだけでなく、呼び出しのスタッキングを防止してより詳細なコントロールが出来ます。`foo`それ自身が今や、再度実行するかしないかを決める事が出来るのです。 -### Manually Clearing Timeouts +### 手動でタイムアウトをクリアする -Clearing timeouts and intervals works by passing the respective ID to -`clearTimeout` or `clearInterval`, depending which `set` function was used in -the first place. +タイムアウトとインターバルのクリアは、`clearTimeout`か`clearInterval`に個別のIDを渡せば出来ます。最初に`set`関数を使った場所に依存します。 var id = setTimeout(foo, 1000); clearTimeout(id); From b0540700d7b1b6861edccf508e4c4ff378b213ee Mon Sep 17 00:00:00 2001 From: HIRAKI Satoru Date: Sun, 13 Nov 2011 19:43:34 +0900 Subject: [PATCH 165/463] translate "Clearing all timeouts" in "Others" to ja --- doc/ja/other/timeouts.md | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/doc/ja/other/timeouts.md b/doc/ja/other/timeouts.md index 5ca1c6b7..94b8e3ac 100644 --- a/doc/ja/other/timeouts.md +++ b/doc/ja/other/timeouts.md @@ -65,19 +65,16 @@ JavaScriptは非同期なので、`setTimeout`と`setInterval`関数を使って var id = setTimeout(foo, 1000); clearTimeout(id); -### Clearing all timeouts +### 全てのタイムアウトをクリアする -As there is no built-in method for clearing all timeouts and/or intervals, -it is necessary to use brute force in order to achieve this functionality. +全てのタイムアウトや、インターバルをクリアする組み込みメソッドが無い為、機能的にクリアする為には暴力的な手段を使う必要があります。 - // clear "all" timeouts + // "全ての"タイムアウトをクリアする for(var i = 1; i < 1000; i++) { clearTimeout(i); } -There might still be timeouts that are unaffected by this arbitrary number; -therefore, is is instead recommended to keep track of all the timeout IDs, so -they can be cleared specifically. +ここまでもまだ、任意の数字を与えられた為に影響を受けないタイムアウトがあるかもしれません。しかし、全てのタイムアウトのIDを追跡していく事は推奨されないので、それらは個別にクリアされます。 ### Hidden use of `eval` From 85957bc61751f8171d8af55c5992ae6659d40613 Mon Sep 17 00:00:00 2001 From: HIRAKI Satoru Date: Sun, 13 Nov 2011 20:01:32 +0900 Subject: [PATCH 166/463] translate "Hidden use of `eval`" in "Others" to ja --- doc/ja/other/timeouts.md | 34 +++++++++++++++------------------- 1 file changed, 15 insertions(+), 19 deletions(-) diff --git a/doc/ja/other/timeouts.md b/doc/ja/other/timeouts.md index 94b8e3ac..1bdf8064 100644 --- a/doc/ja/other/timeouts.md +++ b/doc/ja/other/timeouts.md @@ -76,48 +76,44 @@ JavaScriptは非同期なので、`setTimeout`と`setInterval`関数を使って ここまでもまだ、任意の数字を与えられた為に影響を受けないタイムアウトがあるかもしれません。しかし、全てのタイムアウトのIDを追跡していく事は推奨されないので、それらは個別にクリアされます。 -### Hidden use of `eval` +### 隠された`eval`の使用 -`setTimeout` and `setInterval` can also take a string as their first parameter. -This feature should **never** be used, since it internally makes use of `eval`. +`setTimeout`と`setInterval` は、第一引数に文字列を取る事が可能です。この仕様は内部で`eval`を使用する為に、**絶対に**使うべきではありません。 -> **Note:** Since the timeout functions are **not** specified by the ECMAScript -> standard, the exact workings when a string is passed to them might differ in -> various JavaScript implementations. For example, Microsoft's JScript makes use of -> the `Function` constructor in place of `eval`. +> **注意点:** タイムアウト関数はECMAScript標準では制定されて**いない**為に +> 文字列を引数にした場合に厳密な動作は色々なJavaScript実装により異なります。 +> 例えば、MicrosoftのJScriptは`eval`の代わりに`Function`コンストラクターを +> 使用します。 function foo() { - // will get called + // この先呼ばれる } function bar() { function foo() { - // never gets called + // 絶対に呼ばれない } setTimeout('foo()', 1000); } bar(); -Since `eval` is not getting called [directly](#core.eval) in this case, the string -passed to `setTimeout` will get executed in the *global scope*; thus, it will -not use the local variable `foo` from the scope of `bar`. +この場合、`eval`は[直接](#core.eval)呼ばれないので、文字列が渡された`setTimeout`は*global scope*で実行されます。よって、`bar`のスコープから`foo`のローカル変数は使われないのです。 -It is further recommended to **not** use a string for passing arguments to the -function that will get called by either of the timeout functions. +さらに、文字列を関数に渡さ**ない**ように推奨される理由として、それぞれのタイムアウト関数から呼び出されるという事があります。 function foo(a, b, c) {} - // NEVER use this + // 絶対にこのように使わない setTimeout('foo(1,2, 3)', 1000) - // Instead use an anonymous function + // 匿名関数を代わりに使用する setTimeout(function() { foo(a, b, c); }, 1000) -> **Note:** While it is also possible to use the syntax -> `setTimeout(foo, 1000, a, b, c)`, it is not recommended, as its use may lead -> to subtle errors when used with [methods](#function.this). +> **注意点:** `setTimeout(foo, 1000, a, b, c)`のようなシンタックスを使用する事も +> できますが、[メソッド](#function.this)を使用した際に、分かりにくいエラーが起りえるので +> 使用はお勧めしません。 ### In Conclusion From fd79e45e77be93f8ab79a7f311cd29ee6296979c Mon Sep 17 00:00:00 2001 From: HIRAKI Satoru Date: Sun, 13 Nov 2011 20:07:21 +0900 Subject: [PATCH 167/463] translate "In Conclusion" in "Others" to ja --- doc/ja/other/timeouts.md | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/doc/ja/other/timeouts.md b/doc/ja/other/timeouts.md index 1bdf8064..c1875b4f 100644 --- a/doc/ja/other/timeouts.md +++ b/doc/ja/other/timeouts.md @@ -115,15 +115,11 @@ JavaScriptは非同期なので、`setTimeout`と`setInterval`関数を使って > できますが、[メソッド](#function.this)を使用した際に、分かりにくいエラーが起りえるので > 使用はお勧めしません。 -### In Conclusion +### 終りに -**Never** should a string be used as the parameter of `setTimeout` or -`setInterval`. It is a clear sign of **really** bad code, when arguments need -to be supplied to the function that gets called. An *anonymous function* should -be passed that then takes care of the actual call. +`setTimeout`や`setInterval`のパラメーターに文字列を使用する事は**絶対**するべきではありません。引数が関数に呼び出される必要がある場合**本当**に悪いコードの明確なサインになります。実際の呼び出しには*匿名関数*を渡すべきです。 -Further, the use of `setInterval` should be avoided since its scheduler is not -blocked by executing JavaScript. +その上で、`setInterval`の使用はそのスケジューラーがJavaScriptの実行をブロックするので避けるべきでしょう。 [1]: http://en.wikipedia.org/wiki/Document_Object_Model "Document Object Model" From 22b5551d40d3347d70e74b70394ddc4a3b1f0b02 Mon Sep 17 00:00:00 2001 From: HIRAKI Satoru Date: Tue, 15 Nov 2011 03:27:40 +0900 Subject: [PATCH 168/463] fix translate in "this" --- doc/ja/function/this.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/ja/function/this.md b/doc/ja/function/this.md index 424760d9..4e6e27aa 100644 --- a/doc/ja/function/this.md +++ b/doc/ja/function/this.md @@ -16,7 +16,7 @@ JavaScriptの`this`と名付けられた特殊なキーワードは他のプロ この`this`は、再度*グローバル*オブジェクトを参照しています。 > **ES5での注意:** strictモードでは、このグローバルのケースは**もはや**存在していません。 -> この場合`this`の代わりに`undefined`値を持つことになります。 +> この場合`this`は`undefined`値を代わりに持つことになります。 ### メソッド呼び出しとして @@ -48,7 +48,7 @@ JavaScriptの`this`と名付けられた特殊なキーワードは他のプロ ### 良くある落し穴 -これらほとんどのケースで見てきたように、最初のケースでは**絶対に**実用化できないという言語設計のミスを考慮しないとなりません。 +これらのケースのほとんどは理にかなったものですが、最初のケースは実際に利用されることが**絶対**にないので、間違った言語設計だとみなせるでしょう。 Foo.method = function() { function test() { @@ -78,7 +78,7 @@ JavaScriptを使用する上で、もう一つ動か**ない**ものが関数の var test = someObject.methodTest; test(); -最初のケースの`test`は通常の関数呼び出しになる為に、この中の`this`は、最早`someobject`を参照できなくなってしまいます。 +最初のケースの`test`は通常の関数呼び出しになる為に、この中の`this`は、もはや`someobject`を参照できなくなってしまいます。 `this`の遅延バインディングは最初見た時にはダメなアイデアに見えますが、[プロトタイプ継承](#object.prototype)により、きちんと動作します。 From b897c747252c7178e9a49c554cfcc8cdd2cb519c Mon Sep 17 00:00:00 2001 From: ZhangYiJiang Date: Fri, 18 Nov 2011 17:09:45 +0800 Subject: [PATCH 169/463] Updated .gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index ff4e6c39..7aa6a9ed 100644 --- a/.gitignore +++ b/.gitignore @@ -10,6 +10,7 @@ /site/fi /site/pl /site/tr +/site/ko /site/ja *.md~ *.src.md From fd1069797a428328f8984fc31a06a31d57d28ba7 Mon Sep 17 00:00:00 2001 From: ZhangYiJiang Date: Fri, 18 Nov 2011 17:23:25 +0800 Subject: [PATCH 170/463] Updated CSS to accomodate more languages --- site/style/garden.css | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/site/style/garden.css b/site/style/garden.css index d6843ce2..402ca551 100644 --- a/site/style/garden.css +++ b/site/style/garden.css @@ -87,8 +87,9 @@ nav > div li { } nav > div li a, #top, #hide_menu { - padding: 7px 10px 9px 10px; + padding: 8px 6px 7px; cursor: pointer; + font-size: 12px; } nav > div li.active a { From cfcee4614eb5e6acf07e062d50fe1182798caa29 Mon Sep 17 00:00:00 2001 From: HIRAKI Satoru Date: Tue, 22 Nov 2011 01:48:40 +0900 Subject: [PATCH 171/463] fix translate in "Clousures and References" --- doc/ja/function/closures.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/ja/function/closures.md b/doc/ja/function/closures.md index 618af73f..809f906d 100644 --- a/doc/ja/function/closures.md +++ b/doc/ja/function/closures.md @@ -1,6 +1,6 @@ ## クロージャと参照 -JavaScriptの一番パワフルな特徴の一つとして*クロージャ*が使える事が挙げられます。これはスコープが**いつも**外部に定義されたスコープにアクセスできるという事です。JavaScriptの唯一のスコープは[関数スコープ](#function.scopes)ですが、全ての関数は標準でクロージャとして振る舞います。 +JavaScriptの一番パワフルな特徴の一つとして*クロージャ*が使える事が挙げられます。これはスコープが自身の定義されている外側のスコープに**いつでも**アクセスできるという事です。JavaScriptの唯一のスコープは[関数スコープ](#function.scopes)ですが、全ての関数は標準でクロージャとして振る舞います。 ### プライベート変数をエミュレートする From f14a45621a017e69a88fcb4f6c698e9d7265685e Mon Sep 17 00:00:00 2001 From: HIRAKI Satoru Date: Tue, 22 Nov 2011 01:57:24 +0900 Subject: [PATCH 172/463] fix translate in "Avoiding the Reference Problem" --- doc/ja/function/closures.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/ja/function/closures.md b/doc/ja/function/closures.md index 809f906d..ed06014b 100644 --- a/doc/ja/function/closures.md +++ b/doc/ja/function/closures.md @@ -66,7 +66,7 @@ JavaScriptでは、スコープ自体を参照・代入する事が出来無い `e`を参照している`setTimeout`を受け取った匿名関数はループによって値が変わる事が**ありません**。 -他にこのような事を実現する方法があります。それは匿名ラッパーから関数を返してあげる事です。これは上記のコードと同じような効果があります。 +他にこのような事を実現する方法があります。それは匿名ラッパーから関数を返してあげる事です。これは上記のコードと同じ振る舞いをします。 for(var i = 0; i < 10; i++) { setTimeout((function(e) { From 9f67e37d9b4fb5d2d84f4808fe960e92323cac52 Mon Sep 17 00:00:00 2001 From: HIRAKI Satoru Date: Tue, 22 Nov 2011 02:03:42 +0900 Subject: [PATCH 173/463] fix strong range --- doc/ja/function/closures.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/ja/function/closures.md b/doc/ja/function/closures.md index ed06014b..b17f6eb3 100644 --- a/doc/ja/function/closures.md +++ b/doc/ja/function/closures.md @@ -64,7 +64,7 @@ JavaScriptでは、スコープ自体を参照・代入する事が出来無い 外部の匿名関数は`i`を即座に第一引数として呼び出し、引数`e`を`i`の**値**のコピーとして受け取ります。 -`e`を参照している`setTimeout`を受け取った匿名関数はループによって値が変わる事が**ありません**。 +`e`を参照している`setTimeout`を受け取った匿名関数はループによって値が変わる事が**ありません。** 他にこのような事を実現する方法があります。それは匿名ラッパーから関数を返してあげる事です。これは上記のコードと同じ振る舞いをします。 From 3e1802b5448a1bcd22fbe03597a0bc7d532808e2 Mon Sep 17 00:00:00 2001 From: HIRAKI Satoru Date: Tue, 22 Nov 2011 02:28:57 +0900 Subject: [PATCH 174/463] fix translate "Constructors" --- doc/ja/function/constructors.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/doc/ja/function/constructors.md b/doc/ja/function/constructors.md index 99290411..4d0728a1 100644 --- a/doc/ja/function/constructors.md +++ b/doc/ja/function/constructors.md @@ -18,7 +18,7 @@ JavaScriptのコンストラクタは色々ある他のプログラム言語と 上記で`Foo`はコンストラクタとして呼び出され、`Foo.prototype`として新規に生成された`prototype`を設定されています。 -明示的に`return`ステートメントがある場合、`Object`の値を返す**だけでなく**関数はこのステートメントを返します。 +明示的に`return`ステートメントがある場合、関数は返り値が`Object`である場合に**限り**ステートメントで明示した値を返します。 function Bar() { return 2; @@ -64,16 +64,16 @@ JavaScriptのコンストラクタは色々ある他のプログラム言語と `Bar`で呼び出されたものは両方とも全く同じものものになります。これには、`method`と呼ばれるプロパティを持ったオブジェクトが新しく生成されますが、これは[クロージャ](#function.closures)です。 -また、注意する点として呼び出された`new Bar()`は返ってきたオブジェクトのプロトタイプに影響**しません**。プロトタイプが新しく生成されたオブジェクトにセットされるまで、`Bar`は絶対に新しいオブジェクトを返さないのです。 +また、注意する点として呼び出された`new Bar()`は返ってきたオブジェクトのプロトタイプに影響**しません**。プロトタイプは新しく生成されたオブジェクトにセットされはしますが、`Bar`は絶対にその新しいオブジェクトを返さないのです。 上記の例では、`new`キーワードの使用の有無は機能的に違いがありません。 ### ファクトリーとして新しくオブジェクトを作成する -大半の場合に推奨されるのは、`new`の付け忘れによるバグを引き起こしやすいので使用**しない**事です。 +多くの場合に推奨される事として、`new`の付け忘れによるバグを引き起こしやすいので、`new`を使用**しない**ようにするという事があります。 -新しいオブジェクトを作成するためにファクトリーを使用するか、そのファクトリー内部に新しいオブジェクトを構築する必要があります。 +新しいオブジェクトを作成するためにファクトリーを使用して、そのファクトリー内部に新しいオブジェクトを作成すべきだという事です。 function Foo() { var obj = {}; @@ -98,6 +98,6 @@ JavaScriptのコンストラクタは色々ある他のプログラム言語と ### 終わりに -`new`キーワードが省略される事により、バグの可能性がもたらされますがプロトタイプを使わない確実な理由には**なりません**。最終的には、アプリケーションの必要性により、どちらの解決法がより良いかが決まってきます。特に大切なのは、オブジェクトの作成に特定のスタイルを選ぶ事、また**そのスタイルに固執する事**です。 +`new`キーワードが省略される事によりバグの可能性がもたらされますが、それによりプロトタイプを全く使わないという確かな理由には**なりません**。最終的には、アプリケーションの必要性により、どちらの解決法がより良いかが決まってきます。特に大切なのは、オブジェクトの作成に特定のスタイルを選ぶ事、また**そのスタイルに固執する事**です。 From 103ca5d94383ae86a33ed69923f0cc51ec45df8a Mon Sep 17 00:00:00 2001 From: Krawaller Date: Sun, 27 Nov 2011 10:25:58 +0100 Subject: [PATCH 175/463] removed trailing whitespace in comment on line 55 which caused line to spill outside code container --- doc/fi/function/arguments.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/fi/function/arguments.md b/doc/fi/function/arguments.md index 153dad34..af70618e 100644 --- a/doc/fi/function/arguments.md +++ b/doc/fi/function/arguments.md @@ -52,7 +52,7 @@ Tästä seuraa, että muodollisen parametrin arvon muuttaminen muuttaa myös `ar function foo(a, b, c) { arguments[0] = 2; - a; // 2 + a; // 2 b = 4; arguments[1]; // 4 From 2499aed2a385d97720ab012c4d1d587fe7d03754 Mon Sep 17 00:00:00 2001 From: HIRAKI Satoru Date: Sun, 27 Nov 2011 21:24:49 +0900 Subject: [PATCH 176/463] fix translateion in "prototype" --- doc/ja/object/prototype.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/ja/object/prototype.md b/doc/ja/object/prototype.md index eb37cc39..c188ce85 100644 --- a/doc/ja/object/prototype.md +++ b/doc/ja/object/prototype.md @@ -39,7 +39,7 @@ JavaScriptはプロトタイプベースが採用されている唯一の広範 Object.prototype { toString: ... /* その他 */ } -上記では`test`は`Bar.prototype`と`Foo.prototype`の2つのオブジェクトより継承されます。その為`Foo`の中で設定された`method`関数にアクセスできるようになります。また、`Foo`のプロトタイプとしてのインスタンス**それ自体**の`value`プロパティにもアクセスが可能です。`new Bar()`は`Foo`のインスタンスを新しく作ら**ない**という事は非常に注目されるべき点ですが、それ自身のプロトタイプを再利用しています。従って全ての`Bar`インスタンスは**同じ**`value`プロパティを共有します。 +上記では`test`は`Bar.prototype`と`Foo.prototype`の2つのオブジェクトより継承されます。その為`Foo`の中で設定された`method`関数にアクセスできるようになります。また、`Foo`のプロトタイプとしてのインスタンス**それ自体**の`value`プロパティにもアクセスが可能です。`new Bar()`は`Foo`のインスタンスを新しく作**りません**が、プロトタイプに割り合てられた`Foo`インスタンスを再利用している事は注目に値します。従って全ての`Bar`インスタンスは**同じ**`value`プロパティを共有します。 > **注意:** `Bar.prototype = Foo`のような使い方は**しない**で下さい。`Foo`はそのプロトタイプではなく、 > 関数オブジェクト`Foo`自体を指しているからです。 @@ -54,12 +54,12 @@ JavaScriptはプロトタイプベースが採用されている唯一の広範 ### プロトタイププロパティ -プロトタイププロパティはJavaScriptの中でプロトタイプチェーンを構築する為に使われていますが、**任意**の値を代入する事も可能になっています。この時プロトタイプに代入されている値は単に無視されるだけです。 +プロトタイププロパティはJavaScriptの中でプロトタイプチェーンを構築する為に使われていますが、**任意**の値を代入する事も可能になっています。しかし、プロトタイプとしてプリミティブが代入された場合は単に無視されるだけです。 function Foo() {} Foo.prototype = 1; // 効果無し -割り当てられているオブジェクトは上記の例で示されている通りに動作し、動的にプロトタイプチェーンを作ります。 +オブジェクトの代入は上記の例のように動作し、動的にプロトタイプチェーンを作る事ができます。 ### パフォーマンス From e077114a821c9d843d5de155e33d5937acb7f86b Mon Sep 17 00:00:00 2001 From: HIRAKI Satoru Date: Sun, 27 Nov 2011 21:27:54 +0900 Subject: [PATCH 177/463] fix translation in "for in loop" --- doc/ja/object/forinloop.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/ja/object/forinloop.md b/doc/ja/object/forinloop.md index ffd6eb1c..180620be 100644 --- a/doc/ja/object/forinloop.md +++ b/doc/ja/object/forinloop.md @@ -2,7 +2,7 @@ `in`オペレーターは単に、`for in`ループの中でオブジェクトのプロパティをプロトタイプチェーンの中で繰り返し遡る為にあるものです。 -> **注意:** `for in`ループは`列挙`される属性が`false`にセットされているプロパティを反復処理**しません**。; +> **注意:** `for in`ループは`enumerable`属性が`false`にセットされているプロパティを反復処理**しません**。; > 例えば、配列の`length`プロパティなどがそれに当たります。 // Object.prototype汚染 From a55f6bef57ff8d270c84c3c3610a7692fc878286 Mon Sep 17 00:00:00 2001 From: HIRAKI Satoru Date: Sun, 27 Nov 2011 21:41:07 +0900 Subject: [PATCH 178/463] fix translation in "general" --- doc/ja/function/general.md | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/doc/ja/function/general.md b/doc/ja/function/general.md index d3ce0237..a1c490b5 100644 --- a/doc/ja/function/general.md +++ b/doc/ja/function/general.md @@ -25,14 +25,13 @@ しかし、コードの実行時にのみこの割り当てがされるため、`foo`という変数は対応するコードが実行される前にデフォルト値である[undefined](#core.undefined)が代入されるのです。 -### 名前付き関数宣言 +### 名前付き関数式 -他に特殊なケースとして、命名関数があります。 +他に特殊なケースとして、名前付き関数があります。 var foo = function bar() { bar(); // 動作する } bar(); // ReferenceError -この場合の`bar`は`foo`に対して関数を割り当てるだけなので、外部スコープでは使用できません。しかし、`bar`は内部では使用できます。これはJavaScriptでは[名前解決](#function.scopes)による動作です。関数名は*いつも*関数自体のローカルスコープ内で有効になっています。 - +この場合の`bar`は`foo`に対して関数を割り当てるだけなので、外部スコープでは使用できません。しかし、`bar`は内部では使用できます。これはJavaScriptの[名前解決](#function.scopes)の方法によるもので、関数名は*いつも*関数自身のローカルスコープ内で有効になっています。 From cf2da10a43ded4d82a71172e81d5b8c4433d7445 Mon Sep 17 00:00:00 2001 From: HIRAKI Satoru Date: Sun, 27 Nov 2011 21:47:21 +0900 Subject: [PATCH 179/463] fix translate in "clusures" --- doc/ja/function/closures.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/ja/function/closures.md b/doc/ja/function/closures.md index b17f6eb3..718f84c5 100644 --- a/doc/ja/function/closures.md +++ b/doc/ja/function/closures.md @@ -32,7 +32,7 @@ JavaScriptでは、スコープ自体を参照・代入する事が出来無い count = 1337; }; -上記のコードは`Counter`のスコープ中にある変数`count`の値を変更する事は**ありません**。`foo.hack`は**その**スコープで定義されていないからです。これは*グローバル*変数`count`の作成 -またはオーバーライド- の代わりになるでしょう。 +上記のコードは`Counter`のスコープ中にある変数`count`の値を変更する事は**ありません**。`foo.hack`は**その**スコープで定義されていないからです。これは(`Counter`内の変数`count`の変更)の代わりに*グローバル*変数`count`の作成 -または上書き- する事になります。 ### ループ中のクロージャ From 07bf7e487bfa2ce0f31a27835ba590459e340b63 Mon Sep 17 00:00:00 2001 From: HIRAKI Satoru Date: Sun, 27 Nov 2011 21:49:05 +0900 Subject: [PATCH 180/463] fix translation in "aruguments" --- doc/ja/function/arguments.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/ja/function/arguments.md b/doc/ja/function/arguments.md index e1738aaf..cb0982c9 100644 --- a/doc/ja/function/arguments.md +++ b/doc/ja/function/arguments.md @@ -3,7 +3,7 @@ JavaScriptの全ての関数スコープは`arguments`と呼ばれる特別な変数にアクセスできます。この変数は関数が受け取った全ての引数を保持する変数です。 > **注意:** `arguments`が既に`var`や正式なパラメーターにより -> 関数のスコープが定義されている場合は +> 関数のスコープ内部で定義されている場合は > `arguments`オブジェクトは作られません。 `arguments`オブジェクトは`Array`では**ありません**。これは配列と同じような -`length`プロパティと名付けられています- 文法を持っていますが、`Array.prototype`を継承している訳では無いので、実際`Object`になります。 From 786c17056cc82af05b3d91ad6a2f5b6e5119118d Mon Sep 17 00:00:00 2001 From: HIRAKI Satoru Date: Mon, 28 Nov 2011 00:42:05 +0900 Subject: [PATCH 181/463] fix transition in "scopes" --- doc/ja/function/scopes.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/doc/ja/function/scopes.md b/doc/ja/function/scopes.md index 451140f3..f6c97854 100644 --- a/doc/ja/function/scopes.md +++ b/doc/ja/function/scopes.md @@ -27,7 +27,7 @@ JavaScriptはまた明確な名前空間を持ちません。この事は全て 上記の2つのスクリプトは同じ効果を持って**いません**。スクリプト Aは`foo`と呼ばれる変数を、*グローバル*スコープに定義しており、スクリプト Bは`foo`を*現在*のスコープで定義ています。 -再び、`var`が重大な影響を持っていない、*同じ効果*では**無い**スクリプトになります。 +繰り返しますが、この2つのスクリプトは*同じ影響*を全く持って**いない**スクリプトになります。`var`を使用しない事は重大な意味を持ちます。 // グローバルスコープ var foo = 42; @@ -38,7 +38,7 @@ JavaScriptはまた明確な名前空間を持ちません。この事は全て test(); foo; // 21 -`test`関数の中の`var`ステートメントを省略すると`foo`の値をオーバーライドします。最初の内は大した事ではないように思いますが、JavaScriptが何千行規模になると、`var`を使っていない事で恐怖とバグの追跡の困難さを招くことになります。 +`test`関数の中の`var`ステートメントを省略すると`foo`の値をオーバーライドします。最初の内は大した事ではないように思いますが、JavaScriptが何千行規模になると、`var`を使っていない事でバグの追跡が酷く困難になります。 // グローバルスコープ var items = [/* 同じリスト */]; @@ -53,7 +53,7 @@ JavaScriptはまた明確な名前空間を持ちません。この事は全て } } -外側のループは`subloop`が最初に呼ばれた後に終了します。なぜなら、`subloop`がグローバル変数`i`の値で上書きされているからです。2番目の`for`ループに`var`を使用する事によって簡単にこのエラーを回避する事ができます。`var`ステートメントは*希望する影響*を外側のスコープに与える場合を除いては、**絶対**に残してはいけません。 +外側のループは`subloop`が最初に呼ばれた後に終了します。なぜなら、`subloop`がグローバル変数`i`の値で上書きされているからです。2番目の`for`ループに`var`を使用する事によって簡単にこのエラーを回避する事ができます。*目的とする効果*を外側のスコープに与えようとしない限り、**絶対**に`var`ステートメントは省略してはいけません。 ### ローカル変数 @@ -73,11 +73,11 @@ JavaScriptのローカル変数の為の唯一のソースは[function](#functio } test(10); -`foo`と`i`は、関数`test`のスコープ内のローカル変数ですが、`bar`の割り当ては同じ名前のグローバル変数で上書きされてしまいます。 +`foo`と`i`は、関数`test`のスコープ内のローカル変数ですが、`bar`の代入は同じ名前のグローバル変数で上書きしてしまいます。 ### 巻き上げ -JavaScriptの**巻き上げ**宣言。この言葉の意味は`var`ステートメントと`function`宣言が、それらの外側のスコープに移動するというものです。 +JavaScriptは宣言を**巻き上げ**ます。これは`var`ステートメントと`function`宣言が、それらを含むスコープの一番先頭に移動するという事を意味します。 bar(); var bar = function() {}; @@ -96,7 +96,7 @@ JavaScriptの**巻き上げ**宣言。この言葉の意味は`var`ステート } } -上記のコードは何も実行されないうちに変換されてしまいます。JavaScriptは`var`ステートメントと同じように、直近で囲んでいる`function`宣言を先頭に移動させます。 +上記のコードは、実行を開始する前に変換されてしまいます。JavaScriptは`var`ステートメントと同じように、直近で囲んでいる`function`宣言を先頭に移動させます。 // varステートメントはここに移動する var bar, someValue; // 'undefined'がデフォルト @@ -121,7 +121,7 @@ JavaScriptの**巻き上げ**宣言。この言葉の意味は`var`ステート test(); -ブロックスコープの欠落はループ外の`var`ステートメントの移動だけでなく、その本体も移動させます。これはまた`if`が直感的じゃない結果になってしまいます。 +ブロックスコープの欠落は`var`ステートメントをループやボディの外に移動するだけでなく、`if`の構成を直感的ではないものにしてしまいます。 元のコードの中の`if`ステートメントは*グローバル変数*である`goo`も変更しているように見えますが、実際には -巻き上げが適用された後に- *ローカル変数*を変更しています。 From 563d23ebd386b4c95612007503fc74af9e9b1865 Mon Sep 17 00:00:00 2001 From: HIRAKI Satoru Date: Mon, 28 Nov 2011 01:15:11 +0900 Subject: [PATCH 182/463] fix translation in "general" --- doc/ja/array/general.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/ja/array/general.md b/doc/ja/array/general.md index c9331224..521ad177 100644 --- a/doc/ja/array/general.md +++ b/doc/ja/array/general.md @@ -1,6 +1,6 @@ ## 配列の繰り返しとプロパティ -JavaScriptの配列もまたオブジェクトですので[`for in ループ`](#object.forinloop)を配列の繰り返しで使用するような理由はありません。実際、配列に`for in`を使用**しない**為の正当な理由はたくさんあります。 +JavaScriptの配列もまたオブジェクトですが、[`for in ループ`](#object.forinloop)を配列の繰り返し処理で使用することの良い理由は1つもありません。実際、配列に`for in`を使用**しない**為の正当な理由はたくさんあります。 > **注意:** JavaScriptの配列は*連想配列*では**ありません**。JavaScriptは[objects](#object.general)だけがキーバリューをマッピングするものです。 > また、連想配列は順序を**保持**しますが、オブジェクトは**保持しません**。 @@ -16,9 +16,9 @@ JavaScriptの配列もまたオブジェクトですので[`for in ループ`](# console.log(list[i]); } -上記の例では一つ余分に変数がありますが、それは配列の長さを取るための`l = list.length`の部分です。 +上記の例では1つ追加の仕掛けがありますが、それは配列の長さを取るための`l = list.length`の部分です。 -また、`length`プロパティは配列自身に定義されていますが、ループのそれぞれの繰り返しで探索する為のオーバーヘッドがまだあります。最近のJavaScriptエンジンはこのような場合に最適化する**はず**です。新しいエンジンか古いエンジンで実行されるかどうかをコードが知る方法はありません。 +また、`length`プロパティは配列自身に定義されていますが、ループ中の繰り返し毎回参照を行なうというオーバーヘッドがまだ存在します。最近のJavaScriptエンジンはこのような場合に最適化する**はず**ですが、コードが新しいエンジンで実行されるかどうか、知る方法はありません。 実際には、キャッシュを抜きにするとループの結果はキャッシュされたものに比べて、**半分だけ高速**になっています。 From 8507575343317044a2538b5a3c29b0cebe0e403b Mon Sep 17 00:00:00 2001 From: HIRAKI Satoru Date: Mon, 28 Nov 2011 02:41:11 +0900 Subject: [PATCH 183/463] fix translation in "equality" --- doc/ja/types/equality.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/ja/types/equality.md b/doc/ja/types/equality.md index ea99d187..a37828ed 100644 --- a/doc/ja/types/equality.md +++ b/doc/ja/types/equality.md @@ -1,6 +1,6 @@ ## 等価と比較 -JavaScriptはオブジェクトの値の等価の比較方法が2種類持っています。 +JavaScriptはオブジェクトの値の等価の比較方法を2種類持っています。 ### 等価演算子 From 6523453156df47c90944eb0dafb32ef8ea70c21d Mon Sep 17 00:00:00 2001 From: HIRAKI Satoru Date: Mon, 28 Nov 2011 02:41:48 +0900 Subject: [PATCH 184/463] fix translation in "instans of" --- doc/ja/types/instanceof.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/ja/types/instanceof.md b/doc/ja/types/instanceof.md index 9efd399c..82a5b80f 100644 --- a/doc/ja/types/instanceof.md +++ b/doc/ja/types/instanceof.md @@ -24,7 +24,7 @@ 'foo' instanceof String; // false 'foo' instanceof Object; // false -ここで一つ重要な事は、この`instanceof`は異なるJavaScriptのコンテキストが起源のオブジェクト(例:ブラウザの異なるウィンドウ)では、そのコンストラクタが正確に同じオブジェクトになる訳では無いので、同じオブジェクトとして動作しないという事です。 +ここで1つ重要な事は、異なるJavaScriptのコンテキスト(例えば、ブラウザの異なるウィンドウ)を元としたオブジェクトでは、コンストラクタが厳密に同じものでは無い為に`instanceof`は上手く動作しません。 ### 終わりに From be27b0126d5ee6048566b082b2b4e1d857586a31 Mon Sep 17 00:00:00 2001 From: Jonathan B Date: Wed, 7 Dec 2011 14:24:14 -0500 Subject: [PATCH 185/463] grammar --- doc/en/function/this.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/en/function/this.md b/doc/en/function/this.md index 440900e8..c2ef238f 100644 --- a/doc/en/function/this.md +++ b/doc/en/function/this.md @@ -46,7 +46,7 @@ When using the `call` or `apply` methods of `Function.prototype`, the value of `this` inside the called function gets **explicitly set** to the first argument of the corresponding function call. -As a result, the above example the *method case* does **not** apply, and `this` +As a result, in the above example the *method case* does **not** apply, and `this` inside of `foo` will be set to `bar`. > **Note:** `this` **cannot** be used to refer to the object inside of an `Object` From d314228f454cf9c4184dda6542604f16cf52b15b Mon Sep 17 00:00:00 2001 From: HIRAKI Satoru Date: Sat, 10 Dec 2011 01:46:31 +0900 Subject: [PATCH 186/463] fix representation in "undefined" --- doc/ja/core/undefined.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/ja/core/undefined.md b/doc/ja/core/undefined.md index 9d6949f3..e3a895c1 100644 --- a/doc/ja/core/undefined.md +++ b/doc/ja/core/undefined.md @@ -11,14 +11,14 @@ JavaScriptは`nothing`を表す2つの別個の値を持っています。`undef > **ES5での注意点:** ECMAScript 5での`undefined`は **もはや** strict modeでは *書き変えられない* > ようになっています。しかし、この名前は`undefined`という名前の関数の例に痕跡が見られるだけです。 -`undefined`が帰される時の例をいくつか挙げます。 +`undefined`が返される時の例をいくつか挙げます。 - (未定義の)グローバル変数`undefined`にアクセスした時 - `return`文が無い為に、暗黙のうちに関数が返された時 - 何も返されない`return`がある時 - 存在しないプロパティを探索する時 - 関数のパラメーターで明示的な値が何も無い時 - - 全ての`undefined`が設定された値 + - `undefined`が設定された全ての値 ### `undefined`の値に変更する処理 From 1cc24a47d1f1cb63541473be18a118258aa904ac Mon Sep 17 00:00:00 2001 From: HIRAKI Satoru Date: Sat, 10 Dec 2011 01:56:45 +0900 Subject: [PATCH 187/463] fix translate in "others" --- doc/ja/other/timeouts.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/doc/ja/other/timeouts.md b/doc/ja/other/timeouts.md index c1875b4f..3f5d2deb 100644 --- a/doc/ja/other/timeouts.md +++ b/doc/ja/other/timeouts.md @@ -10,7 +10,7 @@ JavaScriptは非同期なので、`setTimeout`と`setInterval`関数を使って `setTimeout`が呼ばれた時に、タイムアウトのIDと`foo`この先の**おおよそ**1000msに実行するスケジュールを返します。`foo`は正確に**1度**だけ実行されます。 -コードが実行されているJavaScriptエンジンのタイマー分解能によって決まります。この事実はJavaScriptがシングルスレッドのなので、他のスレッドでの実行を妨害してしまう事があるかもしれません。これは、`setTimeout`の呼び出しにより指定された正確なディレイで実行するという確実な賭けという**意味ではありません**。 +コードが実行されているJavaScriptエンジンのタイマー分解能によって決まります。この事実はJavaScriptがシングルスレッドのなので、他のスレッドでの実行を妨害してしまう事があるかもしれません。これは、`setTimeout`関数の呼び出しで指定した遅延時間を正確に間違いなく得られるという**意味では決してありません**。 第一パラメーターを渡された関数は*グローバルオブジェクト*によって呼び出されます。これは呼び出された関数の内部で[`this`](#functionis)がまさにこのオブジェクトを参照しているという事になります。 @@ -99,10 +99,10 @@ JavaScriptは非同期なので、`setTimeout`と`setInterval`関数を使って この場合、`eval`は[直接](#core.eval)呼ばれないので、文字列が渡された`setTimeout`は*global scope*で実行されます。よって、`bar`のスコープから`foo`のローカル変数は使われないのです。 -さらに、文字列を関数に渡さ**ない**ように推奨される理由として、それぞれのタイムアウト関数から呼び出されるという事があります。 +タイムアウト関数によって呼び出される関数を引数に渡すために文字列を使わ**ない**という事は、それ以上に推奨されています。 function foo(a, b, c) {} - + // 絶対にこのように使わない setTimeout('foo(1,2, 3)', 1000) @@ -119,7 +119,7 @@ JavaScriptは非同期なので、`setTimeout`と`setInterval`関数を使って `setTimeout`や`setInterval`のパラメーターに文字列を使用する事は**絶対**するべきではありません。引数が関数に呼び出される必要がある場合**本当**に悪いコードの明確なサインになります。実際の呼び出しには*匿名関数*を渡すべきです。 -その上で、`setInterval`の使用はそのスケジューラーがJavaScriptの実行をブロックするので避けるべきでしょう。 +さらに、`setInterval`の使用はスケジューラーがJavaScriptの実行によってブロックされないので、避けるべきでしょう。 [1]: http://en.wikipedia.org/wiki/Document_Object_Model "Document Object Model" From cd06184a6fc8c579e7e0ff18b51f170462e161a4 Mon Sep 17 00:00:00 2001 From: oozcitak Date: Tue, 13 Dec 2011 00:26:23 +0200 Subject: [PATCH 188/463] [tr] Fixed type --- doc/tr/function/scopes.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/tr/function/scopes.md b/doc/tr/function/scopes.md index 7b9d4a24..d826f1aa 100644 --- a/doc/tr/function/scopes.md +++ b/doc/tr/function/scopes.md @@ -14,7 +14,7 @@ kapsamı **bulunmaz**; bu nedenle, dilde sadece *fonksiyon kapsamı* mevcuttur. > kullanıldığında `{...}` notasyonu bir nesne değişmezi olarak **değil** > blok ifade olarak değerlendirilir. Bu özellik > [otomatik noktalı virgül ilavesi](#core.semicolon) ile birleştiğinde fark -> edilmesizor hatalara neden olabilir. +> edilmesi zor hatalara neden olabilir. JavaScript'te isim uzayları kavramı da bulunmaz, tanımlanan herşey *genel olarak paylaşılmış* tek bir isim uzayının içindedir. From c8258d13f05f90b6f952209c783786a6c3ba9d82 Mon Sep 17 00:00:00 2001 From: oozcitak Date: Tue, 13 Dec 2011 00:27:08 +0200 Subject: [PATCH 189/463] [tr] Translated delete --- doc/tr/core/delete.md | 84 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 84 insertions(+) create mode 100644 doc/tr/core/delete.md diff --git a/doc/tr/core/delete.md b/doc/tr/core/delete.md new file mode 100644 index 00000000..51695e1a --- /dev/null +++ b/doc/tr/core/delete.md @@ -0,0 +1,84 @@ +## `delete` Operatörü + +Kısaca genel kapsamda tanımlanmış değişkenleri, fonksiyonları ve `DontDelete` +niteliğine sahip bazı başka şeyleri silmek *imkansızdır*. + +### Genel kapsam ve fonksiyon kapsamı + +Bir değişken veya fonksiyon genel kapsamda veya +[fonksiyon kapsamında](#function.scopes) tanımlandığında aktivasyon nesnesinin +veya global nesnenin bir özelliği olacaktır. Bu tür özelliklerin bir takım +nitelikleri vardır ve bunlardan biri `DontDelete` niteliğidir. Genel kapsamda ve +fonksiyon kapsamında tanımlanan değişkenler ve fonksiyonlar yaratıldıklarında +her zaman `DontDelete` niteliğine sahip olacaktır, ve bu nedenle silinemezler. + + // genel kapsam değişkeni: + var a = 1; // DontDelete niteliğine sahip + delete a; // false + a; // 1 + + // normal bir fonksiyon: + function f() {} // DontDelete niteliğine sahip + delete f; // false + typeof f; // "function" + + // başka bir değişkene atamak işe yaramaz: + f = 1; + delete f; // false + f; // 1 + +### Açıkça tanımlanan özellikler + +Açıkça tanımlanan özellikleri silmek mümkündür. + + // tanımlanan özellik: + var obj = {x: 1}; + obj.y = 2; + delete obj.x; // true + delete obj.y; // true + obj.x; // undefined + obj.y; // undefined + +Yukarıdaki örnekte `obj.x` ve `obj.y` silinebilir çünkü `DontDelete` niteliğine +sahip değillerdir. Aynı nedenle aşağıdakini yapmak da mümkündür: + + // IE hariç çalışır: + var GLOBAL_OBJECT = this; + GLOBAL_OBJECT.a = 1; + a === GLOBAL_OBJECT.a; // true - genel değişken + delete GLOBAL_OBJECT.a; // true + GLOBAL_OBJECT.a; // undefined + +Burada `a`'yı silmek için bir hile kullanıyoruz. [`this`](#function.this) +burada genel nesneye işaret ediyor ve `a` değişkenini onun özelliği olarak +atıyoruz, ve böylece onu silebiliyoruz. + +IE (en azından 6-8) bazı hatalar içerdiğinden yukarıdaki örenk çalışmayacaktır. + +### Fonksiyon argümanları ve önceden tanımlı özellikler + +Fonksiyonlara verilen argümanlar, [`arguments` nesnesi](#function.arguments) +ve önceden tanımlı özellikler de `DontDelete` niteliğine sahiptir. + + // fonksiyon argümanları ve özellikler: + (function (x) { + delete arguments; // false + typeof arguments; // "object" + + delete x; // false + x; // 1 + + function f(){} + delete f.length; // false + typeof f.length; // "number" + })(1); + +### *Host* nesneler + +`Host` nesneler üzerinde kullanıldığında `delete` operatörünün davranışı belirsiz +olabilir. Standarda göre `host` nesneler istedikleri davranışı uygulayabilirler. + +### Sonuç + +`delete` operatörünün davranışı genellikle belirsizdir ve güvenle kullanılabileceği +tek yer sıradanan nesneler üzerinde açıkça tanımlanan özelliklerdir. From 753fd7880ff222a2da6d4082350982d87cd2307f Mon Sep 17 00:00:00 2001 From: oozcitak Date: Tue, 13 Dec 2011 00:47:56 +0200 Subject: [PATCH 190/463] Added delete to index --- doc/tr/index.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/doc/tr/index.json b/doc/tr/index.json index e6654186..3003d441 100644 --- a/doc/tr/index.json +++ b/doc/tr/index.json @@ -54,7 +54,8 @@ "articles": [ "eval", "undefined", - "semicolon" + "semicolon", + "delete" ] }, { From 919b581282b010c2adabeb5fa6897f1a1932e3a4 Mon Sep 17 00:00:00 2001 From: oozcitak Date: Tue, 13 Dec 2011 20:23:03 +0200 Subject: [PATCH 191/463] [tr] Fixed typo --- doc/tr/core/delete.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/tr/core/delete.md b/doc/tr/core/delete.md index 51695e1a..de19f1a4 100644 --- a/doc/tr/core/delete.md +++ b/doc/tr/core/delete.md @@ -1,6 +1,6 @@ ## `delete` Operatörü -Kısaca genel kapsamda tanımlanmış değişkenleri, fonksiyonları ve `DontDelete` +Kısacası, genel kapsamda tanımlanmış değişkenleri, fonksiyonları ve `DontDelete` niteliğine sahip bazı başka şeyleri silmek *imkansızdır*. ### Genel kapsam ve fonksiyon kapsamı @@ -53,7 +53,7 @@ Burada `a`'yı silmek için bir hile kullanıyoruz. [`this`](#function.this) burada genel nesneye işaret ediyor ve `a` değişkenini onun özelliği olarak atıyoruz, ve böylece onu silebiliyoruz. -IE (en azından 6-8) bazı hatalar içerdiğinden yukarıdaki örenk çalışmayacaktır. +IE (en azından 6-8) bazı hatalar içerdiğinden yukarıdaki örnek çalışmayacaktır. ### Fonksiyon argümanları ve önceden tanımlı özellikler From d4c46e6254dc13f8d474b90854f93974cc739534 Mon Sep 17 00:00:00 2001 From: HIRAKI Satoru Date: Mon, 19 Dec 2011 02:57:25 +0900 Subject: [PATCH 192/463] fix translate in "constuctors" --- doc/ja/function/constructors.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/ja/function/constructors.md b/doc/ja/function/constructors.md index 4d0728a1..792d5fa6 100644 --- a/doc/ja/function/constructors.md +++ b/doc/ja/function/constructors.md @@ -16,7 +16,7 @@ JavaScriptのコンストラクタは色々ある他のプログラム言語と var test = new Foo(); -上記で`Foo`はコンストラクタとして呼び出され、`Foo.prototype`として新規に生成された`prototype`を設定されています。 +上記は、`Foo`をコンストラクタとして呼び出し、新規に生成されたオブジェクトの`prototype`を`Foo.prototype`に設定しています。 明示的に`return`ステートメントがある場合、関数は返り値が`Object`である場合に**限り**ステートメントで明示した値を返します。 @@ -41,7 +41,7 @@ JavaScriptのコンストラクタは色々ある他のプログラム言語と } Foo(); // undefinedが返る -上記の例では、いくつかのケースでは動作するように見える場合があります。JavaScriptの[`this`](#function.this)の働きのせいで、*グローバルオブジェクト*が`this`の値として使用されるからです。 +JavaScriptの[`this`](#function.this)の働きのせいで、上記の例ではいくつかのケースでは動作するように見える場合がありますが、それは*グローバルオブジェクト*が`this`の値として使用されるからです。 ### ファクトリー From 8d1819ef89577291d0b80fc92ff59b32edb4bf92 Mon Sep 17 00:00:00 2001 From: HIRAKI Satoru Date: Mon, 19 Dec 2011 03:09:01 +0900 Subject: [PATCH 193/463] fix transition in "constructors" --- doc/ja/function/constructors.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/ja/function/constructors.md b/doc/ja/function/constructors.md index 792d5fa6..94561c08 100644 --- a/doc/ja/function/constructors.md +++ b/doc/ja/function/constructors.md @@ -2,7 +2,7 @@ JavaScriptのコンストラクタは色々ある他のプログラム言語とは一味違います。`new`キーワードが付いているどんな関数呼び出しも、コンストラクタとして機能します。 -コンストラクタ内部では -呼び出された関数の事です- `this`の値は新規に生成された`Object`を参照しています。この**新規**のオブジェクトの[`prototype`](#object.prototype)は、コンストラクタとして起動した関数オブジェクトの`prototype`として設定されています。 +コンストラクタ内部では -呼び出された関数の事です- `this`の値は新規に生成された`Object`を参照しています。この**新規**のオブジェクトの[`prototype`](#object.prototype)は、コンストラクタとして起動した関数オブジェクトの`prototype`に設定されています。 もし呼び出された関数が、`return`ステートメントを明示していない場合は、暗黙の了解で`this`の値を -新規のオブジェクトとして- 返します。 From 887ece3ba8c12750e75c586694f305cb56e55162 Mon Sep 17 00:00:00 2001 From: HIRAKI Satoru Date: Mon, 19 Dec 2011 03:09:50 +0900 Subject: [PATCH 194/463] fix transition in "scopes" --- doc/ja/function/scopes.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/doc/ja/function/scopes.md b/doc/ja/function/scopes.md index f6c97854..997c6e4a 100644 --- a/doc/ja/function/scopes.md +++ b/doc/ja/function/scopes.md @@ -10,7 +10,7 @@ JavaScriptはブロックに2つのペアの中括弧を使うのが素晴しい } > **注意:** 代入が使用されてない時、return文や関数の引数、`{...}`表記はブロック文として -> 解釈されて、オブジェクトリテラルトは**なりません**。これは[セミコロン自動挿入](#core.semicolon) +> 解釈されて、オブジェクトリテラルとは**なりません**。これは[セミコロン自動挿入](#core.semicolon) > と連動して奇妙なエラーを引き起こすことになります。 JavaScriptはまた明確な名前空間を持ちません。この事は全て一つの*グローバルで共有された*名前空間で定義されるという事です。 @@ -41,7 +41,7 @@ JavaScriptはまた明確な名前空間を持ちません。この事は全て `test`関数の中の`var`ステートメントを省略すると`foo`の値をオーバーライドします。最初の内は大した事ではないように思いますが、JavaScriptが何千行規模になると、`var`を使っていない事でバグの追跡が酷く困難になります。 // グローバルスコープ - var items = [/* 同じリスト */]; + var items = [/* 何かのリスト */]; for(var i = 0; i < 10; i++) { subLoop(); } @@ -57,7 +57,7 @@ JavaScriptはまた明確な名前空間を持ちません。この事は全て ### ローカル変数 -JavaScriptのローカル変数の為の唯一のソースは[function](#function.general)パラメーターと`var`ステートメントを宣言された変数になります。 +JavaScriptのローカル変数の為の唯一の作成方法は[function](#function.general)パラメーターと`var`ステートメントによって宣言された変数になります。 // グローバルスコープ var foo = 1; @@ -73,7 +73,7 @@ JavaScriptのローカル変数の為の唯一のソースは[function](#functio } test(10); -`foo`と`i`は、関数`test`のスコープ内のローカル変数ですが、`bar`の代入は同じ名前のグローバル変数で上書きしてしまいます。 +`foo`と`i`は、関数`test`のスコープ内のローカル変数ですが、`bar`の代入は同じ名前でグローバル変数で上書きしてしまいます。 ### 巻き上げ @@ -132,7 +132,7 @@ JavaScriptは宣言を**巻き上げ**ます。これは`var`ステートメン var SomeImportantThing = {}; } -しかし、勿論上記の動きは`val`ステートメントが*グローバルスコープ*の上に移動しているという事実に基づいています。 +しかし、勿論上記の動きは`var`ステートメントが*グローバルスコープ*の上に移動しているという事実に基づいています。 var SomeImportantThing; From 92e134a23614a5547c72dfd91047d6a96aaaa2df Mon Sep 17 00:00:00 2001 From: HIRAKI Satoru Date: Mon, 19 Dec 2011 03:17:37 +0900 Subject: [PATCH 195/463] fix transition in "scopes" --- doc/ja/function/scopes.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/ja/function/scopes.md b/doc/ja/function/scopes.md index 997c6e4a..ddbe08c6 100644 --- a/doc/ja/function/scopes.md +++ b/doc/ja/function/scopes.md @@ -147,7 +147,7 @@ JavaScriptは宣言を**巻き上げ**ます。これは`var`ステートメン JavaScriptの*グローバルスコープ*を含む、全てのスコープは、*現在のオブジェクト*を参照している特殊な名前[`this`](#function.this)を持っています。 -関数スコープはまた、関数を通過してきた引数を含んでいる[`arguments`](#function.arguments)という名前も持っています。 +関数スコープはまた、[`arguments`](#function.arguments)という名前も持っています。それは関数スコープの中で定義され、関数に渡された引数を含んでいます。 例として、関数の中で`foo`と命名された変数にアクセスしようとする場合を考えましょう。JavaScriptは以下の順番で、その名前を探索しようとします。 From 1db1d02590d79978b3bdd60cd80d82f36cdc267b Mon Sep 17 00:00:00 2001 From: HIRAKI Satoru Date: Sun, 25 Dec 2011 01:20:49 +0900 Subject: [PATCH 196/463] fix translate in "General" --- doc/ja/array/general.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/ja/array/general.md b/doc/ja/array/general.md index 521ad177..0b7925dc 100644 --- a/doc/ja/array/general.md +++ b/doc/ja/array/general.md @@ -16,11 +16,11 @@ JavaScriptの配列もまたオブジェクトですが、[`for in ループ`](# console.log(list[i]); } -上記の例では1つ追加の仕掛けがありますが、それは配列の長さを取るための`l = list.length`の部分です。 +上記の例では1つ追加の仕掛けがありますが、それは`l = list.length`によって配列の長さをキャッシュする部分です。 また、`length`プロパティは配列自身に定義されていますが、ループ中の繰り返し毎回参照を行なうというオーバーヘッドがまだ存在します。最近のJavaScriptエンジンはこのような場合に最適化する**はず**ですが、コードが新しいエンジンで実行されるかどうか、知る方法はありません。 -実際には、キャッシュを抜きにするとループの結果はキャッシュされたものに比べて、**半分だけ高速**になっています。 +実際には、キャッシュを抜きにするとループの結果はキャッシュされたものに比べてたった**半分の速度**にしかなりません。 ### `length`プロパティ From 83649e4b7d733bcc35db5711c0496b58a7a89ebd Mon Sep 17 00:00:00 2001 From: HIRAKI Satoru Date: Sun, 25 Dec 2011 01:25:10 +0900 Subject: [PATCH 197/463] fix translate "Equality" --- doc/ja/types/equality.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/ja/types/equality.md b/doc/ja/types/equality.md index a37828ed..617d38af 100644 --- a/doc/ja/types/equality.md +++ b/doc/ja/types/equality.md @@ -50,7 +50,7 @@ JavaScriptは*弱い型付け*を特徴としています。これは等価演 var foo = {}; foo === foo; // true -これら2つの演算子は**同一性**と等価**ではない**事を比較しています。これは、これらの演算子はPythonの`is`演算子やCのポインター比較と同じように、同じオブジェクトの**インスタンス**を比較するという事になります。 +これら2つの演算子は**同一性**を比較していているのであって、等価を比較しているわけでは**ありません**。これは、これらの演算子はPythonの`is`演算子やCのポインター比較と同じように、同じオブジェクトの**インスタンス**を比較するという事になります。 ### 終わりに From e3704b30bf12ac3809ccc19fb65f391928d7a558 Mon Sep 17 00:00:00 2001 From: HIRAKI Satoru Date: Sun, 25 Dec 2011 01:27:27 +0900 Subject: [PATCH 198/463] fix translate in "typeof" --- doc/ja/types/typeof.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/ja/types/typeof.md b/doc/ja/types/typeof.md index 8843c368..f0a4233d 100644 --- a/doc/ja/types/typeof.md +++ b/doc/ja/types/typeof.md @@ -29,7 +29,7 @@ {} Object object new Object() Object object -上記のテーブルの*Type*は値を参照しており、`typeof`演算子が返ってきます。はっきりと分かるように、この値はどれでも一貫しています。 +上記のテーブルにおいて*Type*は`typeof`演算子が返す値を参照しています。はっきりと分かるように、この値はどれでも一貫しています。 *Class*はオブジェクト内部の`[[Class]]`プロパティの値を参照しています。 From e3ec38616696b78fe5e2d441309e0574e962587b Mon Sep 17 00:00:00 2001 From: HIRAKI Satoru Date: Sun, 25 Dec 2011 01:29:56 +0900 Subject: [PATCH 199/463] fix translate in "typeof" --- doc/ja/types/typeof.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/ja/types/typeof.md b/doc/ja/types/typeof.md index f0a4233d..a70ac820 100644 --- a/doc/ja/types/typeof.md +++ b/doc/ja/types/typeof.md @@ -55,7 +55,7 @@ > **ES5での注意点:** 便宜上、ECMAScript 5では > `Object.prototype.toString`の -> `null`と`undefined`は`Object`から +> `null`と`undefined`の返す値は`Object`から > `Null`と`Undefined`に**変更され**ました。 ### 未定義変数のテスト From 5d52cdf792c431817f13309312fef049e4b356e1 Mon Sep 17 00:00:00 2001 From: HIRAKI Satoru Date: Sun, 25 Dec 2011 01:33:41 +0900 Subject: [PATCH 200/463] fix translte in "casting" --- doc/ja/types/casting.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/ja/types/casting.md b/doc/ja/types/casting.md index 44446ea1..42561de7 100644 --- a/doc/ja/types/casting.md +++ b/doc/ja/types/casting.md @@ -19,7 +19,7 @@ JavaScriptは*弱い型付け*の言語なので、可能な**限り**に*型強 > **ES5での注意点:** `0`から始まるNumberリテラルは8進数(基数が8)として解釈されます。 > このような8進数のサポートはECMAScript5のstrict modeでは**削除されました**。 -上記の自体を避ける為に、[strict equal operator](#types.equality)を使用する事を**強く**推奨します。また、これはたくさんある落し穴を避けますが、それでもまだJavaScriptの弱い型付けシステムから発生する色々な課題が残っています。 +上記の自体を避ける為に、[厳格等価演算子](#types.equality)を使用する事を**強く**推奨します。また、これはたくさんある落し穴を避けますが、それでもまだJavaScriptの弱い型付けシステムから発生する色々な課題が残っています。 ### 組み込み型のコンストラクタ From 9c87e5b8d58ab52fbd8984963fc50fb2b193a460 Mon Sep 17 00:00:00 2001 From: HIRAKI Satoru Date: Sun, 25 Dec 2011 01:36:01 +0900 Subject: [PATCH 201/463] fix translate in "undefined" --- doc/ja/core/undefined.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/ja/core/undefined.md b/doc/ja/core/undefined.md index e3a895c1..ac8761a4 100644 --- a/doc/ja/core/undefined.md +++ b/doc/ja/core/undefined.md @@ -1,6 +1,6 @@ ## `undefined`と`null` -JavaScriptは`nothing`を表す2つの別個の値を持っています。`undefined`はこれら2つの内より便利な存在です。 +JavaScriptは`nothing`を表す2つの別個の値を持っています。これら2つの内で`undefined`はより便利な存在です。 ### `undefined`の値 From 901b13f46b9127b37350620f44ef2bd8f3ad06ec Mon Sep 17 00:00:00 2001 From: HIRAKI Satoru Date: Sun, 25 Dec 2011 01:41:29 +0900 Subject: [PATCH 202/463] fix translate in "semicolon" --- doc/ja/core/semicolon.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/doc/ja/core/semicolon.md b/doc/ja/core/semicolon.md index f7d7c07d..72b00011 100644 --- a/doc/ja/core/semicolon.md +++ b/doc/ja/core/semicolon.md @@ -77,9 +77,10 @@ JavaScriptはセミコロン無しの言語ではありません。実際に、 })(window); //<- 挿入 -> **注意点:** JavaScriptパーサーは新しい行のreturn文を「正しく」返してはいないですが、 -> これは必要という訳では無いので自動セミコロン挿入の障害になります。 -> このお陰で不必要な副作用を無くす事にもなります。 +> **注意点:** JavaScriptパーサーは、すぐ後に改行が続く return文を正しく扱いません。 +> これは必ずしも自動セミコロン挿入の欠点によるものではありませんが、 +> それもまた望まない副作用となりえます。 + パーサーは上記のコードの振舞いを劇的に変化させます。あるケースにおいては、**間違っている事**にもなってしまいます。 @@ -98,4 +99,4 @@ JavaScriptはセミコロン無しの言語ではありません。実際に、 ### 終わりに -セミコロンを省略するのは**絶対**にお勧めしません。この事はまた括弧をその終端と一緒の行に書く事が推奨されてますし、1つの`if`や`else`文を絶対に省略してはなりません。これら両方の処理がコードの整合性を高めてくれる上、JavaScriptパーサーの振舞いを変えてしまうのを防いでくれるでしょう。 +セミコロンを省略するのは**絶対**にお勧めしません。括弧を対応する文と同じ行に記述すること、および一行の`if / else`文に対して括弧を省略しないことが推奨されています。これら両方の処理がコードの整合性を高めてくれるだけでなく、JavaScriptパーサーの振舞いを変えてしまうのを防いでくれるでしょう。 From d738831621967d0639abc462853d31bafafa0f60 Mon Sep 17 00:00:00 2001 From: HIRAKI Satoru Date: Mon, 2 Jan 2012 18:45:55 +0900 Subject: [PATCH 203/463] fix translate in "timeout" --- doc/ja/other/timeouts.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/doc/ja/other/timeouts.md b/doc/ja/other/timeouts.md index 3f5d2deb..3a4cbda1 100644 --- a/doc/ja/other/timeouts.md +++ b/doc/ja/other/timeouts.md @@ -8,9 +8,9 @@ JavaScriptは非同期なので、`setTimeout`と`setInterval`関数を使って function foo() {} var id = setTimeout(foo, 1000); // Number > 0を返す -`setTimeout`が呼ばれた時に、タイムアウトのIDと`foo`この先の**おおよそ**1000msに実行するスケジュールを返します。`foo`は正確に**1度**だけ実行されます。 +`setTimeout`が呼ばれた時に、タイムアウトのIDを返し、この先**おおよそ**1000ms以内に実行する`foo`をスケジュールします。`foo`は正確に**1度**だけ実行されます。 -コードが実行されているJavaScriptエンジンのタイマー分解能によって決まります。この事実はJavaScriptがシングルスレッドのなので、他のスレッドでの実行を妨害してしまう事があるかもしれません。これは、`setTimeout`関数の呼び出しで指定した遅延時間を正確に間違いなく得られるという**意味では決してありません**。 +これは、`setTimeout`関数の呼び出しで指定した遅延時間を正確に間違いなく得られるという**事では決してありません**。コードが実行されているJavaScriptエンジンのタイマー分解能によって決まります。この事実はJavaScriptがシングルスレッドなので、他のスレッドでの実行を妨害してしまう事があるかもしれません。 第一パラメーターを渡された関数は*グローバルオブジェクト*によって呼び出されます。これは呼び出された関数の内部で[`this`](#functionis)がまさにこのオブジェクトを参照しているという事になります。 @@ -44,7 +44,7 @@ JavaScriptは非同期なので、`setTimeout`と`setInterval`関数を使って 上記のコードでは、`foo`が1回呼び出されて、1秒ブロックされます。 -`foo`がコードをブロックしている間、`setInterval`は呼び出される予定を確保しています。`foo`が完了した瞬間に、実行を待っている間に**10回**以上呼び出されている事になります。 +`foo`がコードをブロックしている間、`setInterval`は呼び出される予定を確保しています。`foo`が完了した瞬間に、実行を待っている呼び出しが**10回**以上存在しているでしょう。 ### ブロッキング可能なコードの取り扱い @@ -74,7 +74,7 @@ JavaScriptは非同期なので、`setTimeout`と`setInterval`関数を使って clearTimeout(i); } -ここまでもまだ、任意の数字を与えられた為に影響を受けないタイムアウトがあるかもしれません。しかし、全てのタイムアウトのIDを追跡していく事は推奨されないので、それらは個別にクリアされます。 +ここまでもまだ、任意の数字を与えられた為に影響を受けないタイムアウトがあるかもしれません。そのため、代わりに全てのタイムアウトのIDを追跡する事が推奨されます。それで個別にクリアされます。 ### 隠された`eval`の使用 @@ -99,7 +99,7 @@ JavaScriptは非同期なので、`setTimeout`と`setInterval`関数を使って この場合、`eval`は[直接](#core.eval)呼ばれないので、文字列が渡された`setTimeout`は*global scope*で実行されます。よって、`bar`のスコープから`foo`のローカル変数は使われないのです。 -タイムアウト関数によって呼び出される関数を引数に渡すために文字列を使わ**ない**という事は、それ以上に推奨されています。 +いずれかのタイムアウト関数によって呼び出される関数に引数を渡すために文字列を使わ**ない**という事は、さらに推奨されています。 function foo(a, b, c) {} From e932fb122c4688fcd7226fca76c0a10847df2a04 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julio=20Napur=C3=AD?= Date: Sat, 7 Jan 2012 15:04:01 -0500 Subject: [PATCH 204/463] Updated .gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 7aa6a9ed..237404f0 100644 --- a/.gitignore +++ b/.gitignore @@ -12,5 +12,6 @@ /site/tr /site/ko /site/ja +/site/es *.md~ *.src.md From 4a9d9a1e05d529c9ffe63af418113c3a778ef992 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julio=20Napur=C3=AD?= Date: Sat, 7 Jan 2012 15:04:20 -0500 Subject: [PATCH 205/463] Updated language.json --- doc/language.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/language.json b/doc/language.json index ad49560d..19ef049f 100644 --- a/doc/language.json +++ b/doc/language.json @@ -1,5 +1,5 @@ { "default": "en", - "listed": ["en", "fi", "ru", "zh", "tr", "pl", "ko", "ja"] + "listed": ["en", "fi", "ru", "zh", "tr", "pl", "ko", "ja", "es"] } From b0c71b2704ddd2a9f57023321a340ce97727c0ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julio=20Napur=C3=AD?= Date: Sat, 7 Jan 2012 15:04:49 -0500 Subject: [PATCH 206/463] Spanish translation --- doc/es/array/constructor.md | 35 +++++ doc/es/array/general.md | 58 ++++++++ doc/es/core/delete.md | 87 ++++++++++++ doc/es/core/eval.md | 47 +++++++ doc/es/core/semicolon.md | 114 ++++++++++++++++ doc/es/core/undefined.md | 72 ++++++++++ doc/es/function/arguments.md | 119 ++++++++++++++++ doc/es/function/closures.md | 98 ++++++++++++++ doc/es/function/constructors.md | 129 ++++++++++++++++++ doc/es/function/general.md | 48 +++++++ doc/es/function/scopes.md | 231 ++++++++++++++++++++++++++++++++ doc/es/function/this.md | 111 +++++++++++++++ doc/es/index.json | 68 ++++++++++ doc/es/intro/index.md | 47 +++++++ doc/es/object/forinloop.md | 51 +++++++ doc/es/object/general.md | 99 ++++++++++++++ doc/es/object/hasownproperty.md | 53 ++++++++ doc/es/object/prototype.md | 116 ++++++++++++++++ doc/es/other/timeouts.md | 155 +++++++++++++++++++++ doc/es/types/casting.md | 70 ++++++++++ doc/es/types/equality.md | 71 ++++++++++ doc/es/types/instanceof.md | 38 ++++++ doc/es/types/typeof.md | 87 ++++++++++++ 23 files changed, 2004 insertions(+) create mode 100644 doc/es/array/constructor.md create mode 100644 doc/es/array/general.md create mode 100644 doc/es/core/delete.md create mode 100644 doc/es/core/eval.md create mode 100644 doc/es/core/semicolon.md create mode 100644 doc/es/core/undefined.md create mode 100644 doc/es/function/arguments.md create mode 100644 doc/es/function/closures.md create mode 100644 doc/es/function/constructors.md create mode 100644 doc/es/function/general.md create mode 100644 doc/es/function/scopes.md create mode 100644 doc/es/function/this.md create mode 100644 doc/es/index.json create mode 100644 doc/es/intro/index.md create mode 100644 doc/es/object/forinloop.md create mode 100644 doc/es/object/general.md create mode 100644 doc/es/object/hasownproperty.md create mode 100644 doc/es/object/prototype.md create mode 100644 doc/es/other/timeouts.md create mode 100644 doc/es/types/casting.md create mode 100644 doc/es/types/equality.md create mode 100644 doc/es/types/instanceof.md create mode 100644 doc/es/types/typeof.md diff --git a/doc/es/array/constructor.md b/doc/es/array/constructor.md new file mode 100644 index 00000000..46c5c16f --- /dev/null +++ b/doc/es/array/constructor.md @@ -0,0 +1,35 @@ +## El constructor `Array` + +Desde el constructor `Array` es ambiguo en la forma en que ocupa sus párametros, +es recomendable siempre el uso de arrays literales - la notación `[]` - +cuando se crean nuevos arrays. + + [1, 2, 3]; // Resultado: [1, 2, 3] + new Array(1, 2, 3); // Resultado: [1, 2, 3] + + [3]; // Resultado: [3] + new Array(3); // Resultado: [] + new Array('3') // Resultado: ['3'] + +En casos cuando sólo hay un argumento pasado al constructor del `Array`, +y que el argumento es un `Número`, el contructor devolverá un array *disperso* +con la propiedad `length` establecida al valor del argumento. Esto debe señalarse +que la propiedad `length` **sólo** del nuevo array se establecerá de esa manera, +los índices reales de la matriz no se iniciará. + + var arr = new Array(3); + arr[1]; // undefined + 1 in arr; // falso, el índice no se ha establecido + +El comportamiento de poder establecer la longitud de un array inicial sólo es útil +en algunos casos array, como la repetición de una cadena, en la que se evita el uso +del código de `bucle for`. + + new Array(count + 1).join(stringToRepeat); + +### En conclusión + +El uso de un constructor `Array` debe ser devuelto como sea posible. +Los literales son definitivamente preferidos. Estos son más cortos y tienen una +sintaxis más limpia; por lo tanto, también se incrementa la legibilidad del código. + diff --git a/doc/es/array/general.md b/doc/es/array/general.md new file mode 100644 index 00000000..944590b0 --- /dev/null +++ b/doc/es/array/general.md @@ -0,0 +1,58 @@ +## Iteración de un Array y sus propiedades + +A pesar que los arrays en JavaScript son objetos, no existe un buena razón para +usarlo en un [`bucle for`](#object.forinloop) para una interación de este. De +hecho, hay un número de buenas razones **contra** el uso de `for in` en arrays. + +> **Nota:** Los arrays de JavaScript **no** son *arrays asociativos*. JavaScript sólo +> tiene [objetos](#object.general) para el mapeo de keys a valores. Y mientras +> que los arrays asociativos **preservan** el orden, los objetos **no**. + +Dado que el bucle `for in` enumera todas las propiedades que están en una cadena +de prototipo y la única manera para excluir estas propiedades es el uso de +[`hasOwnProperty`](#object.hasownproperty), ya que es **veinte veces** más +lento que un bucle `for` normal. + +### Iteración + +Con el fin de obtener el mejor rendimiento cuando se repite la interación de arrays, +es lo mejor hacer uso del clásico bucle `for`. + + var list = [1, 2, 3, 4, 5, ...... 100000000]; + for(var i = 0, l = list.length; i < l; i++) { + console.log(list[i]); + } + +Hay una captura adicional en el ejemplo anterior, que es el almacenamiento de la +caché de longitud del array vía `l = list.length`. + +Aunque la propiedad `length` es definida en el mismo array, todavía posee una sobrecarga +para realizar la búsqueda en cada interación del bucle. Y mientras que los últimos +motores de JavaScript **pueden** aplicar optimizaciones en este caso, no hay manera +de saber si el ćodigo se ejecutará en uno de estos nuevos motores nuevos o no. + +De hecho, dejando de lado el alamacenamiento en caché puede resultar que el bucle +inicie sólo la **mitad de rápido** que con la longitud de la caché. + +### La propiedad `length` + +Mientras que *getter* de la propiedad `length` simplemente retorne el número de +elementos son contenidos en un array, el *setter* puede ser usado para +**truncar** el array. + + var foo = [1, 2, 3, 4, 5, 6]; + foo.length = 3; + foo; // [1, 2, 3] + + foo.length = 6; + foo; // [1, 2, 3] + +La asignación de un menor número de longitud trunca al array, pero incrementando la +longitud no tiene ningún efecto sobre el array. + +### En conclusión + +Para obtener el mejor rendimiento es recomendable siempre usar el bucle `for` +y alamacenar en caché la propiedad `length`. El uso del bucle `for in` en un array +es señal de un código mal escrito propenso a errores y un mal desempeño. + diff --git a/doc/es/core/delete.md b/doc/es/core/delete.md new file mode 100644 index 00000000..1d0d198a --- /dev/null +++ b/doc/es/core/delete.md @@ -0,0 +1,87 @@ +## The `delete` Operator + +In short, it's *impossible* to delete global variables, functions and some other +stuff in JavaScript which have a `DontDelete` attribute set. + +### Global code and Function code + +When a variable or a function is defined in a global +or a [function scope](#function.scopes) it is a property of either +Activation object or Global object. Such properties have a set of attributes, +one of these is `DontDelete`. Variable and function declarations in global +and function code always create properties with `DontDelete`, therefore +cannot be deleted. + + // global variable: + var a = 1; // DontDelete is set + delete a; // false + a; // 1 + + // normal function: + function f() {} // DontDelete is set + delete f; // false + typeof f; // "function" + + // reassigning doesn't help: + f = 1; + delete f; // false + f; // 1 + +### Explicit properties + +There are things which can be deleted normally: these are explicitly set +properties. + + // explicitly set property: + var obj = {x: 1}; + obj.y = 2; + delete obj.x; // true + delete obj.y; // true + obj.x; // undefined + obj.y; // undefined + +In the example above `obj.x` and `obj.y` can be deleted because they have no +`DontDelete` atribute. That's why an example below works too. + + // this works fine, except for IE: + var GLOBAL_OBJECT = this; + GLOBAL_OBJECT.a = 1; + a === GLOBAL_OBJECT.a; // true - just a global var + delete GLOBAL_OBJECT.a; // true + GLOBAL_OBJECT.a; // undefined + +Here we use a trick to delete `a`. [`this`](#function.this) here refers +to the Global object and we explicitly declare variable `a` as it's property +which allows us to delete it. + +IE (at least 6-8) has some bugs, so code above doesn't work. + +### Function arguments and built-ins + +Functions' normal arguments, [`arguments` object](#function.arguments) +and built-in properties also have `DontDelete` set. + + // function arguments and properties: + (function (x) { + + delete arguments; // false + typeof arguments; // "object" + + delete x; // false + x; // 1 + + function f(){} + delete f.length; // false + typeof f.length; // "number" + + })(1); + +### Host objects + +Behaviour of `delete` operator can be unpredictable for hosted objects. Due to +specification, host objects are allowed to implement any kind of behavior. + +### In conclusion + +`delete` operator often has an unexpected behaviour and can be safely used +only for dealing with explicitly set properties on normal objects. diff --git a/doc/es/core/eval.md b/doc/es/core/eval.md new file mode 100644 index 00000000..208bd280 --- /dev/null +++ b/doc/es/core/eval.md @@ -0,0 +1,47 @@ +## ¿Por qué no usar `eval`? + +La función `eval` ejecuta un string como código JavaScript en el ámbito local. + + var foo = 1; + function test() { + var foo = 2; + eval('foo = 3'); + return foo; + } + test(); // 3 + foo; // 1 + +Pero `eval` sólo ejecutará en ámbito local cuando es llamado **directamente** *y* +el nombre de la función llamada es `eval`. + + var foo = 1; + function test() { + var foo = 2; + var bar = eval; + bar('foo = 3'); + return foo; + } + test(); // 2 + foo; // 3 + +El uso de `eval` debe evitarse **a toda costa**. El 99.9% de su "uso" puede +lograrse **sin** su uso.. + +### `eval` disfrazado + +Las funciones de [tiempo de espera](#other.timeouts) `setTimeout` y `setInterval` pueden +tomar un string como primer argumento. En este caso, el string **siempre** se ejecutará en +el ámbito global ya que `eval` no ha sido llamado directamente. + +### Problemas de seguridad + +`eval` es también un problema de seguridad ya que ejecuta **cualquier** código enviado, +y **nunca** debe usarse con strings que no se conozcan o tengan un origen no confiable. + +### En conclusión + +`eval` nunca debe ser usado, cualquier código que haga uso del mismo debe ser cuestionado +en su funcionamiento, rendimiento y seguridad. En caso de que se necesite trabajar con +`eval`, el diseño ha de ser cuestionado y **no** debe utilizarse en primer lugar, se +debe usar un *mejor diseño*, que no requiera el uso de `eval`. + diff --git a/doc/es/core/semicolon.md b/doc/es/core/semicolon.md new file mode 100644 index 00000000..f03f7d82 --- /dev/null +++ b/doc/es/core/semicolon.md @@ -0,0 +1,114 @@ +## Automatic Semicolon Insertion + +Although JavaScript has C style syntax, it does **not** enforce the use of +semicolons in the source code, so it is possible to omit them. + +JavaScript is not a semicolon-less language. In fact, it needs the +semicolons in order to understand the source code. Therefore, the JavaScript +parser **automatically** inserts them whenever it encounters a parse +error due to a missing semicolon. + + var foo = function() { + } // parse error, semicolon expected + test() + +Insertion happens, and the parser tries again. + + var foo = function() { + }; // no error, parser continues + test() + +The automatic insertion of semicolon is considered to be one of **biggest** +design flaws in the language because it *can* change the behavior of code. + +### How it Works + +The code below has no semicolons in it, so it is up to the parser to decide where +to insert them. + + (function(window, undefined) { + function test(options) { + log('testing!') + + (options.list || []).forEach(function(i) { + + }) + + options.value.test( + 'long string to pass here', + 'and another long string to pass' + ) + + return + { + foo: function() {} + } + } + window.test = test + + })(window) + + (function(window) { + window.someLibrary = {} + + })(window) + +Below is the result of the parser's "guessing" game. + + (function(window, undefined) { + function test(options) { + + // Not inserted, lines got merged + log('testing!')(options.list || []).forEach(function(i) { + + }); // <- inserted + + options.value.test( + 'long string to pass here', + 'and another long string to pass' + ); // <- inserted + + return; // <- inserted, breaks the return statement + { // treated as a block + + // a label and a single expression statement + foo: function() {} + }; // <- inserted + } + window.test = test; // <- inserted + + // The lines got merged again + })(window)(function(window) { + window.someLibrary = {}; // <- inserted + + })(window); //<- inserted + +> **Note:** The JavaScript parser does not "correctly" handle return statements +> which are followed by a new line, while this is not neccessarily the fault of +> the automatic semicolon insertion, it can still be an unwanted side-effect. + +The parser drastically changed the behavior of the code above. In certain cases, +it does the **wrong thing**. + +### Leading Parenthesis + +In case of a leading parenthesis, the parser will **not** insert a semicolon. + + log('testing!') + (options.list || []).forEach(function(i) {}) + +This code gets transformed into one line. + + log('testing!')(options.list || []).forEach(function(i) {}) + +Chances are **very** high that `log` does **not** return a function; therefore, +the above will yield a `TypeError` stating that `undefined is not a function`. + +### In Conclusion + +It is highly recommended to **never** omit semicolons; it is also advocated to +keep braces on the same line with their corresponding statements and to never omit +them for one single-line `if` / `else` statements. Both of these measures will +not only improve the consistency of the code, but they will also prevent the +JavaScript parser from changing its behavior. + diff --git a/doc/es/core/undefined.md b/doc/es/core/undefined.md new file mode 100644 index 00000000..deda99bc --- /dev/null +++ b/doc/es/core/undefined.md @@ -0,0 +1,72 @@ +## `undefined` y `null` + +JavaScript tiene dos valores distintos para `nothing`, el más útil de estos dos +es `undefined`. + +### El valor `undefined` + +`undefined` es un tipo de dato con exactamente el mismo valor: `undefined`. + +El lenguaje también define una variable global que tiene el valor de `undefined`, +Esta variable es también llamada `undefined`. Sin embargo, esta variable **no** es una +constante, ni es una palabra reservada del lenguaje. Esto significa que el *valor* +puede ser sobreescrito fácilmente. + +> **Nota ES5:** `undefined` en ECMAScript 5 **ya no es** *modificable* en modo esstricto, +> pero su nombre todavía puede por ejemplo establecer una función con el nombre +> `undefined`. + +Algunos ejemplos de cuando el valor retorna `undefined`: + + - Acceso a la variable global (sin modificar) `undefined`. + - Retorna implícitamente las funciones que no posean la sentencia `return`. + - `return` statements which do not explicitly return anything. + - Lookups of non-existent properties. + - Function parameters which do not had any explicit value passed. + - Anything that has been set to the value of `undefined`. + +### Handling Changes to the Value of `undefined` + +Since the global variable `undefined` only holds a copy of the actual *value* of +`undefined`, assigning a new value to it does **not** change the value of the +*type* `undefined`. + +Still, in order to compare something against the value of `undefined` it is +necessary to retrieve the value of `undefined` first. + +In order to protect code against a possible overwritten `undefined` variable, a +common technique used is to add an additional parameter to an +[anonymous wrapper](#function.scopes), that gets no argument passed to it. + + var undefined = 123; + (function(something, foo, undefined) { + // undefined in the local scope does + // now again refer to the value + + })('Hello World', 42); + +Another way to achieve the same effect would be to use a declaration inside the +wrapper. + + var undefined = 123; + (function(something, foo) { + var undefined; + ... + + })('Hello World', 42); + +The only difference being here, that this version results in 4 more bytes being +used in case it is minified and there is no other `var` statement inside the +anonymous wrapper. + +### Uses of `null` + +While `undefined` in the context of the JavaScript language is mostly used in +the sense of a traditional *null*, the actual `null` (both a literal and a type) +is more or less just another data type. + +It is used in some JavaScript internals (like declaring the end of the +prototype chain by setting `Foo.prototype = null`), but in almost all cases it +can be replaced by `undefined`. + + diff --git a/doc/es/function/arguments.md b/doc/es/function/arguments.md new file mode 100644 index 00000000..0eff8daf --- /dev/null +++ b/doc/es/function/arguments.md @@ -0,0 +1,119 @@ +## El objeto `arguments` + +Cada ámbito de la función de JavaScript puede acceder a la variable especial `arguments`. +Está variable contiene una lista de todos los argumentos que se pasan a la función. + +> **Nota:** En este caso `arguments` ya se ha definido dentro del ámbito de la +> función ya sea através de la sentencia `var` o como un parámetro formal, +> el objeto `arguments` no se creará. + +El objeto `arguments` **no** es un `Array`. Si bien cuenta con la semántica +de un array - concretamente la propiedad `length` - no hereda de +`Array.prototype` y es de hecho un `Objeto`. + +Debido a esto, **no** es posible usar los métodos estándar de los arrays como `push`, +`pop` o `slice` en `arguments`. Mientras que la iteración es un simple bucle `for` que +funciona muy bien, esto se convierte necesariamente en un `Array` real con el +fin de utilizar los métodos de un `Array`. + +### Conversión de un Array + +El siguiente código devuelve un nuevo `Array` que contiene todos los elementos del +objeto `arguments`. + + Array.prototype.slice.call(arguments); + +Esta conversión es **lenta**, **no es recomendable** usarlo en puntos criticos que +afecten el rendimiento del código. + +### Pasar Argumentos + +El siguiente método es recomendado para pasar argumentos desde una función a +otra. + + function foo() { + bar.apply(null, arguments); + } + function bar(a, b, c) { + // do stuff here + } + +Otro truco es utilizar tanto `call` y `apply` juntos para crear contenedores rápidos y +consolidados. + + function Foo() {} + + Foo.prototype.method = function(a, b, c) { + console.log(this, a, b, c); + }; + + // Crea una versión sin consolidar de "method" + // Se toma los parámetros: this, arg1, arg2...argN + Foo.method = function() { + + // Resultado: Foo.prototype.method.call(this, arg1, arg2... argN) + Function.call.apply(Foo.prototype.method, arguments); + }; + + +### Los parámetros formales y argumentos de índices + +El objeto `arguments` crea las funciones de *getter* y *setter* para sus +propiedades, así como parámetros formales de la función. + +Como resultado, se ha cambiado el valor formal del parámetro también se cambio el +valor de la propiedad correspondiente del objeto `arguments`, y al revés. + + 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); + +### Mitos y verdades sobre el rendimiento + +El objeto `arguments` es siempre creado con las dos únicas excepciones cuando es +el caso en que declarado como un nombre dentro de la función o uno de los +parámetros formales. No importa si se utiliza o no. + +Ambos *getters* y *setters* son **siempre** creados; por lo tanto, con que casi no se +tiene un impacto en el rendimiento en todo, especialemente no en el código real donde no +es más que un simple acceso a las propiedades del objeto `arguments`. + +> **Nota ES5:** Estos *getters* y *setters* no son creados en modo estricto. + +Sin embargo, hay casos en que se reducirá drásticamente el rendimiento en los motores +modernos de JavaScript. Este es el caso del uso de `arguments.callee`. + + function foo() { + arguments.callee; // realiza algo con la función del objeto + arguments.callee.caller; // y llama a la función del objeto + } + + function bigLoop() { + for(var i = 0; i < 100000; i++) { + foo(); // Debería ser normalmente entre líneas... + } + } + +El código anterior, `foo` no puede estar sujeto a la [expansión en línea][1] ya que se +necesita saber acerca de sí mismo y la llamada. Esto no sólo denota los posibles beneficios +de rendimiento que surgen con la expansión en línea, ya que también interrumpe la encapsulación +ya que la función ahora puede ser dependiente de un contexto específico de llamada. + +Es **muy recomendable** **nunca** hacer uso de `arguments.callee` o de cualquier +de sus propiedades. + +> **Nota ES5:** En modo estricto, `arguments.callee` generará una excepción de `TypeError` ya que +> su uso ha quedado obsoleto. + +[1]: http://en.wikipedia.org/wiki/Inlining + + diff --git a/doc/es/function/closures.md b/doc/es/function/closures.md new file mode 100644 index 00000000..40a77215 --- /dev/null +++ b/doc/es/function/closures.md @@ -0,0 +1,98 @@ +## Closures y referencias + +Una de las características más poderosas de JavaScript es la disponibilidad de *closures* (cerraduras), +esto significa que los ámbitos **siempre** podrán ser accedidos por ámbitos externos donde +fueron definidos. Dado que sólo el alcance es único en JavaScript en el +[ámbito de la función](#function.scopes), todas las funciones, por omisión, actúan como closures. + +### Emulando variables privadas + + function Counter(start) { + var count = start; + return { + increment: function() { + count++; + }, + + get: function() { + return count; + } + } + } + + var foo = Counter(4); + foo.increment(); + foo.get(); // 5 + +En este caso, `Counter` retorna **dos** closures. La función `increment` y la +función `get`. Ambas funciones mantienen el ámbito de la **referencia** de +`Counter` y, por lo tanto, siempre accede a la variable `count` que fue definido +en el ámbito. + +### ¿Por qué las variables privadas trabajan? + +Dado que no es posible referenciar o asignar ámbitos en JavaScript, **no** hay +manera de acceder a la variable `count` desde fuera. Sólo existe una forma para +interactuar con estos vía los dos closures. + + var foo = new Counter(4); + foo.hack = function() { + count = 1337; + }; + +El código anterior **no** ha cambiado la variable `count` en el ámbito de `Counter`, +desde `foo.hack` no es definido en **ese** ámbito. En su lugar se creará - o +se anulará - la variable *global* `count`. + +### Closures dentro de bucles + +Un error frecuente en el uso de closures dentro de bucles, es como si se tratará +de copiar el valor del índice de la variable del bucle. + + for(var i = 0; i < 10; i++) { + setTimeout(function() { + console.log(i); + }, 1000); + } + +El código anterior **no** tendrá como salida los números del `0` al `9`, sino +simplementemente se imprimirá el número `10` diez veces. + +La función *anónima* hace **referencia** a `i` y se llama a +`console.log`, el `bucle for` ya ha terminado y finalizo el valor de +`i` a `10`. + +Con el fin de obtener el comportamiento deseado, es necesario crear una **copia** +del valor de `i`. + +### Evitando el problema de referencia + +Con el fin de copiar el valor de la variable índice del bucle, lo mejor es utilizar +un [contenedor anónimo](#function.scopes). + + for(var i = 0; i < 10; i++) { + (function(e) { + setTimeout(function() { + console.log(e); + }, 1000); + })(i); + } + +La función anónima externa llamará inmediatamente a `i` como su primer +argumento y recibirá la copia del **valor** de `i` como parámetro de `e`. + +La función anónima que se pasa a `setTimeout` ahora es una referencia a +`e`, cuyo valor **no** han sido cambiados por el bucle. + +No hay otra manera de lograr esto; se debe retornar una función desde +el contenedor anónimo, que tendrá el mismo comportamiento que el código +anterior. + + for(var i = 0; i < 10; i++) { + setTimeout((function(e) { + return function() { + console.log(e); + } + })(i), 1000) + } + diff --git a/doc/es/function/constructors.md b/doc/es/function/constructors.md new file mode 100644 index 00000000..0850cb4b --- /dev/null +++ b/doc/es/function/constructors.md @@ -0,0 +1,129 @@ +## Constructores + +Los constructores en JavaScript todavía son diferentes a los de otros lenguajes. +Cualquier llamada que es precedida por la palabra `new` actua como un constructor. + +Dentro del constructor - la función llama - el valor de `this` se refiere a un +`Objeto` recién creado. El [`prototipo`](#object.prototype) de este **nuevo** +objeto se establece en el `prototipo` de la funcióno que es invocado como el +constructor. + +Si la función que se llama no tiene una sentencia `return` explícita, entonces +implícitamente devuelve el valor de `this` - el nuevo objeto. + + function Foo() { + this.bla = 1; + } + + Foo.prototype.test = function() { + console.log(this.bla); + }; + + var test = new Foo(); + +La llamada de `Foo` por encima del constructor y establece el `prototipo` del objeto +recién creado a `Foo.prototype`. + +En caso explícito de la sentencia `return` de la función devuelva el valor especificado +que la declaración, **pero sólo** si el valor devuelto es un `Object`. + + function Bar() { + return 2; + } + new Bar(); // a new object + + function Test() { + this.value = 2; + + return { + foo: 1 + }; + } + new Test(); // the returned object + +Cuando una `nueva` keyword es omitidad, la función **no** devuelve un nuevo objeto. + + function Foo() { + this.bla = 1; // se establece en el objeto global + } + Foo(); // undefined + +Auqnue el ejemplo anterior puede parecer que trabaja en algunos casos, debido +a los trabajos de [`this`](#function.this) en JavaScript, que usará el +*objeto global* como valor de `this`. + +### Fábricas + +Con el fin de ser capaz de omitir un `nuevo` keyword, la función del tiene +explícitamente devolver un valor. + + function Bar() { + var value = 1; + return { + method: function() { + return value; + } + } + } + Bar.prototype = { + foo: function() {} + }; + + new Bar(); + Bar(); + +Ambos llamadas a `Bar` devuelven exactamente lo mismo, un reciente objeto creado que +tiene como propiedad llamada el `method`, esto es un +[Closure](#function.closures). + +También hay que notar que la llamada `new Bar()` **no** afecta al prototipo +del objeto devuelto. Mientras que el prototipo se establece en el objeto recién creado, + `Bar` nunca devuelve un nuevo objeto. + +En el ejemplo anterior, no hay diferencia funcional entre usar y no usar +el keyword `new`. + + +### Creación de nuevos objetos vía Factorias + +Una recomendación a menudo es **no** utilizar `new` ya que su uso puede +conducir a errores. + +Con el fin de crear un nuevo objeto, uno bien debe utilizar una fábrica y un +constructor para crear un nuevo objeto dentro de la fábrica. + + function Foo() { + var obj = {}; + obj.value = 'blub'; + + var private = 2; + obj.someMethod = function(value) { + this.value = value; + } + + obj.getPrivate = function() { + return private; + } + return obj; + } + +Aunque lo anterior es robuesto frente a la keyword `new` y, ciertamente hace +que el uso de [variables privadas](#function.closures) sea fácil, esto viene con +algunas desventajas. + + 1. Se utiliza más memoria, ya que los objetos creados **no** comparten los métodos de + un prototipo. + 2. Con el fin de heredar de una fábrica se necesita copiar todos los métodos a otro + objeto o poner todo en un prototipo de nuevo objeto. + 3. La eliminación de una cadena de prototipo sólo por dejar la keyword `new` de + alguna manera va en contra del espíritu del lenguaje. + +### En conclusión + +Mientras que se omite el keyword `new` podría dar a errores, **no** es ciertamente +una razón para abandonar el uso de prototipos por completo. Al final todo se reduce a +la solución que se adapta mejor a las necesidades de la aplicación, especialmente si es +importante elegir un estilo específico en la creación de objetos +**y resistirse**. + + diff --git a/doc/es/function/general.md b/doc/es/function/general.md new file mode 100644 index 00000000..d9621bc5 --- /dev/null +++ b/doc/es/function/general.md @@ -0,0 +1,48 @@ +## La declaración de funciones y expresiones + +Las funciones en JavaScript son las primeras clases de objetos. Esto significa que se +puede pasar como cualquier otro valor. Un uso común de está característica es pasar de +una *función anónima* a otra, posiblemente una función asíncrona. Esto se conoce como `callback`. + +### La declaración `function` + + function foo() {} + +La función anterior se [carga](#function.scopes) así mismo antes de iniciar la ejecución del +programa; por lo tanto, está disponible en *todo* el scope (ámbito) de la aplicación +donde se ha *definido*, aunque hubiera sido llamado antes de definirse en el código. + + foo(); // Funciona porque foo ha sido creado antes que este código se ejecute + function foo() {} + +### La expresión `function` + + var foo = function() {}; + +Este ejemplo asigna una función sin nombre y anónima a la variable `foo`. + + foo; // 'undefined' + foo(); // Lanza TypeError + var foo = function() {}; + +Debido a la declaración de `var`, que carga el nombre de la variable `foo` antes +de la ejecución real del inicio del código, `foo` ya estará definidido cuando se +ejecute el script. + +Pero se asigna sólo si ocurre en tiempo de ejecución, el valor de `foo` de forma +predetermina es [undefined](#core.undefined) antes de que el código se ejecute. + +### Expresión nombre de función + +Otro caso especial de asignación de nombre de funciones. + + var foo = function bar() { + bar(); // Funciona + } + bar(); // ReferenceError + +Aquí `bar` no está disponible en el ámbito externo (scope), ya que la función sólo es +asignada a `foo`; Sin embargo, dentro de `bar` si está disponible. Esto se debe a la forma +en como trabaja la [resolución de nombres](#function.scopes) en JavaScript, el nombre de +la función esta *siempre* disponible en el ámbito local de la propia función. + diff --git a/doc/es/function/scopes.md b/doc/es/function/scopes.md new file mode 100644 index 00000000..d641a939 --- /dev/null +++ b/doc/es/function/scopes.md @@ -0,0 +1,231 @@ +## Ámbitos y Namespaces + +A pesar que JavaScript tiene una muy buena sintaxis de dos llaves para los bloques, +está **no** es compatible con el soporte de ámbito de bloques; por lo que todo se deja +al lenguaje con el *ámbito de la función*. + + function test() { // un ámbito + for(var i = 0; i < 10; i++) { // no es un ámbito + // cuenta + } + console.log(i); // 10 + } + +> **Nota:** Cuando no use una instrucción, de retorno o una función como +> argumento, la notación de `{...}` serán interpretadas como una declaración de bloques y +> **no** como un objeto literal. Esto, en conjunto con la +> [inserción automática de punto y coma](#core.semicolon), puede conducir a errores sutiles. + +Tampoco hay distintos namespaces en JavaScript, lo que significa que todo se define +en un namespace *global y compartido*. + +Cada vez que una variable es referenciada, JavaScript recorre hacia arriba a través de todos +los ámbitos hasta encontrarlo. En este caso que llegue al ámbito global y todavía no ha +encontrado el nombre solicitado, se generará un error `ReferenceError`. + +### El terror de las variables globales + + // script A + foo = '42'; + + // script B + var foo = '42' + +Estos dos scripts **no** tienen el mismo efecto. El script A define una variable +llamada `foo` en el ámbito *global* y el script B define `foo` en el +*actual* ámbito. + +Una vez más, esto **no** tiene el *mismo efecto* para todo, no usar `var` puede tener +mayor implicación. + + // ámbito global + var foo = 42; + function test() { + // ámbito local + foo = 21; + } + test(); + foo; // 21 + +Dejando de lador la sentencia `var` dentro de la función `test` sobre escribiría el +valor de `foo`. Si bien al principio puede parecer un gran cambio, se tiene +miles de líneas de código en JavaScript y no se usaría `var` introduciendose en un +horrible y difícil detección de errores. + + // ámbito global + var items = [/* some list */]; + for(var i = 0; i < 10; i++) { + subLoop(); + } + + function subLoop() { + // ámbito de subLoop + for(i = 0; i < 10; i++) { // falta la sentencia var + // ¡realizar cosas asombrosas! + } + } + +El bucle externo terminará después de la primera llamada a `subLoop`, desde `subLoop` +sobreescribe el valor global de `i`. Usando `var` para el segundo bucle `for` se hace +fácil evitar este error. La sentencia `var` no debe **nunca** dejarse a menos que +el *efecto deseado* es afectado por el ámbito exteriror. + +### Variables locales + +La única fuente para las variables locales en JavaScript son los parámetros de la +[función](#function.general) y variables que fueron declaradas vía la sentencia +`var`. + + // ámbito global + var foo = 1; + var bar = 2; + var i = 2; + + function test(i) { + // ámbito local de la función test + i = 5; + + var foo = 3; + bar = 4; + } + test(10); + +Mientras `foo` y `i` son variables locales dentro del ámbitor de la función `test`, +ela asignación de `bar` sobreescribe la variable global con el mismo nombre. + +### Hoisting + +La declaración de **hoists** en JavaScript. Esto significa que tanto la declaración de `var` y +la `función` declarada se translada a la parte superior de su ámbito que lo contiene. + + 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]; + } + } + +El código anterior transforma antes de ejecutarse. JavaScript mueve +la declaracione `var` aspi como las declaraciones de la `función` a la parte superior a +lo más cercano del ámbito circundante. + + // declaraciones var movidas aquí + var bar, someValue; // por omisión 'undefined' + + // la función declarada es movida aquí también + function test(data) { + var goo, i, e; // se pierde el ámbito del bloque movido aquí + if (false) { + goo = 1; + + } else { + goo = 2; + } + for(i = 0; i < 100; i++) { + e = data[i]; + } + } + + bar(); // falla con TypeError desde bar sigue en 'undefined' + someValue = 42; // las asignaciones no se ven afectadas por hoisting + bar = function() {}; + + test(); + +La falta de alcance del bloque no sólo moverá la declaración `var` fuera de los bucles y +su contenido, sino también hará que los resultados de ciertos constructores `if` +no sean intuitivas. + +En el código original la declaración de `if` si parecía modificar la *variable +global* `goo`, mientras actualmente este modifica la *variable local* - después hoisting +ha sido aplicado. + +Sin el conocimiento acerca de *hoisting*, a continuación el código puede parecer +un `ReferenceError`. + + // comprueba si SomeImportantThing ha iniciado + if (!SomeImportantThing) { + var SomeImportantThing = {}; + } + +Pero, por supuesto, lo anterior funciona debido a que la declaración `var` es movida +a la parte superior del *ámbito global*. + + var SomeImportantThing; + + // otro código podría iniciar SomeImportantThing aqui, o no + + // asegúrese de que está ahí + if (!SomeImportantThing) { + SomeImportantThing = {}; + } + +### Name Resolution Order + +All scopes in JavaScript, including the *global scope*, have the special name +[`this`](#function.this), defined in them, which refers to the *current object*. + +Function scopes also have the name [`arguments`](#function.arguments), defined in +them, which contains the arguments that were passed to a function. + +For example, when trying to access a variable named `foo` inside the scope of a +function, JavaScript will lookup the name in the following order: + + 1. In case there is a `var foo` statement in the current scope, use that. + 2. If one of the function parameters is named `foo`, use that. + 3. If the function itself is called `foo`, use that. + 4. Go to the next outer scope, and start with **#1** again. + +> **Note:** Having a parameter called `arguments` will **prevent** the creation +> of the default `arguments` object. + +### Namespaces + +A common problem of having only one global namespace is the likeliness of running +into problems where variable names clash. In JavaScript, this problem can +easily be avoided with the help of *anonymous wrappers*. + + (function() { + // a self contained "namespace" + + window.foo = function() { + // an exposed closure + }; + + })(); // execute the function immediately + + +Unnamed functions are considered [expressions](#function.general); so in order to +being callable, they must first be evaluated. + + ( // evaluate the function inside the paranthesis + function() {} + ) // and return the function object + () // call the result of the evaluation + +There are other ways for evaluating and calling the function expression; which, +while different in syntax, do behave the exact same way. + + // Two other ways + +function(){}(); + (function(){}()); + +### In Conclusion + +It is recommended to always use an *anonymous wrapper* for encapsulating code in +its own namespace. This does not only protect code against name clashes, but it +also allows for better modularization of programs. + +Additionally, the use of global variables is considered **bad practice**. **Any** +use of them indicates badly written code that is prone to errors and hard to maintain. + diff --git a/doc/es/function/this.md b/doc/es/function/this.md new file mode 100644 index 00000000..7b1c0554 --- /dev/null +++ b/doc/es/function/this.md @@ -0,0 +1,111 @@ +## Cómo trabaja `this` + +JavaScript tiene un concepto diferente sobre el nombre especial `this` referido a la +mayoría de lenguajes de programación. Hay exactamente **cinco** formas distintas en donde +es posible ver el valor de `this` dentro de lo posible en el lenguaje. + +### El ámbito global (Global Scope) + + this; + +Cuando se utiliza `this` en el ámbito global, simplemente se refiere al objeto *global*. + + +### Llamar a una función + + foo(); + +Aquí `this` se refiere al objeto *global*. + +> **Nota ES5:** En modo estricto (strict mode), global **ya no** existe. +> `this` tendrá el valor de `undefined` en este caso. + +### Llamar a un método + + test.foo(); + +En este ejemplo `this` se referiere a `test`. + +### Llamar a un constructor + + new foo(); + +Llamar a una función que esta precedida por la palabra clave `new` actúa como +un [constructor](#function.constructors). Dentro de la función, `this` se refiere +al `Objeto` *recién creado*. + +### Ajuste explícito de `this` + + function foo(a, b, c) {} + + var bar = {}; + foo.apply(bar, [1, 2, 3]); // array que se apilará + foo.call(bar, 1, 2, 3); // resultados a = 1, b = 2, c = 3 + +Cuando se utiliza los métodos `call` o `apply` en `Function.prototype`, el valor de +`this` dentro de la función llamada se ajustará **explícitamente** al primer argumento +correspondiente a la llamada de la función. + +Como resultado, el ejemplo anterior sobre los *casos de métodos* estos **no** se aplican, y `this` +dentro de `foo` puede establecerse en `bar`. + +> **Nota:** `this` **no puede** ser usado para referirse a un objeto dentro de un `Objeto` +> literal. Así `var obj = {me: this}` **no** dará ninǵun resultado en `me` refiriendose a +> `obj`, ya que `this` sólo será obtenido por uno de los cincos casos enumerados. + +### Errores comunes + +Si bien en la mayoría de los casos esto tiene sentido, el primero puede cosiderarse como otro +mal diseño del lenguaje, ya que **nunca** tiene un uso práctico. + + Foo.method = function() { + function test() { + // this es establecido como un objeto global + } + test(); + } + +Un error común es que `this` dentro de `test` haga referencia a `Foo`, mientras que en +realidad esto **no es así**. + +Con el fin de acceder a `Foo` desde dentro de `test` es necesario crear una variable local +dentro del `método` para referirse a `Foo`. + + Foo.method = function() { + var that = this; + function test() { + // Use that instead of this here + } + test(); + } + +`that` es justo un nombre normal, pero es comúnmente usado para referenciar a `this` +de forma externa. En combinación con [closures](#function.closures), esto puede ser +también usado para pasar `this` como valor. + +### Asignación de métodos + +Otra cosa que **no** funciona en JavaScript son los alias en las funciones, es decir, +**asignar** un método a una variable. + + var test = someObject.methodTest; + test(); + +Debido al primer caso, `test` actúa como una función de llamada; por lo que +`this` dentro de este no estará referido a `someObject`. + +Mientras que la unión de `this` puede parecer una mala idea en un principio, esto es en +realidad lo que hace trabajar a la [herencia de prototipo](#object.prototype). + + function Foo() {} + Foo.prototype.method = function() {}; + + function Bar() {} + Bar.prototype = Foo.prototype; + + new Bar().method(); + +Cuando los `métodos` son llamados desde una instancia de `Bar`, `this` se referirá a una +instancia. + + diff --git a/doc/es/index.json b/doc/es/index.json new file mode 100644 index 00000000..f38ef6b8 --- /dev/null +++ b/doc/es/index.json @@ -0,0 +1,68 @@ +{ + "title": "Jardín de JavaScript", + "langTitle": "JavaScript Garden es Español", + "description": "Una guía sobre lo peculiar y defectos de JavaScript.", + "sections": [ + { + "title": "Introducción", + "dir": "intro", + "articles": [] + }, + { + "title": "Objetos", + "dir": "object", + "articles": [ + "general", + "prototype", + "hasownproperty", + "forinloop" + ] + }, + { + "title": "Funciones", + "dir": "function", + "articles": [ + "general", + "this", + "closures", + "arguments", + "constructors", + "scopes" + ] + }, + { + "title": "Arrays", + "dir": "array", + "articles": [ + "general", + "constructor" + ] + }, + { + "title": "Types", + "dir": "types", + "articles": [ + "equality", + "typeof", + "instanceof", + "casting" + ] + }, + { + "title": "Núcleo", + "dir": "core", + "articles": [ + "eval", + "undefined", + "semicolon" + ] + }, + { + "title": "Otros", + "dir": "other", + "articles": [ + "timeouts" + ] + } + ] +} diff --git a/doc/es/intro/index.md b/doc/es/intro/index.md new file mode 100644 index 00000000..4f61c42c --- /dev/null +++ b/doc/es/intro/index.md @@ -0,0 +1,47 @@ +## Introducción + +**El Jardín de JavaScript** es una guía de documentación acerca de las +partes más peculiares de este lenguaje de programación. Brinda consejos para evitar +los errores más comunes y sutiles, así como problemas de rendimiento y de malas +prácticas que los programadores menos experimentados en JavaScript pueden resolver +en sus esfuerzos por profundizar en el lenguaje. + +El Jardín de JavaScript **no** prentende enseñar JavaScript. +Se recomienda un conocimiento sobre el lenguaje para entender los temas tratados en +esta guía. Con el fin de aprender los conceptos básicos del lenguaje, por favor +diríjase a la excelente [guía][1] de los desarrolladores de Mozilla. + +## Los autores + +Esta guía es el trabajo de dos encantadores usuarios del foro Stack Overflow, +[Ivo Wetzel][3] (Escrito) y [Zhang Yi Jiang][4] (Diseño). + +## Colaboradores + + - [Caio Romão][5] (Correciones ortográficas) + - [Andreas Blixt][6] (Correciones de idioma) + +## Hosting + +JavaScript Garden es hospedado en GitHub, además [Cramer Development][7] nos apoya +con un sitio espejo en [JavaScriptGarden.info][8]. + +## Licencia + +El Jardín de JavaScript es publicado bajo la [licencia MIT][9] y es hospedado en +[GitHub][10]. Si encuentra algún error o errata por favor publique [una incidencia][11] o +envie un pull request a nuestro repositorio. También nos puede encontrar en la +[sala de chat de JavaScript][12] en Stack Overflow. + +[1]: https://developer.mozilla.org/en/JavaScript/Guide +[2]: http://stackoverflow.com/ +[3]: http://stackoverflow.com/users/170224/ivo-wetzel +[4]: http://stackoverflow.com/users/313758/yi-jiang +[5]: https://github.com/caio +[6]: https://github.com/blixt +[7]: http://cramerdev.com/ +[8]: http://javascriptgarden.info/ +[9]: https://github.com/BonsaiDen/JavaScript-Garden/blob/next/LICENSE +[10]: https://github.com/BonsaiDen/JavaScript-Garden +[11]: https://github.com/BonsaiDen/JavaScript-Garden/issues +[12]: http://chat.stackoverflow.com/rooms/17/javascript diff --git a/doc/es/object/forinloop.md b/doc/es/object/forinloop.md new file mode 100644 index 00000000..48058682 --- /dev/null +++ b/doc/es/object/forinloop.md @@ -0,0 +1,51 @@ +## El bucle `for in` + +Al igual que el operador `in`, el bucle `for in` también recorre sobre la +cadena de prototipo cuando este se repite en una iteración en las propiedades de un objeto. + +> **Nota:** El bucle `for in` **no** se repetirá en cualquier propiedad que +> tenga atributos `enumerables` asignados a `false`; por ejemplo, la propiedad +> `length` de un array. + + // Envenenamiento en Object.prototype + Object.prototype.bar = 1; + + var foo = {moo: 2}; + for(var i in foo) { + console.log(i); // Imprime ambos bar y moo + } + +Dado que no es posible cambiar el comportamiento del bucle `for in` en sí mismo, es +necesario filtrar las propiedades internas no deseadas dentro del bucle, +esto se hace mediante el uso del método [`hasOwnProperty`](#object.hasownproperty) del +`Object.prototype`. + +> **Nota:** Dado que `for in` siempre recorre por completo la cadena de prototipo, +> este se pondrá más lento con cada capa adicional que un objeto herede. + +### Usando `hasOwnProperty` para filtrado + + // Aún es el foo del código de arriba + for(var i in foo) { + if (foo.hasOwnProperty(i)) { + console.log(i); + } + } + +Está versión es la única forma correcta de uso. Esto se debe **sólo** al uso de +`hasOwnProperty` que imprimirá `moo`. Cuando `hasOwnProperty` se omita, el código es +propenso a errores en los casos de prototipos nativos - ej. `Object.prototype` - +se ha extendedido. + +Uno de los frameworks más usado que implementa estas funcionalidades es [Prototype][1]. Cuando el +framework es incluido, el bucle `for in` que no utilicen `hasOwnProperty` no podrá garantizar que +se interrumpa. + +### En conclusión + +Se recomienda utilizar **siempre** el uso de `hasOwnProperty`. Nunca debe suponer +ningún entorno donde el código se ejecute, o si los prototipos +nativos han sido extendidos o no. + +[1]: http://www.prototypejs.org/ + diff --git a/doc/es/object/general.md b/doc/es/object/general.md new file mode 100644 index 00000000..bd3bab18 --- /dev/null +++ b/doc/es/object/general.md @@ -0,0 +1,99 @@ +## Uso de objetos y propiedades + +Todo en JavaScript actúa como un objeto, con las dos únicas excepciones de +[`null`](#core.undefined) y [`undefined`](#core.undefined). + + false.toString() // 'false' + [1, 2, 3].toString(); // '1,2,3' + + function Foo(){} + Foo.bar = 1; + Foo.bar; // 1 + +Un error muy común es el uso de literales númericos como objetos. +Esto se debe a un error en el parser de JavaScript que intenta analizar la +*notación de puntos* como un literal de punto flotante. + + 2.toString(); // lanza SyntaxError + +Existe un par de soluciones que pueden utilizarse para hacer que los +literales númericos actúen como objetos. + + 2..toString(); // el segundo punto es reconocido correctamente + 2 .toString(); // observe el espacio a la izquierda del punto + (2).toString(); // el número 2 se evalúa primero + +### Objetos como un tipo de datos + +Los objetos en JavaScript también pueden ser utilizados como una Tabla Hash o conocido como [*Hashmap*][1] en inglés, consisten +principalmente en nombres de propiedades asignadoles valores a estos. + +El uso de un objeto literal - con notación `{}` - puede crear un +objeto plano. Este nuevo objeto [heredado](#object.prototype) desde `Object.prototype` +no posee [propiedades propias](#object.hasownproperty) definidas. + + var foo = {}; // un nuevo objeto vacío + + // un nuevo objeto con la propiedad llamada 'test' con el valor 12 + var bar = {test: 12}; + +### Acceso a las propiedades + +Se puede acceder a las propiedades de un objeto de dos maneras, ya sea a través de la +notación de punto o desde la notación de corchetes. + + var foo = {name: 'Kitten'} + foo.name; // kitten + foo['name']; // kitten + + var get = 'name'; + foo[get]; // kitten + + foo.1234; // SyntaxError + foo['1234']; // ¡funciona! + +Ambas notaciones son idénticas en su funcionamiento, la única diferencia es la +notación de corchetes permite el ajuste dinámico de las propiedades, así como +el uso de propiedades que de otro modo daría lugar a error de sintaxis. + +### Eliminando propiedades + +La única manera de eliminar una propiedad desde un objeto es usando el +operador `delete`; Se establece la propiedad a `undefined` o `null` sólo al +*valor* asociado de la propiedad, pero no ha un *key* (valor clave). + + 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]); + } + } + +Los resultados de la salida son `bar undefined` y `foo null` - sólo `baz` ha +sido removido y por lo tanto no aparece en la salida. + +### Notación de Keys + + var test = { + 'case': 'Soy una palabra clave y debo ser anotado como string', + delete: 'Soy una palabra clave también' // lanza SyntaxError + }; + +Las propiedades de los objetos puede ser simbolizados como caracteres planos y como strings. Debido +a otro mal diseño del parser de JavaScript, lo anterior es una excepción +de `SyntaxError` antes de ECMAScript 5. + +Este error se debe al `eliminar` una *keyword*; por lo tanto, debe ser +anotado como un *string literal* para asegurarse que será interpretado correctamente +por diversos motorores de JavaScript. + +[1]: http://en.wikipedia.org/wiki/Hashmap + diff --git a/doc/es/object/hasownproperty.md b/doc/es/object/hasownproperty.md new file mode 100644 index 00000000..feb44ae9 --- /dev/null +++ b/doc/es/object/hasownproperty.md @@ -0,0 +1,53 @@ +## `hasOwnProperty` + +Con el fin de comprobar si un objeto posee una propiedad definida *en sí* mismo y **no** +en algún lugar de su [cadena de prototipo](#object.prototype), es necesario utilizar +el método `hasOwnProperty` ya que todos los objetos herendan de `Object.prototype`. + +> **Nota:** **No** es suficiente con comprobar si una propiedad está `definida`. +> La propiedad bien podría existir, pero su valor sólo pasa a ser definido como +> `undefined`. + +`hasOwnProperty` es la única utilidad en JavaScript que se ocupa de las propiedades +y **no** las salta en la cadena de prototipo. + + // Envenenamiento en Object.prototype + Object.prototype.bar = 1; + var foo = {goo: undefined}; + + foo.bar; // 1 + 'bar' in foo; // true + + foo.hasOwnProperty('bar'); // false + foo.hasOwnProperty('goo'); // true + +Sólo `hasOwnProperty` retornará el resultado correcto y esperado, esto es +ensencial cuando se repite una iteración en las propiedades de cualquier objeto. No hay +otra maner de excluir las propiedades que no están definidas en el mismo objeto, pero +en alguna parte de su cadena de prototipo si. + +### `hasOwnProperty` como propiedad + +JavaScript **no** protege el nombre de la propiedad `hasOwnProperty`; de este modo, si existe +la posibilidad de que un objeto tenga una propiedad con el mismo nombre, es necesario utilizar +`hasOwnProperty` como propiedad *externa* con el fin de obtener resultados correctos. + + var foo = { + hasOwnProperty: function() { + return false; + }, + bar: 'Here be dragons' + }; + + foo.hasOwnProperty('bar'); // siempre devolverá false + + // Utilice otro objeto con hasOwnProperty y llamelo con 'this' para asignarlo a foo + ({}).hasOwnProperty.call(foo, 'bar'); // true + +### En conclusión + +Cuando se necesite comprobar la existencia de una propiedad en un objeto, `hasOwnProperty` es +el **único** método para hacerlo. También se recomienda el uso de `hasOwnProperty` como +parte de un [bucle `for in`](#object.forinloop), esto evitará errores desde +extenciones de [prototipos](#object.prototype) nativos. + diff --git a/doc/es/object/prototype.md b/doc/es/object/prototype.md new file mode 100644 index 00000000..ac654c75 --- /dev/null +++ b/doc/es/object/prototype.md @@ -0,0 +1,116 @@ +## Prototipo + +JavaScript no posee en sus características un sistema clásico de herencia, sino que +utiliza un *prototipo* para esto. + +Si bien a menudo se considera uno de los puntos débiles de JavaScript, el +modelo de herecia prototipado es de hecho más poderoso que el modelo clásico. +Por ejemplo, es bastante trivial construir un modelo clásico en la parte superior del mismo, +mientras esto es una tarea mucho más difícil. + +Debido al hecho que JavaScript es básicamente el único lenguaje que utiliza +apliamente la herencia prototipada, se necesita algo de tiempo para adaptarse a +las diferencias entre los dos modelos. + +La primera gran diferencia es que la herencia en JavaScript se realiza usando +llamadas de *cadenas de prototipo* (*prototype chains*). + +> **Nota:** Simplemente usando `Bar.prototype = Foo.prototype` dará lugar a dos objetos + > que comparten el **mismo** prototipo. Por lo tanto, los cambios que se realicen en un +> objeto afectará al otro objeto, así, en la mayoría de los casos no es el efecto +> deseado. + + function Foo() { + this.value = 42; + } + Foo.prototype = { + method: function() {} + }; + + function Bar() {} + + // Asigna el prototipo de Bar como una nueva instancia de Foo + Bar.prototype = new Foo(); + Bar.prototype.foo = 'Hello World'; + + // Asegura que el constructor sea Bar + Bar.prototype.constructor = Bar; + + var test = new Bar() // crea una nueva instancia de Bar + + // Resultado de cadena de prototipos (prototype chain) + test [instance of Bar] + Bar.prototype [instance of Foo] + { foo: 'Hello World' } + Foo.prototype + { method: ... } + Object.prototype + { toString: ... /* etc. */ } + +En el código anterior, el objeto `test` hereda de `Bar.prototype` y `Foo.prototype`; +por lo tanto, tendrá acceso a la función `method` que se ha definido en `Foo`. +También se tendrá acceso a a la propiedad `value` de la **única** instancia de `Foo` +que compone su prototipo. Es importante tomar en cuenta que `new Bar()` **no** creará una nueva +instancia de `Foo`, pero retornará lo asignado en su prototipo; de este modo, todas las instancias +de `Bar` tendrán que compartir el **mismo** `valor` de la propiedad. + +> **Nota:** **No** utilice `Bar.prototype = Foo`, ya que no apunta al prototipo +> de `Foo`, sino al objeto de la función `Foo`. Así la cadena de prototipo +> cambiará a `Function.prototype` y no a `Foo.prototype`; +> Por lo tanto, el `método` no estará disponible en la cadena de prototipo. + +### Búsqueda de propiedades + +Cuando se accede a las propiedades de un objeto, JavaScript recorre la cadena de +prototipo hacia **arriba** hasta encontrar la propiedad con el nombre solicitado. + +Cuando se llega al final de la cadena - concretamente `Object.prototype` - y aún +no se ha encontrado la propiedad especificada, se retornará un valor +[undefined](#core.undefined) en su lugar. + +### La propiedad prototype + +Aunque la propiedad prototype es usada por el lenguaje para construir la cadena +de prototipos, es posible asignar **cualquier** valor. Aunque los tipos primitivos +serán ignorados cuando se asigne en prototype. + + function Foo() {} + Foo.prototype = 1; // no tendrá efecto + +La asignación de objetos, como se muestra en el ejemplo anterior, funcionará, y permitirá +la creación dinámica de cadena de prototipos. + +### Rendimiento + +El tiempo tomado en la búsqueda de propiedades es alta y la cadena de prototipo puede +presentar un impacto negativo critico en el rendimiento en partes del código. Además, +si ha tratado de acceder a propiedades que no existen este saltara a la cadena de prototipo. + +Además, al recorrer en [iteración](#object.forinloop) las propiedades de un objeto +y **cada** propiedad será encontrada en la cadena de prototipo de manera ennumerada. + +### Extensión de prototipos nativos + +Una mala característica que se suele utilizar para extender `Object.prototype` o cualquier +otro prototipo construido. + +Esta técnica es conocida en inglés como [monkey patching][1] ya que *encapsula* lo que se interrumpe en el código. +Si bien es utilizado en frameworks como [Prototype][2], todavía no existen buenas razones para adoptarlo o integrarlo +como tipos de dato o como funcionalidad no estándar. + +La **única** buena razón para extender un prototipo es acondicionarlo a nuevas +características en motores de JavaScript; por ejemplo, +[`Array.forEach`][3]. + +### En conclusión + +Se **debe** entender por completo el módelo de herencia prototipado antes de +escribir código complejo que lo utlilice. Además, observe la longitud de la +cadena de prototipo y modificala si es necesario para evitar posibles problemas de +rendimiento. Con relación a los prototipos nativos, estos **nunca** deben ser extendidos a +menos que sea para mantener la compatibilidad con nuevas características de JavaScript. + +[1]: http://en.wikipedia.org/wiki/Monkey_patch +[2]: http://prototypejs.org/ +[3]: https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/forEach + diff --git a/doc/es/other/timeouts.md b/doc/es/other/timeouts.md new file mode 100644 index 00000000..3a306bdd --- /dev/null +++ b/doc/es/other/timeouts.md @@ -0,0 +1,155 @@ +### `setTimeout` and `setInterval` + +Since JavaScript is asynchronous, it is possible to schedule the execution of a +function by using the `setTimeout` and `setInterval` functions. + +> **Note:** Timeouts are **not** part of the ECMAScript Standard. They are +> implemented as part of the [DOM][1]. + + function foo() {} + var id = setTimeout(foo, 1000); // returns a Number > 0 + +When `setTimeout` gets called, it will return the ID of the timeout and schedule +`foo` to run in **approximately** one thousand milliseconds in the future. +`foo` will then get executed exactly **once**. + +Depending on the timer resolution of the JavaScript engine that is running the +code, as well as the fact that JavaScript is single threaded and other code that +gets executed might block the thread, it is by **no means** a safe bet that one +will get the exact delay that was specified in the `setTimeout` call. + +The function that was passed as the first parameter will get called by the +*global object*, which means that [`this`](#function.this) inside the called function +refers to that very object. + + function Foo() { + this.value = 42; + this.method = function() { + // this refers to the global object + console.log(this.value); // will log undefined + }; + setTimeout(this.method, 500); + } + new Foo(); + + +> **Note:** As `setTimeout` takes a **function object** as its first parameter, an +> often made mistake is to use `setTimeout(foo(), 1000)`, which will use the +> **return value** of the call `foo` and **not** `foo`. This is, most of the time, +> a silent error, since when the function returns `undefined` `setTimeout` will +> **not** raise any error. + +### Stacking Calls with `setInterval` + +While `setTimeout` only runs the function once, `setInterval` - as the name +suggests - will execute the function **every** `X` milliseconds, but its use is +discouraged. + +When code that is being executed blocks the timeout call, `setInterval` will +still issue more calls to the specified function. This can, especially with small +intervals, result in function calls stacking up. + + function foo(){ + // something that blocks for 1 second + } + setInterval(foo, 100); + +In the above code, `foo` will get called once and will then block for one second. + +While `foo` blocks the code, `setInterval` will still schedule further calls to +it. Now, when `foo` has finished, there will already be **ten** further calls to +it waiting for execution. + +### Dealing with Possible Blocking Code + +The easiest solution, as well as most controllable solution, is to use `setTimeout` within +the function itself. + + function foo(){ + // something that blocks for 1 second + setTimeout(foo, 100); + } + foo(); + +Not only does this encapsulate the `setTimeout` call, but it also prevents the +stacking of calls and it gives additional control. `foo` itself can now decide +whether it wants to run again or not. + +### Manually Clearing Timeouts + +Clearing timeouts and intervals works by passing the respective ID to +`clearTimeout` or `clearInterval`, depending which `set` function was used in +the first place. + + var id = setTimeout(foo, 1000); + clearTimeout(id); + +### Clearing all timeouts + +Because there is no built-in method for clearing all timeouts and/or intervals, +it is necessary to use brute force in order to achieve this functionality. + + // clear "all" timeouts + for(var i = 1; i < 1000; i++) { + clearTimeout(i); + } + +There might still be timeouts that are unaffected by this arbitrary number; +therefore, is is instead recommended to keep track of all the timeout IDs, so +they can be cleared specifically. + +### Hidden use of `eval` + +`setTimeout` and `setInterval` can also take a string as their first parameter. +This feature should **never** be used because it internally makes use of `eval`. + +> **Note:** Since the timeout functions are **not** specified by the ECMAScript +> standard, the exact workings when a string is passed to them might differ in +> various JavaScript implementations. For example, Microsoft's JScript makes use of +> the `Function` constructor in place of `eval`. + + function foo() { + // will get called + } + + function bar() { + function foo() { + // never gets called + } + setTimeout('foo()', 1000); + } + bar(); + +Since `eval` is not getting called [directly](#core.eval) in this case, the string +passed to `setTimeout` will get executed in the *global scope*; thus, it will +not use the local variable `foo` from the scope of `bar`. + +It is further recommended to **not** use a string for passing arguments to the +function that will get called by either of the timeout functions. + + function foo(a, b, c) {} + + // NEVER use this + setTimeout('foo(1,2, 3)', 1000) + + // Instead use an anonymous function + setTimeout(function() { + foo(a, b, c); + }, 1000) + +> **Note:** While it is also possible to use the syntax +> `setTimeout(foo, 1000, a, b, c)`, it is not recommended, as its use may lead +> to subtle errors when used with [methods](#function.this). + +### In Conclusion + +**Never** should a string be used as the parameter of `setTimeout` or +`setInterval`. It is a clear sign of **really** bad code, when arguments need +to be supplied to the function that gets called. An *anonymous function* should +be passed that then takes care of the actual call. + +Furthermore, the use of `setInterval` should be avoided because its scheduler is not +blocked by executing JavaScript. + +[1]: http://en.wikipedia.org/wiki/Document_Object_Model "Document Object Model" + diff --git a/doc/es/types/casting.md b/doc/es/types/casting.md new file mode 100644 index 00000000..34d6fd78 --- /dev/null +++ b/doc/es/types/casting.md @@ -0,0 +1,70 @@ +## Type Casting + +JavaScript is a *weakly typed* language, so it will apply *type coercion* +**wherever** possible. + + // These are true + new Number(10) == 10; // Number.toString() is converted + // back to a number + + 10 == '10'; // Strings gets converted to Number + 10 == '+10 '; // More string madness + 10 == '010'; // And more + isNaN(null) == false; // null converts to 0 + // which of course is not NaN + + // These are false + 10 == 010; + 10 == '-10'; + +> **ES5 Note:** Number literals that start with a `0` are interpreted as octal +> (Base 8). Octal support for these has been **removed** in ECMAScript 5 strict +> mode. + +In order to avoid the above, use of the [strict equal operator](#types.equality) +is **highly** recommended. Although this avoids a lot of common pitfalls, there +are still many further issues that arise from JavaScript's weak typing system. + +### Constructors of Built-In Types + +The constructors of the built in types like `Number` and `String` behave +differently when being used with the `new` keyword and without it. + + new Number(10) === 10; // False, Object and Number + Number(10) === 10; // True, Number and Number + new Number(10) + 0 === 10; // True, due to implicit conversion + +Using a built-in type like `Number` as a constructor will create a new `Number` +object, but leaving out the `new` keyword will make the `Number` function behave +like a converter. + +In addition, having literals or non-object values in there will result in even +more type coercion. + +The best option is to cast to one of the three possible types **explicitly**. + +### Casting to a String + + '' + 10 === '10'; // true + +By prepending an empty string, a value can easily be casted to a string. + +### Casting to a Number + + +'10' === 10; // true + +Using the **unary** plus operator, it is possible to cast to a number. + +### Casting to a Boolean + +By using the **not** operator twice, a value can be converted a boolean. + + !!'foo'; // true + !!''; // false + !!'0'; // true + !!'1'; // true + !!'-1' // true + !!{}; // true + !!true; // true + + diff --git a/doc/es/types/equality.md b/doc/es/types/equality.md new file mode 100644 index 00000000..5665917f --- /dev/null +++ b/doc/es/types/equality.md @@ -0,0 +1,71 @@ +## Equality and Comparisons + +JavaScript has two different ways of comparing the values of objects for equality. + +### The Equality Operator + +The equality operator consists of two equal signs: `==` + +JavaScript features *weak typing*. This means that the equality operator +**coerces** types in order to compare them. + + "" == "0" // false + 0 == "" // true + 0 == "0" // true + false == "false" // false + false == "0" // true + false == undefined // false + false == null // false + null == undefined // true + " \t\r\n" == 0 // true + +The above table shows the results of the type coercion, and it is the main reason +why the use of `==` is widely regarded as bad practice. It introduces +hard-to-track-down bugs due to its complicated conversion rules. + +Additionally, there is also a performance impact when type coercion is in play; +for example, a string has to be converted to a number before it can be compared +to another number. + +### The Strict Equality Operator + +The strict equality operator consists of **three** equal signs: `===`. + +It works exactly like the normal equality operator, except that strict equality +operator does **not** perform type coercion between its operands. + + "" === "0" // false + 0 === "" // false + 0 === "0" // false + false === "false" // false + false === "0" // false + false === undefined // false + false === null // false + null === undefined // false + " \t\r\n" === 0 // false + +The above results are a lot clearer and allow for early breakage of code. This +hardens code to a certain degree and also gives performance improvements in case +the operands are of different types. + +### Comparing Objects + +While both `==` and `===` are stated as **equality** operators, they behave +differently when at least one of their operands happens to be an `Object`. + + {} === {}; // false + new String('foo') === 'foo'; // false + new Number(10) === 10; // false + var foo = {}; + foo === foo; // true + +Here, both operators compare for **identity** and **not** equality; that is, they +will compare for the same **instance** of the object, much like `is` in Python +and pointer comparison in C. + +### In Conclusion + +It is highly recommended to only use the **strict equality** operator. In cases +where types need to be coerced, it should be done [explicitly](#types.casting) +and not left to the language's complicated coercion rules. + diff --git a/doc/es/types/instanceof.md b/doc/es/types/instanceof.md new file mode 100644 index 00000000..84251128 --- /dev/null +++ b/doc/es/types/instanceof.md @@ -0,0 +1,38 @@ +## The `instanceof` Operator + +The `instanceof` operator compares the constructors of its two operands. It is +only useful when comparing custom made objects. Used on built-in types, it is +nearly as useless as the [typeof operator](#types.typeof). + +### Comparing Custom Objects + + function Foo() {} + function Bar() {} + Bar.prototype = new Foo(); + + new Bar() instanceof Bar; // true + new Bar() instanceof Foo; // true + + // This just sets Bar.prototype to the function object Foo + // But not to an actual instance of Foo + Bar.prototype = Foo; + new Bar() instanceof Foo; // false + +### Using `instanceof` with Native Types + + new String('foo') instanceof String; // true + new String('foo') instanceof Object; // true + + 'foo' instanceof String; // false + 'foo' instanceof Object; // false + +One important thing to note here is that `instanceof` does not work on objects +that originate from different JavaScript contexts (e.g. different documents +in a web browser), since their constructors will not be the exact same object. + +### In Conclusion + +The `instanceof` operator should **only** be used when dealing with custom made +objects that originate from the same JavaScript context. Just like the +[`typeof`](#types.typeof) operator, every other use of it should be **avoided**. + diff --git a/doc/es/types/typeof.md b/doc/es/types/typeof.md new file mode 100644 index 00000000..00377db4 --- /dev/null +++ b/doc/es/types/typeof.md @@ -0,0 +1,87 @@ +## The `typeof` Operator + +The `typeof` operator (together with +[`instanceof`](#types.instanceof)) is probably the biggest +design flaw of JavaScript, as it is near of being **completely broken**. + +Although `instanceof` still has its limited uses, `typeof` really has only one +practical use case, which does **not** happen to be checking the type of an +object. + +> **Note:** While `typeof` can also be called with a function like syntax +> i.e. `typeof(obj)`, this is not a function call. The two parenthesis will +> behave like normal and the return value will be used as the operand of the +> `typeof` operator. There is **no** `typeof` function. + +### The JavaScript Type Table + + Value Class Type + ------------------------------------- + "foo" String string + new String("foo") String object + 1.2 Number number + new Number(1.2) Number object + true Boolean boolean + new Boolean(true) Boolean object + new Date() Date object + new Error() Error object + [1,2,3] Array object + new Array(1, 2, 3) Array object + new Function("") Function function + /abc/g RegExp object (function in Nitro/V8) + new RegExp("meow") RegExp object (function in Nitro/V8) + {} Object object + new Object() Object object + +In the above table, *Type* refers to the value that the `typeof` operator returns. +As can be clearly seen, this value is anything but consistent. + +The *Class* refers to the value of the internal `[[Class]]` property of an object. + +> **From the Specification:** The value of `[[Class]]` can be one of the +> following strings. `Arguments`, `Array`, `Boolean`, `Date`, `Error`, +> `Function`, `JSON`, `Math`, `Number`, `Object`, `RegExp`, `String`. + +In order to retrieve the value of `[[Class]]`, one has to make use of the +`toString` method of `Object.prototype`. + +### The Class of an Object + +The specification gives exactly one way of accessing the `[[Class]]` value, +with the use of `Object.prototype.toString`. + + function is(type, obj) { + var clas = Object.prototype.toString.call(obj).slice(8, -1); + return obj !== undefined && obj !== null && clas === type; + } + + is('String', 'test'); // true + is('String', new String('test')); // true + +In the above example, `Object.prototype.toString` gets called with the value of +[this](#function.this) being set to the object whose `[[Class]]` value should be +retrieved. + +> **ES5 Note:** For convenience the return value of `Object.prototype.toString` +> for both `null` and `undefined` was **changed** from `Object` to `Null` and +> `Undefined` in ECMAScript 5. + +### Testing for Undefined Variables + + typeof foo !== 'undefined' + +The above will check whether `foo` was actually declared or not; just +referencing it would result in a `ReferenceError`. This is the only thing +`typeof` is actually useful for. + +### In Conclusion + +In order to check the type of an object, it is highly recommended to use +`Object.prototype.toString` because this is the only reliable way of doing so. +As shown in the above type table, some return values of `typeof` are not defined +in the specification; thus, they can differ across various implementations. + +Unless checking whether a variable is defined, `typeof` should be avoided at +**all costs**. + + From f1a5f8c404b1fe3e7ad57785213e6a6d8817918f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julio=20Napur=C3=AD?= Date: Sat, 7 Jan 2012 16:20:34 -0500 Subject: [PATCH 207/463] Spanish updated core.undefined.md --- doc/es/core/undefined.md | 56 +++++++++++++++++++++------------------- 1 file changed, 29 insertions(+), 27 deletions(-) diff --git a/doc/es/core/undefined.md b/doc/es/core/undefined.md index deda99bc..41dde82b 100644 --- a/doc/es/core/undefined.md +++ b/doc/es/core/undefined.md @@ -16,36 +16,38 @@ puede ser sobreescrito fácilmente. > pero su nombre todavía puede por ejemplo establecer una función con el nombre > `undefined`. -Algunos ejemplos de cuando el valor retorna `undefined`: +Algunos ejemplos cuando el valor retorna `undefined`: - Acceso a la variable global (sin modificar) `undefined`. - Retorna implícitamente las funciones que no posean la sentencia `return`. - - `return` statements which do not explicitly return anything. - - Lookups of non-existent properties. - - Function parameters which do not had any explicit value passed. - - Anything that has been set to the value of `undefined`. + - Sentencia `return` que no retorna nada de forma explicíta. + - Búsquedas de propiedades inexistentes. + - Párametros de la función que no tienen ningún valor explicíto pasado. + - Cualquier valor que se estable en `undefined`. -### Handling Changes to the Value of `undefined` +### Manejar los cambios en el valor deChanges `undefined` -Since the global variable `undefined` only holds a copy of the actual *value* of -`undefined`, assigning a new value to it does **not** change the value of the -*type* `undefined`. +Dado que la variable `undefined` sólo tiene una copia del *value* de +`undefined`, assigna un nuevo valor que **no** cambie el valor del +*tipo* `undefined`. -Still, in order to compare something against the value of `undefined` it is -necessary to retrieve the value of `undefined` first. -In order to protect code against a possible overwritten `undefined` variable, a -common technique used is to add an additional parameter to an -[anonymous wrapper](#function.scopes), that gets no argument passed to it. +Aún con el fin de comparar con el valor de `undefined` es necesario +recuperar el valor de `undefined` primero. + +Con el fin de proteger una posible sobreescritura en la variable `undefined`, +una técnica común es agregar un párametro adicional a un +[wrapper anónimo](#function.scopes), que consiga ningún párametro que se le pase. + var undefined = 123; (function(something, foo, undefined) { - // undefined in the local scope does - // now again refer to the value + // undefined en el ámbito local + // ahora hace referencia al valor })('Hello World', 42); -Another way to achieve the same effect would be to use a declaration inside the +Otra forma de lograrlo un mismo efecto es declarar dentro un wrapper. var undefined = 123; @@ -55,18 +57,18 @@ wrapper. })('Hello World', 42); -The only difference being here, that this version results in 4 more bytes being -used in case it is minified and there is no other `var` statement inside the -anonymous wrapper. +La única diferencia, es que está versión es de 4 bytes más que utiliza, y en +caso se comprima y no hay otra declaración de 'var' dentro del +wrapper anónimo. -### Uses of `null` -While `undefined` in the context of the JavaScript language is mostly used in -the sense of a traditional *null*, the actual `null` (both a literal and a type) -is more or less just another data type. +### Uso de `null` -It is used in some JavaScript internals (like declaring the end of the -prototype chain by setting `Foo.prototype = null`), but in almost all cases it -can be replaced by `undefined`. +Mientras que `undefined` en el contexto del lenguaje JavaScript es muy usado +en el sentido tradicional como *null*, el actual `null` (ambos literal y de un tipo) +es más o menos que otro tipo de datos. +Es utilizado en algunos detalles internos de JavaScript (como declarar al final de un +cadena de prototipo estableciendo `Foo.prototype = null`), pero en casi todos los +casos, puede ser reemplazado por `undefined`. From 4ac4dfdc28d9d10462a50919fa9bc4172595b757 Mon Sep 17 00:00:00 2001 From: HIRAKI Satoru Date: Mon, 9 Jan 2012 01:08:27 +0900 Subject: [PATCH 208/463] fix translate in "Array" --- doc/ja/array/general.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/ja/array/general.md b/doc/ja/array/general.md index 0b7925dc..7afc71df 100644 --- a/doc/ja/array/general.md +++ b/doc/ja/array/general.md @@ -18,7 +18,7 @@ JavaScriptの配列もまたオブジェクトですが、[`for in ループ`](# 上記の例では1つ追加の仕掛けがありますが、それは`l = list.length`によって配列の長さをキャッシュする部分です。 -また、`length`プロパティは配列自身に定義されていますが、ループ中の繰り返し毎回参照を行なうというオーバーヘッドがまだ存在します。最近のJavaScriptエンジンはこのような場合に最適化する**はず**ですが、コードが新しいエンジンで実行されるかどうか、知る方法はありません。 +`length`プロパティは配列自身に定義されてはいますが、ループ中の繰り返しで毎回これを参照してしまうと、やはりオーバーヘッドが存在してしまいます。最近のJavaScriptエンジンはこのような場合に最適化する**はず**ですが、コードが新しいエンジンで実行されるかどうか、知る方法はありません。 実際には、キャッシュを抜きにするとループの結果はキャッシュされたものに比べてたった**半分の速度**にしかなりません。 From 2c719a22327f7cae8137e6f3b12bce2d71900d54 Mon Sep 17 00:00:00 2001 From: HIRAKI Satoru Date: Mon, 9 Jan 2012 01:17:55 +0900 Subject: [PATCH 209/463] cp core/delete --- doc/ja/core/delete.md | 87 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 87 insertions(+) create mode 100644 doc/ja/core/delete.md diff --git a/doc/ja/core/delete.md b/doc/ja/core/delete.md new file mode 100644 index 00000000..37a12816 --- /dev/null +++ b/doc/ja/core/delete.md @@ -0,0 +1,87 @@ +## The `delete` Operator + +In short, it's *impossible* to delete global variables, functions and some other +stuff in JavaScript which have a `DontDelete` attribute set. + +### Global code and Function code + +When a variable or a function is defined in a global +or a [function scope](#function.scopes) it is a property of either +Activation object or Global object. Such properties have a set of attributes, +one of these is `DontDelete`. Variable and function declarations in global +and function code always create properties with `DontDelete`, therefore +cannot be deleted. + + // global variable: + var a = 1; // DontDelete is set + delete a; // false + a; // 1 + + // normal function: + function f() {} // DontDelete is set + delete f; // false + typeof f; // "function" + + // reassigning doesn't help: + f = 1; + delete f; // false + f; // 1 + +### Explicit properties + +There are things which can be deleted normally: these are explicitly set +properties. + + // explicitly set property: + var obj = {x: 1}; + obj.y = 2; + delete obj.x; // true + delete obj.y; // true + obj.x; // undefined + obj.y; // undefined + +In the example above `obj.x` and `obj.y` can be deleted because they have no +`DontDelete` atribute. That's why an example below works too. + + // this works fine, except for IE: + var GLOBAL_OBJECT = this; + GLOBAL_OBJECT.a = 1; + a === GLOBAL_OBJECT.a; // true - just a global var + delete GLOBAL_OBJECT.a; // true + GLOBAL_OBJECT.a; // undefined + +Here we use a trick to delete `a`. [`this`](#function.this) here refers +to the Global object and we explicitly declare variable `a` as it's property +which allows us to delete it. + +IE (at least 6-8) has some bugs, so code above doesn't work. + +### Function arguments and built-ins + +Functions' normal arguments, [`arguments` object](#function.arguments) +and built-in properties also have `DontDelete` set. + + // function arguments and properties: + (function (x) { + + delete arguments; // false + typeof arguments; // "object" + + delete x; // false + x; // 1 + + function f(){} + delete f.length; // false + typeof f.length; // "number" + + })(1); + +### Host objects + +Behaviour of `delete` operator can be unpredictable for hosted objects. Due to +specification, host objects are allowed to implement any kind of behavior. + +### In conclusion + +`delete` operator often has an unexpected behaviour and can be safely used +only for dealing with explicitly set properties on normal objects. From 62aa1a2e7887bb6d139095428f52d21a7aed327a Mon Sep 17 00:00:00 2001 From: Ed Lui Date: Mon, 16 Jan 2012 12:00:56 -0500 Subject: [PATCH 210/463] Fix typo in setInterval/setTimeout to be 1000, not 100. Addresses https://github.com/BonsaiDen/JavaScript-Garden/issues/119 --- doc/en/other/timeouts.md | 4 ++-- doc/fi/other/timeouts.md | 4 ++-- doc/ja/other/timeouts.md | 4 ++-- doc/ko/other/timeouts.md | 4 ++-- doc/pl/other/timeouts.md | 4 ++-- doc/ru/other/timeouts.md | 4 ++-- doc/tr/other/timeouts.md | 4 ++-- doc/zh/other/timeouts.md | 4 ++-- 8 files changed, 16 insertions(+), 16 deletions(-) diff --git a/doc/en/other/timeouts.md b/doc/en/other/timeouts.md index 3a306bdd..4304ec2f 100644 --- a/doc/en/other/timeouts.md +++ b/doc/en/other/timeouts.md @@ -52,7 +52,7 @@ intervals, result in function calls stacking up. function foo(){ // something that blocks for 1 second } - setInterval(foo, 100); + setInterval(foo, 1000); In the above code, `foo` will get called once and will then block for one second. @@ -67,7 +67,7 @@ the function itself. function foo(){ // something that blocks for 1 second - setTimeout(foo, 100); + setTimeout(foo, 1000); } foo(); diff --git a/doc/fi/other/timeouts.md b/doc/fi/other/timeouts.md index ba361f54..e7c5e581 100644 --- a/doc/fi/other/timeouts.md +++ b/doc/fi/other/timeouts.md @@ -34,7 +34,7 @@ Mikäli suoritettava koodi blokkaa katkaisufunktion kutsun, `setInterval` lisä function foo(){ // jotain joka blokkaa sekunnin ajaksi } - setInterval(foo, 100); + setInterval(foo, 1000); Yllä olevassa koodissa `foo`-funktiota kutsutaan, jonka jälleen se blokkaa sekunnin ajan. @@ -46,7 +46,7 @@ Helpoin ja joustavin tapa on käyttää `setTimeout`-funktiota funktiossa itsess function foo(){ // jotain joka blokkaa sekunnin ajaksi - setTimeout(foo, 100); + setTimeout(foo, 1000); } foo(); diff --git a/doc/ja/other/timeouts.md b/doc/ja/other/timeouts.md index c1875b4f..2c03fee8 100644 --- a/doc/ja/other/timeouts.md +++ b/doc/ja/other/timeouts.md @@ -40,7 +40,7 @@ JavaScriptは非同期なので、`setTimeout`と`setInterval`関数を使って function foo(){ // 1秒おきにブロックの何かを実行 } - setInterval(foo, 100); + setInterval(foo, 1000); 上記のコードでは、`foo`が1回呼び出されて、1秒ブロックされます。 @@ -52,7 +52,7 @@ JavaScriptは非同期なので、`setTimeout`と`setInterval`関数を使って function foo(){ // 1秒ブロックする何か - setTimeout(foo, 100); + setTimeout(foo, 1000); } foo(); diff --git a/doc/ko/other/timeouts.md b/doc/ko/other/timeouts.md index e2d627a9..859aa107 100644 --- a/doc/ko/other/timeouts.md +++ b/doc/ko/other/timeouts.md @@ -34,7 +34,7 @@ JavaScript 엔진의 단위 시간(timer resolution)에 따라서 코드를 실 function foo(){ // 1초 동안 블럭함. } - setInterval(foo, 100); + setInterval(foo, 1000); `foo`는 단순히 호출될 때마다 1초 동안 블럭하는 함수다. @@ -46,7 +46,7 @@ JavaScript 엔진의 단위 시간(timer resolution)에 따라서 코드를 실 function foo(){ // something that blocks for 1 second - setTimeout(foo, 100); + setTimeout(foo, 1000); } foo(); diff --git a/doc/pl/other/timeouts.md b/doc/pl/other/timeouts.md index 9cf78d13..06c47114 100644 --- a/doc/pl/other/timeouts.md +++ b/doc/pl/other/timeouts.md @@ -55,7 +55,7 @@ szczególnie przy krótkim interwale. function foo(){ // coś co blokuje wykonanie na 1 sekundę } - setInterval(foo, 100); + setInterval(foo, 1000); W powyższym kodzie kod `foo` zostanie wywołany tylko raz i zablokuje wywołanie na jedną sekundę. @@ -71,7 +71,7 @@ wewnątrz wywoływanej funkcji. function foo(){ // coś co blokuje wykonanie na 1 sekundę - setTimeout(foo, 100); + setTimeout(foo, 1000); } foo(); diff --git a/doc/ru/other/timeouts.md b/doc/ru/other/timeouts.md index 7e2a6647..36ddf97d 100644 --- a/doc/ru/other/timeouts.md +++ b/doc/ru/other/timeouts.md @@ -35,7 +35,7 @@ function foo(){ // что-то, что выполняется одну секунду } - setInterval(foo, 100); + setInterval(foo, 1000); В приведённом коде `foo` выполнится один раз и заблокирует этим главный поток на одну секунду. @@ -47,7 +47,7 @@ function foo(){ // что-то, выполняющееся одну секунду - setTimeout(foo, 100); + setTimeout(foo, 1000); } foo(); diff --git a/doc/tr/other/timeouts.md b/doc/tr/other/timeouts.md index 5454b8e8..f15cb976 100644 --- a/doc/tr/other/timeouts.md +++ b/doc/tr/other/timeouts.md @@ -55,7 +55,7 @@ kullanıldığında, fonksiyon çağrılarının istiflenmesine neden olur. function foo(){ // 1 saniye süren bir işlem } - setInterval(foo, 100); + setInterval(foo, 1000); Yukarıdaki örnekte `foo` fonksiyonu bir kez çağrılıp bir saniye boyunca bloke edecektir. @@ -71,7 +71,7 @@ kullanmaktır. function foo(){ // 1 saniye süren bir işlem - setTimeout(foo, 100); + setTimeout(foo, 1000); } foo(); diff --git a/doc/zh/other/timeouts.md b/doc/zh/other/timeouts.md index 5993e362..4865417d 100755 --- a/doc/zh/other/timeouts.md +++ b/doc/zh/other/timeouts.md @@ -40,7 +40,7 @@ function foo(){ // 阻塞执行 1 秒 } - setInterval(foo, 100); + setInterval(foo, 1000); 上面代码中,`foo` 会执行一次随后被阻塞了一分钟。 @@ -53,7 +53,7 @@ function foo(){ // 阻塞执行 1 秒 - setTimeout(foo, 100); + setTimeout(foo, 1000); } foo(); From 985299bfd1fce480cdf5cd8dfd56eee083518619 Mon Sep 17 00:00:00 2001 From: HIRAKI Satoru Date: Tue, 17 Jan 2012 02:41:12 +0900 Subject: [PATCH 211/463] fix typo --- doc/ja/function/general.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/ja/function/general.md b/doc/ja/function/general.md index a1c490b5..f53e2dd3 100644 --- a/doc/ja/function/general.md +++ b/doc/ja/function/general.md @@ -1,6 +1,6 @@ ## 関数の宣言と式 -関数はJavaScriptの第一級オブジェクトです。この事は、その他の値と同じように渡す事が出来るという事です。この機能で良く使われる一つとして**匿名関数**を他のオジェクトにコールバックとして渡すというものがあり、これで非同期での実装が可能になります。 +関数はJavaScriptの第一級オブジェクトです。この事は、その他の値と同じように渡す事が出来るという事です。この機能で良く使われる一つとして**匿名関数**を他のオブジェクトにコールバックとして渡すというものがあり、これで非同期での実装が可能になります。 ### `関数`宣言 From 09b4f9c407b0b8b8e960c38539d065fe4cdf14cd Mon Sep 17 00:00:00 2001 From: Changwoo Park Date: Tue, 24 Jan 2012 22:55:38 +0900 Subject: [PATCH 212/463] [ko] proofreading --- doc/ko/array/constructor.md | 6 +++--- doc/ko/array/general.md | 16 +++++++------- doc/ko/core/delete.md | 26 +++++++++++----------- doc/ko/core/eval.md | 4 ++-- doc/ko/core/semicolon.md | 28 ++++++++++++------------ doc/ko/core/undefined.md | 8 +++---- doc/ko/function/arguments.md | 30 +++++++++++++------------- doc/ko/function/closures.md | 16 +++++++------- doc/ko/function/constructors.md | 8 +++---- doc/ko/function/general.md | 11 +++++----- doc/ko/function/scopes.md | 38 ++++++++++++++++----------------- doc/ko/function/this.md | 2 +- doc/ko/intro/index.md | 6 +++--- doc/ko/object/forinloop.md | 12 +++++------ doc/ko/object/general.md | 6 +++--- doc/ko/object/hasownproperty.md | 9 ++++---- doc/ko/object/prototype.md | 14 ++++++------ doc/ko/other/timeouts.md | 2 +- doc/ko/types/casting.md | 4 ++-- doc/ko/types/equality.md | 6 +++--- doc/ko/types/typeof.md | 6 +++--- 21 files changed, 128 insertions(+), 130 deletions(-) diff --git a/doc/ko/array/constructor.md b/doc/ko/array/constructor.md index 5297fc73..471fd60d 100644 --- a/doc/ko/array/constructor.md +++ b/doc/ko/array/constructor.md @@ -1,6 +1,6 @@ ## `Array` 생성자 -`Array` 생성자가 파라미터를 처리하는 방법은 모호하기 때문에 항상 `[]` 노테이션으로 Array를 만들어야 한다. +`Array` 생성자가 파라미터를 처리하는 방법은 모호하다. 그래서 항상 `[]` 노테이션으로 Array를 만들어야 한다. [1, 2, 3]; // Result: [1, 2, 3] new Array(1, 2, 3); // Result: [1, 2, 3] @@ -9,13 +9,13 @@ new Array(3); // Result: [] new Array('3') // Result: ['3'] -`Array` 생성자에 인자로 숫자 하나를 넘기면 생성자는 `length`가 그 숫자인 텅 빈 `Array` 하나를 반환한다. 생성자는 **오직** `length` 프로퍼티에 할당하기만 하고 실제 `Array`는 초기화하지 않는다는 것을 기억해야 한다. +`Array` 생성자에 인자로 숫자를 넘기면 `length`가 그 숫자인 텅 빈 `Array` 하나를 반환된다. 생성자는 **오직** `length` 프로퍼티에 그 숫자를 할당하기만 하고 `Array`는 실제로 초기화하지 않는다. var arr = new Array(3); arr[1]; // undefined 1 in arr; // false, 이 인덱스는 초기화되지 않음. -Array의 length 프로퍼티에 숫자를 할당해주는 이 기능이 유용할 때도 있긴 있다. `for loop`을 사용하지 않고 스트링을 더하는 경우가 그렇다. +Array의 length 프로퍼티에 숫자를 할당해주는 이 기능이 유용할 때도 있긴 있다. `for loop`을 사용하지 않고 스트링을 더할 때가 그렇다. new Array(count + 1).join(stringToRepeat); diff --git a/doc/ko/array/general.md b/doc/ko/array/general.md index 69214a15..0a396d2e 100644 --- a/doc/ko/array/general.md +++ b/doc/ko/array/general.md @@ -1,29 +1,29 @@ ## Array Iteration과 프로퍼티 -JavaScript에서는 Array도 객체지만 Iterate를 할 때 [`for in`](#object.forinloop)을 사용해서 좋을 게 없다. +JavaScript에서는 Array도 객체 Iterate를 할 때 [`for in`](#object.forinloop)을 사용해서 좋을 게 없다. 실제로 Array에 `for in`을 사용하지 말아야 할 근거가 매우 많다. -> **Note:** JavaScript의 Array는 *Associative Array*가 **아니다**. JavaScript [객체](#object.general)는 key/value만 mapping 할 뿐이다. Associative Array는 순서를 보장하지만, 객체는 보장하지 않는다. +> **Note:** JavaScript의 Array는 *Associative Array*가 **아니다**. JavaScript [객체](#object.general)는 key/value만 Mapping할 뿐이다. Associative Array는 순서를 보장하지만, 객체는 보장하지 않는다. `for in`은 프로토타입 체인에 있는 프로퍼티를 모두 훑는(enumerate) 데다가 객체 자신의 프로퍼티만 훑으려면 [`hasOwnProperty`](#object.hasownproperty)를 사용해야 하기 때문에 `for`보다 20배 느리다. ### Iteration -Array를 Iterate 할 때에는 구식인 `for`를 사용하는 것이 가장 빠르다. +Array를 Iterate할 때에는 구식인 `for`를 사용하는 것이 가장 빠르다. var list = [1, 2, 3, 4, 5, ...... 100000000]; for(var i = 0, l = list.length; i < l; i++) { console.log(list[i]); } -위 예제에서 꼭 기억해야 하는 것은 `l = list.length`로 Array의 length 값을 캐시 했다는 것이다. +이 예제에서 `l = list.length`로 Array의 length 값을 캐시해야 한다는 것을 꼭 기억해야 한다. -Array에 있는 `length` 프로퍼티를 iterate마다 사용하는 것은 좀 부담스럽다. 최신 JavaScript 엔진은 이 일을 알아서 처리하기도 하지만 코드가 새 엔진에서 실행되도록 보장할 방법이 없다. +매 Iterate마다 Array에 있는 `length` 프로퍼티에 접근하는 것은 좀 부담스럽다. 최신 JavaScript 엔진은 이 일을 알아서 처리해주기도 하지만 코드가 늘 새 엔진에서 실행되도록 보장할 방법이 없다. 실제로 캐시 하지 않으면 성능이 반으로 줄어든다. ### `length` 프로퍼티 -`length` 프로퍼티의 *getter*는 단순히 Array 안에 있는 엘리먼트의 개수를 반환하고 *setter*는 할당한 수로 Array를 잘라 버린다. +`length` 프로퍼티의 *getter*는 단순히 Array 안에 있는 엘리먼트의 개수를 반환하고 *setter*는 Array를 할당한 수만큼 잘라 버린다. var foo = [1, 2, 3, 4, 5, 6]; foo.length = 3; @@ -32,8 +32,8 @@ Array에 있는 `length` 프로퍼티를 iterate마다 사용하는 것은 좀 foo.length = 6; foo; // [1, 2, 3] -현재 크기보다 더 작은 값을 할당하면 Array를 자르지만, 현재 크기보다 더 큰 값을 할당하면 아무것도 하지 않는다. +현재 크기보다 더 작은 값을 할당하면 Array를 자르지만, 현재 크기보다 더 큰 값을 할당한다고 해서 Array를 늘리지 않는다. ### 결론 -최적의 성능을 위해서 `for`를 사용하고 `length` 프로퍼티 값을 캐시 하길 바란다. Array에 `for in`을 사용하면 성능도 떨어지고 버그 나기도 쉽다. +최적의 성능을 위해서는 `for`를 사용하고 `length` 프로퍼티 값을 캐시해야 한다. Array에 `for in`을 사용하면 성능도 떨어지고 버그 나기도 쉽다. diff --git a/doc/ko/core/delete.md b/doc/ko/core/delete.md index 0effdd10..53e04e04 100644 --- a/doc/ko/core/delete.md +++ b/doc/ko/core/delete.md @@ -1,17 +1,17 @@ ## `delete` -간단히 말해서 global 변수, 함수, 등은 `DontDelete` 속성이기 때문에 삭제 못 한다. +간단히 말해서 global 변수, Function, 등은 `DontDelete` 속성이기 때문에 delete하지 못 한다. -### Global 코드와 함수 코드 +### Global 코드와 Function 코드 -Global이나 Function scope에 정의된 함수나 변수는 모두 Activation 객체나 Global 객체의 프로퍼티다. 이 프로퍼티는 모두 `DontDelete`속성을 가진다. Global이나 Function 코드에서 변수나 함수의 정의하면 항상 `DontDelete` 프로퍼티로 만들어진다. 그러니까 삭제할 수 없다: +Global이나 Function Scope에 정의한 Fuction이나 변수는 모두 Activation 객체나 Global 객체의 프로퍼티다. 이 프로퍼티는 모두 `DontDelete` 속성을 가진다. Global이나 Function 코드에서 변수나 Function의 정의하면 항상 `DontDelete` 프로퍼티로 만들어진다. 그러니까 delete할 수 없다: // Global 변수: var a = 1; // DontDelete가 설정된다. delete a; // false a; // 1 - // 함수: + // Function: function f() {} // DontDelete가 설정된다. delete f; // false typeof f; // "function" @@ -23,7 +23,7 @@ Global이나 Function scope에 정의된 함수나 변수는 모두 Activation ### Explicit 프로퍼티 -다음 예제에서 만드는 property는 정상적으로 지워진다. 이런 걸 Explicit 프로퍼티라고 부른다: +다음 예제에서 만드는 프로퍼티는 delete할 수 있다. 이런 걸 Explicit 프로퍼티라고 부른다: // Explicit 프로퍼티를 만든다: var obj = {x: 1}; @@ -33,24 +33,24 @@ Global이나 Function scope에 정의된 함수나 변수는 모두 Activation obj.x; // undefined obj.y; // undefined -`obj.x`와 `obj.y`는 `DontDelete` 속성이 아녀서 삭제된다. 그러나 다음과 같은 코드도 잘 동작하기 때문에 헷갈린다.: +`obj.x`와 `obj.y`는 `DontDelete` 속성이 아니라서 delete할 수 있다. 그러나 다음과 같은 코드도 잘 동작하기 때문에 헷갈린다: - // IE를 빼고 잘 동작한다.: + // IE를 빼고 잘 동작한다: var GLOBAL_OBJECT = this; GLOBAL_OBJECT.a = 1; - a === GLOBAL_OBJECT.a; // true - 진짜 Global 변순지 확인하는 것 + a === GLOBAL_OBJECT.a; // true - 진짜 Global 변수인지 확인하는 것 delete GLOBAL_OBJECT.a; // true GLOBAL_OBJECT.a; // undefined -[`this`](#function.this)가 Global 객체를 가리키는 것을 이용해서 명시적으로 프로퍼티 `a`를 선언하면 삭제할 수 있다. 이런 꼼수가 가능하다. +[`this`](#function.this)가 Global 객체를 가리키는 것을 이용해서 명시적으로 프로퍼티 `a`를 선언하면 삭제할 수 있다. 이것은 꼼수다. IE (적어도 6-8)는 버그가 있어서 안 된다. -### arguments와 함수의 기본 프로퍼티 +### Argument들과 Function의 기본 프로퍼티 -함수의 [`arguments` 객체](#function.arguments)와 built-in 프로퍼티도 `DontDelete` 속성이다. +Function의 [`arguments` 객체](#function.arguments)와 기본 프로퍼티도 `DontDelete` 속성이다. - // 함수의 arguments와 프로퍼티: + // Function의 arguments와 프로퍼티: (function (x) { delete arguments; // false @@ -69,7 +69,7 @@ IE (적어도 6-8)는 버그가 있어서 안 된다. (역주, Host 객체들은 document같은 DOM 객체를 말한다.) -Host 객체를 delete하면 어떻게 될지 알 수 없다. 어떻게 Host 객체를 delete해야 하는지 표준에 정의되지 않았다. +Host 객체를 delete하면 어떻게 될지 알 수 없다. 표준에는 어떻게 Host 객체를 delete해야 하는지 정의하지 않았다. ### 결론 diff --git a/doc/ko/core/eval.md b/doc/ko/core/eval.md index f366401c..80706598 100644 --- a/doc/ko/core/eval.md +++ b/doc/ko/core/eval.md @@ -27,7 +27,7 @@ ### 가짜 `eval` -[timeout functions](#other.timeouts)인 `setTimeout`과 `setInterval`은 첫 번째 인자로 스트링을 입력받을 수 있다. 이 경우에는 `eval`을 직접 호출하는 것이 아녀서 항상 global scope에서 실행된다. +[`setTimeout`과 `setInterval`](#other.timeouts)은 첫 번째 인자로 스트링을 입력받을 수 있다. 이 경우에는 `eval`을 직접 호출하는 것이 아니라서 항상 Global Scope에서 실행된다. ### 보안 이슈 @@ -35,4 +35,4 @@ ### 결론 -`eval`은 사용하지 않는 게 좋다. `eval`을 사용하는 모든 코드는 성능, 보안, 버그의 문제를 일으킬 수 있다. 만약 `eval`이 필요해지면 *설계를 변경*하여 `eval`이 필요 없게 만들어야 한다. +`eval`은 사용하지 않는 게 좋다. `eval`을 사용하는 모든 코드는 성능, 보안, 버그 문제를 일으킬 수 있다. 만약 `eval`이 필요해지면 *설계를 변경*하여 `eval`이 필요 없게 만들어야 한다. diff --git a/doc/ko/core/semicolon.md b/doc/ko/core/semicolon.md index 723ff2d4..f58e1782 100644 --- a/doc/ko/core/semicolon.md +++ b/doc/ko/core/semicolon.md @@ -1,24 +1,24 @@ -## 세미콜론을 자동으로 삽입해준다. +## 쎄미콜론을 자동으로 삽입해준다. -JavaScript는 C와 문법이 비슷하지만, 꼭 코드에 semicolon을 사용하도록 강제하지 않는다. 그래서 생략할 수 있다. +JavaScript는 C와 문법이 비슷하지만, 꼭 코드에 쎄미콜론을 사용하도록 강제하지 않는다. 그래서 생략할 수 있다. -사실 JavaScript는 semicolon이 꼭 있어야 하고 없으면 이해하지 못한다. 그래서 JavaScript 파서는 semicolon이 없으면 **자동으로** semicolon을 추가한다. +사실 JavaScript는 쎄미콜론이 꼭 있어야 하고 없으면 이해하지 못한다. 그래서 JavaScript 파서는 쎄미콜론이 없으면 **자동으로** 쎄미콜론을 추가한다. var foo = function() { - } // 세미콜론이 없으니 에러 난다. + } // 쎄미콜론이 없으니 에러 난다. test() -파서는 세미콜론을 삽입하고 다시 시도한다. +파서는 쎄미콜론을 삽입하고 다시 시도한다. var foo = function() { }; // 에러가 없어짐. test() -JavaScript에서 세미콜론을 자동으로 삽입한 것은 **대표적인** 설계 오류 중 하나다. 세미콜론 유무에 따라 *전혀* 다른 코드가 될 수 있다. +쎄미콜론을 자동으로 삽입한 것이 **대표적인** JavaScript 설계 오류다. 쎄미콜론 유무에 따라 *전혀* 다른 코드가 될 수 있다. ### 어떻게 다를까? -코드에 세미콜론이 없으면 파서가 어디에 넣을지 결정한다. +코드에 쎄미콜론이 없으면 파서가 어디에 넣을지 결정한다. (function(window, undefined) { function test(options) { @@ -47,12 +47,12 @@ JavaScript에서 세미콜론을 자동으로 삽입한 것은 **대표적인** })(window) -파서는 다음과 같이 삽입한다. +파서는 이 코드에 쎄미콜론을 다음과 같이 삽입한다. (function(window, undefined) { function test(options) { - // 세미콜론을 넣는 것이 아니라 줄을 합친다. + // 쎄미콜론을 넣는 것이 아니라 줄을 합친다. log('testing!')(options.list || []).forEach(function(i) { }); // <- 여기 @@ -66,7 +66,7 @@ JavaScript에서 세미콜론을 자동으로 삽입한 것은 **대표적인** { // 파서는 단순 블럭이라고 생각하고 // 단순한 레이블과 함수 - foo: function() {} + foo: function() {} }; // <- 여기 } window.test = test; // <- 여기 @@ -75,15 +75,15 @@ JavaScript에서 세미콜론을 자동으로 삽입한 것은 **대표적인** })(window)(function(window) { window.someLibrary = {}; // <- 여기 - })(window); //<- 여기에 파서는 세미콜론을 넣는다. + })(window); //<- 여기에 파서는 쎄미콜론을 넣는다. -> **주의:** JavaScript 파서는 new line 문자가 뒤따라 오는 return 구문을 제대로 처리하지 못한다. 자동으로 세미콜론을 넣는 것 자체의 문제는 아니지만 어쨌든 여전히 문제로 남아있다. +> **주의:** JavaScript 파서는 new line 문자가 뒤따라 오는 return 구문을 제대로 처리하지 못한다. 자동으로 쎄미콜론을 넣는 것 자체의 문제는 아니지만 어쨌든 여전히 문제다. 파서는 완전히 다른 코드로 만들어 버린다. 이것은 **오류**다. ### Parenthesis -세미콜론 없이 괄호가 붙어 있으면 파서는 세미콜론을 넣지 않는다. +쎄미콜론 없이 괄호가 붙어 있으면 파서는 쎄미콜론을 넣지 않는다. log('testing!') (options.list || []).forEach(function(i) {}) @@ -96,4 +96,4 @@ JavaScript에서 세미콜론을 자동으로 삽입한 것은 **대표적인** ### 결론 -세미콜론은 반드시 사용해야 한다. 그리고 `{}`도 생략하지 않고 꼭 사용하는 것이 좋다. 한 줄밖에 안 되는 `if` / `else` 블럭에서도 꼭 사용해야 한다. 이 두 가지 규칙을 잘 지키면 JavaScript 파서가 잘못 해석하는 일을 미리 방지하고 코드도 튼튼해진다. +쎄미콜론은 반드시 사용해야 한다. 그리고 `{}`도 생략하지 않고 꼭 사용하는 것이 좋다. 한 줄밖에 안 되는 `if` / `else` 블럭에서도 꼭 사용해야 한다. 이 두 가지 규칙을 잘 지키면 JavaScript 파서가 잘못 해석하는 일을 미리 방지하고 코드도 튼튼해진다. diff --git a/doc/ko/core/undefined.md b/doc/ko/core/undefined.md index c66078ad..e91f7771 100644 --- a/doc/ko/core/undefined.md +++ b/doc/ko/core/undefined.md @@ -25,7 +25,7 @@ global 변수 `undefined`는 `undefined`라는 객체를 가리키는 것뿐이 그래서 `undefined`와 비교하려면 먼저 `undefined`의 값을 찾아와야 한다. -보통 `undefined` 변수가 바뀌어 있을 때를 대비해서 undefined라는 변수를 인자로 받는 [anonymous wrapper](#function.scopes)로 감싸고 아무런 인자를 넘기지 않는 꼼수를 사용한다. +`undefined` 변수가 바뀔 때를 대비해서 `undefined`라는 변수를 인자로 받는 [anonymous wrapper](#function.scopes)로 감싸고 아무런 인자를 넘기지 않는 꼼수를 사용한다. var undefined = 123; (function(something, foo, undefined) { @@ -34,7 +34,7 @@ global 변수 `undefined`는 `undefined`라는 객체를 가리키는 것뿐이 })('Hello World', 42); -wrapper 안에서 변수를 새로 정의하는 방법으로도 같은 효과를 볼 수 있다. +wrapper 안에 변수를 새로 정의하는 방법으로도 같은 효과를 볼 수 있다. var undefined = 123; (function(something, foo) { @@ -47,6 +47,6 @@ wrapper 안에서 변수를 새로 정의하는 방법으로도 같은 효과를 ### `Null` 객체의 용도 -JavaScript 언어에서는 `undefined`를 다른 언어에서 *null*을 사용하듯이 쓰고 진짜 `null`은 그냥 다른 데이터 타입 중 하나일 뿐이다. +JavaScript 언어에서는 `undefined`를 다른 언어의 *null* 처럼 쓴다. 진짜 `null`은 그냥 데이터 타입 중 하나일 뿐이지 더도덜도 아니다. -JavaScript 내부적인 곳에 사용하는 경우가 아니면 null 대신 `undefined`를 사용해도 된다(`Foo.prototype = null`같이 프로토타입 체인을 끊을 때는 null을 사용한다). +JavaScript를 깊숙히 건드리는 것이 아니면 null 대신 `undefined`를 사용해도 된다(`Foo.prototype = null`같이 프로토타입 체인을 끊을 때는 null을 사용한다). diff --git a/doc/ko/function/arguments.md b/doc/ko/function/arguments.md index e6f5a553..cda8407c 100644 --- a/doc/ko/function/arguments.md +++ b/doc/ko/function/arguments.md @@ -1,12 +1,12 @@ ## `arguments` 객체 -JavaScript의 모든 Function Scope에는 `arguments`라는 특별한 변수가 있다. 이 변수는 함수에 넘겨진 모든 인자에 대한 정보가 담겨 있다. +JavaScript의 모든 Function Scope에는 `arguments`라는 특별한 변수가 있다. 이 변수는 Function에 넘겨진 모든 인자에 대한 정보가 담겨 있다. -> **Note:** `arguments` 변수는 함수 안에서 다시 정의할 수 없다. `var` 구문이나 파라미터에 `arguments`라는 이름으로 변수를 정의해도 변수가 재정의되지 않는다. +> **Note:** `arguments` 변수는 Function 안에서 다시 정의할 수 없다. `var` 구문이나 파라미터에 `arguments`라는 이름으로 변수를 정의해도 변수가 재정의되지 않는다. -`length` 프로퍼티도 있고 대체로 Array와 비슷하게 생겼지만 Array.prototype을 상속받지 않았다. `arguments` 객체는 `Array`가 아니다. +`length` 프로퍼티도 있는 데다가 여러모로 Array와 비슷하게 생겼지만 Array.prototype을 상속받지 않았다. `arguments` 객체는 `Array`가 아니다. -그래서 `arguments`에는 `push`, `pop`, `slice`같은 표준 메소드가 없다. `for`로 하는 iteration은 원래 잘되지만 `Array`의 메소드를 이용하려면 `arguments`를 Array로 변환해야 한다. +그래서 `arguments`에는 `push`, `pop`, `slice` 같은 표준 메소드가 없다. `for`로 하는 Iteration은 원래 잘되지만 `Array`의 메소드를 이용하려면 `arguments`를 Array로 변환해야 한다. ### Array로 변환하기 @@ -18,7 +18,7 @@ JavaScript의 모든 Function Scope에는 `arguments`라는 특별한 변수가 ### arguemnts 객체 넘기기 -어떤 함수에서 다른 함수로 arguments 객체를 넘길 때에는 다음과 같이 하는 것이 좋다. +어떤 Function에서 다른 Function로 arguments 객체를 넘길 때에는 다음과 같이 하는 것이 좋다. function foo() { bar.apply(null, arguments); @@ -36,18 +36,18 @@ JavaScript의 모든 Function Scope에는 `arguments`라는 특별한 변수가 }; // "method"의 unbound 버전 - // 이 함수의 인자: this, arg1, arg2...argN + // 이 Function의 인자: this, arg1, arg2...argN Foo.method = function() { // 결과: Foo.prototype.method.call(this, arg1, arg2... argN) Function.call.apply(Foo.prototype.method, arguments); }; -### 파라미터로 선언한 것과 arguments 객체 인덱스 +### 파라미터와 arguments 객체 인덱스 -`arguments` 객체의 프로퍼티와 파라미터는 모두 *getter*와 *setter*가 만들어진다. +파라미터와 `arguments` 객체의 프로퍼티는 모두 *getter*와 *setter*를 가진다. -그래서 파라미터의 값이나 `arguments` 객체의 프로퍼티 중 하나를 바꾸면 같이 바뀐다. +그래서 파라미터나 `arguments` 객체의 프로퍼티의 값을 바꾸면 둘 다 바뀐다. function foo(a, b, c) { arguments[0] = 2; @@ -64,17 +64,17 @@ JavaScript의 모든 Function Scope에는 `arguments`라는 특별한 변수가 ### 성능에 대한 진실과 오해. -`arguments`라는 이름의 변수를 함수 안에 정의하거나 파라미터로 정의해도 `arguments` 객체는 만들어진다. +`arguments` 객체는 항상 만들어 지지만 예외도 있다. `arguments`라는 이름의 변수를 Function 안에 정의하거나 그 이름으로 파라미터를 만들면 `arguemnts` 객체는 만들어지지 않는다. 그렇지만, 이럴때는 어차피 안쓰겠다는 의미니까 상관 없다. -getter*와 *setter*는 항상 생성되기 때문에 getter/setter를 사용하는 것은 성능에 별 영향을 끼치지 않는다. 단순히 `arguments` 객체의 프로퍼티에 접근하는 수준이 아닌 실제 코드에서도 그렇다. +그리고 *getter*와 *setter*는 항상 생성되기 때문에 getter/setter를 사용하는 것은 성능에 별 영향을 끼치지 않는다. 예제처럼 단순한 코드가 아니라 `arguments` 객체를 다방면으로 활용하는 실제 코드에서도 마찬가지다. > **ES5 Note:** strict 모드에서는 *getter*와 *setter*가 생성되지 않는다. 그러나 예외도 있다. 최신 JavaScript 엔진에서 `arguments.callee`를 사용하면 성능이 확 떨어진다. function foo() { - arguments.callee; // 이 함수를 가리킨다. - arguments.callee.caller; // 이 함수를 호출한 함수를 가리킨다. + arguments.callee; // 이 Function를 가리킨다. + arguments.callee.caller; // 이 Function를 호출한 Function를 가리킨다. } function bigLoop() { @@ -83,10 +83,10 @@ getter*와 *setter*는 항상 생성되기 때문에 getter/setter를 사용하 } } -이 코드에서 callee와 caller를 알아야 하기 때문에 `foo`는 더는 [inlining][1]되지 않는다. 이렇게 쓰면 inlining이 주는 성능상 장점을 포기해야 하는데다가 함수가 호출되는 상황(calling context)에 의존하게 돼 버려서 encapsulation도 해친다. +이 코드에서 Callee와 Caller를 알아야 하기 때문에 `foo`는 더는 [인라인][1]하지 않는다. 이렇게 쓰면 인라인이 주는 성능상 장점을 포기해야 하는데다가 Function이 호출되는 상황(calling context)에 의존하게 돼 버려서 Encapsulation도 해친다. `arguments.callee`와 그 프로퍼티들은 **절대** 사용하지 말아야 한다. > **ES5 Note:** strict 모드에서 `arguments.callee`는 deprecated됐기 때문에 사용하면 `TypeError`가 난다. -[1]: http://en.wikipedia.org/wiki/Inlining \ No newline at end of file +[1]: http://en.wikipedia.org/wiki/Inlining diff --git a/doc/ko/function/closures.md b/doc/ko/function/closures.md index c9b7e989..49628231 100644 --- a/doc/ko/function/closures.md +++ b/doc/ko/function/closures.md @@ -1,6 +1,6 @@ ## Closure와 Reference -JavaScript가 두드러지는 점 중의 하나가 *Closure*를 사용할 수 있다는 것이다. Closure는 항상 그 Closure를 만든 외부 Scope에 접근할 수 있다. JavaScript에서 Scope을 만들려면 [function Scope](#function.scopes)을 사용하는 방법뿐이기 때문에 기본적으로 모든 함수는 Closure다. +*Closure*는 JavaScript의 특장점 중 하나다. Closure에서는 그 Closure를 만든 외부 Scope에 접근할 있다. JavaScript에서 Scope을 만들려면 [Function Scope](#function.scopes)을 사용하는 방법밖에 없기 때문에 Closure는 함수로 만든다. ### private 변수 @@ -21,11 +21,11 @@ JavaScript가 두드러지는 점 중의 하나가 *Closure*를 사용할 수 foo.increment(); foo.get(); // 5 -`Counter`는 `increment` closure와 `get` closure를 두 개 반환한다. 이 두 closure는 `Counter` Scope에 대한 **reference**를 유지하고 있기 때문에 그 Scope에 있는 count 변수에 계속 접근할 수 있다. +`Counter`는 `increment` Closure와 `get` Closure 두 개를 반환한다. 이 두 Closure는 `Counter` Scope에 대한 **reference**를 유지하고 있기 때문에 그 Scope에 있는 count 변수에 계속 접근할 수 있다. ### Private 변수가 진짜 맞나? -JavaScript에서 Scope을 어딘가에 할당하거나 저장해두는 것이 불가능해서 Scope 밖에서 count 변수에 직접 접근할 방법은 없다. 꼭 Scope 안에서 정의한 두 closure를 통해서만 접근할 수 있다. +JavaScript에서 Scope을 어딘가에 할당하거나 저장해두는 것이 불가능하다. 그래서 Scope 밖에서는 count 변수에 직접 접근할 수 없다. 꼭 Scope 안에서 정의한 두 closure를 통해서만 접근할 수 있다. var foo = new Counter(4); foo.hack = function() { @@ -36,7 +36,7 @@ JavaScript에서 Scope을 어딘가에 할당하거나 저장해두는 것이 ### Loop에서 Closure 사용하기 -많은 사람은 Loop에서 closure를 사용할 때 자주 index 변수를 잘못 사용한다. +많은 사람은 Loop에서 Closure를 사용할 때 자주 index 변수를 잘못 사용한다. for(var i = 0; i < 10; i++) { setTimeout(function() { @@ -46,13 +46,13 @@ JavaScript에서 Scope을 어딘가에 할당하거나 저장해두는 것이 이 코드는 `0`부터 `9`까지의 수를 출력하지 않고 `10`만 열 번 출력한다. -이 *anonymous* function은 변수 `i`에 대한 참조를 저장했다가 `console.log`가 호출되는 시점에 `i`의 값을 사용한다. `console.log`가 호출되는 시점은 `for loop`이 이미 끝난 상태라서 `i` 값은 10이다. +이 *Anonymous* Function은 변수 `i`에 대한 참조를 저장했다가 `console.log`가 호출되는 시점에 `i`의 값을 사용한다. `console.log`가 호출되는 시점은 `for loop`이 이미 끝난 상태라서 `i` 값은 10이다. 기대한 결과를 얻으려면 `i` 값을 복사해 두어야 한다. ### 이 Reference 문제 해결하기 -[anonymous wrapper](#function.scopes)로 index 값을 복사하는 것이 좋다. +[Anonymous Wrapper](#function.scopes)로 index 값을 복사하는 것이 좋다. for(var i = 0; i < 10; i++) { (function(e) { @@ -62,11 +62,11 @@ JavaScript에서 Scope을 어딘가에 할당하거나 저장해두는 것이 })(i); } -이 anonymous function의 인자로 `i`를 넘기면 이 함수의 파라미터 e에 i의 **값**이 복사된다. +이 Anonymous Function의 인자로 `i`를 넘기면 이 함수의 파라미터 e에 i의 **값**이 복사된다. 이 `setTimeout`는 anonymous function 파라미터인 `e`에 대한 참조를 갖게 되고 `e`는 loop의 상태에 따라 변하지 않는다. -함수를 반환하는 anonymous wrapper를 이용하는 방법도 있다. 다음 코드는 위 코드와 같다. +함수를 반환하는 Anonymous Wrapper를 이용하는 방법도 있다. 다음 코드는 위 코드와 같다. for(var i = 0; i < 10; i++) { setTimeout((function(e) { diff --git a/doc/ko/function/constructors.md b/doc/ko/function/constructors.md index 9ee49f57..2365c8a5 100644 --- a/doc/ko/function/constructors.md +++ b/doc/ko/function/constructors.md @@ -70,9 +70,9 @@ new 키워드가 있으나 없으니 `Bar` 생성자는 똑같이 동작한다. ### 팩토리로 객체 만들기 -`new` 키워들 빼먹었을 때 버그가 생긴다는 이유로 **아예 new를 사용하지 말 것**을 권하기도 한다. +`new` 키워드를 빼먹었을 때 버그가 생긴다는 이유로 **아예 new를 사용하지 말 것**을 권하기도 한다. -이를 위해서 객체를 만들고 반환해주는 팩토리를 사용할 수 있다. +객체를 만들고 반환해주는 팩토리를 사용하여 `new` 키워드 문제를 회피할 수 있다. function Foo() { var obj = {}; @@ -95,6 +95,6 @@ new 키워드가 있으나 없으니 `Bar` 생성자는 똑같이 동작한다. 2. 팩토리를 상속하려면 모든 메소드를 복사하거나 객체의 prototype에 객체를 할당해 주어야 한다. 3. `new` 키워드를 누락시켜서 prototype chain을 끊어버리는 것은 아무래도 언어의 의도에 어긋난다. -### 결론 +### 결론 -`new` 키워가 생략되면 버그가 생길 수 있지만 그렇다고 prototype을 사용하지 않을 이유가 되지 않는다. 애플리케이션에 맞는 방법을 선택하는 것이 나을 거고 어떤 방법이든 **엄격하고 한결같이* 지켜야 한다. +`new` 키워드가 생략되면 버그가 생길 수 있지만 그렇다고 prototype을 사용하지 않을 이유가 되지 않는다. 애플리케이션에 맞는 방법을 선택하는 것이 나을 거고 어떤 방법이든 **엄격하고 한결같이* 지켜야 한다. diff --git a/doc/ko/function/general.md b/doc/ko/function/general.md index 54401b08..402a34ec 100644 --- a/doc/ko/function/general.md +++ b/doc/ko/function/general.md @@ -1,12 +1,12 @@ -## Function Declarations and Expressions +## Function Declarations과 Function Expressions -JavaScript의 Function은 first class object라서 일반 객체처럼 취급될 수 있다. 그래서 익명 함수를 비동기 함수의 callback 같은 거로 넘길 수 있다. +JavaScript의 Function은 First Class Object라서 일반 객체처럼 취급될 수 있다. 그래서 익명 함수를 비동기 함수의 callback 같은 거로 넘길 수 있다. ### `function` Declaration function foo() {} -코드를 실행하기 전에 이 함수 [hoist](#function.scopes)되기 때문에 해당 Scope 어디에서나 이 함수를 호출할 수 있다. 심지어 함수를 정의하기 전에 호출해도 된다. +코드를 실행하기 전에 이 함수는 [Hoist](#function.scopes)되기 때문에 해당 Scope 어디에서나 이 함수를 호출할 수 있다. 심지어 함수를 정의하기 전에 호출해도 된다. foo(); // 이 코드가 실행되기 전에 foo가 만들어져서 잘 호출된다. function foo() {} @@ -21,7 +21,7 @@ JavaScript의 Function은 first class object라서 일반 객체처럼 취급될 foo(); // TypeError가 난다. var foo = function() {}; -JavaScript가 hoist하는 것은 `var`로 선언하는 부분뿐이기 때문에 코드가 실행하기 전에 `foo` 변수는 정의된다. +JavaScript가 Hoist하는 것은 `var`로 선언하는 부분뿐이기 때문에 코드가 실행하기 전에 `foo` 변수는 정의된다. 그러나 할당은 런타임에만 가능한 일이라 할당하는 코드가 실행될 때까지 `foo`변수는 기본 값인 [undefined](#core.undefined)다. @@ -34,5 +34,4 @@ Named Function을 할당하는 경우는 조금 특이하다. } bar(); // ReferenceError -함수 밖에서 `bar`를 사용할 수 없지만, 함수 안에서는 사용할 수 있다. JavaScript가 [이름을 찾는 방법](#function.scopes)이 있는데 function Scope에서는 항상 그 함수의 이름을 사용할 수 있다. - +함수 밖에서는 `bar`를 사용할 수 없지만, 함수 안에서는 사용할 수 있다. JavaScript가 [이름을 찾는 방법](#function.scopes)이 있는데 function Scope에서는 항상 그 함수의 이름을 사용할 수 있다. diff --git a/doc/ko/function/scopes.md b/doc/ko/function/scopes.md index c72c49c5..3e887ab5 100644 --- a/doc/ko/function/scopes.md +++ b/doc/ko/function/scopes.md @@ -9,13 +9,13 @@ JavaScript는 '{}' Block이 배배 꼬여 있어도 문법적으로는 잘 처 console.log(i); // 10 } -> **Note:** 할당할 때, 반환할 때, 함수 인자에서 사용되는 것을 제외하면 `{...}`는 모두 객체 리터럴이 아니라 Block 구문으로 해석된다. 그래서 [세미콜론을 자동으로 넣어주면](#core.semicolon) 에러가 생길 수 있다. +> **Note:** 할당할 때, 반환할 때, Function 인자에서 사용되는 것을 제외하면 `{...}`는 모두 객체 리터럴이 아니라 Block 구문으로 해석된다. 그래서 [세미콜론을 자동으로 넣어주면](#core.semicolon) 에러가 생길 수 있다. -그리고 JavaScript에는 namespace 개념이 없어서 *항상 공유하는* namepace가 하나 있는 거다. +그리고 JavaScript에는 Namepspace 개념이 없어서 *항상 공유하는* namepace가 딱 하나다. -변수를 사용할 때마다 JavaScript는 아는 Scope을 상위방향으로 찾는다. Global Scope에까지 해당 변수를 찾지 못하면 `ReferenceError`가 난다. +변수를 사용할 때마다 JavaScript는 아는 Scope을 상위 방향으로 찾는다. Global Scope에까지 해당 변수를 찾지 못하면 `ReferenceError`가 난다. -### Global 변수의 지옥. +### Global 변수 지옥. // script A foo = '42'; @@ -23,9 +23,9 @@ JavaScript는 '{}' Block이 배배 꼬여 있어도 문법적으로는 잘 처 // script B var foo = '42' -이 두 스크립트는 다르다. Script A는 *Global* Scope에 `foo`라는 변수를 정의하는 것이고 Script B는 *현* Scope에 변수 `foo`를 정의하는 것이다. +이 두 스크립트는 전혀 다르다. Script A는 *Global* Scope에 `foo`라는 변수를 정의하는 것이고 Script B는 *현* Scope에 변수 `foo`를 정의하는 것이다. -다시 말하지만, 이 둘은 전혀 다르고 `var`가 없는 것이 중요한 의미가 있다. +다시 말하지만, 이 둘은 전혀 다르고 `var`가 없을 때 특별한 의미가 있다. // Global Scope var foo = 42; @@ -36,7 +36,7 @@ JavaScript는 '{}' Block이 배배 꼬여 있어도 문법적으로는 잘 처 test(); foo; // 21 -함수에서 `var` 구문을 빼버리면 Global Scope의 `foo`의 값을 바꿔버린다. '뭐 이게 뭐가 문제야'라고 생각될 수 있지만 수천 줄인 JavaScript 코드에서 `var`를 빼먹어서 생긴 버그를 해결하는 것은 정말 어렵다. +Function에서 `var` 구문을 빼버리면 Global Scope의 `foo`의 값을 바꿔버린다. '뭐 이게 뭐가 문제야'라고 생각될 수 있지만 수천 줄인 JavaScript 코드에서 `var`를 빼먹어서 생긴 버그를 해결하는 것은 정말 어렵다. // Global Scope var items = [/* some list */]; @@ -47,7 +47,7 @@ JavaScript는 '{}' Block이 배배 꼬여 있어도 문법적으로는 잘 처 function subLoop() { // Scope of subLoop for(i = 0; i < 10; i++) { // var가 없다. - // 내가 for문도 하는데... + // 내가 for문도 해봐서 아는데... } } @@ -55,7 +55,7 @@ subLoop이 Global 변수 `i`의 값을 변경해버리기 때문에 외부 Loop ### Local 변수 -JavaScript에서 Local 변수를 정의하는 방법은 [함수 파라미터](#function.general)와 `var`로 정의한 변수뿐이다. +JavaScript에서 Local 변수는 [Function 파라미터](#function.general)와 `var`로 정의한 변수뿐이다. // Global Scope var foo = 1; @@ -63,7 +63,7 @@ JavaScript에서 Local 변수를 정의하는 방법은 [함수 파라미터](#f var i = 2; function test(i) { - // test 함수의 local Scope + // test Function의 local Scope i = 5; var foo = 3; @@ -123,7 +123,7 @@ Block Scope이 없으므로 Loop이나 if의 Block 안에 있는 `var` 구문들 원래 코드에서 `if` Block은 *Global 변수* `goo`를 바꾸는 것처럼 보였지만 Hoisting 후에는 *local 변수*를 바꾼다. -*Hoisting*을 모르면 다음과 같은 코드는 `ReferenceError`가 날 것으로 생각할 것이다. +*Hoisting*을 모르면 다음과 같은 코드는 `ReferenceError`를 낼 것으로 생각할 것이다. // SomeImportantThing이 초기화됐는지 검사한다. if (!SomeImportantThing) { @@ -145,29 +145,29 @@ Block Scope이 없으므로 Loop이나 if의 Block 안에 있는 `var` 구문들 JavaScript의 모든 Scope은 *현 객체*를 가리키는 [`this`](#function.this)를 가지고 있다. *Global Scope*에도 this가 있다. -Function Scope에는 [`arguments`](#function.arguments)라는 변수가 하나 더 있다. 이 변수는 함수에 넘겨진 인자들이 담겨 있다. +Function Scope에는 [`arguments`](#function.arguments)라는 변수가 하나 더 있다. 이 변수는 Function에 넘겨진 인자들이 담겨 있다. 예를 들어 Function Scope에서 `foo`라는 변수에 접근할 때 JavaScript는 다음과 같은 순서로 찾는다. 1. 해당 Scope에서 `var foo` 구문으로 선언된 것을 찾는다. - 2. 함수 파라미터에서 `foo`라는 것을 찾는다. - 3. 해당 함수 이름이 `foo`인지 찾는다. + 2. Function 파라미터에서 `foo`라는 것을 찾는다. + 3. 해당 Function 이름이 `foo`인지 찾는다. 4. 상위 Scope으로 있는지 확인하고 있으면 **#1**부터 다시 한다. > **Note:** `arguments`라는 파라미터가 있으면 Function의 기본 객체인 `arguments`가 생성되지 않는다. ### Namespace -JavaScript에서는 Global namespace 하나밖에 없어서 변수 이름이 중복되는 문제가 발생하기 쉽다. *Anonymous Wrappers*가 있어서 쉽게 피해갈 수 있다. +JavaScript에서는 Global Namepspace 하나밖에 없어서 변수 이름이 중복되기 쉽다. 하지만 *Anonymous Wrappers*가 있어서 쉽게 피해갈 수 있다. (function() { - // 일종의 namespace라고 할 수 있다. + // 일종의 Namepspace라고 할 수 있다. window.foo = function() { // 이 Closure는 Global Scope에 노출된다. }; - })(); // 함수를 정의하자마자 실행한다. + })(); // Function를 정의하자마자 실행한다. Unnamed Function은 [expressions](#function.general)이기 때문에 호출되려면 먼저 Evaluate돼야 한다. @@ -184,6 +184,6 @@ Unnamed Function은 [expressions](#function.general)이기 때문에 호출되 ### 결론 -코드를 캡슐화할 때는 늘 *Anonymous Wrapper*로 namespace를 만들어 사용해야 한다. 이 Wrapper는 이름이 중복되는 것을 막아 주고 더 쉽게 모듈화할 수 있도록 해준다. +코드를 캡슐화할 때는 늘 *Anonymous Wrapper*로 Namepspace를 만들어 사용해야 한다. 이 Wrapper는 이름이 중복되는 것을 막아 주고 더 쉽게 모듈화할 수 있도록 해준다. -그리고 Global 변수를 사용하는 것은 악질 습관이다. 이유야 어쨌든 에러 나기 쉽고 관리하기 어렵다. +그리고 Global 변수를 사용하는 것은 악질적인 습관이다. 이유야 어쨌든 에러 나기 쉽고 관리하기도 어렵다. diff --git a/doc/ko/function/this.md b/doc/ko/function/this.md index ddc18692..116b1250 100644 --- a/doc/ko/function/this.md +++ b/doc/ko/function/this.md @@ -14,7 +14,7 @@ Global Scope에서도 this가 사용될 수 있고 이때에는 *Global* 객체 이때에도 `this`는 *Global* 객체를 가리킨다. -> **ES5 Note:** strict 모드에서는 더는 Global 객체를 가리키지 않고 대신 `undefined`를 가리킨다. +> **ES5 Note:** strict 모드에서 더는 Global 객체를 가리키지 않고 대신 `undefined`를 가리킨다. ### 메소드로 호출할 때 diff --git a/doc/ko/intro/index.md b/doc/ko/intro/index.md index 2f04336b..16d2ed66 100644 --- a/doc/ko/intro/index.md +++ b/doc/ko/intro/index.md @@ -1,8 +1,8 @@ ## Intro -**JavaScript Garden**은 JavaScript 언어의 핵심에 대한 글을 모은 것이다. 이 글은 초보자들이 JavaScript 익히면서 자주 겪는 실수, 미묘한 버그, 성능 이슈, 나쁜 습관들 줄일 수 있도록 도와줄 것이다. +JavaScript 언어의 핵심에 대한 내용을 모아 **JavaScript Garden**을 만들어 었다. 이 글이 초보자가 JavaScript 익히면서 자주 겪는 실수, 미묘한 버그, 성능 이슈, 나쁜 습관들 줄일 수 있도록 도와줄 것이다. -JavaScript Garden은 단순히 JavaScript를 설명하려 만들지 않았다. 그래서 이 글에서 설명하는 주제들을 이해하려면 반드시 언어에 대한 기본 지식이 필요하다. 먼저 Mozilla Developer Network에 있는 [문서][1]로 JavaScript 언어를 공부하기 바란다. +JavaScript Garden은 단순히 JavaScript 언어 자체를 설명하려 만들지 않았다. 그래서 이 글에서 설명하는 주제들을 이해하려면 반드시 언어에 대한 기본 지식이 필요하다. 먼저 Mozilla Developer Network에 있는 [문서][1]로 JavaScript 언어를 공부하기 바란다. ## 저자들 @@ -24,7 +24,7 @@ JavaScript Garden은 Github에서 호스팅하고 있고 [Cramer Development][7] ## 저작권 -JavaScript Garden은 [MIT license][9]를 따르고 [GitHub][10]에서 호스팅하고 있다. 문제를 발견하면 [이슈를 보고][11]하거나 수정해서 Pull Request를 하라. 아니면 Stack Overflow 채팅 사이트의 [Javascript room][12]에서 우리를 찾아도 된다. +JavaScript Garden은 [MIT license][9]를 따르고 [GitHub][10]에서 호스팅하고 있다. 문제를 발견하면 [이슈를 보고][11]하거나 수정해서 Pull Request를 하라. 아니면 Stack Overflow 채팅 사이트의 [Javascript room][12]에서 우리를 찾으라. [1]: https://developer.mozilla.org/en/JavaScript/Guide [2]: http://stackoverflow.com/ diff --git a/doc/ko/object/forinloop.md b/doc/ko/object/forinloop.md index 26687e1b..5a619c47 100644 --- a/doc/ko/object/forinloop.md +++ b/doc/ko/object/forinloop.md @@ -1,8 +1,8 @@ ## `for in` Loop -`in` 연산자와 마찬가지로 `for in`도 객체의 프로퍼티뿐만 아니라 프로토타입 체인까지 traverse 한다. +`in` 연산자와 마찬가지로 `for in`도 객체의 프로퍼티뿐만 아니라 프로토타입 체인까지 Traverse 한다. -> **Note:** `for in`은 Array의 `length`처럼 `enumerable` 속성이 `false`인 프로퍼티는 iterate 하지 않는다. +> **Note:** `for in`은 Array의 `length`처럼 `enumerable` 속성이 `false`인 프로퍼티는 Iterate 하지 않는다. // 원래는 Object.prototype을 바꾸면 안 된다. Object.prototype.bar = 1; @@ -12,9 +12,9 @@ console.log(i); // bar와 moo 둘 다 출력한다. } -선택적으로 iterate 하려면 `for in`은 바꿀 수 없으니까 loop 바디에서 하는 수밖에 없다. `Object.prototype`의 [`hasOwnProperty`](#object.hasownproperty)메소드를 사용하면 객체의 프로퍼티만 골라낼 수 있다. +선택적으로 Iterate 하려면 `for in`은 바꿀 수 없으니까 Loop 바디에서 하는 수밖에 없다. `Object.prototype`의 [`hasOwnProperty`](#object.hasownproperty)메소드를 사용하면 객체의 프로퍼티만 골라낼 수 있다. -> **Note:** `for in`은 프로토타입 체인을 모두 traverse 한다. 그래서 상속할 때마다 더 느려진다. +> **Note:** `for in`은 프로토타입 체인을 모두 Traverse 한다. 그래서 상속할 때마다 더 느려진다. ### `hasOwnProperty`로 필터링 하기 @@ -27,10 +27,10 @@ 실무에 사용할 작정이라면 이렇게 써야 옳다. `hasOwnProperty` 때문에 **오직** `moo`만 출력된다. `hasOwnProperty`가 없으면 `Object.prototype`같은 네이티브 프로토타입이 확장될 때 에러 날 수 있다. -네이티브 프로토타입을 확장하는 [Proptotype 라이브러리][1]을 사용할 때 `hasOwnProperty`가 없는 `for in` loop은 꼭 문제가 발생한다. +네이티브 프로토타입을 확장하는 [Proptotype 라이브러리][1]을 사용하면 `hasOwnProperty`가 없는 `for in` Loop은 꼭 문제를 일으킨다. ### 결론 `hasOwnProperty`는 항상 사용해야 한다. 실제로 코드가 동작할 환경에서 네이티브 프로토타입의 확장 여부에 대해 어떠한 가정도 하지 말아야 한다. -[1]: http://www.prototypejs.org/ \ No newline at end of file +[1]: http://www.prototypejs.org/ diff --git a/doc/ko/object/general.md b/doc/ko/object/general.md index 0db98e14..51ae6f60 100644 --- a/doc/ko/object/general.md +++ b/doc/ko/object/general.md @@ -49,7 +49,7 @@ JavaScript 객체는 name/value 쌍으로 된 프로퍼티로 구성되기 때 ### 프로퍼티 삭제 -객체의 프로퍼티를 삭제하는 방법은 `delete`를 사용하는 것뿐이다. 프로퍼티에 `undefined`나 `null`을 할당하는 것은 프로퍼티를 삭제하는 것이 아니라 프로퍼티에 할당된 *value*만 지우고 *key*는 그대로 두는 것이다. +객체의 프로퍼티는 `delete`로만 삭제할 수 있다. 프로퍼티에 `undefined`나 `null`을 할당하는 것은 프로퍼티를 삭제하는 것이 아니라 프로퍼티에 할당된 *value*만 지우고 *key*는 그대로 두는 것이다. var obj = { bar: 1, @@ -76,8 +76,8 @@ JavaScript 객체는 name/value 쌍으로 된 프로퍼티로 구성되기 때 delete: 'I am a keyword, so me too' // SyntaxError가 난다. }; -프로퍼티의 key에 문자열이나 스트링을 사용할 수 있다. 이 부분도 JavaScript 파서가 좀 잘못 설계된 거다. ECMAScript 5 이전에는 `SystaxError`가 났었다. +프로퍼티의 key에 문자열이나 스트링을 사용할 수 있다. 이 부분도 JavaScript 파서의 설계 오류다. ECMAScript 5 이전에는 `SystaxError`가 났었다. 이 에러는 `delete`가 키워드이기 때문에 발생하는 것이다. key를 스트링 리터럴로 정의하면 JavaScript 엔진은 언제나 잘 해석한다. -[1]: http://en.wikipedia.org/wiki/Hashmap \ No newline at end of file +[1]: http://en.wikipedia.org/wiki/Hashmap diff --git a/doc/ko/object/hasownproperty.md b/doc/ko/object/hasownproperty.md index d1437f47..871c7cd0 100644 --- a/doc/ko/object/hasownproperty.md +++ b/doc/ko/object/hasownproperty.md @@ -4,8 +4,7 @@ > **Note:** 이 메소드로는 프로퍼티의 값이 `undefined`인지 확인할 수 없다. 프로퍼티가 존재해도 그 값은 `undefined`일 수 있다. -프로토타입 체인을 traverse 하지 않으려면 `hasOwnProperty`를 사용하는 방법밖에 없다. - +프로토타입 체인을 Traverse 하지 않으려면 `hasOwnProperty`를 사용하는 방법밖에 없다. // Object.prototype을 더럽힌다. Object.prototype.bar = 1; @@ -17,11 +16,11 @@ foo.hasOwnProperty('bar'); // false foo.hasOwnProperty('goo'); // true -프로퍼티의 존재 여부를 확인하는 방법은 `hasOwnProperty` 메소드 뿐이다. 이 메소드는 프로토타입 체인의 프로퍼티말고 해당 객체의 프로퍼티만 iterate 할 때 유용하다. 객체 자체의 프로퍼티와 프로토타입 체인 어딘가에 있는 프로퍼티를 골라 주는 다른 방법은 없다. +프로퍼티의 존재 여부를 확인하는 방법은 `hasOwnProperty` 메소드 뿐이다. 이 메소드는 프로토타입 체인의 프로퍼티말고 해당 객체의 프로퍼티만 Iterate할 때 유용하다. 객체 자체의 프로퍼티와 프로토타입 체인 어딘가에 있는 프로퍼티를 골라 주는 다른 방법은 없다. ### `hasOwnProperty`도 프로퍼티 -JavaScript는 `hasOwnProperty` 프로퍼티 역시 보호하지 않는다. 그래서 객체에 `hasOwnProperty` 프로퍼티가 있으면 다른 객체의 `hasOwnProperty` 메소드를 빌려 사용해야 한다. +JavaScript는 `hasOwnProperty` 프로퍼티도 보호해주지 않는다. 그래서 객체에 `hasOwnProperty` 프로퍼티가 있으면 다른 객체의 `hasOwnProperty` 메소드를 빌려 사용해야 한다. var foo = { hasOwnProperty: function() { @@ -37,4 +36,4 @@ JavaScript는 `hasOwnProperty` 프로퍼티 역시 보호하지 않는다. 그 ### 결론 -객체에 프로퍼티가 있는지 `hasOwnProperty`로만 확인할 수 있다. [`for in` loop](#object.forinloop)은 항상 `hasOwnProperty`와 함께 사용하길 권장한다. 네이티브 객체의 [프로토타입](#object.prototype)이 확장하는 사태가 일어나도 안전하게 지켜준다. \ No newline at end of file +객체에 프로퍼티가 있는지 `hasOwnProperty`로만 확인할 수 있다. [`for in` loop](#object.forinloop)은 항상 `hasOwnProperty`와 함께 사용해야 한다. 네이티브 객체의 [프로토타입](#object.prototype)을 확장하는 사태가 일어나도 안전하게 지켜줄 것이다. diff --git a/doc/ko/object/prototype.md b/doc/ko/object/prototype.md index feb69086..e2d591cc 100644 --- a/doc/ko/object/prototype.md +++ b/doc/ko/object/prototype.md @@ -4,7 +4,7 @@ Javascript는 클래스 스타일의 상속 모델을 사용하지 않고 *프 '이 점이 JavaScript의 약점이다.'라고 말하는 사람들도 있지만 실제로는 prototypal inheritance 모델이 훨씬 더 강력하다. 왜냐하면, 프로토타입 모델에서 클래스 모델을 흉내 내기는 매우 쉽지만, 반대로 클래스 모델에서 프로토타입 모델을 흉내 내기란 너무 어렵다. -실제로 prototypal inheritance 모델을 채용한 언어 중에서 JavaScript만큼 널리 사용되는 언어는 없었기 때문에 너무 늦게 두 모델의 차이점이 정리된 감도 있다. +실제로 Prototypal Inheritance 모델을 채용한 언어 중에서 JavaScript만큼 널리 사용되는 언어는 없었기 때문에 너무 늦게 두 모델의 차이점이 정리된 감이 있다. JavaScript는 *프로토타입 체인*이라는 것으로 상속을 구현한다. @@ -39,7 +39,7 @@ JavaScript는 *프로토타입 체인*이라는 것으로 상속을 구현한다 `Bar.prototype`과 `Foo.prototype`을 둘 다 상속받았기 때문에 `test` 객체는 Foo에 정의한 `method` 함수에 접근할 수 있다. 프로토타입 체인에 있는 `Foo` 인스턴스의 `value` 프로퍼티도 사용할 수 있다. `new Bar()`를 해도 `Foo` 인스턴스는 새로 만들어지지 않고 Bar의 prototype에 있는 것을 재사용한다. 그래서 모든 Bar 인스턴스의 `value` 프로퍼티에 들어 있는 객체는 전부 **같은 객체다**. -> **Note:** `Bar.prototype = Foo`라고 하는 것은 `Foo`의 prototype을 가리키는 것이 아니라 Foo라는 function의 prototype을 가리키는 것이다. 그래서 프로토타입 체인에 `Foo.prototype` 대신 `Function.prototype`이 들어서는 것이기 때문에 `method` 프로퍼티는 못 찾는다. +> **Note:** `Bar.prototype = Foo`라고 하는 것은 `Foo`의 prototype을 가리키는 것이 아니라 Foo라는 Function의 prototype을 가리키는 것이다. 그래서 프로토타입 체인에 `Foo.prototype` 대신 `Function.prototype`이 들어서는 것이기 때문에 `method` 프로퍼티는 못 찾는다. ### 프로토타입 찾기 @@ -60,20 +60,20 @@ prototype 프로퍼티는 프로토타입 체인을 만드는 데 사용하고 성능이 중요한 부분에서는 프로토타입 체인을 따라 프로퍼티를 찾는 것이 부담일 수 있다. 게다가 없는 프로퍼티에 접근하면 항상 프로토타입 체인 전체를 뒤진다. -객체를 [iterating](#object.forinloop)하면 프로토타입 체인에 있는 **모든** 프로퍼티가 나열된다. +객체를 [Iterate](#object.forinloop)하면 프로토타입 체인에 있는 **모든** 프로퍼티가 나열된다. ### 네이티브 프로토타입의 확장 JavaScript에서는 `Object.prototype`같이 네이티브 객체들의 프로토타입도 확장할 수 있지만, 이것도 잘못 설계됐다. -이것을 [monkey patching][1]라고 부르는데 *캡슐화*를 망친다. 굉장히 많이 사용하는 [Prototype][2]도 굳이 기본 타입에 표준도 아닌 것들을 추가하는 이유를 아직 설명하지 못하고 있다. +이것을 [Monkey Patching][1]라고 부르는데 *캡슐화*를 망친다. 굉장히 많이 사용하는 [Prototype][2]도 굳이 기본 타입에 표준도 아닌 것들을 추가하는 이유를 아직 설명하지 못하고 있다. -기본 타입을 확장해야 하는 경우도 하나 있다. [`Array.forEach`][3]같이 새 JavaScript 엔진에 추가된 기능을 위한 backport를 만들 때는 유용하다. +기본 타입을 확장하는 것이 좋을 때도 있다. [`Array.forEach`][3]같이 새 JavaScript 엔진에 추가된 기능을 위한 backport를 만들 때는 유용하다. ### 결론 -prototypal inheritance 모델을 사용하는 코드를 작성하기 전에는 이 모델을 완벽하게 이해해야 한다. 프로토타입 체인과 관련된 성능 문제로 고생하지 않으려면 프로토타입 체인의 길이에 주의하고 너무 길지 않게 적당히 끊어줘야 한다. JavaScript의 새 기능에 대한 호환성을 유지하려는 경우를 제외하고 절대로 네이티브 프로토타입을 확장하면 안 된다. +Prototypal Inheritance 모델을 사용하는 코드를 작성하기 전에는 이 모델을 완벽하게 이해해야 한다. 프로토타입 체인과 관련된 성능 문제로 고생하지 않으려면 프로토타입 체인의 길이에 주의하고 너무 길지 않게 적당히 끊어줘야 한다. JavaScript의 새 기능에 대한 호환성을 유지하려는 경우를 제외하고 절대로 네이티브 프로토타입을 확장하면 안 된다. [1]: http://en.wikipedia.org/wiki/Monkey_patch [2]: http://prototypejs.org/ -[3]: https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/forEach \ No newline at end of file +[3]: https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/forEach diff --git a/doc/ko/other/timeouts.md b/doc/ko/other/timeouts.md index 859aa107..5757ee6b 100644 --- a/doc/ko/other/timeouts.md +++ b/doc/ko/other/timeouts.md @@ -7,7 +7,7 @@ JavaScript는 비동기이기 때문에 `setTimeout`과 `setInterval` 로 함수 function foo() {} var id = setTimeout(foo, 1000); // 0보다 큰 수를 반환한다. -`setTimeout`을 호출하면 timeout의 ID를 반환하고 **대충** 1,000밀리 초 후에 `foo`를 실행시킨다. `foo`는 **딱 한 번만** 실행된다. +`setTimeout`을 호출하면 timeout의 ID를 반환하고 **대충** 1,000밀리 초 후에 `foo`를 실행시킨다. `foo`는 **딱 한 번만** 실행한다. JavaScript 엔진의 단위 시간(timer resolution)에 따라서 코드를 실행시키고 단일 쓰레드인 JavaScript를 특정 코드가 블록 시켜 버릴 수도 있기 때문에 `setTimeout`으로 코드가 실행돼야 할 시간을 정해줘도 **정확하게 그 시간에 실행되지 않는다.**. diff --git a/doc/ko/types/casting.md b/doc/ko/types/casting.md index 99328ebb..eb89f546 100644 --- a/doc/ko/types/casting.md +++ b/doc/ko/types/casting.md @@ -1,6 +1,6 @@ ## Type Casting -JavaScript는 weak typing 언어이기 때문에 필요할 때마다 알아서 타입을 변환한다. +JavaScript는 Weak Typing 언어이기 때문에 필요할 때마다 알아서 타입을 변환한다. // 다음은 모두 true new Number(10) == 10; // Number.toString()이 호출되고 @@ -37,7 +37,7 @@ JavaScript는 weak typing 언어이기 때문에 필요할 때마다 알아서 '' + 10 === '10'; // true -숫자를 빈 스트링과 더하면 쉽게 스트링으로 변환된다. +숫자를 빈 스트링과 더하면 쉽게 스트링으로 변환할 수 있다. ### 숫자로 변환하기 diff --git a/doc/ko/types/equality.md b/doc/ko/types/equality.md index 3be20fbe..970b2c14 100644 --- a/doc/ko/types/equality.md +++ b/doc/ko/types/equality.md @@ -4,9 +4,9 @@ JavaScript에서 객체를 비교하는 방법은 두 가지다. ### Equality Operator -`==`가 equality operator이다. +`==`가 Equality Operator이다. -JavaScript는 weak typing을 따르기 때문에 equality operator가 비교할 때 두 객체의 자료형을 **강제로** 변환한다. +JavaScript는 Weak Typing을 따르기 때문에 equality operator가 비교할 때 두 객체의 자료형을 **강제로** 변환한다. "" == "0" // false 0 == "" // true @@ -54,4 +54,4 @@ Strict Equality Operator는 `===`이다. ### 결론 -반드시 **Strict Equality Operator**를 사용해야 한다. 비교하기 위해서 꼭 타입 변환이 필요하면 언어의 복잡한 변환 규칙에 맡기지 말고 꼭 명시적으로 변환하고 나서 비교해야 한다. \ No newline at end of file +반드시 **Strict Equality Operator**를 사용해야 한다. 비교하기 위해서 꼭 타입 변환이 필요하면 언어의 복잡한 변환 규칙에 맡기지 말고 꼭 명시적으로 변환하고 나서 비교해야 한다. diff --git a/doc/ko/types/typeof.md b/doc/ko/types/typeof.md index aed2e210..fb7c6576 100644 --- a/doc/ko/types/typeof.md +++ b/doc/ko/types/typeof.md @@ -36,7 +36,7 @@ Class는 객체 내부에 있는 `[[Class]]` 프로퍼티의 값이다. ### 객체의 클래스 -표준에 의하면 `[[Class]]` 값을 얻는 방법은 `Object.prototype.toString`하나뿐이다. +표준에 의하면 `[[Class]]` 값을 얻는 방법은 `Object.prototype.toString` 하나뿐이다. function is(type, obj) { var clas = Object.prototype.toString.call(obj).slice(8, -1); @@ -56,8 +56,8 @@ Class는 객체 내부에 있는 `[[Class]]` 프로퍼티의 값이다. 이것은 `foo`가 정의됐는지 아닌지를 확인해준다. 정의되지 않은 변수에 접근하면 `ReferenceError` 나는데 이것을 방지할 수 있다. `typeof`가 유용한 건 이때뿐이다. -### In Conclusion +### 결론 객체의 타입을 검사하려면 `Object.prototype.toString`를 사용해야 한다. 다른 방법은 신뢰할 수 없다. 위 표에서 보여준 것처럼 typeof가 반환하는 값은 표준에 나와 있지 않기 때문에 구현마다 다르다. -변수가 정의됐는지 확인할 때는 빼고 **목숨을 걸고** `typeof`를 못 사용하게 해야 한다. +변수가 정의됐는지 확인할 때는 빼고 **목숨을 걸고** `typeof`를 사용하지 못하게 해야 한다. From 01fe309ec1828a99a91b1eb2d939d8f07387155e Mon Sep 17 00:00:00 2001 From: Ivo Wetzel Date: Thu, 26 Jan 2012 23:28:12 +0100 Subject: [PATCH 213/463] Finally get around and start fixing some issues --- doc/en/core/undefined.md | 2 ++ doc/en/function/constructors.md | 2 +- doc/en/function/scopes.md | 10 ++++++---- doc/en/object/hasownproperty.md | 4 ++++ 4 files changed, 13 insertions(+), 5 deletions(-) diff --git a/doc/en/core/undefined.md b/doc/en/core/undefined.md index d27761f0..c819920f 100644 --- a/doc/en/core/undefined.md +++ b/doc/en/core/undefined.md @@ -19,11 +19,13 @@ overwritten. Some examples for when the value `undefined` is returned: - Accessing the (unmodified) global variable `undefined`. + - Accessing a declared *but not* yet initialized variable - Implicit returns of functions due to missing `return` statements. - `return` statements which do not explicitly return anything. - Lookups of non-existent properties. - Function parameters which do not had any explicit value passed. - Anything that has been set to the value of `undefined`. + - Any expression in the form of `void(expression)` ### Handling Changes to the Value of `undefined` diff --git a/doc/en/function/constructors.md b/doc/en/function/constructors.md index a8e450a4..42e152b4 100644 --- a/doc/en/function/constructors.md +++ b/doc/en/function/constructors.md @@ -4,7 +4,7 @@ Constructors in JavaScript are yet again different from many other languages. An function call that is preceded by the `new` keyword acts as a constructor. Inside the constructor - the called function - the value of `this` refers to a -newly created `Object`. The [`prototype`](#object.prototype) of this **new** +newly created object. The [prototype](#object.prototype) of this **new** object is set to the `prototype` of the function object that was invoked as the constructor. diff --git a/doc/en/function/scopes.md b/doc/en/function/scopes.md index efb9d882..bf02d5c9 100644 --- a/doc/en/function/scopes.md +++ b/doc/en/function/scopes.md @@ -2,7 +2,7 @@ Although JavaScript deals fine with the syntax of two matching curly braces for blocks, it does **not** support block scope; hence, all that is left -is in the language is *function scope*. +in the language is *function scope*. function test() { // a scope for(var i = 0; i < 10; i++) { // not a scope @@ -213,12 +213,14 @@ being callable, they must first be evaluated. ) // and return the function object () // call the result of the evaluation -There are other ways for evaluating and calling the function expression; which, +There are other ways for evaluating and directly calling the function expression; which, while different in syntax, do behave the exact same way. - // Two other ways - +function(){}(); + // A few other styles for directly invoking the + !function(){}() + +function(){}() (function(){}()); + // and so on... ### In Conclusion diff --git a/doc/en/object/hasownproperty.md b/doc/en/object/hasownproperty.md index 576c50c6..c21721b4 100644 --- a/doc/en/object/hasownproperty.md +++ b/doc/en/object/hasownproperty.md @@ -44,6 +44,10 @@ necessary to use an *external* `hasOwnProperty` in order to get correct results. // Use another Object's hasOwnProperty and call it with 'this' set to foo ({}).hasOwnProperty.call(foo, 'bar'); // true + // It's also possible use the hasOwnProperty property from the Object property for this purpuse + Object.prototype.hasOwnProperty.call(obj, 'bar'); // true + + ### In Conclusion When checking for the existence of a property on a object, `hasOwnProperty` is From c712143c690d73328f86d9a0df4a269cd9965682 Mon Sep 17 00:00:00 2001 From: Changwoo Park Date: Fri, 27 Jan 2012 14:55:00 +0900 Subject: [PATCH 214/463] [ko] Translate updated contents up to 01fe309 --- doc/ko/core/delete.md | 2 +- doc/ko/core/undefined.md | 5 +++++ doc/ko/function/constructors.md | 2 +- doc/ko/function/scopes.md | 6 ++++-- doc/ko/object/hasownproperty.md | 4 ++++ doc/ko/other/timeouts.md | 13 +++++++++++-- 6 files changed, 26 insertions(+), 6 deletions(-) diff --git a/doc/ko/core/delete.md b/doc/ko/core/delete.md index 53e04e04..342c04e9 100644 --- a/doc/ko/core/delete.md +++ b/doc/ko/core/delete.md @@ -67,7 +67,7 @@ Function의 [`arguments` 객체](#function.arguments)와 기본 프로퍼티도 ### Host 객체 -(역주, Host 객체들은 document같은 DOM 객체를 말한다.) +> **역주:** Host 객체는 document같은 DOM 객체를 말한다. Host 객체를 delete하면 어떻게 될지 알 수 없다. 표준에는 어떻게 Host 객체를 delete해야 하는지 정의하지 않았다. diff --git a/doc/ko/core/undefined.md b/doc/ko/core/undefined.md index e91f7771..65748e1e 100644 --- a/doc/ko/core/undefined.md +++ b/doc/ko/core/undefined.md @@ -13,11 +13,16 @@ JavaScript는 `nothing`을 두 가지로 표현할 수 있고 그중 `undefined` `undefined` 값이 반환될 때: - global 변수 `undefined`에 접근할 때. + - 아직 초기화하지 않은 변수 + - `return` 구문이 없는 함수는 `undefined`를 반환함. - `return` 구문이 없는 함수는 `undefined`를 반환함. - `return` 구문으로 아무것도 반환하지 않을 때. - 없는 프로퍼티를 찾을 때. - 함수 인자가 생략될 때. - `undefined`가 할당된 모든 것. + - `void(expression)` 형식으로 된 표현 + +> **역주:** 예를 들어 CoffeeScript Compliler는 CoffeeScript의 `undefined`를 JavaScript의 `void 0`로 컴파일한다. ### `undefined`가 바뀔 때를 대비하기 diff --git a/doc/ko/function/constructors.md b/doc/ko/function/constructors.md index 2365c8a5..cb71cdeb 100644 --- a/doc/ko/function/constructors.md +++ b/doc/ko/function/constructors.md @@ -2,7 +2,7 @@ JavaScript에서 생성자는 다른 언어들과 다르게 `new` 키워드로 호출되는 함수가 생성자다. -어쨌든 생성자로 호출된 함수의 this는 막 만들어진 객체를 참조한다. **막 만든** 객체의 [`prototype`](#object.prototype)에는 생성자의 prototype이 할당된다. +어쨌든 생성자로 호출된 함수의 this는 막 만들어진 객체를 참조한다. **막 만든** 객체의 [prototype](#object.prototype)에는 생성자의 prototype이 할당된다. 생성자에 `return` 구문이 없으면 this가 가리키는 객체를 반환한다. diff --git a/doc/ko/function/scopes.md b/doc/ko/function/scopes.md index 3e887ab5..ad40e0f3 100644 --- a/doc/ko/function/scopes.md +++ b/doc/ko/function/scopes.md @@ -176,11 +176,13 @@ Unnamed Function은 [expressions](#function.general)이기 때문에 호출되 ) // 그리고 Function 객체를 반환한다. () // Evaluation된 결과를 호출한다. -같은 표기법이 두 가지 더 있다. 문법은 다르지만 똑같다. +Function을 Evaluate하고 바로 호출하는 방법이 몇가지 더 있다. 문법은 다르지만 똑같다. - // 두 가지 다른 방법 + // Fucntion을 Evaluate하자마자 호출하는 방법들... + !function(){}(); +function(){}(); (function(){}()); + // 등등... ### 결론 diff --git a/doc/ko/object/hasownproperty.md b/doc/ko/object/hasownproperty.md index 871c7cd0..b53ad583 100644 --- a/doc/ko/object/hasownproperty.md +++ b/doc/ko/object/hasownproperty.md @@ -34,6 +34,10 @@ JavaScript는 `hasOwnProperty` 프로퍼티도 보호해주지 않는다. 그래 // 다른 객체의 hasOwnProperty를 사용하여 foo 객체의 프로퍼티 유무를 확인한다. ({}).hasOwnProperty.call(foo, 'bar'); // true + // Object에 원래 있는 hasOwnProperty를 사용해도 된다. + Object.prototype.hasOwnProperty.call(obj, 'bar'); // true + + ### 결론 객체에 프로퍼티가 있는지 `hasOwnProperty`로만 확인할 수 있다. [`for in` loop](#object.forinloop)은 항상 `hasOwnProperty`와 함께 사용해야 한다. 네이티브 객체의 [프로토타입](#object.prototype)을 확장하는 사태가 일어나도 안전하게 지켜줄 것이다. diff --git a/doc/ko/other/timeouts.md b/doc/ko/other/timeouts.md index 5757ee6b..fb0384ed 100644 --- a/doc/ko/other/timeouts.md +++ b/doc/ko/other/timeouts.md @@ -61,14 +61,23 @@ JavaScript 엔진의 단위 시간(timer resolution)에 따라서 코드를 실 ### timeout을 전부 없애기 -등록한 timeout과 interval을 한꺼번에 삭제하는 메소드는 없다. 구현해서 사용해야 한다. +등록한 timeout과 interval을 한꺼번에 제거하는 메소드는 없다. 구현해서 사용해야 한다. // clear "all" timeouts for(var i = 1; i < 1000; i++) { clearTimeout(i); } -Id가 1부터 1000 사이에 있는 timeout들을 삭제했지만, 그 외의 것은 아직 남아있다. 완벽하게 구현하려면 만들어진 timeout id를 모두 저장했다가 삭제해야 한다. +Id가 1부터 1000 사이에 있는 timeout들을 제거했지만, 그 외의 것은 아직 남아있다. 또 다른 방법이 있다. `setTimeout`은 항상 호출될 때마다 전보다 1만큼 큰 수를 ID로 반환한다. 이 점을 이용해 1부터 가장최근 ID까지 모두 삭제할 수 있다. + + // clear "all" timeouts + var biggestTimeoutId = window.setTimeout(function(){}, 1), + i; + for(i = 1; i <= biggestTimeoutId; i++) { + clearTimeout(i); + } + +이 방법은 모든 주요 브라우저에서 문제없이 잘 동작한다. 하지만 ID가 항상 순차적이어야 한다고 표준에 명시된 것이 아니다. 그러므로 timeout ID를 모두 저장했다가 삭제하는 것이 가장 안전하다. 그러면 전부 깨끗하게 제거할 수 있다. ### 숨겨진 `eval` From cd7c86a6a401218158f18b0ad5fc2577cc62fd21 Mon Sep 17 00:00:00 2001 From: HIRAKI Satoru Date: Sun, 29 Jan 2012 20:55:05 +0900 Subject: [PATCH 215/463] translate 'The delete Operator' in 'delete' to ja --- doc/ja/core/delete.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/doc/ja/core/delete.md b/doc/ja/core/delete.md index 37a12816..900c67f5 100644 --- a/doc/ja/core/delete.md +++ b/doc/ja/core/delete.md @@ -1,7 +1,6 @@ -## The `delete` Operator +## `delete`演算子 -In short, it's *impossible* to delete global variables, functions and some other -stuff in JavaScript which have a `DontDelete` attribute set. +端的に言って、JavaScriptの関数やその他の要素は`DontDelete`属性が設定されているので、グローバル変数を消去する事は*不可能*です。 ### Global code and Function code From 623ba2c67b6423d270e6f059a1738d4ba38499be Mon Sep 17 00:00:00 2001 From: HIRAKI Satoru Date: Sun, 29 Jan 2012 21:37:17 +0900 Subject: [PATCH 216/463] translate "Global code and Function code" in "delete" to ja --- doc/ja/core/delete.md | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/doc/ja/core/delete.md b/doc/ja/core/delete.md index 900c67f5..ff01e373 100644 --- a/doc/ja/core/delete.md +++ b/doc/ja/core/delete.md @@ -2,26 +2,21 @@ 端的に言って、JavaScriptの関数やその他の要素は`DontDelete`属性が設定されているので、グローバル変数を消去する事は*不可能*です。 -### Global code and Function code +### グローバルコードと関数コード -When a variable or a function is defined in a global -or a [function scope](#function.scopes) it is a property of either -Activation object or Global object. Such properties have a set of attributes, -one of these is `DontDelete`. Variable and function declarations in global -and function code always create properties with `DontDelete`, therefore -cannot be deleted. +変数や、関数がグローバルまたは[関数スコープ](#function.scopes)で定義された時は、そのプロパティは有効なオブジェクトかグローバルオブジェクトになります。このようなプロパティは属性のセットを持っていますが、それらの内の1つが`DontDelete`になります。変数や関数がグローバルや関数コードで宣言されると、常に`DontDelete`属性を作るために、消去できません。 - // global variable: - var a = 1; // DontDelete is set + // グローバル変数: + var a = 1; // DontDelete属性が設定される delete a; // false a; // 1 - // normal function: - function f() {} // DontDelete is set + // 通常関数: + function f() {} // DontDelete属性が設定される delete f; // false typeof f; // "function" - // reassigning doesn't help: + // 再代入も役に立たない: f = 1; delete f; // false f; // 1 From 80dc784661e85474d5abd953da41eac1a27579bf Mon Sep 17 00:00:00 2001 From: skim Date: Sun, 29 Jan 2012 18:08:04 -0600 Subject: [PATCH 217/463] fixes spelling, grammar, format --- doc/en/array/general.md | 2 +- doc/en/core/delete.md | 4 ++-- doc/en/function/general.md | 2 +- doc/en/function/scopes.md | 4 ++-- doc/en/object/general.md | 4 ++-- doc/en/object/hasownproperty.md | 2 +- doc/en/other/timeouts.md | 2 +- 7 files changed, 10 insertions(+), 10 deletions(-) diff --git a/doc/en/array/general.md b/doc/en/array/general.md index 9f804d4c..85062846 100644 --- a/doc/en/array/general.md +++ b/doc/en/array/general.md @@ -1,7 +1,7 @@ ## Array Iteration and Properties Although arrays in JavaScript are objects, there are no good reasons to use -the [`for in loop`](#object.forinloop) in for iteration on them. In fact, there +the [`for in`](#object.forinloop) loop. In fact, there are a number of good reasons **against** the use of `for in` on arrays. > **Note:** JavaScript arrays are **not** *associative arrays*. JavaScript only diff --git a/doc/en/core/delete.md b/doc/en/core/delete.md index 37a12816..fdde18a4 100644 --- a/doc/en/core/delete.md +++ b/doc/en/core/delete.md @@ -51,10 +51,10 @@ In the example above `obj.x` and `obj.y` can be deleted because they have no GLOBAL_OBJECT.a; // undefined Here we use a trick to delete `a`. [`this`](#function.this) here refers -to the Global object and we explicitly declare variable `a` as it's property +to the Global object and we explicitly declare variable `a` as its property which allows us to delete it. -IE (at least 6-8) has some bugs, so code above doesn't work. +IE (at least 6-8) has some bugs, so the code above doesn't work. ### Function arguments and built-ins diff --git a/doc/en/function/general.md b/doc/en/function/general.md index 7ca180f0..e3d2a0bc 100644 --- a/doc/en/function/general.md +++ b/doc/en/function/general.md @@ -2,7 +2,7 @@ Functions in JavaScript are first class objects. That means they can be passed around like any other value. One common use of this feature is to pass -an *anonymous function* as a callback to another, possibly asynchronous function. +an *anonymous function* as a callback to another, possibly an asynchronous function. ### The `function` Declaration diff --git a/doc/en/function/scopes.md b/doc/en/function/scopes.md index bf02d5c9..022ecaed 100644 --- a/doc/en/function/scopes.md +++ b/doc/en/function/scopes.md @@ -153,7 +153,7 @@ has been applied. Without the knowledge about *hoisting*, the below code might seem to raise a `ReferenceError`. - // check whether SomeImportantThing has been initiliazed + // check whether SomeImportantThing has been initialized if (!SomeImportantThing) { var SomeImportantThing = {}; } @@ -163,7 +163,7 @@ moved to the top of the *global scope*. var SomeImportantThing; - // other code might initiliaze SomeImportantThing here, or not + // other code might initialize SomeImportantThing here, or not // make sure it's there if (!SomeImportantThing) { diff --git a/doc/en/object/general.md b/doc/en/object/general.md index bc52f1f7..aefbfb90 100644 --- a/doc/en/object/general.md +++ b/doc/en/object/general.md @@ -28,7 +28,7 @@ literals act as objects too. Objects in JavaScript can also be used as a [*Hashmap*][1]; they mainly consist of named properties mapping to values. -Using a object literal - `{}` notation - it is possible to create a +Using an object literal - `{}` notation - it is possible to create a plain object. This new object [inherits](#object.prototype) from `Object.prototype` and has no [own properties](#object.hasownproperty) defined on it. @@ -42,7 +42,7 @@ has no [own properties](#object.hasownproperty) defined on it. The properties of an object can be accessed in two ways, via either the dot notation or the square bracket notation. - var foo = {name: 'Kitten'} + var foo = {name: 'kitten'} foo.name; // kitten foo['name']; // kitten diff --git a/doc/en/object/hasownproperty.md b/doc/en/object/hasownproperty.md index c21721b4..6aa13d5c 100644 --- a/doc/en/object/hasownproperty.md +++ b/doc/en/object/hasownproperty.md @@ -44,7 +44,7 @@ necessary to use an *external* `hasOwnProperty` in order to get correct results. // Use another Object's hasOwnProperty and call it with 'this' set to foo ({}).hasOwnProperty.call(foo, 'bar'); // true - // It's also possible use the hasOwnProperty property from the Object property for this purpuse + // It's also possible use the hasOwnProperty property from the Object property for this purpose Object.prototype.hasOwnProperty.call(obj, 'bar'); // true diff --git a/doc/en/other/timeouts.md b/doc/en/other/timeouts.md index 0808242c..28e672e0 100644 --- a/doc/en/other/timeouts.md +++ b/doc/en/other/timeouts.md @@ -138,7 +138,7 @@ function that will get called by either of the timeout functions. function foo(a, b, c) {} // NEVER use this - setTimeout('foo(1,2, 3)', 1000) + setTimeout('foo(1, 2, 3)', 1000) // Instead use an anonymous function setTimeout(function() { From 51fc96dd35fc280587a9274f0d36846e00d3ed16 Mon Sep 17 00:00:00 2001 From: Tobie Langel Date: Sat, 4 Feb 2012 20:44:33 +0000 Subject: [PATCH 218/463] Fix incorrect description of array.length assignment. --- doc/en/array/general.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/en/array/general.md b/doc/en/array/general.md index 9f804d4c..86a0f756 100644 --- a/doc/en/array/general.md +++ b/doc/en/array/general.md @@ -45,10 +45,10 @@ elements that are contained in the array, the *setter* can be used to foo; // [1, 2, 3] foo.length = 6; - foo; // [1, 2, 3] + foo.push(4); + foo; // [1, 2, 3, undefined, undefined, undefined, 4] -Assigning a smaller length does truncate the array, but increasing the length -does not have any effect on the array. +Assigning a smaller length truncates the array. Increasing it creates a sparse array. ### In Conclusion From 414e75038a70aa95a9c1821037a945b9e0de06c6 Mon Sep 17 00:00:00 2001 From: HIRAKI Satoru Date: Wed, 8 Feb 2012 17:23:02 +0900 Subject: [PATCH 219/463] add delete menu into "core" --- doc/ja/index.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/doc/ja/index.json b/doc/ja/index.json index 70be20fc..6fdb018d 100644 --- a/doc/ja/index.json +++ b/doc/ja/index.json @@ -54,7 +54,8 @@ "articles": [ "eval", "undefined", - "semicolon" + "semicolon", + "delete" ] }, { From 777a432f352a8c5c1c72a1fa4a81e71fc954822a Mon Sep 17 00:00:00 2001 From: HIRAKI Satoru Date: Mon, 20 Feb 2012 03:10:57 +0900 Subject: [PATCH 220/463] translate "Explicit properties" in "delete" to ja --- doc/ja/core/delete.md | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/doc/ja/core/delete.md b/doc/ja/core/delete.md index ff01e373..ebb512d2 100644 --- a/doc/ja/core/delete.md +++ b/doc/ja/core/delete.md @@ -21,12 +21,11 @@ delete f; // false f; // 1 -### Explicit properties +### 明示的なプロパティ -There are things which can be deleted normally: these are explicitly set -properties. +普通にプロパティを消去できる方法が存在します:プロパティを明示的に設定するのです。 - // explicitly set property: + // プロパティを明示的に設定する var obj = {x: 1}; obj.y = 2; delete obj.x; // true @@ -34,21 +33,19 @@ properties. obj.x; // undefined obj.y; // undefined -In the example above `obj.x` and `obj.y` can be deleted because they have no -`DontDelete` atribute. That's why an example below works too. +上記の例の中で、`obj.x`と`obj.y`はそれぞれ`DontDelete`属性が無い為に削除できます。これが下記の例でも動作する理由です。 - // this works fine, except for IE: + // IE以外では、これも動作する var GLOBAL_OBJECT = this; GLOBAL_OBJECT.a = 1; - a === GLOBAL_OBJECT.a; // true - just a global var + a === GLOBAL_OBJECT.a; // true - ただのグローバルのvar delete GLOBAL_OBJECT.a; // true GLOBAL_OBJECT.a; // undefined -Here we use a trick to delete `a`. [`this`](#function.this) here refers -to the Global object and we explicitly declare variable `a` as it's property -which allows us to delete it. +ここでは`a`. [`this`](#function.this)を消す為にグローバルオブジェクトと明示的に宣言した`a`をそのプロパティとして参照させて、消去する事を許可するトリックを使います。 + +IE(最低でも6-8で)は多少のバグがある為に、上記のコードは動作しません。 -IE (at least 6-8) has some bugs, so code above doesn't work. ### Function arguments and built-ins From 23f1d007878c942141c41a294d3efe19fddf48a5 Mon Sep 17 00:00:00 2001 From: HIRAKI Satoru Date: Fri, 24 Feb 2012 19:06:54 +0900 Subject: [PATCH 221/463] translate "Function arguments and built-ins" in delete --- doc/ja/core/delete.md | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/doc/ja/core/delete.md b/doc/ja/core/delete.md index ebb512d2..df3b5e65 100644 --- a/doc/ja/core/delete.md +++ b/doc/ja/core/delete.md @@ -47,24 +47,23 @@ IE(最低でも6-8で)は多少のバグがある為に、上記のコードは動作しません。 -### Function arguments and built-ins +### 関数の引数と組み込み引数 -Functions' normal arguments, [`arguments` object](#function.arguments) -and built-in properties also have `DontDelete` set. +関数の通常の引数である、[`arguments` object](#function.arguments)と組み込みのプロパティもまた、`DontDelete`が設定されています。 - // function arguments and properties: + // 関数の引数とプロパティ: (function (x) { - + delete arguments; // false typeof arguments; // "object" - + delete x; // false x; // 1 - + function f(){} delete f.length; // false typeof f.length; // "number" - + })(1); ### Host objects From 49ed22c25151555da46e62acf4858300af3a29ed Mon Sep 17 00:00:00 2001 From: HIRAKI Satoru Date: Sat, 25 Feb 2012 20:18:05 +0900 Subject: [PATCH 222/463] translate "Host objects" to ja in "delete" --- doc/ja/core/delete.md | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/doc/ja/core/delete.md b/doc/ja/core/delete.md index df3b5e65..b63e4189 100644 --- a/doc/ja/core/delete.md +++ b/doc/ja/core/delete.md @@ -66,10 +66,9 @@ IE(最低でも6-8で)は多少のバグがある為に、上記のコードは })(1); -### Host objects - -Behaviour of `delete` operator can be unpredictable for hosted objects. Due to -specification, host objects are allowed to implement any kind of behavior. +### ホストオブジェクト + +`delete`演算子の振る舞いはホストオブジェクトにとって予測不可能になりかねません。仕様によりホストオブジェクトは、あらゆる振る舞いの実行が許可されている為です。 ### In conclusion From 698ff8e1f8d87ea86f32879228a00b0d8805bee7 Mon Sep 17 00:00:00 2001 From: HIRAKI Satoru Date: Sat, 25 Feb 2012 20:21:52 +0900 Subject: [PATCH 223/463] translate "In conclusion" to ja in "delete" --- doc/ja/core/delete.md | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/doc/ja/core/delete.md b/doc/ja/core/delete.md index b63e4189..632dc142 100644 --- a/doc/ja/core/delete.md +++ b/doc/ja/core/delete.md @@ -68,9 +68,8 @@ IE(最低でも6-8で)は多少のバグがある為に、上記のコードは ### ホストオブジェクト -`delete`演算子の振る舞いはホストオブジェクトにとって予測不可能になりかねません。仕様によりホストオブジェクトは、あらゆる振る舞いの実行が許可されている為です。 +`delete`演算子の挙動はホストオブジェクトにとって予測不可能になりかねません。仕様によりホストオブジェクトは、あらゆる挙動の実行が許可されている為です。 -### In conclusion +### 終わりに -`delete` operator often has an unexpected behaviour and can be safely used -only for dealing with explicitly set properties on normal objects. +`delete`演算子は、しばしば予期せぬ挙動をします。唯一安全な仕様方法は通常のオブジェクトに明示的に設定されたプロパティを扱う場合だけです。 From b8bada45df81f5951bd84d9bd783c8dbaf9fd4c3 Mon Sep 17 00:00:00 2001 From: ambar Date: Mon, 9 Apr 2012 10:47:40 +0800 Subject: [PATCH 224/463] [lang=zh] correct some typing errors --- doc/zh/function/arguments.md | 2 +- doc/zh/function/general.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/zh/function/arguments.md b/doc/zh/function/arguments.md index b86e72f6..ef351e9e 100755 --- a/doc/zh/function/arguments.md +++ b/doc/zh/function/arguments.md @@ -80,7 +80,7 @@ JavaScript 中每个函数内都能访问一个特别变量 `arguments`。这个 `arguments` 对象总会被创建,除了两个特殊情况 - 作为局部变量声明和作为形式参数。 而不管它是否有被使用。 -`arguments` 的 *getters* 和 *setters* 方法总会被创佳;因此使用 `arguments` 对性能不会有什么影响。 +`arguments` 的 *getters* 和 *setters* 方法总会被创建;因此使用 `arguments` 对性能不会有什么影响。 除非是需要对 `arguments` 对象的属性进行多次访问。 > **ES5 提示:** 这些 *getters* 和 *setters* 在严格模式下(strict mode)不会被创建。 diff --git a/doc/zh/function/general.md b/doc/zh/function/general.md index 41a63a3d..964ce094 100755 --- a/doc/zh/function/general.md +++ b/doc/zh/function/general.md @@ -1,7 +1,7 @@ ##函数声明与表达式 函数是JavaScript中的一等对象,这意味着可以把函数像其它值一样传递。 -一个常见的用法是把*匿名函数*作为回调函数传递对异步函数中。 +一个常见的用法是把*匿名函数*作为回调函数传递到异步函数中。 ###函数声明 From 569be23e30a4a1c507a25910c882e04b92db382e Mon Sep 17 00:00:00 2001 From: David Matas Date: Fri, 13 Apr 2012 13:28:23 +0200 Subject: [PATCH 225/463] Improved some spanish translation --- doc/es/object/general.md | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/doc/es/object/general.md b/doc/es/object/general.md index bd3bab18..ccdd1cce 100644 --- a/doc/es/object/general.md +++ b/doc/es/object/general.md @@ -1,22 +1,22 @@ ## Uso de objetos y propiedades -Todo en JavaScript actúa como un objeto, con las dos únicas excepciones de +Todo en JavaScript actúa como un objeto, con las dos únicas excepciones de [`null`](#core.undefined) y [`undefined`](#core.undefined). false.toString() // 'false' [1, 2, 3].toString(); // '1,2,3' - + function Foo(){} Foo.bar = 1; Foo.bar; // 1 -Un error muy común es el uso de literales númericos como objetos. +Un error muy común es el uso de literales númericos como objetos. Esto se debe a un error en el parser de JavaScript que intenta analizar la *notación de puntos* como un literal de punto flotante. 2.toString(); // lanza SyntaxError -Existe un par de soluciones que pueden utilizarse para hacer que los +Existe un par de soluciones que pueden utilizarse para hacer que los literales númericos actúen como objetos. 2..toString(); // el segundo punto es reconocido correctamente @@ -25,30 +25,30 @@ literales númericos actúen como objetos. ### Objetos como un tipo de datos -Los objetos en JavaScript también pueden ser utilizados como una Tabla Hash o conocido como [*Hashmap*][1] en inglés, consisten +Los objetos en JavaScript también pueden ser utilizados como una Tabla Hash o conocido como [*Hashmap*][1] en inglés, consisten principalmente en nombres de propiedades asignadoles valores a estos. -El uso de un objeto literal - con notación `{}` - puede crear un +El uso de un objeto literal - con notación `{}` - puede crear un objeto plano. Este nuevo objeto [heredado](#object.prototype) desde `Object.prototype` no posee [propiedades propias](#object.hasownproperty) definidas. var foo = {}; // un nuevo objeto vacío // un nuevo objeto con la propiedad llamada 'test' con el valor 12 - var bar = {test: 12}; + var bar = {test: 12}; ### Acceso a las propiedades Se puede acceder a las propiedades de un objeto de dos maneras, ya sea a través de la -notación de punto o desde la notación de corchetes. - +notación de punto o desde la notación de corchetes. + var foo = {name: 'Kitten'} foo.name; // kitten foo['name']; // kitten - + var get = 'name'; foo[get]; // kitten - + foo.1234; // SyntaxError foo['1234']; // ¡funciona! @@ -59,8 +59,8 @@ el uso de propiedades que de otro modo daría lugar a error de sintaxis. ### Eliminando propiedades La única manera de eliminar una propiedad desde un objeto es usando el -operador `delete`; Se establece la propiedad a `undefined` o `null` sólo al -*valor* asociado de la propiedad, pero no ha un *key* (valor clave). +operador `delete`; establecer la propiedad a `undefined` o `null` solamente +elimina el *valor* asociado a la propiedad, pero no la *key* (valor clave). var obj = { bar: 1, From 3928be67c914932cdeddc50a33a184993c9c537e Mon Sep 17 00:00:00 2001 From: "Michael C. Harris" Date: Thu, 31 May 2012 18:55:07 +1000 Subject: [PATCH 226/463] Specify minimum version of forever. Rather than using a specific version of forever, which is no longer available via npm, use it as a minimum. Without this `npm install` fails. --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 98500980..fdaecf9b 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "version": "0.0.0", "dependencies": { "fomatto": "0.5.0", - "forever": "0.4.1", + "forever": ">=0.4.1", "jade": "0.9.1", "neko": "1.1.2", "node-markdown": "0.1.0" From 9e3e75664e49ef7ae30c7aee6d3355e4be07d08e Mon Sep 17 00:00:00 2001 From: "Michael C. Harris" Date: Sun, 3 Jun 2012 12:06:48 +1000 Subject: [PATCH 227/463] Clean up language in the function section. --- doc/en/function/arguments.md | 9 ++++----- doc/en/function/closures.md | 4 ++-- doc/en/function/constructors.md | 32 ++++++++++++++++---------------- doc/en/function/general.md | 6 +++--- doc/en/function/scopes.md | 28 ++++++++++++++-------------- doc/en/function/this.md | 8 ++++---- 6 files changed, 43 insertions(+), 44 deletions(-) diff --git a/doc/en/function/arguments.md b/doc/en/function/arguments.md index 37f3a634..2394177d 100644 --- a/doc/en/function/arguments.md +++ b/doc/en/function/arguments.md @@ -79,9 +79,9 @@ of the corresponding property on the `arguments` object, and the other way aroun ### Performance Myths and Truths -The `arguments` object is always created with the only two exceptions being the -cases where it is declared as a name inside of a function or one of its formal -parameters. It does not matter whether it is used or not. +The only time the `arguments` object is not created is where it is declared as +a name inside of a function or one of its formal parameters. It does not matter +whether it is used or not. Both *getters* and *setters* are **always** created; thus, using it has nearly no performance impact at all, especially not in real world code where there is @@ -108,8 +108,7 @@ needs to know about both itself and its caller. This not only defeats possible performance gains that would arise from inlining, but it also breaks encapsulation because the function may now be dependent on a specific calling context. -It is **highly recommended** to **never** make use of `arguments.callee` or any of -its properties. +Making use of `arguments.callee` or any of its properties is **highly discouraged**. > **ES5 Note:** In strict mode, `arguments.callee` will throw a `TypeError` since > its use has been deprecated. diff --git a/doc/en/function/closures.md b/doc/en/function/closures.md index 2e2a4ef6..76f2d078 100644 --- a/doc/en/function/closures.md +++ b/doc/en/function/closures.md @@ -27,7 +27,7 @@ were defined. Since the only scoping that JavaScript has is Here, `Counter` returns **two** closures: the function `increment` as well as the function `get`. Both of these functions keep a **reference** to the scope of `Counter` and, therefore, always keep access to the `count` variable that was -defined in that very scope. +defined in that scope. ### Why Private Variables Work @@ -47,7 +47,7 @@ override - the *global* variable `count`. ### Closures Inside Loops One often made mistake is to use closures inside of loops, as if they were -copying the value of the loops index variable. +copying the value of the loop's index variable. for(var i = 0; i < 10; i++) { setTimeout(function() { diff --git a/doc/en/function/constructors.md b/doc/en/function/constructors.md index 42e152b4..bf9771dc 100644 --- a/doc/en/function/constructors.md +++ b/doc/en/function/constructors.md @@ -25,7 +25,7 @@ The above calls `Foo` as constructor and sets the `prototype` of the newly created object to `Foo.prototype`. In case of an explicit `return` statement, the function returns the value -specified that statement, **but only** if the return value is an `Object`. +specified by that statement, but **only** if the return value is an `Object`. function Bar() { return 2; @@ -72,13 +72,13 @@ explicitly return a value. new Bar(); Bar(); -Both calls to `Bar` return the exact same thing, a newly create object which -has a property called `method` on it, which is a +Both calls to `Bar` return the same thing, a newly create object that +has a property called `method`, which is a [Closure](#function.closures). -It is also to note that the call `new Bar()` does **not** affect the prototype -of the returned object. While the prototype will be set on the newly created -object, `Bar` never returns that new object. +It should also be noted that the call `new Bar()` does **not** affect the +prototype of the returned object. While the prototype will be set on the newly +created object, `Bar` never returns that new object. In the above example, there is no functional difference between using and not using the `new` keyword. @@ -86,10 +86,10 @@ not using the `new` keyword. ### Creating New Objects via Factories -An often made recommendation is to **not** use `new` because forgetting its use -may lead to bugs. +It is often recommended to **not** use `new` because forgetting its use may +lead to bugs. -In order to create new object, one should rather use a factory and construct a +In order to create a new object, one should rather use a factory and construct a new object inside of that factory. function Foo() { @@ -113,16 +113,16 @@ downsides. 1. It uses more memory since the created objects do **not** share the methods on a prototype. - 2. In order to inherit the factory needs to copy all the methods from another + 2. In order to inherit, the factory needs to copy all the methods from another object or put that object on the prototype of the new object. 3. Dropping the prototype chain just because of a left out `new` keyword - somehow goes against the spirit of the language. + is contrary to the spirit of the language. ### In Conclusion -While omitting the `new` keyword might lead to bugs, it is certainly **not** a -reason to drop the use of prototypes altogether. In the end it comes down to -which solution is better suited for the needs of the application, it is -especially important to choose a specific style of object creation **and stick** -with it. +While omitting the `new` keyword might lead to bugs, it is certainly **not** a +reason to drop the use of prototypes altogether. In the end it comes down to +which solution is better suited for the needs of the application. It is +especially important to choose a specific style of object creation and use it +**consistently**. diff --git a/doc/en/function/general.md b/doc/en/function/general.md index e3d2a0bc..b2788e46 100644 --- a/doc/en/function/general.md +++ b/doc/en/function/general.md @@ -8,9 +8,9 @@ an *anonymous function* as a callback to another, possibly an asynchronous funct function foo() {} -The above function gets [hoisted](#function.scopes) before the execution of the -program starts; thus, it is available *everywhere* in the scope it was *defined* -in, even if called before the actual definition in the source. +The above function gets [hoisted](#function.scopes) before the execution of the +program starts; thus, it is available *everywhere* in the scope it was +*defined*, even if called before the actual definition in the source. foo(); // Works because foo was created before this code runs function foo() {} diff --git a/doc/en/function/scopes.md b/doc/en/function/scopes.md index 022ecaed..879e1e8a 100644 --- a/doc/en/function/scopes.md +++ b/doc/en/function/scopes.md @@ -73,7 +73,7 @@ unless the *desired effect* is to affect the outer scope. ### Local Variables The only source for local variables in JavaScript are -[function](#function.general) parameters and variables that were declared via the +[function](#function.general) parameters and variables declared via the `var` statement. // global scope @@ -115,8 +115,8 @@ JavaScript **hoists** declarations. This means that both `var` statements and } } -The above code gets transformed before any execution is started. JavaScript moves -the `var` statements, as well as the `function` declarations to the top of the +The above code gets transformed before execution starts. JavaScript moves +the `var` statements, as well as `function` declarations, to the top of the nearest surrounding scope. // var statements got moved here @@ -150,7 +150,7 @@ In the original code, although the `if` statement seemed to modify the *global variable* `goo`, it actually modifies the *local variable* - after hoisting has been applied. -Without the knowledge about *hoisting*, the below code might seem to raise a +Without knowledge of *hoisting*, one might suspect the code below would raise a `ReferenceError`. // check whether SomeImportantThing has been initialized @@ -158,7 +158,7 @@ Without the knowledge about *hoisting*, the below code might seem to raise a var SomeImportantThing = {}; } -But of course, the above works due to the fact that the `var` statement is being +But of course, this works due to the fact that the `var` statement is being moved to the top of the *global scope*. var SomeImportantThing; @@ -176,10 +176,10 @@ All scopes in JavaScript, including the *global scope*, have the special name [`this`](#function.this), defined in them, which refers to the *current object*. Function scopes also have the name [`arguments`](#function.arguments), defined in -them, which contains the arguments that were passed to a function. +them, which contains the arguments that were passed to the function. For example, when trying to access a variable named `foo` inside the scope of a -function, JavaScript will lookup the name in the following order: +function, JavaScript will look up the name in the following order: 1. In case there is a `var foo` statement in the current scope, use that. 2. If one of the function parameters is named `foo`, use that. @@ -191,9 +191,9 @@ function, JavaScript will lookup the name in the following order: ### Namespaces -A common problem of having only one global namespace is the likeliness of running -into problems where variable names clash. In JavaScript, this problem can -easily be avoided with the help of *anonymous wrappers*. +A common problem associated with having only one global namespace is the +likelihood of running into problems where variable names clash. In JavaScript, +this problem can easily be avoided with the help of *anonymous wrappers*. (function() { // a self contained "namespace" @@ -208,13 +208,13 @@ easily be avoided with the help of *anonymous wrappers*. Unnamed functions are considered [expressions](#function.general); so in order to being callable, they must first be evaluated. - ( // evaluate the function inside the paranthesis + ( // evaluate the function inside the parentheses function() {} ) // and return the function object () // call the result of the evaluation -There are other ways for evaluating and directly calling the function expression; which, -while different in syntax, do behave the exact same way. +There are other ways to evaluate and directly call the function expression +which, while different in syntax, behave the same way. // A few other styles for directly invoking the !function(){}() @@ -224,7 +224,7 @@ while different in syntax, do behave the exact same way. ### In Conclusion -It is recommended to always use an *anonymous wrapper* for encapsulating code in +It is recommended to always use an *anonymous wrapper* to encapsulate code in its own namespace. This does not only protect code against name clashes, but it also allows for better modularization of programs. diff --git a/doc/en/function/this.md b/doc/en/function/this.md index c2ef238f..48070d2e 100644 --- a/doc/en/function/this.md +++ b/doc/en/function/this.md @@ -1,7 +1,7 @@ ## How `this` Works JavaScript has a different concept of what the special name `this` refers to -than most other programming languages do. There are exactly **five** different +than most other programming languages. There are exactly **five** different ways in which the value of `this` can be bound in the language. ### The Global Scope @@ -55,7 +55,7 @@ inside of `foo` will be set to `bar`. ### Common Pitfalls -While most of these cases make sense, the first one is to be considered another +While most of these cases make sense, the first can be considered another mis-design of the language because it **never** has any practical use. Foo.method = function() { @@ -69,7 +69,7 @@ A common misconception is that `this` inside of `test` refers to `Foo`; while in fact, it **does not**. In order to gain access to `Foo` from within `test`, it is necessary to create a -local variable inside of `method` which refers to `Foo`. +local variable inside of `method` that refers to `Foo`. Foo.method = function() { var that = this; @@ -105,7 +105,7 @@ fact, it is what makes [prototypal inheritance](#object.prototype) work. new Bar().method(); -When `method` gets called on a instance of `Bar`, `this` will now refer to that +When `method` gets called on an instance of `Bar`, `this` will now refer to that very instance. From 1246d87583bf590b3c412095b368a3248f27d214 Mon Sep 17 00:00:00 2001 From: "Michael C. Harris" Date: Sun, 3 Jun 2012 12:13:54 +1000 Subject: [PATCH 228/463] Clean up language in the array section. --- doc/en/array/constructor.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/doc/en/array/constructor.md b/doc/en/array/constructor.md index 1d9abe18..8930b605 100644 --- a/doc/en/array/constructor.md +++ b/doc/en/array/constructor.md @@ -21,15 +21,15 @@ the actual indexes of the array will not be initialized. arr[1]; // undefined 1 in arr; // false, the index was not set -The behavior of being able to set the length of the array upfront only comes in -handy in a few cases, like repeating a string, in which it avoids the use of a -`for loop` code. +Being able to set the length of the array in advance is only useful in a few +cases, like repeating a string, in which it avoids the use of a `for loop` +code. new Array(count + 1).join(stringToRepeat); ### In Conclusion -The use of the `Array` constructor should be avoided as much as possible. -Literals are definitely preferred. They are shorter and have a clearer syntax; -therefore, they also increase the readability of the code. +The use of the `Array` constructor should be avoided. Literals are definitely +preferred. They are shorter, have a clearer syntax, and increase code +readability. From 23dac36960c06495dbffe2c65096dd65db87a856 Mon Sep 17 00:00:00 2001 From: "Michael C. Harris" Date: Sun, 3 Jun 2012 12:39:25 +1000 Subject: [PATCH 229/463] Clean up language in the types section. --- doc/en/types/casting.md | 8 ++++---- doc/en/types/equality.md | 6 +++--- doc/en/types/instanceof.md | 4 ++-- doc/en/types/typeof.md | 17 ++++++++--------- 4 files changed, 17 insertions(+), 18 deletions(-) diff --git a/doc/en/types/casting.md b/doc/en/types/casting.md index 34d6fd78..0dcbc92b 100644 --- a/doc/en/types/casting.md +++ b/doc/en/types/casting.md @@ -21,7 +21,7 @@ JavaScript is a *weakly typed* language, so it will apply *type coercion* > (Base 8). Octal support for these has been **removed** in ECMAScript 5 strict > mode. -In order to avoid the above, use of the [strict equal operator](#types.equality) +To avoid the issues above, use of the [strict equal operator](#types.equality) is **highly** recommended. Although this avoids a lot of common pitfalls, there are still many further issues that arise from JavaScript's weak typing system. @@ -38,8 +38,8 @@ Using a built-in type like `Number` as a constructor will create a new `Number` object, but leaving out the `new` keyword will make the `Number` function behave like a converter. -In addition, having literals or non-object values in there will result in even -more type coercion. +In addition, passing literals or non-object values will result in even more +type coercion. The best option is to cast to one of the three possible types **explicitly**. @@ -47,7 +47,7 @@ The best option is to cast to one of the three possible types **explicitly**. '' + 10 === '10'; // true -By prepending an empty string, a value can easily be casted to a string. +By prepending an empty string, a value can easily be cast to a string. ### Casting to a Number diff --git a/doc/en/types/equality.md b/doc/en/types/equality.md index 5665917f..e47752a4 100644 --- a/doc/en/types/equality.md +++ b/doc/en/types/equality.md @@ -31,7 +31,7 @@ to another number. The strict equality operator consists of **three** equal signs: `===`. -It works exactly like the normal equality operator, except that strict equality +It works like the normal equality operator, except that strict equality operator does **not** perform type coercion between its operands. "" === "0" // false @@ -50,8 +50,8 @@ the operands are of different types. ### Comparing Objects -While both `==` and `===` are stated as **equality** operators, they behave -differently when at least one of their operands happens to be an `Object`. +While both `==` and `===` are called **equality** operators, they behave +differently when at least one of their operands is an `Object`. {} === {}; // false new String('foo') === 'foo'; // false diff --git a/doc/en/types/instanceof.md b/doc/en/types/instanceof.md index 84251128..2fe41064 100644 --- a/doc/en/types/instanceof.md +++ b/doc/en/types/instanceof.md @@ -13,8 +13,8 @@ nearly as useless as the [typeof operator](#types.typeof). new Bar() instanceof Bar; // true new Bar() instanceof Foo; // true - // This just sets Bar.prototype to the function object Foo - // But not to an actual instance of Foo + // This just sets Bar.prototype to the function object Foo, + // but not to an actual instance of Foo Bar.prototype = Foo; new Bar() instanceof Foo; // false diff --git a/doc/en/types/typeof.md b/doc/en/types/typeof.md index 00377db4..637ea2bc 100644 --- a/doc/en/types/typeof.md +++ b/doc/en/types/typeof.md @@ -2,16 +2,16 @@ The `typeof` operator (together with [`instanceof`](#types.instanceof)) is probably the biggest -design flaw of JavaScript, as it is near of being **completely broken**. +design flaw of JavaScript, as it is almost **completely broken**. -Although `instanceof` still has its limited uses, `typeof` really has only one +Although `instanceof` still has limited uses, `typeof` really has only one practical use case, which does **not** happen to be checking the type of an object. -> **Note:** While `typeof` can also be called with a function like syntax -> i.e. `typeof(obj)`, this is not a function call. The two parenthesis will -> behave like normal and the return value will be used as the operand of the -> `typeof` operator. There is **no** `typeof` function. +> **Note:** While `typeof` can also be called with a function like syntax, i.e. +> `typeof(obj)`, this is not a function call. The parentheses behave as normal +> and the return value will be used as the operand of the `typeof` operator. +> There is **no** `typeof` function. ### The JavaScript Type Table @@ -79,9 +79,8 @@ referencing it would result in a `ReferenceError`. This is the only thing In order to check the type of an object, it is highly recommended to use `Object.prototype.toString` because this is the only reliable way of doing so. As shown in the above type table, some return values of `typeof` are not defined -in the specification; thus, they can differ across various implementations. +in the specification; thus, they can differ between implementations. -Unless checking whether a variable is defined, `typeof` should be avoided at -**all costs**. +Unless checking whether a variable is defined, `typeof` should be avoided. From d9aeb54a3fc9e08db17f4dfa62fe045b9bdd3c9d Mon Sep 17 00:00:00 2001 From: "Michael C. Harris" Date: Sun, 3 Jun 2012 12:58:22 +1000 Subject: [PATCH 230/463] Clean up language in the core section. --- doc/en/core/delete.md | 28 +++++++++++++--------------- doc/en/core/eval.md | 18 +++++++++--------- doc/en/core/semicolon.md | 12 ++++++------ doc/en/core/undefined.md | 20 ++++++++++---------- 4 files changed, 38 insertions(+), 40 deletions(-) diff --git a/doc/en/core/delete.md b/doc/en/core/delete.md index fdde18a4..067fcfdb 100644 --- a/doc/en/core/delete.md +++ b/doc/en/core/delete.md @@ -5,12 +5,11 @@ stuff in JavaScript which have a `DontDelete` attribute set. ### Global code and Function code -When a variable or a function is defined in a global -or a [function scope](#function.scopes) it is a property of either -Activation object or Global object. Such properties have a set of attributes, -one of these is `DontDelete`. Variable and function declarations in global -and function code always create properties with `DontDelete`, therefore -cannot be deleted. +When a variable or a function is defined in a global or a [function +scope](#function.scopes) it is a property of either the Activation object or +the Global object. Such properties have a set of attributes, one of which is +`DontDelete`. Variable and function declarations in global and function code +always create properties with `DontDelete`, and therefore cannot be deleted. // global variable: var a = 1; // DontDelete is set @@ -29,8 +28,7 @@ cannot be deleted. ### Explicit properties -There are things which can be deleted normally: these are explicitly set -properties. +Explicitly set properties can be deleted normally. // explicitly set property: var obj = {x: 1}; @@ -40,8 +38,8 @@ properties. obj.x; // undefined obj.y; // undefined -In the example above `obj.x` and `obj.y` can be deleted because they have no -`DontDelete` atribute. That's why an example below works too. +In the example above, `obj.x` and `obj.y` can be deleted because they have no +`DontDelete` atribute. That's why the example below works too. // this works fine, except for IE: var GLOBAL_OBJECT = this; @@ -58,7 +56,7 @@ IE (at least 6-8) has some bugs, so the code above doesn't work. ### Function arguments and built-ins -Functions' normal arguments, [`arguments` object](#function.arguments) +Functions' normal arguments, [`arguments` objects](#function.arguments) and built-in properties also have `DontDelete` set. // function arguments and properties: @@ -78,10 +76,10 @@ and built-in properties also have `DontDelete` set. ### Host objects -Behaviour of `delete` operator can be unpredictable for hosted objects. Due to -specification, host objects are allowed to implement any kind of behavior. +The behaviour of `delete` operator can be unpredictable for hosted objects. Due +to the specification, host objects are allowed to implement any kind of behavior. ### In conclusion -`delete` operator often has an unexpected behaviour and can be safely used -only for dealing with explicitly set properties on normal objects. +The `delete` operator often has unexpected behaviour and can only be safely +used to delete explicitly set properties on normal objects. diff --git a/doc/en/core/eval.md b/doc/en/core/eval.md index 160ba1f0..2d929902 100644 --- a/doc/en/core/eval.md +++ b/doc/en/core/eval.md @@ -12,7 +12,7 @@ The `eval` function will execute a string of JavaScript code in the local scope. foo; // 1 However, `eval` only executes in the local scope when it is being called -**directly** *and* when the name of the called function is actually `eval`. +directly *and* when the name of the called function is actually `eval`. var foo = 1; function test() { @@ -24,8 +24,8 @@ However, `eval` only executes in the local scope when it is being called test(); // 2 foo; // 3 -The use of `eval` should be avoided at **all costs**. 99.9% of its "uses" can be -achieved **without** it. +The use of `eval` should be avoided. 99.9% of its "uses" can be achieved +**without** it. ### `eval` in Disguise @@ -35,13 +35,13 @@ in the global scope since `eval` is not being called directly in that case. ### Security Issues -`eval` also is a security problem. Because it executes **any** code given to it, -it should **never** be used with strings of unknown or untrusted origins. +`eval` also is a security problem, because it executes **any** code given to it. +It should **never** be used with strings of unknown or untrusted origins. ### In Conclusion -`eval` should never be used. Any code that makes use of it is to be questioned in -its workings, performance and security. In case something requires `eval` in -order to work, it should **not** be used in the first place. -A *better design* should be used, that does not require the use of `eval`. +`eval` should never be used. Any code that makes use of it should be questioned +in its workings, performance and security. If something requires `eval` in +order to work, it should **not** be used in the first place. A *better design* +should be used, that does not require the use of `eval`. diff --git a/doc/en/core/semicolon.md b/doc/en/core/semicolon.md index f03f7d82..a2529da9 100644 --- a/doc/en/core/semicolon.md +++ b/doc/en/core/semicolon.md @@ -84,7 +84,7 @@ Below is the result of the parser's "guessing" game. })(window); //<- inserted > **Note:** The JavaScript parser does not "correctly" handle return statements -> which are followed by a new line, while this is not neccessarily the fault of +> that are followed by a new line. While this is not neccessarily the fault of > the automatic semicolon insertion, it can still be an unwanted side-effect. The parser drastically changed the behavior of the code above. In certain cases, @@ -106,9 +106,9 @@ the above will yield a `TypeError` stating that `undefined is not a function`. ### In Conclusion -It is highly recommended to **never** omit semicolons; it is also advocated to -keep braces on the same line with their corresponding statements and to never omit -them for one single-line `if` / `else` statements. Both of these measures will -not only improve the consistency of the code, but they will also prevent the -JavaScript parser from changing its behavior. +It is highly recommended to **never** omit semicolons. It is also recommended +that braces be kept on the same line as their corresponding statements and to +never omit them for single-line `if` / `else` statements. These measures will +not only improve the consistency of the code, but they will also prevent the +JavaScript parser from changing code behavior. diff --git a/doc/en/core/undefined.md b/doc/en/core/undefined.md index c819920f..1bea5411 100644 --- a/doc/en/core/undefined.md +++ b/doc/en/core/undefined.md @@ -1,7 +1,7 @@ ## `undefined` and `null` -JavaScript has two distinct values for `nothing`, the more useful of these two -being `undefined`. +JavaScript has two distinct values for nothing, `null` and `undefined`, with +the latter being more useful. ### The Value `undefined` @@ -16,14 +16,14 @@ overwritten. > mode, but its name can still be shadowed by for example a function with the name > `undefined`. -Some examples for when the value `undefined` is returned: +Here are some examples of when the value `undefined` is returned: - Accessing the (unmodified) global variable `undefined`. - - Accessing a declared *but not* yet initialized variable + - Accessing a declared *but not* yet initialized variable. - Implicit returns of functions due to missing `return` statements. - - `return` statements which do not explicitly return anything. + - `return` statements that do not explicitly return anything. - Lookups of non-existent properties. - - Function parameters which do not had any explicit value passed. + - Function parameters that do not have any explicit value passed. - Anything that has been set to the value of `undefined`. - Any expression in the form of `void(expression)` @@ -36,14 +36,14 @@ Since the global variable `undefined` only holds a copy of the actual *value* of Still, in order to compare something against the value of `undefined`, it is necessary to retrieve the value of `undefined` first. -In order to protect code against a possible overwritten `undefined` variable, a -common technique used is to add an additional parameter to an -[anonymous wrapper](#function.scopes) that gets no argument passed to it. +To protect code against a possible overwritten `undefined` variable, a common +technique used is to add an additional parameter to an [anonymous +wrapper](#function.scopes) that gets no argument passed to it. var undefined = 123; (function(something, foo, undefined) { // undefined in the local scope does - // now again refer to the value + // now again refer to the value `undefined` })('Hello World', 42); From 5f55365986d11375538cf22fa6128887cb78f787 Mon Sep 17 00:00:00 2001 From: "Michael C. Harris" Date: Sun, 3 Jun 2012 13:09:36 +1000 Subject: [PATCH 231/463] Clean up language in the other section. --- doc/en/other/timeouts.md | 50 ++++++++++++++++++++++------------------ 1 file changed, 27 insertions(+), 23 deletions(-) diff --git a/doc/en/other/timeouts.md b/doc/en/other/timeouts.md index 28e672e0..578fad5f 100644 --- a/doc/en/other/timeouts.md +++ b/doc/en/other/timeouts.md @@ -1,7 +1,7 @@ ### `setTimeout` and `setInterval` Since JavaScript is asynchronous, it is possible to schedule the execution of a -function by using the `setTimeout` and `setInterval` functions. +function using the `setTimeout` and `setInterval` functions. > **Note:** Timeouts are **not** part of the ECMAScript Standard. They are > implemented as part of the [DOM][1]. @@ -9,18 +9,18 @@ function by using the `setTimeout` and `setInterval` functions. function foo() {} var id = setTimeout(foo, 1000); // returns a Number > 0 -When `setTimeout` gets called, it will return the ID of the timeout and schedule -`foo` to run in **approximately** one thousand milliseconds in the future. -`foo` will then get executed exactly **once**. +When `setTimeout` is called, it returns the ID of the timeout and schedule +`foo` to run **approximately** one thousand milliseconds in the future. +`foo` will then be executed **once**. -Depending on the timer resolution of the JavaScript engine that is running the -code, as well as the fact that JavaScript is single threaded and other code that -gets executed might block the thread, it is by **no means** a safe bet that one -will get the exact delay that was specified in the `setTimeout` call. +Depending on the timer resolution of the JavaScript engine running the code, as +well as the fact that JavaScript is single threaded and other code that gets +executed might block the thread, it is by **no means** a safe bet that one will +get the exact delay specified in the `setTimeout` call. The function that was passed as the first parameter will get called by the *global object*, which means that [`this`](#function.this) inside the called function -refers to that very object. +refers to the global object. function Foo() { this.value = 42; @@ -34,7 +34,7 @@ refers to that very object. > **Note:** As `setTimeout` takes a **function object** as its first parameter, an -> often made mistake is to use `setTimeout(foo(), 1000)`, which will use the +> common mistake is to use `setTimeout(foo(), 1000)`, which will use the > **return value** of the call `foo` and **not** `foo`. This is, most of the time, > a silent error, since when the function returns `undefined` `setTimeout` will > **not** raise any error. @@ -72,21 +72,21 @@ the function itself. foo(); Not only does this encapsulate the `setTimeout` call, but it also prevents the -stacking of calls and it gives additional control. `foo` itself can now decide +stacking of calls and gives additional control. `foo` itself can now decide whether it wants to run again or not. ### Manually Clearing Timeouts Clearing timeouts and intervals works by passing the respective ID to -`clearTimeout` or `clearInterval`, depending which `set` function was used in -the first place. +`clearTimeout` or `clearInterval`, depending on which `set` function was used +in the first place. var id = setTimeout(foo, 1000); clearTimeout(id); -### Clearing all timeouts +### Clearing All Timeouts -Because there is no built-in method for clearing all timeouts and/or intervals, +As there is no built-in method for clearing all timeouts and/or intervals, it is necessary to use brute force in order to achieve this functionality. // clear "all" timeouts @@ -94,7 +94,9 @@ it is necessary to use brute force in order to achieve this functionality. clearTimeout(i); } -But there might still be timeouts that are unaffected by this arbitrary number. Another way of doing this is to consider that the ID given to a timeout is incremented by one everytime you call `setTimeout`. +But there might still be timeouts that are unaffected by this arbitrary number. +Another way of doing this is to consider that the ID given to a timeout is +incremented by one every time you call `setTimeout`. // clear "all" timeouts var biggestTimeoutId = window.setTimeout(function(){}, 1), @@ -103,17 +105,19 @@ But there might still be timeouts that are unaffected by this arbitrary number. clearTimeout(i); } -But even though this works on all main browsers nowadays, it isn't specified that the IDs should be ordered that way and it may change. Therefore, it is instead recommended to keep track of all the timeout IDs, so -they can be cleared specifically. +Even though this works on all major browsers today, it isn't specified that +the IDs should be ordered that way and it may change. Therefore, it is instead +recommended to keep track of all the timeout IDs, so they can be cleared +specifically. -### Hidden use of `eval` +### Hidden Use of `eval` `setTimeout` and `setInterval` can also take a string as their first parameter. This feature should **never** be used because it internally makes use of `eval`. > **Note:** Since the timeout functions are **not** specified by the ECMAScript > standard, the exact workings when a string is passed to them might differ in -> various JavaScript implementations. For example, Microsoft's JScript makes use of +> various JavaScript implementations. For example, Microsoft's JScript uses > the `Function` constructor in place of `eval`. function foo() { @@ -129,10 +133,10 @@ This feature should **never** be used because it internally makes use of `eval`. bar(); Since `eval` is not getting called [directly](#core.eval) in this case, the string -passed to `setTimeout` will get executed in the *global scope*; thus, it will +passed to `setTimeout` will be executed in the *global scope*; thus, it will not use the local variable `foo` from the scope of `bar`. -It is further recommended to **not** use a string for passing arguments to the +It is further recommended to **not** use a string to pass arguments to the function that will get called by either of the timeout functions. function foo(a, b, c) {} @@ -151,7 +155,7 @@ function that will get called by either of the timeout functions. ### In Conclusion -**Never** should a string be used as the parameter of `setTimeout` or +A string should **never** be used as the parameter of `setTimeout` or `setInterval`. It is a clear sign of **really** bad code, when arguments need to be supplied to the function that gets called. An *anonymous function* should be passed that then takes care of the actual call. From 3dc251c1277739415afb0d48a108f373478ef35f Mon Sep 17 00:00:00 2001 From: "Michael C. Harris" Date: Sat, 2 Jun 2012 15:29:23 +1000 Subject: [PATCH 232/463] Clean up language in the object section. --- doc/en/object/forinloop.md | 18 +++++++------- doc/en/object/general.md | 16 ++++++------- doc/en/object/hasownproperty.md | 18 +++++++------- doc/en/object/prototype.md | 42 +++++++++++++++++---------------- 4 files changed, 48 insertions(+), 46 deletions(-) diff --git a/doc/en/object/forinloop.md b/doc/en/object/forinloop.md index cb776b36..3d366f8c 100644 --- a/doc/en/object/forinloop.md +++ b/doc/en/object/forinloop.md @@ -1,6 +1,6 @@ ## The `for in` Loop -Just like the `in` operator, the `for in` loop also traverses the prototype +Just like the `in` operator, the `for in` loop traverses the prototype chain when iterating over the properties of an object. > **Note:** The `for in` loop will **not** iterate over any properties that @@ -17,10 +17,10 @@ chain when iterating over the properties of an object. Since it is not possible to change the behavior of the `for in` loop itself, it is necessary to filter out the unwanted properties inside the loop body; -this is done by using the [`hasOwnProperty`](#object.hasownproperty) method of +this is done using the [`hasOwnProperty`](#object.hasownproperty) method of `Object.prototype`. -> **Note:** Since the `for in` always traverses the complete prototype chain, it +> **Note:** Since `for in` always traverses the complete prototype chain, it > will get slower with each additional layer of inheritance added to an object. ### Using `hasOwnProperty` for Filtering @@ -37,15 +37,15 @@ will **only** print out `moo`. When `hasOwnProperty` is left out, the code is prone to errors in cases where the native prototypes - e.g. `Object.prototype` - have been extended. -One widely used framework which does this is [Prototype][1]. When this -framework is included, `for in` loops that do not use `hasOwnProperty` are -guaranteed to break. +One widely used framework that extends `Object.prototype` is [Prototype][1]. +When this framework is included, `for in` loops that do not use +`hasOwnProperty` are guaranteed to break. ### In Conclusion -It is recommended to **always** use `hasOwnProperty`. Never should any -assumptions be made about the environment the code is running in, or whether the -native prototypes have been extended or not. +It is recommended to **always** use `hasOwnProperty`. Assumptions should never +be made about the environment the code is running in, or whether the native +prototypes have been extended or not. [1]: http://www.prototypejs.org/ diff --git a/doc/en/object/general.md b/doc/en/object/general.md index aefbfb90..d064d498 100644 --- a/doc/en/object/general.md +++ b/doc/en/object/general.md @@ -16,8 +16,8 @@ notation* on a number as a floating point literal. 2.toString(); // raises SyntaxError -There are a couple of workarounds which can be used in order make number -literals act as objects too. +There are a couple of workarounds that can be used to make number literals act +as objects too. 2..toString(); // the second point is correctly recognized 2 .toString(); // note the space left to the dot @@ -25,16 +25,16 @@ literals act as objects too. ### Objects as a Data Type -Objects in JavaScript can also be used as a [*Hashmap*][1]; they mainly consist +Objects in JavaScript can also be used as [*Hashmaps*][1]; they mainly consist of named properties mapping to values. Using an object literal - `{}` notation - it is possible to create a plain object. This new object [inherits](#object.prototype) from `Object.prototype` and -has no [own properties](#object.hasownproperty) defined on it. +does not have [own properties](#object.hasownproperty) defined. var foo = {}; // a new empty object - // a new object with a property called 'test' with value 12 + // a new object with a 'test' property with value 12 var bar = {test: 12}; ### Accessing Properties @@ -52,13 +52,13 @@ notation or the square bracket notation. foo.1234; // SyntaxError foo['1234']; // works -Both notations are identical in their workings, with the only difference being that -the square bracket notation allows for dynamic setting of properties, as well as +The notations work almost identically, with the only difference being that the +square bracket notation allows for dynamic setting of properties and the use of property names that would otherwise lead to a syntax error. ### Deleting Properties -The only way to actually remove a property from an object is to use the `delete` +The only way to remove a property from an object is to use the `delete` operator; setting the property to `undefined` or `null` only removes the *value* associated with the property, but not the *key*. diff --git a/doc/en/object/hasownproperty.md b/doc/en/object/hasownproperty.md index 6aa13d5c..0033b4ba 100644 --- a/doc/en/object/hasownproperty.md +++ b/doc/en/object/hasownproperty.md @@ -1,7 +1,7 @@ ## `hasOwnProperty` -In order to check whether a object has a property defined on *itself* and **not** -somewhere on its [prototype chain](#object.prototype), it is necessary to use the +To check whether an object has a property defined on *itself* and not somewhere +on its [prototype chain](#object.prototype), it is necessary to use the `hasOwnProperty` method which all objects inherit from `Object.prototype`. > **Note:** It is **not** enough to check whether a property is `undefined`. The @@ -23,14 +23,14 @@ does **not** traverse the prototype chain. Only `hasOwnProperty` will give the correct and expected result; this is essential when iterating over the properties of any object. There is **no** other -way to exclude properties that are not defined on the object *itself*, but +way to exclude properties that are not defined on the object itself, but somewhere on its prototype chain. ### `hasOwnProperty` as a Property -JavaScript does **not** protect the property name `hasOwnProperty`; thus, if the +JavaScript does not protect the property name `hasOwnProperty`; thus, if the possibility exists that an object might have a property with this name, it is -necessary to use an *external* `hasOwnProperty` in order to get correct results. +necessary to use an *external* `hasOwnProperty` to get correct results. var foo = { hasOwnProperty: function() { @@ -44,14 +44,14 @@ necessary to use an *external* `hasOwnProperty` in order to get correct results. // Use another Object's hasOwnProperty and call it with 'this' set to foo ({}).hasOwnProperty.call(foo, 'bar'); // true - // It's also possible use the hasOwnProperty property from the Object property for this purpose + // It's also possible to use the hasOwnProperty property from the Object property for this purpose Object.prototype.hasOwnProperty.call(obj, 'bar'); // true ### In Conclusion -When checking for the existence of a property on a object, `hasOwnProperty` is -the **only** method of doing so. It is also recommended to make `hasOwnProperty` -part of **every** [`for in` loop](#object.forinloop); this will avoid errors from +Using `hasOwnProperty` is the **only** reliable method to check for the +existence of a property on an object. It is recommended that `hasOwnProperty` +is used in **every** [`for in` loop](#object.forinloop) to avoid errors from extended native [prototypes](#object.prototype). diff --git a/doc/en/object/prototype.md b/doc/en/object/prototype.md index 0a3b6d0c..abb67c58 100644 --- a/doc/en/object/prototype.md +++ b/doc/en/object/prototype.md @@ -4,16 +4,16 @@ JavaScript does not feature a classical inheritance model; instead, it uses a *prototypal* one. While this is often considered to be one of JavaScript's weaknesses, the -prototypal inheritance model is in fact more powerful than the classic model. -It is, for example, fairly trivial to build a classic model on top of it, while the -other way around is a far more difficult task. +prototypal inheritance model is in fact more powerful than the classic model. +It is, for example, fairly trivial to build a classic model on top of a +prototypal model, while the other way around is a far more difficult task. -Due to the fact that JavaScript is basically the only widely used language that -features prototypal inheritance, it takes some time to adjust to the -differences between the two models. +JavaScript is the only widely used language that features prototypal +inheritance, so it can take time to adjust to the differences between the two +models. -The first major difference is that inheritance in JavaScript is done by using so -called *prototype chains*. +The first major difference is that inheritance in JavaScript uses *prototype +chains*. > **Note:** Simply using `Bar.prototype = Foo.prototype` will result in both objects > sharing the **same** prototype. Therefore, changes to either object's prototype @@ -47,7 +47,7 @@ called *prototype chains*. Object.prototype { toString: ... /* etc. */ } -In the above, the object `test` will inherit from both `Bar.prototype` and +In the code above, the object `test` will inherit from both `Bar.prototype` and `Foo.prototype`; hence, it will have access to the function `method` that was defined on `Foo`. It will also have access to the property `value` of the **one** `Foo` instance that is its prototype. It is important to note that `new @@ -64,7 +64,7 @@ its prototype; thus, all `Bar` instances will share the **same** `value` propert When accessing the properties of an object, JavaScript will traverse the prototype chain **upwards** until it finds a property with the requested name. -When it reaches the top of the chain - namely `Object.prototype` - and still +If it reaches the top of the chain - namely `Object.prototype` - and still hasn't found the specified property, it will return the value [undefined](#core.undefined) instead. @@ -82,12 +82,13 @@ creation of prototype chains. ### Performance -The lookup time for properties that are high up on the prototype chain can have a -negative impact on performance critical sections of code. Additionally, trying to -access non-existent properties will always traverse the full prototype chain. +The lookup time for properties that are high up on the prototype chain can have +a negative impact on performance, and this may be significant in code where +performance is critical. Additionally, trying to access non-existent properties +will always traverse the full prototype chain. Also, when [iterating](#object.forinloop) over the properties of an object -**every** property that is on the prototype chain will get enumerated. +**every** property that is on the prototype chain will be enumerated. ### Extension of Native Prototypes @@ -95,7 +96,7 @@ One mis-feature that is often used is to extend `Object.prototype` or one of the other built in prototypes. This technique is called [monkey patching][1] and breaks *encapsulation*. While -used by widely spread frameworks such as [Prototype][2], there is still no good +used by popular frameworks such as [Prototype][2], there is still no good reason for cluttering built-in types with additional *non-standard* functionality. The **only** good reason for extending a built-in prototype is to backport @@ -104,11 +105,12 @@ the features of newer JavaScript engines; for example, ### In Conclusion -It is a **must** to understand the prototypal inheritance model completely -before writing complex code which makes use of it. Also, watch the length of -the prototype chains and break them up if necessary to avoid possible -performance issues. Further, the native prototypes should **never** be extended -unless it is for the sake of compatibility with newer JavaScript features. +It is **essential** to understand the prototypal inheritance model before +writing complex code that makes use of it. Also, be aware of the length of the +prototype chains in your code and break them up if necessary to avoid possible +performance problems. Further, the native prototypes should **never** be +extended unless it is for the sake of compatibility with newer JavaScript +features. [1]: http://en.wikipedia.org/wiki/Monkey_patch [2]: http://prototypejs.org/ From 472df35b9ddb5efd0716b7cf4a512af114a0eb00 Mon Sep 17 00:00:00 2001 From: Dawid Spiechowicz Date: Wed, 13 Jun 2012 11:19:19 +0300 Subject: [PATCH 233/463] Typo fix --- doc/pl/function/general.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/pl/function/general.md b/doc/pl/function/general.md index e3f035b2..c960c9b5 100644 --- a/doc/pl/function/general.md +++ b/doc/pl/function/general.md @@ -5,7 +5,7 @@ być przekazywane jak każda inna wartość. Jednym z typowych zastosowań tej c jest przekazywanie *anonimowej funkcji* jako callback do innej, prawdopodobnie asynchronicznej funkcji. -### Deklaracja funckcji +### Deklaracja funkcji function foo() {} From 3ec1079f22ba9f2c9834283baa66afac4e66d6d1 Mon Sep 17 00:00:00 2001 From: Dawid Spiechowicz Date: Wed, 13 Jun 2012 12:55:25 +0300 Subject: [PATCH 234/463] remove not needed english part --- doc/pl/function/this.md | 5 ----- 1 file changed, 5 deletions(-) diff --git a/doc/pl/function/this.md b/doc/pl/function/this.md index 89a5a1e5..3fa2d477 100644 --- a/doc/pl/function/this.md +++ b/doc/pl/function/this.md @@ -4,17 +4,12 @@ JavaScript posiada inną koncepcję odnośnie tego na co wskazuje słowo kluczow `this`, niż większość innych języków programowania. Istnieje dokładnie **pięć** różnych sytuacji, w których wartość `this` jest przypisana w języku JavaScript. -JavaScript has a different concept of what the special name `this` refers to -than most other programming languages do. There are exactly **five** different -ways in which the value of `this` can be bound in the language. - ### Zasięg globalny this; Używanie `this` w globalnym zasięgu, zwróci po prostu referencję do obiektu *global*. - ### Wywołanie funkcji foo(); From 332dcf0a6b1f5e007e7e8fce7a88cb5f8d21bc6b Mon Sep 17 00:00:00 2001 From: Dawid Spiechowicz Date: Wed, 13 Jun 2012 13:39:44 +0300 Subject: [PATCH 235/463] typo fix --- doc/pl/function/closures.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/pl/function/closures.md b/doc/pl/function/closures.md index 8cb6fb79..2c72db1b 100644 --- a/doc/pl/function/closures.md +++ b/doc/pl/function/closures.md @@ -3,7 +3,7 @@ Jedną z najpotężniejszych funkcjonalności języka JavaScript są *domknięcia*. Oznacza to że zasięg **zawsze** posiada dostęp do zewnętrznego zasięgu, w którym został zdefiniowany. Ponieważ zasięg w JavaScript można definiować tylko poprzez -[funckję](#function.scopes), wszystkie funkcje domyślnie zachowują się jak domknięcia. +[funkcję](#function.scopes), wszystkie funkcje domyślnie zachowują się jak domknięcia. ### Emulowanie prywatnych zmiennych From bb2ccece392d4883c3c12e6e9ccb9c46b7d7d7d4 Mon Sep 17 00:00:00 2001 From: Dawid Spiechowicz Date: Wed, 13 Jun 2012 14:01:11 +0300 Subject: [PATCH 236/463] typo fix, remove unused english part --- doc/pl/function/constructors.md | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/doc/pl/function/constructors.md b/doc/pl/function/constructors.md index 4e0f502e..d9be52a0 100644 --- a/doc/pl/function/constructors.md +++ b/doc/pl/function/constructors.md @@ -22,7 +22,7 @@ fukcja domyślnie zwraca wartość `this` - nowy obiekt. var test = new Foo(); -Powyżej wywołanya została funkcja `Foo` jako konstruktor oraz ustawia +Powyżej wywołana została funkcja `Foo` jako konstruktor oraz ustawia nowo utworzonemu obiektowi właściwość `prototype` na `Foo.prototype`. W tym przypadku jawna deklaracja `return` w funkcji zwraca wartość @@ -53,7 +53,7 @@ obiektu. Mimo że powyższy kod może zadziałać w pewnych przypadkach, w związku z działaniem [`this`](#function.this) w języku JavaScript, to jako -wartość `this`zostanie wykorzystany **obiekt global**. +wartość `this` zostanie wykorzystany **obiekt global**. ### Fabryki @@ -113,9 +113,7 @@ nowy obiekt wewnątrz tej fabryki. Mimo że powyższy kod jest odporny na brak słowa kluczowego `new` i ułatwia korzystanie ze [zmiennych prywatnych](#function.closures), to posiada pewne wady. -While the above is robust against a missing `new` keyword and certainly makes -the use of [private variables](#function.closures) easier, it comes with some -downsides. + 1. Zużywa więcej pamięci, ponieważ tworzony obiekt **nie** współdzieli metod poprzez prototyp. 2. Aby móc dziedziczyć fabryka musi skopiować wszystkie metody z dziedziczonego From 7d66a4b621d1a734e1ba029a7e85b96c3f1bc542 Mon Sep 17 00:00:00 2001 From: Dawid Spiechowicz Date: Wed, 13 Jun 2012 15:19:14 +0300 Subject: [PATCH 237/463] typo fix --- doc/pl/types/equality.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/pl/types/equality.md b/doc/pl/types/equality.md index 48f4197a..c655a795 100644 --- a/doc/pl/types/equality.md +++ b/doc/pl/types/equality.md @@ -58,7 +58,7 @@ to zachowują się różnie, gdy jednym z operandów jest obiekt typu `Object`. var foo = {}; foo === foo; // true -Oba operatory porównują **toższmość** a **nie** równość, czyli będą porównywać czy +Oba operatory porównują **tożsamość** a **nie** równość, czyli będą porównywać czy jeden i drugi operand jest tą samą **instancją** obiektu (podobnie jak operator `is` w Pythonie i porównanie wskaźników w C). From 0b7ecf874f31fee0fba7694099b862f07ca281e3 Mon Sep 17 00:00:00 2001 From: Dawid Spiechowicz Date: Wed, 13 Jun 2012 20:24:24 +0300 Subject: [PATCH 238/463] typo fix --- doc/pl/intro/license.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/pl/intro/license.md b/doc/pl/intro/license.md index c9329aab..5b0e855d 100644 --- a/doc/pl/intro/license.md +++ b/doc/pl/intro/license.md @@ -1,7 +1,7 @@ ## Licencja JavaScript Garden jest publikowany w ramach [licencji MIT] [1] i kod źródłowy znajduje -się na serwerze [GitHub] [2]. Jeśli znajdziesz jakieś błędy lub literówek zgłoś proszę +się na serwerze [GitHub] [2]. Jeśli znajdziesz jakieś błędy lub literówki, zgłoś proszę [problem] [3] lub rozwiąż go i zgloś pull request ze swojego repozytorium. Możesz nas także znaleźć w pokoju [JavaScript] [4] na chacie Stack Overflow. From 41d1d7e2f6701a8e6267b72e48d51f1fd9bb8a95 Mon Sep 17 00:00:00 2001 From: Evan Goer Date: Wed, 13 Jun 2012 21:19:50 -0700 Subject: [PATCH 239/463] Update master --- doc/en/types/typeof.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/en/types/typeof.md b/doc/en/types/typeof.md index 00377db4..348f8c9a 100644 --- a/doc/en/types/typeof.md +++ b/doc/en/types/typeof.md @@ -2,7 +2,7 @@ The `typeof` operator (together with [`instanceof`](#types.instanceof)) is probably the biggest -design flaw of JavaScript, as it is near of being **completely broken**. +design flaw of JavaScript, as it is nearly **completely broken**. Although `instanceof` still has its limited uses, `typeof` really has only one practical use case, which does **not** happen to be checking the type of an From c7177a380758ccb9c0fcccf0ef0109704ada5cff Mon Sep 17 00:00:00 2001 From: Seong-Rak Choi Date: Fri, 20 Jul 2012 10:34:24 +0900 Subject: [PATCH 240/463] =?UTF-8?q?-=20fix=20an=20mistranslated=20word:=20?= =?UTF-8?q?'=EB=AF=B8=EB=AC=98=ED=95=9C'=20to=20'=EC=9E=A1=EC=95=84?= =?UTF-8?q?=EB=82=B4=EA=B8=B0=20=EC=96=B4=EB=A0=A4=EC=9A=B4'=20-=20wrap=20?= =?UTF-8?q?the=20`method`=20keyword=20with=20link?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- doc/ko/other/timeouts.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/ko/other/timeouts.md b/doc/ko/other/timeouts.md index fb0384ed..ba2f6356 100644 --- a/doc/ko/other/timeouts.md +++ b/doc/ko/other/timeouts.md @@ -111,7 +111,7 @@ Id가 1부터 1000 사이에 있는 timeout들을 제거했지만, 그 외의 foo(a, b, c); }, 1000) -> **Note:** `setTimeout(foo, 1000, a, b, c)`처럼 사용하는 것도 가능하지만, 이것도 권장하지 않는다. 메소드를 사용할 때 미묘한 에러가 날 수 있다. +> **Note:** `setTimeout(foo, 1000, a, b, c)`처럼 사용하는 것도 가능하지만, 이것도 권장하지 않는다. [메소드](#function.this)를 사용할 때 잡아내기 어려운 에러가 날 수 있다. ### 결론 From deb2f903ebafc995715078c7a21a2d12f4e512a1 Mon Sep 17 00:00:00 2001 From: dishuostec Date: Fri, 27 Jul 2012 10:00:13 +0800 Subject: [PATCH 241/463] Fixed typo --- doc/zh/types/equality.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/zh/types/equality.md b/doc/zh/types/equality.md index eef0e9da..02f5280c 100755 --- a/doc/zh/types/equality.md +++ b/doc/zh/types/equality.md @@ -18,7 +18,7 @@ JavaScript 是*弱类型*语言,这就意味着,等于操作符会为了比 null == undefined // true " \t\r\n" == 0 // true -上面的表格展示了强类型转换,这也是使用 `==` 被广泛认为是不好编程习惯的主要原因, +上面的表格展示了强制类型转换,这也是使用 `==` 被广泛认为是不好编程习惯的主要原因, 由于它的复杂转换规则,会导致难以跟踪的问题。 此外,强制类型转换也会带来性能消耗,比如一个字符串为了和一个数组进行比较,必须事先被强制转换为数字。 @@ -27,7 +27,7 @@ JavaScript 是*弱类型*语言,这就意味着,等于操作符会为了比 严格等于操作符由**三**个等号组成:`===` -不想普通的等于操作符,严格等于操作符**不会**进行强制类型转换。 +不像普通的等于操作符,严格等于操作符**不会**进行强制类型转换。 "" === "0" // false 0 === "" // false From 213a3db7c161aab8f8ec560768c8365ab8b183ee Mon Sep 17 00:00:00 2001 From: Dr_rOot Date: Thu, 2 Aug 2012 15:42:50 +0800 Subject: [PATCH 242/463] Corrected a typing error. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 本省 => 本身 --- doc/zh/types/instanceof.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/zh/types/instanceof.md b/doc/zh/types/instanceof.md index 191c43c4..e2783ef7 100755 --- a/doc/zh/types/instanceof.md +++ b/doc/zh/types/instanceof.md @@ -12,7 +12,7 @@ new Bar() instanceof Bar; // true new Bar() instanceof Foo; // true - // 如果仅仅设置 Bar.prototype 为函数 Foo 本省,而不是 Foo 构造函数的一个实例 + // 如果仅仅设置 Bar.prototype 为函数 Foo 本身,而不是 Foo 构造函数的一个实例 Bar.prototype = Foo; new Bar() instanceof Foo; // false From 6196e7802f522d160d63f702f54f1ef1f5814e68 Mon Sep 17 00:00:00 2001 From: Changwoo Park Date: Mon, 10 Sep 2012 15:35:35 +0900 Subject: [PATCH 243/463] [ko] Up to date --- doc/ko/array/general.md | 7 ++++--- doc/ko/other/timeouts.md | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/doc/ko/array/general.md b/doc/ko/array/general.md index 0a396d2e..3f7ae206 100644 --- a/doc/ko/array/general.md +++ b/doc/ko/array/general.md @@ -1,6 +1,6 @@ ## Array Iteration과 프로퍼티 -JavaScript에서는 Array도 객체 Iterate를 할 때 [`for in`](#object.forinloop)을 사용해서 좋을 게 없다. 실제로 Array에 `for in`을 사용하지 말아야 할 근거가 매우 많다. +JavaScript에서는 Array도 객체지만 [`for in`](#object.forinloop)을 사용해서 좋을 게 없다. 실제로 Array에 `for in`을 사용하지 말아야 할 근거가 매우 많다. > **Note:** JavaScript의 Array는 *Associative Array*가 **아니다**. JavaScript [객체](#object.general)는 key/value만 Mapping할 뿐이다. Associative Array는 순서를 보장하지만, 객체는 보장하지 않는다. @@ -30,9 +30,10 @@ Array를 Iterate할 때에는 구식인 `for`를 사용하는 것이 가장 빠 foo; // [1, 2, 3] foo.length = 6; - foo; // [1, 2, 3] + foo.push(4); + foo; // [1, 2, 3, undefined, undefined, undefined, 4] -현재 크기보다 더 작은 값을 할당하면 Array를 자르지만, 현재 크기보다 더 큰 값을 할당한다고 해서 Array를 늘리지 않는다. +현재 크기보다 더 작은 값을 할당하면 Array를 자르고, 현재 크기보다 더 큰 값을 할당하면 늘어난다. ### 결론 diff --git a/doc/ko/other/timeouts.md b/doc/ko/other/timeouts.md index fb0384ed..2083137e 100644 --- a/doc/ko/other/timeouts.md +++ b/doc/ko/other/timeouts.md @@ -104,7 +104,7 @@ Id가 1부터 1000 사이에 있는 timeout들을 제거했지만, 그 외의 function foo(a, b, c) {} // 절대 사용하면 안 됨 - setTimeout('foo(1,2, 3)', 1000) + setTimeout('foo(1, 2, 3)', 1000) // 대신 익명 함수를 사용하는 게 좋다. setTimeout(function() { From f6d46411c0108529f816e60e6ac33d07437dfe3e Mon Sep 17 00:00:00 2001 From: Zurian Vitaliy Date: Mon, 1 Oct 2012 16:33:30 +0300 Subject: [PATCH 244/463] Minor syntax changes --- doc/en/object/general.md | 2 +- doc/es/object/general.md | 2 +- doc/fi/object/general.md | 2 +- doc/ja/object/general.md | 2 +- doc/ko/object/general.md | 2 +- doc/pl/object/general.md | 2 +- doc/ru/object/general.md | 2 +- doc/tr/object/general.md | 2 +- doc/zh/object/general.md | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/doc/en/object/general.md b/doc/en/object/general.md index aefbfb90..12f9c939 100644 --- a/doc/en/object/general.md +++ b/doc/en/object/general.md @@ -3,7 +3,7 @@ Everything in JavaScript acts like an object, with the only two exceptions being [`null`](#core.undefined) and [`undefined`](#core.undefined). - false.toString() // 'false' + false.toString(); // 'false' [1, 2, 3].toString(); // '1,2,3' function Foo(){} diff --git a/doc/es/object/general.md b/doc/es/object/general.md index ccdd1cce..90bc39e0 100644 --- a/doc/es/object/general.md +++ b/doc/es/object/general.md @@ -3,7 +3,7 @@ Todo en JavaScript actúa como un objeto, con las dos únicas excepciones de [`null`](#core.undefined) y [`undefined`](#core.undefined). - false.toString() // 'false' + false.toString(); // 'false' [1, 2, 3].toString(); // '1,2,3' function Foo(){} diff --git a/doc/fi/object/general.md b/doc/fi/object/general.md index c169117f..d3cf8c8f 100644 --- a/doc/fi/object/general.md +++ b/doc/fi/object/general.md @@ -2,7 +2,7 @@ Kaikki muuttujat, kahta poikkeusta lukuunottamatta, käyttäytyvät JavaScriptissä oliomaisesti. Nämä poikkeukset ovat [`null`](#core.undefined) sekä [`undefined`](#core.undefined). - false.toString() // epätosi + false.toString(); // epätosi [1, 2, 3].toString(); // '1,2,3' function Foo(){} diff --git a/doc/ja/object/general.md b/doc/ja/object/general.md index 2838cf91..7dd037a2 100644 --- a/doc/ja/object/general.md +++ b/doc/ja/object/general.md @@ -3,7 +3,7 @@ JavaScriptの全ての要素は2つの例外を除いて、オブジェクトのように振る舞います。 その2つとは[`null`](#core.undefined)と[`undefined`](#core.undefined)です。 - false.toString() // 'false' + false.toString(); // 'false' [1, 2, 3].toString(); // '1,2,3' function Foo(){} diff --git a/doc/ko/object/general.md b/doc/ko/object/general.md index 51ae6f60..ed07b39f 100644 --- a/doc/ko/object/general.md +++ b/doc/ko/object/general.md @@ -2,7 +2,7 @@ JavaScript에서 [`null`](#core.undefined)과 [`undefined`](#core.undefined)를 제외한 모든 것은 객체다. - false.toString() // 'false' + false.toString(); // 'false' [1, 2, 3].toString(); // '1,2,3' function Foo(){} diff --git a/doc/pl/object/general.md b/doc/pl/object/general.md index 9512c293..11589d72 100644 --- a/doc/pl/object/general.md +++ b/doc/pl/object/general.md @@ -3,7 +3,7 @@ Wszystko w JavaScripcie zachowuje sie jak obiekt, z dwoma wyjątkami [`null`](#core.undefined) oraz [`undefined`](#core.undefined). - false.toString() // 'false' + false.toString(); // 'false' [1, 2, 3].toString(); // '1,2,3' function Foo(){} diff --git a/doc/ru/object/general.md b/doc/ru/object/general.md index d5b65e7a..d3a12795 100644 --- a/doc/ru/object/general.md +++ b/doc/ru/object/general.md @@ -2,7 +2,7 @@ В JavaScript всё является объектом, лишь за двумя исключениями — [`null`](#core.undefined) и [`undefined`](#core.undefined). - false.toString() // 'false' + false.toString(); // 'false' [1, 2, 3].toString(); // '1,2,3' function Foo(){} diff --git a/doc/tr/object/general.md b/doc/tr/object/general.md index 6107ca66..cd4eb2f9 100644 --- a/doc/tr/object/general.md +++ b/doc/tr/object/general.md @@ -4,7 +4,7 @@ JavaScript'te iki istisna dışında her şey bir nesne olarak davranır; bu istisnalar da [`null`](#core.undefined) ve [`undefined`](#core.undefined) 'dır. - false.toString() // 'false' + false.toString(); // 'false' [1, 2, 3].toString(); // '1,2,3' function Foo(){} diff --git a/doc/zh/object/general.md b/doc/zh/object/general.md index b75b0fea..fa0adf2b 100755 --- a/doc/zh/object/general.md +++ b/doc/zh/object/general.md @@ -2,7 +2,7 @@ JavaScript 中所有变量都是对象,除了两个例外 [`null`](#core.undefined) 和 [`undefined`](#core.undefined)。 - false.toString() // 'false' + false.toString(); // 'false' [1, 2, 3].toString(); // '1,2,3' function Foo(){} From 5d68a8d5d5534d37d871165622ee7558a9128b78 Mon Sep 17 00:00:00 2001 From: jifeon Date: Mon, 8 Oct 2012 01:58:09 +0400 Subject: [PATCH 245/463] Update doc/ru/object/general.md fixes for #63 and #148 --- doc/ru/object/general.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/doc/ru/object/general.md b/doc/ru/object/general.md index d5b65e7a..e00adfb6 100644 --- a/doc/ru/object/general.md +++ b/doc/ru/object/general.md @@ -84,14 +84,14 @@ // валидный JavaScript и валидный JSON { - 'foo': 'oof', - 'bar': 'rab' + "foo": "oof", + "bar": "rab" } - // валидный JavaScript и НЕ валидный JSON + // валидный JavaScript и НЕвалидный JSON { - foo: 'oof', - bar: 'rab' + foo: "oof", + bar: "rab" } [1]: http://ru.wikipedia.org/wiki/%D0%A5%D0%B5%D1%88-%D1%82%D0%B0%D0%B1%D0%BB%D0%B8%D1%86%D0%B0 From fe2b2d27e54a84ea9dac1a6702825279926cd3d1 Mon Sep 17 00:00:00 2001 From: Georgeek Date: Tue, 20 Nov 2012 16:20:10 +0200 Subject: [PATCH 246/463] Translation was clarified acts! --- doc/ru/object/general.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/ru/object/general.md b/doc/ru/object/general.md index 9c22c5f6..21cc5d01 100644 --- a/doc/ru/object/general.md +++ b/doc/ru/object/general.md @@ -1,6 +1,6 @@ ## Объекты и их свойства -В JavaScript всё является объектом, лишь за двумя исключениями — [`null`](#core.undefined) и [`undefined`](#core.undefined). +В JavaScript всё ведет себя, как объект, лишь за двумя исключениями — [`null`](#core.undefined) и [`undefined`](#core.undefined). false.toString(); // 'false' [1, 2, 3].toString(); // '1,2,3' From 46d0058aa6258a12306b0fdc84fbfabe155b6f7f Mon Sep 17 00:00:00 2001 From: "ByungDae, Sohn" Date: Wed, 21 Nov 2012 13:42:31 +0900 Subject: [PATCH 247/463] corrected mistranslation and full korean translation improved --- .project | 11 +++++ doc/ko/array/constructor.md | 10 ++--- doc/ko/array/general.md | 20 ++++----- doc/ko/core/delete.md | 16 +++---- doc/ko/core/eval.md | 8 ++-- doc/ko/core/semicolon.md | 12 +++--- doc/ko/core/undefined.md | 9 ++-- doc/ko/function/arguments.md | 27 ++++++------ doc/ko/function/closures.md | 30 ++++++------- doc/ko/function/constructors.md | 24 ++++++----- doc/ko/function/general.md | 28 ++++++------- doc/ko/function/scopes.md | 74 ++++++++++++++++----------------- doc/ko/function/this.md | 10 ++--- doc/ko/intro/index.md | 3 +- doc/ko/object/forinloop.md | 16 +++---- doc/ko/object/general.md | 23 +++++----- doc/ko/object/hasownproperty.md | 18 ++++---- doc/ko/object/prototype.md | 36 ++++++++-------- doc/ko/other/timeouts.md | 55 ++++++++++++------------ doc/ko/types/casting.md | 6 +-- doc/ko/types/equality.md | 26 ++++++------ doc/ko/types/instanceof.md | 10 ++--- doc/ko/types/typeof.md | 20 ++++----- 23 files changed, 253 insertions(+), 239 deletions(-) create mode 100644 .project diff --git a/.project b/.project new file mode 100644 index 00000000..42a345c2 --- /dev/null +++ b/.project @@ -0,0 +1,11 @@ + + + JavaScript-Garden + + + + + + + + diff --git a/doc/ko/array/constructor.md b/doc/ko/array/constructor.md index 471fd60d..0c60a842 100644 --- a/doc/ko/array/constructor.md +++ b/doc/ko/array/constructor.md @@ -1,6 +1,6 @@ -## `Array` 생성자 +## `배열` 생성자 -`Array` 생성자가 파라미터를 처리하는 방법은 모호하다. 그래서 항상 `[]` 노테이션으로 Array를 만들어야 한다. +배열을 만들때 `배열` 생성자에 파라미터를 넣어 만드는 방법은 헷갈릴수있다. 그래서 항상 각 괄호(`[]`) 노테이션을 이용해 배열을 만들 것을 권한다 [1, 2, 3]; // Result: [1, 2, 3] new Array(1, 2, 3); // Result: [1, 2, 3] @@ -9,16 +9,16 @@ new Array(3); // Result: [] new Array('3') // Result: ['3'] -`Array` 생성자에 인자로 숫자를 넘기면 `length`가 그 숫자인 텅 빈 `Array` 하나를 반환된다. 생성자는 **오직** `length` 프로퍼티에 그 숫자를 할당하기만 하고 `Array`는 실제로 초기화하지 않는다. +`배열` 생성자에 숫자를 인자로 넣으면 그 숫자 크기 만큼의 빈 `배열`을 반환한다. 즉 배열의 `length`는 그 숫자가 된다. 이때 생성자는 **단지** `length` 프로퍼티에 그 숫자를 할당하기만 하고 `배열`은 실제로 초기화 하지도 않는다. var arr = new Array(3); arr[1]; // undefined 1 in arr; // false, 이 인덱스는 초기화되지 않음. -Array의 length 프로퍼티에 숫자를 할당해주는 이 기능이 유용할 때도 있긴 있다. `for loop`을 사용하지 않고 스트링을 더할 때가 그렇다. +`for`문을 사용하지 않고 문자열을 더하는 경우에는 length 프로퍼티에 숫자를 할당해주는 기능이 유용할 때도 있다. new Array(count + 1).join(stringToRepeat); ### 결론 -`Array` 생성자는 가능하면 사용하지 말아야 한다. `[]` 노테이션이 더 알맞다. 더 간략하고 명확하기 때문에 보기도 좋다. +`배열` 생성자는 가능하면 사용하지 말고, 각 괄호 (`[]`) 노테이션이을 사용하자. 후자가 더 간략하고 명확할 뿐만 아니라 보기도 좋다. diff --git a/doc/ko/array/general.md b/doc/ko/array/general.md index 0a396d2e..1a665fa3 100644 --- a/doc/ko/array/general.md +++ b/doc/ko/array/general.md @@ -1,29 +1,29 @@ -## Array Iteration과 프로퍼티 +## 배열 순회와 프로퍼티 -JavaScript에서는 Array도 객체 Iterate를 할 때 [`for in`](#object.forinloop)을 사용해서 좋을 게 없다. 실제로 Array에 `for in`을 사용하지 말아야 할 근거가 매우 많다. +JavaScript에서는 배열(Array)도 객체(Object)지만 객체 순회(Iterate)를 할 때 [`for in`](#object.forinloop)을 사용해서 좋을 게 없다. 실제로 배열을 탐색할때 `for in`문 사용하지 말아야 할 이유가 매우 많다. -> **Note:** JavaScript의 Array는 *Associative Array*가 **아니다**. JavaScript [객체](#object.general)는 key/value만 Mapping할 뿐이다. Associative Array는 순서를 보장하지만, 객체는 보장하지 않는다. +> **Note:** JavaScript의 배열은 *연관 배열(Associative Array)*이 **아니다**. JavaScript는 오직 key/value를 맵핑한 [객체](#object.general)만 있을 뿐이다. 연관 배열은 순서를 보장해주지만 객체는 순서를 보장하지 않는다. `for in`은 프로토타입 체인에 있는 프로퍼티를 모두 훑는(enumerate) 데다가 객체 자신의 프로퍼티만 훑으려면 [`hasOwnProperty`](#object.hasownproperty)를 사용해야 하기 때문에 `for`보다 20배 느리다. -### Iteration +### 배열 순회 -Array를 Iterate할 때에는 구식인 `for`를 사용하는 것이 가장 빠르다. +배열을 순회 할때는 일반적인 `for`문을 사용하는 것이 가장 빠르다. var list = [1, 2, 3, 4, 5, ...... 100000000]; for(var i = 0, l = list.length; i < l; i++) { console.log(list[i]); } -이 예제에서 `l = list.length`로 Array의 length 값을 캐시해야 한다는 것을 꼭 기억해야 한다. +이 예제에서 `l = list.length`로 배열의 length 값을 캐시해야 한다는 것을 꼭 기억해야 한다. -매 Iterate마다 Array에 있는 `length` 프로퍼티에 접근하는 것은 좀 부담스럽다. 최신 JavaScript 엔진은 이 일을 알아서 처리해주기도 하지만 코드가 늘 새 엔진에서 실행되도록 보장할 방법이 없다. +매번 반복할때마다 배열에 있는 `length` 프로퍼티에 접근하는 것은 좀 부담스럽다. 최신 JavaScript 엔진은 이 일을 알아서 처리해주기도 하지만 코드가 늘 새 엔진에서 실행되도록 보장할 방법이 없다. 실제로 캐시 하지 않으면 성능이 반으로 줄어든다. ### `length` 프로퍼티 -`length` 프로퍼티의 *getter*는 단순히 Array 안에 있는 엘리먼트의 개수를 반환하고 *setter*는 Array를 할당한 수만큼 잘라 버린다. +`length` 프로퍼티의 *getter*는 단순히 Array 안에 있는 엘리먼트의 개수를 반환하고 *setter*는 배열을 할당한 수만큼 잘라 버린다. var foo = [1, 2, 3, 4, 5, 6]; foo.length = 3; @@ -32,8 +32,8 @@ Array를 Iterate할 때에는 구식인 `for`를 사용하는 것이 가장 빠 foo.length = 6; foo; // [1, 2, 3] -현재 크기보다 더 작은 값을 할당하면 Array를 자르지만, 현재 크기보다 더 큰 값을 할당한다고 해서 Array를 늘리지 않는다. +현재 크기보다 더 작은 값을 할당하면 배열을 자르지만, 현재 크기보다 더 큰 값을 할당한다고 해서 배열을 늘리진 않는다. ### 결론 -최적의 성능을 위해서는 `for`를 사용하고 `length` 프로퍼티 값을 캐시해야 한다. Array에 `for in`을 사용하면 성능도 떨어지고 버그 나기도 쉽다. +최적의 성능을 위해서는 `for`문을 사용하고 `length` 프로퍼티 값을 캐시해야 한다. 배열에 `for in`을 사용하면 성능도 떨어지고 버그 나기도 쉽다. diff --git a/doc/ko/core/delete.md b/doc/ko/core/delete.md index 342c04e9..7f008b2c 100644 --- a/doc/ko/core/delete.md +++ b/doc/ko/core/delete.md @@ -1,10 +1,10 @@ -## `delete` +## `delete` 연산자 -간단히 말해서 global 변수, Function, 등은 `DontDelete` 속성이기 때문에 delete하지 못 한다. +간단히 말해서 전역 변수와 전역 함수 그리고 `DontDelete` 속성을 가진 자바스크립트 객체는 삭제할 수 없다. ### Global 코드와 Function 코드 -Global이나 Function Scope에 정의한 Fuction이나 변수는 모두 Activation 객체나 Global 객체의 프로퍼티다. 이 프로퍼티는 모두 `DontDelete` 속성을 가진다. Global이나 Function 코드에서 변수나 Function의 정의하면 항상 `DontDelete` 프로퍼티로 만들어진다. 그러니까 delete할 수 없다: +전역이나 함수 스코프에 정의한 함수나 변수는 모두 Activation 객체나 전역 객체의 프로퍼티다. 이 프로퍼티는 모두 `DontDelete` 속성을 가진다. 전역이나 함수 코드에 정의한 변수와 함수는 항상 `DontDelete` 프로퍼티로 만들어지기 때문에 삭제될 수 없다: // Global 변수: var a = 1; // DontDelete가 설정된다. @@ -21,9 +21,9 @@ Global이나 Function Scope에 정의한 Fuction이나 변수는 모두 Activati delete f; // false f; // 1 -### Explicit 프로퍼티 +### 명시적인(Explicit) 프로퍼티 -다음 예제에서 만드는 프로퍼티는 delete할 수 있다. 이런 걸 Explicit 프로퍼티라고 부른다: +다음 예제에서 만드는 프로퍼티는 delete할 수 있다. 이런 걸 명시적인(Explicit) 프로퍼티라고 부른다: // Explicit 프로퍼티를 만든다: var obj = {x: 1}; @@ -33,7 +33,7 @@ Global이나 Function Scope에 정의한 Fuction이나 변수는 모두 Activati obj.x; // undefined obj.y; // undefined -`obj.x`와 `obj.y`는 `DontDelete` 속성이 아니라서 delete할 수 있다. 그러나 다음과 같은 코드도 잘 동작하기 때문에 헷갈린다: +`obj.x`와 `obj.y`는 `DontDelete` 속성이 아니라서 delete할 수 있다. 하지만 다음과 같은 코드도 잘 동작하기 때문에 헷갈린다: // IE를 빼고 잘 동작한다: var GLOBAL_OBJECT = this; @@ -42,7 +42,7 @@ Global이나 Function Scope에 정의한 Fuction이나 변수는 모두 Activati delete GLOBAL_OBJECT.a; // true GLOBAL_OBJECT.a; // undefined -[`this`](#function.this)가 Global 객체를 가리키는 것을 이용해서 명시적으로 프로퍼티 `a`를 선언하면 삭제할 수 있다. 이것은 꼼수다. +[`this`](#function.this)가 전역 객체를 가리키는 것을 이용해서 명시적으로 프로퍼티 `a`를 선언하면 삭제할 수 있다. 이것은 꼼수다. IE (적어도 6-8)는 버그가 있어서 안 된다. @@ -73,4 +73,4 @@ Host 객체를 delete하면 어떻게 될지 알 수 없다. 표준에는 어떻 ### 결론 -`delete` 연산자는 엉뚱하게 동작할 때가 잦다. 명시적으로 정의한 일반 객체의 프로퍼티만 delete하는 것이 안전하다. +`delete` 연산자는 엉뚱하게 동작할 때가 많다. 명시적으로 정의한 일반 객체의 프로퍼티만 delete하는 것이 안전하다. diff --git a/doc/ko/core/eval.md b/doc/ko/core/eval.md index 80706598..528b1883 100644 --- a/doc/ko/core/eval.md +++ b/doc/ko/core/eval.md @@ -1,6 +1,6 @@ ## 왜 `eval`을 사용하면 안 될까? -`eval` 함수는 스트링으로 된 JavaScript 코드를 Local Scope에서 실행한다. +`eval` 함수는 JavaScript 문자열을 지역 스코프에서 실행한다. var foo = 1; function test() { @@ -11,7 +11,7 @@ test(); // 3 foo; // 1 -`eval`을 `eval`이라는 이름으로 **직접** 직행할 때에만 Local Scope에서 실행된다. +`eval`함수는 `eval`이라는 이름으로 **직접** 실행할 때에만 지역 스코프에서 실행된다. 그리고 `eval`이라는 이름에 걸맞게 악명또한 높다. var foo = 1; function test() { @@ -23,7 +23,7 @@ test(); // 2 foo; // 3 -어쨌든 `eval`은 사용하지 말아야 한다. eval을 사용하는 경우의 99.9%는 사실 eval이 필요 없다. +어쨌든 `eval`은 사용하지 말아야 한다. eval을 사용하는 99.9%는 사실 eval 없이도 만들수있다. ### 가짜 `eval` @@ -31,7 +31,7 @@ ### 보안 이슈 -`eval`은 보안 문제도 있다. 단순히 **모든** 코드를 실행하기 때문에 신뢰하지 못하는 코드가 **절대로** 포함되지 않도록 주의해야 한다. +`eval`은 어떤 코드라도 **무조건** 실행하기 때문에 보안 문제도 있다. 따라서 신뢰하지 못하거나 모르는 코드가 포함되어 있을 경우 **절대로** 사용해서는 안된다. ### 결론 diff --git a/doc/ko/core/semicolon.md b/doc/ko/core/semicolon.md index f58e1782..7a384caa 100644 --- a/doc/ko/core/semicolon.md +++ b/doc/ko/core/semicolon.md @@ -1,6 +1,6 @@ -## 쎄미콜론을 자동으로 삽입해준다. +## 자동으로 삽입되는 쎄미콜론 -JavaScript는 C와 문법이 비슷하지만, 꼭 코드에 쎄미콜론을 사용하도록 강제하지 않는다. 그래서 생략할 수 있다. +JavaScript는 C와 문법이 비슷하지만, 꼭 코드에 쎄미콜론을 사용하도록 강제하지는 않는다. 그래서 생략할 수 있다. 사실 JavaScript는 쎄미콜론이 꼭 있어야 하고 없으면 이해하지 못한다. 그래서 JavaScript 파서는 쎄미콜론이 없으면 **자동으로** 쎄미콜론을 추가한다. @@ -81,18 +81,18 @@ JavaScript는 C와 문법이 비슷하지만, 꼭 코드에 쎄미콜론을 사 파서는 완전히 다른 코드로 만들어 버린다. 이것은 **오류**다. -### Parenthesis +### 괄호 해석 -쎄미콜론 없이 괄호가 붙어 있으면 파서는 쎄미콜론을 넣지 않는다. +파서는 괄호에는 쎄미콜론을 넣지 않는다. log('testing!') (options.list || []).forEach(function(i) {}) -파서는 다음과 같이 코드를 바꾼다. +그래서 다음과 같이 한줄로 코드를 바꾼다. log('testing!')(options.list || []).forEach(function(i) {}) -`log` 함수가 함수를 반환할 가능성은 거의 없다. 아마도 `undefined is not a function`이라는 `TypeError`가 발생할 거다. +이렇게 한줄로 바뀌면 `log` 함수가 함수를 반환할 가능성이 거의 없으므로 `undefined is not a function`이라는 `TypeError`가 발생한다. ### 결론 diff --git a/doc/ko/core/undefined.md b/doc/ko/core/undefined.md index 65748e1e..2bacc83b 100644 --- a/doc/ko/core/undefined.md +++ b/doc/ko/core/undefined.md @@ -1,6 +1,6 @@ ## `undefined`와 `null` -JavaScript는 `nothing`을 두 가지로 표현할 수 있고 그중 `undefined`가 더 유용하다. +JavaScript는 `nothing`을 표현할때 `null`과 `undefined` 두 가지로 표현할 수 있고 그중 `undefined`가 더 유용하다. ### `undefined`도 변수 @@ -13,9 +13,8 @@ JavaScript는 `nothing`을 두 가지로 표현할 수 있고 그중 `undefined` `undefined` 값이 반환될 때: - global 변수 `undefined`에 접근할 때. - - 아직 초기화하지 않은 변수 - - `return` 구문이 없는 함수는 `undefined`를 반환함. - - `return` 구문이 없는 함수는 `undefined`를 반환함. + - 선언은 했지만 아직 초기화하지 않은 변수에 접근할 때. + - `return` 구문이 없는 함수는 암묵적으로 `undefined`를 반환함. - `return` 구문으로 아무것도 반환하지 않을 때. - 없는 프로퍼티를 찾을 때. - 함수 인자가 생략될 때. @@ -30,7 +29,7 @@ global 변수 `undefined`는 `undefined`라는 객체를 가리키는 것뿐이 그래서 `undefined`와 비교하려면 먼저 `undefined`의 값을 찾아와야 한다. -`undefined` 변수가 바뀔 때를 대비해서 `undefined`라는 변수를 인자로 받는 [anonymous wrapper](#function.scopes)로 감싸고 아무런 인자를 넘기지 않는 꼼수를 사용한다. +`undefined` 변수가 바뀔 때를 대비해서 `undefined`라는 변수를 인자로 받는 [anonymous wrapper](#function.scopes)로 감싸고 인자를 넘기지 않는 꼼수를 사용한다. var undefined = 123; (function(something, foo, undefined) { diff --git a/doc/ko/function/arguments.md b/doc/ko/function/arguments.md index cda8407c..dcc5e8a2 100644 --- a/doc/ko/function/arguments.md +++ b/doc/ko/function/arguments.md @@ -1,12 +1,12 @@ ## `arguments` 객체 -JavaScript의 모든 Function Scope에는 `arguments`라는 특별한 변수가 있다. 이 변수는 Function에 넘겨진 모든 인자에 대한 정보가 담겨 있다. +JavaScript의 모든 함수 스코프에는 `arguments`라는 특별한 변수가 있다. 이 변수는 함수에 넘겨진 모든 인자에 대한 정보가 담겨 있다. > **Note:** `arguments` 변수는 Function 안에서 다시 정의할 수 없다. `var` 구문이나 파라미터에 `arguments`라는 이름으로 변수를 정의해도 변수가 재정의되지 않는다. -`length` 프로퍼티도 있는 데다가 여러모로 Array와 비슷하게 생겼지만 Array.prototype을 상속받지 않았다. `arguments` 객체는 `Array`가 아니다. +`arguments` 객체는 `Array`가 아니다. 물론 `length` 프로퍼티도 있고 여러모로 Array와 비슷하게 생겼지만 Array.prototype을 상속받지는 않았다. -그래서 `arguments`에는 `push`, `pop`, `slice` 같은 표준 메소드가 없다. `for`로 하는 Iteration은 원래 잘되지만 `Array`의 메소드를 이용하려면 `arguments`를 Array로 변환해야 한다. +그래서 `arguments`에는 `push`, `pop`, `slice` 같은 표준 메소드가 없다. 일반 `for`문을 이용해 순회는 할수 있지만, `Array`의 메소드를 이용하려면 `arguments`를 Array로 변환해야 한다. ### Array로 변환하기 @@ -18,7 +18,7 @@ JavaScript의 모든 Function Scope에는 `arguments`라는 특별한 변수가 ### arguemnts 객체 넘기기 -어떤 Function에서 다른 Function로 arguments 객체를 넘길 때에는 다음과 같이 하는 것이 좋다. +어떤 함수에서 다른 함수로 arguments 객체를 넘길 때에는 다음과 같은 방법을 권한다. (역주: foo 함수는 bar 함수 한번 랩핑한 함수다. ) function foo() { bar.apply(null, arguments); @@ -27,7 +27,7 @@ JavaScript의 모든 Function Scope에는 `arguments`라는 특별한 변수가 // 내곡동에 땅이라도 산다. } -`call`과 `apply`를 함께 사용하여 unbound wrapper도 쉽게 만들 수 있다. +또 다른 방법으로는 함수를 랩핑하지 않고, 풀어서 `call`과 `apply`를 함께 사용하는 방법이 있다. (역주: 프로토타입에 있는 method를 호출하기 전에 Foo 객체 안에 있는 method로 한번더 필터링하는 효과가 있다. ) function Foo() {} @@ -35,7 +35,7 @@ JavaScript의 모든 Function Scope에는 `arguments`라는 특별한 변수가 console.log(this, a, b, c); }; - // "method"의 unbound 버전 + // "method"를 풀어 쓴(unbound) 버전 // 이 Function의 인자: this, arg1, arg2...argN Foo.method = function() { @@ -43,9 +43,9 @@ JavaScript의 모든 Function Scope에는 `arguments`라는 특별한 변수가 Function.call.apply(Foo.prototype.method, arguments); }; -### 파라미터와 arguments 객체 인덱스 +### 일반 파라미터와 arguments 객체의 인덱스 -파라미터와 `arguments` 객체의 프로퍼티는 모두 *getter*와 *setter*를 가진다. +일반 파라미터와 `arguments` 객체의 프로퍼티는 모두 *getter*와 *setter*를 가진다. 그래서 파라미터나 `arguments` 객체의 프로퍼티의 값을 바꾸면 둘 다 바뀐다. @@ -62,7 +62,7 @@ JavaScript의 모든 Function Scope에는 `arguments`라는 특별한 변수가 } foo(1, 2, 3); -### 성능에 대한 진실과 오해. +### 성능에 대한 오해와 진실. `arguments` 객체는 항상 만들어 지지만 예외도 있다. `arguments`라는 이름의 변수를 Function 안에 정의하거나 그 이름으로 파라미터를 만들면 `arguemnts` 객체는 만들어지지 않는다. 그렇지만, 이럴때는 어차피 안쓰겠다는 의미니까 상관 없다. @@ -73,8 +73,8 @@ JavaScript의 모든 Function Scope에는 `arguments`라는 특별한 변수가 그러나 예외도 있다. 최신 JavaScript 엔진에서 `arguments.callee`를 사용하면 성능이 확 떨어진다. function foo() { - arguments.callee; // 이 Function를 가리킨다. - arguments.callee.caller; // 이 Function를 호출한 Function를 가리킨다. + arguments.callee; // 이 함수를 가리킨다. + arguments.callee.caller; // 이 함수를 호출한 부모함수를 가리킨다. } function bigLoop() { @@ -83,9 +83,10 @@ JavaScript의 모든 Function Scope에는 `arguments`라는 특별한 변수가 } } -이 코드에서 Callee와 Caller를 알아야 하기 때문에 `foo`는 더는 [인라인][1]하지 않는다. 이렇게 쓰면 인라인이 주는 성능상 장점을 포기해야 하는데다가 Function이 호출되는 상황(calling context)에 의존하게 돼 버려서 Encapsulation도 해친다. +위 코드에서 'foo' 함수는 자기 자신과 자신을 호출한 함수를 알아야 하기 때문에 더이상 [인라인][1]되지 않는다. 이렇게 쓰면 인라인이 주는 성능상 장점을 포기해야 하는데다가 이 함수가 호출되는 상황(calling context)에 의존하게 돼 버려서 캡슐화(Encapsulation)도 해친다. +(역주: 보통 코드가 컴파일 될때 코드를 인라인 시키면서 최적화 하는데, 위와 같이 arguments.callee나 caller를 사용하게 되면 런타임시에 해당 함수가 결정되므로 인라인 최적화를 할수가 없다.) -`arguments.callee`와 그 프로퍼티들은 **절대** 사용하지 말아야 한다. +`arguments.callee`와 arguments.callee의 프로퍼티들은 **절대** 사용하지 말자!. > **ES5 Note:** strict 모드에서 `arguments.callee`는 deprecated됐기 때문에 사용하면 `TypeError`가 난다. diff --git a/doc/ko/function/closures.md b/doc/ko/function/closures.md index 49628231..4d7463a6 100644 --- a/doc/ko/function/closures.md +++ b/doc/ko/function/closures.md @@ -1,8 +1,8 @@ -## Closure와 Reference +## 클로져(Closure)와 참조(Reference) -*Closure*는 JavaScript의 특장점 중 하나다. Closure에서는 그 Closure를 만든 외부 Scope에 접근할 있다. JavaScript에서 Scope을 만들려면 [Function Scope](#function.scopes)을 사용하는 방법밖에 없기 때문에 Closure는 함수로 만든다. +*클로져*는 JavaScript의 특장점 중 하나다. 클로저를 만들면 클로저 스코프 안에서 클로저를 만든 외부 스코프(Scope)에 항상 접근할 있다. JavaScript에서 스코프는 [함수 스코프](#function.scopes)밖에 없기 때문에 기본적으로 모든 함수는 클로저가 될수있다. -### private 변수 +### private 변수 만들기 function Counter(start) { var count = start; @@ -21,22 +21,22 @@ foo.increment(); foo.get(); // 5 -`Counter`는 `increment` Closure와 `get` Closure 두 개를 반환한다. 이 두 Closure는 `Counter` Scope에 대한 **reference**를 유지하고 있기 때문에 그 Scope에 있는 count 변수에 계속 접근할 수 있다. +여기서 `Counter`는 `increment` 클로저와 `get` 클로저 두 개를 반환한다. 이 두 클로저는 `Counter` 함수 스코프에 대한 **참조**를 유지하고 있기 때문에 이 함수 스코프에 있는 count 변수에 계속 접근할 수 있다. -### Private 변수가 진짜 맞나? +### Private 변수의 동작 원리 -JavaScript에서 Scope을 어딘가에 할당하거나 저장해두는 것이 불가능하다. 그래서 Scope 밖에서는 count 변수에 직접 접근할 수 없다. 꼭 Scope 안에서 정의한 두 closure를 통해서만 접근할 수 있다. +JavaScript에서는 스코프(Scope)를 어딘가에 할당해두거나 참조할수 없기 때문에 스코프 밖에서는 count 변수에 직접 접근할 수 없다. 접근할수 있는 유일한 방법은 스코프 안에 정의한 두 클로저를 이용하는 방법밖에 없다. var foo = new Counter(4); foo.hack = function() { count = 1337; }; -이 코드의 count는 `Counter` Scope의 변수 count가 아니다. `foo.hack`은 그 Scope 안에 정의되지 않았기 때문에 이 `count`는 *Global* 변수를 사용하는 것이다. +위 코드에서 `foo.hack` 함수는 Counter 함수 안에서 정의되지 않았기 때문에 이 함수가 실행되더라도 `Counter` 함수 스코프 안에 있는 count 값은 변하지 않는다. 대신 foo.hack 함수의 `count`는 *Global* 스코프에 생성되거나 이미 만들어진 변수를 덮어쓴다. -### Loop에서 Closure 사용하기 +### 반복문에서 클로저 사용하기 -많은 사람은 Loop에서 Closure를 사용할 때 자주 index 변수를 잘못 사용한다. +사람들이 반복문에서 클로저를 사용할 때 자주 실수를 하는 부분이 있는데 바로 인덱스 변수를 복사할때 발생한다. for(var i = 0; i < 10; i++) { setTimeout(function() { @@ -46,13 +46,13 @@ JavaScript에서 Scope을 어딘가에 할당하거나 저장해두는 것이 이 코드는 `0`부터 `9`까지의 수를 출력하지 않고 `10`만 열 번 출력한다. -이 *Anonymous* Function은 변수 `i`에 대한 참조를 저장했다가 `console.log`가 호출되는 시점에 `i`의 값을 사용한다. `console.log`가 호출되는 시점은 `for loop`이 이미 끝난 상태라서 `i` 값은 10이다. +타이머에 설정된 *익명* 함수는 변수 `i`에 대한 참조를 들고 있다가 `console.log`가 호출되는 시점에 `i`의 값을 사용한다. `console.log`가 호출되는 시점에서 `for loop`는 이미 끝난 상태기 때문에 `i` 값은 10이 된다. 기대한 결과를 얻으려면 `i` 값을 복사해 두어야 한다. -### 이 Reference 문제 해결하기 +### 앞의 참조 문제 해결하기 -[Anonymous Wrapper](#function.scopes)로 index 값을 복사하는 것이 좋다. +반복문의 index 값을 복사하는 가장 좋은 방법은 익명함수로 랩핑[Anonymous Wrapper](#function.scopes)하는 방법이다. for(var i = 0; i < 10; i++) { (function(e) { @@ -62,11 +62,11 @@ JavaScript에서 Scope을 어딘가에 할당하거나 저장해두는 것이 })(i); } -이 Anonymous Function의 인자로 `i`를 넘기면 이 함수의 파라미터 e에 i의 **값**이 복사된다. +이 익명 함수에 `i`를 인자로 넘기면 이 함수의 파라미터 e에 i의 **값**이 복사되어 넘어갈 것이다. -이 `setTimeout`는 anonymous function 파라미터인 `e`에 대한 참조를 갖게 되고 `e`는 loop의 상태에 따라 변하지 않는다. +그리고 `setTimeout`는 익명 함수의 파라미터인 `e`에 대한 참조를 갖게 되고 `e`값은 복사되어 넘어왔으므로 loop의 상태에 따라 변하지 않는다. -함수를 반환하는 Anonymous Wrapper를 이용하는 방법도 있다. 다음 코드는 위 코드와 같다. +또다른 방법으로 랩핑한 익명 함수에서 출력 함수를 반환하는 방법도 있다. 아래 코드는 위 코드와 동일하게 동작한다. for(var i = 0; i < 10; i++) { setTimeout((function(e) { diff --git a/doc/ko/function/constructors.md b/doc/ko/function/constructors.md index cb71cdeb..1aa6de4a 100644 --- a/doc/ko/function/constructors.md +++ b/doc/ko/function/constructors.md @@ -1,10 +1,10 @@ ## 생성자 -JavaScript에서 생성자는 다른 언어들과 다르게 `new` 키워드로 호출되는 함수가 생성자다. +JavaScript의 생성자는 다른 언어들과 다르게 `new` 키워드로 호출되는 함수가 생성자가 된다. -어쨌든 생성자로 호출된 함수의 this는 막 만들어진 객체를 참조한다. **막 만든** 객체의 [prototype](#object.prototype)에는 생성자의 prototype이 할당된다. +생성자로 호출된 함수의 this 객체는 새로 생성된 객체를 가리키고, **새로 만든** 객체의 [prototype](#object.prototype)에는 생성자의 prototype이 할당된다. -생성자에 `return` 구문이 없으면 this가 가리키는 객체를 반환한다. +그리고 생성자에 명시적인 `return` 구문이 없으면 this가 가리키는 객체를 반환한다. function Foo() { this.bla = 1; @@ -16,9 +16,9 @@ JavaScript에서 생성자는 다른 언어들과 다르게 `new` 키워드로 var test = new Foo(); -`new` 키워드가 실행되는 시점에 `Foo`를 생성자로 호출하고 `Foo.prototype`을 새 객체의 prototype에 할당한다. +위 코드는 `new` 키워드가 실행되는 시점에 `Foo`를 생성자로 호출하고 `Foo.prototype`을 새 객체의 prototype에 할당한다. -생성자에 `return` 구문이 있고 literal이 아니라 `객체`를 반환하면 그 객체가 반환된다. +아래 코드와 같이 생성자에 명시적인 `return` 문이 있는 경우에는 반환하는 값이 객체인 경우에만 그 값을 반환한다. function Bar() { return 2; @@ -37,11 +37,12 @@ JavaScript에서 생성자는 다른 언어들과 다르게 `new` 키워드로 new 키워드가 없으면 그 함수는 객체를 반환하지 않는다. function Foo() { - this.bla = 1; // gets set on the global object + this.bla = 1; // 전역객체에 할당된다. } Foo(); // undefined -이 함수는 그때그때 다르게 동작하지만 보통 [`this`](#function.this)의 규칙에 따라 `this`의 값으로 *Global 객체*가 사용된다.:w +위 예제는 그때그때 다르게 동작한다. 그리고 [`this`](#function.this) 객체의 동작 원리에 따라서 Foo 함수안의 `this`의 값은 *Global 객체*를 가리키게된다. +(역주: 결국 new 키워드를 빼고, 코드를 작성할 경우 원치 않은 this 참조 오류가 발생할 수 있다.) ### 팩토리 @@ -62,11 +63,12 @@ new 키워드가 없으면 그 함수는 객체를 반환하지 않는다. new Bar(); Bar(); -new 키워드가 있으나 없으니 `Bar` 생성자는 똑같이 동작한다. [Closure](#function.closures)가 할당된 method 프로퍼티가 있는 객체를 만들어 반환한다. +new 키워드의 유무과 관계없이 `Bar` 생성자의 동작은 동일한다. 즉 [클로저](#function.closures)가 할당된 method 프로퍼티가 있는 새로운 객체를 만들어 반환한다. -`new Bar()`는 반환된 객체의 prototype 프로퍼티에 아무런 영향을 주지 않는다. 객체를 반환하지 않는 생성자로 만들어지는 경우에만 객체의 prototype이 생성자의 것으로 할당된다. +`new Bar()`로 호출되는 생성자는 반환되는 객체의 prototype 프로퍼티에 아무런 영향을 주지 않는다. 객체를 반환하지 않는 생성자로 만들어지는 경우에만 객체의 prototype이 생성자의 것으로 할당된다. -그러니까 이 예제에서 `new` 키워드의 유무는 아무 차이가 없다. +그러니까 이 예제에서 `new` 키워드의 유무는 아무런 차이가 없다. +(역주: 생성자에 객체를 만들어 명시적으로 반환하면 new 키워드에 관계없이 잘 동작하는 생성자를 만들수있다. 즉, new 키워드가 빠졌을때 발생하는 this 참조 오류를 방어해준다.) ### 팩토리로 객체 만들기 @@ -89,7 +91,7 @@ new 키워드가 있으나 없으니 `Bar` 생성자는 똑같이 동작한다. return obj; } -`new` 키워드가 없어도 괜찮고 [private 변수](#function.closures)를 사용하기도 쉽다. 그렇지만, 단점도 있다. +`new` 키워드가 없어도 잘 동작하고 [private 변수](#function.closures)를 사용하기도 쉽다. 그렇지만, 단점도 있다. 1. prototype으로 메소드를 공유하지 않으므로 메모리를 좀 더 사용한다. 2. 팩토리를 상속하려면 모든 메소드를 복사하거나 객체의 prototype에 객체를 할당해 주어야 한다. diff --git a/doc/ko/function/general.md b/doc/ko/function/general.md index 402a34ec..091fd105 100644 --- a/doc/ko/function/general.md +++ b/doc/ko/function/general.md @@ -1,37 +1,37 @@ -## Function Declarations과 Function Expressions +## 함수 선언과 함수 표현식 -JavaScript의 Function은 First Class Object라서 일반 객체처럼 취급될 수 있다. 그래서 익명 함수를 비동기 함수의 callback 같은 거로 넘길 수 있다. +JavaScript에서 함수는 First Class Object다. 즉, 함수 자체가 또 다른 함수의 인자될 수 있다는 말이다. 그래서 익명 함수를 비동기 함수의 콜백으로 넘기는 것도 이런 특징을 이용한 일반적인 사용법이다. -### `function` Declaration +### `함수` 선언 function foo() {} -코드를 실행하기 전에 이 함수는 [Hoist](#function.scopes)되기 때문에 해당 Scope 어디에서나 이 함수를 호출할 수 있다. 심지어 함수를 정의하기 전에 호출해도 된다. +위와 같이 선언한 함수는 프로그램이 실행하기 전에 먼저 [호이스트(Hoist)](#function.scopes) (스코프가 생성)되기 때문에 정의된 스코프(Scope) 안에서는 어디서든 이 함수를 사용할 수 있다. 심지어 함수를 정의하기 전에 호출해도 된다. - foo(); // 이 코드가 실행되기 전에 foo가 만들어져서 잘 호출된다. + foo(); // 이 코드가 실행되기 전에 foo가 만들어지므로 잘 동작한다. function foo() {} -### `function` Expression +### `함수` 표현식 var foo = function() {}; -`foo` 변수에 *익명* 함수를 할당하는 예를 보자. +위 예제는 `foo` 변수에 *익명* 함수를 할당한다. foo; // 'undefined' foo(); // TypeError가 난다. var foo = function() {}; -JavaScript가 Hoist하는 것은 `var`로 선언하는 부분뿐이기 때문에 코드가 실행하기 전에 `foo` 변수는 정의된다. +'var'문을 이용해 선언하는 경우, 코드가 실행되기 전에 'foo' 라는 이름의 변수를 스코프의 맨 위로 올리게 된다.(호이스트 된다) 이때 foo 값은 undefiend로 정의된다. -그러나 할당은 런타임에만 가능한 일이라 할당하는 코드가 실행될 때까지 `foo`변수는 기본 값인 [undefined](#core.undefined)다. +하지만 변수에 값을 할당하는 일은 런타임 상황에서 이루어지게 되므로 실제 코드가 실행되는 순간의 `foo`변수는 기본 값인 [undefined](#core.undefined)이 된다. -### Named Function Expression +### 이름있는 함수 표현식 -Named Function을 할당하는 경우는 조금 특이하다. +이름있는 함수를 할당할때도 특이한 경우가 있다. var foo = function bar() { - bar(); // 된다. + bar(); // 이 경우는 동작 하지만, } - bar(); // ReferenceError + bar(); // 이 경우는 참조에러를 발생시킨다. -함수 밖에서는 `bar`를 사용할 수 없지만, 함수 안에서는 사용할 수 있다. JavaScript가 [이름을 찾는 방법](#function.scopes)이 있는데 function Scope에서는 항상 그 함수의 이름을 사용할 수 있다. +foo 함수 스코프 밖에서는 foo 변수 외에는 다른 값이 없기 때문에 `bar`는 함수 밖에서 사용할 수 없지만 함수 안에서는 사용할 수 있다. [이와 같은 방법](#function.scopes)으로 자바스크립트에서 어떤 함수의 이름은 항상 그 함수의 지역 스코프 안에서 사용할수있다. \ No newline at end of file diff --git a/doc/ko/function/scopes.md b/doc/ko/function/scopes.md index ad40e0f3..7792ee65 100644 --- a/doc/ko/function/scopes.md +++ b/doc/ko/function/scopes.md @@ -1,6 +1,6 @@ -## Scope과 Namespace + ## 스코프와 네임스페이스 -JavaScript는 '{}' Block이 배배 꼬여 있어도 문법적으로는 잘 처리하지만, Block Scope은 지원하지 않는다. 그래서 JavaScript에서는 항상 *Function Scope*을 사용한다. +JavaScript는 '{}' Block이 배배 꼬여 있어도 문법적으로는 잘 처리하지만, Block Scope은 지원하지 않는다. 그래서 JavaScript에서는 항상 *함수 스코프*를 사용한다. function test() { // Scope for(var i = 0; i < 10; i++) { // Scope이 아님 @@ -11,11 +11,11 @@ JavaScript는 '{}' Block이 배배 꼬여 있어도 문법적으로는 잘 처 > **Note:** 할당할 때, 반환할 때, Function 인자에서 사용되는 것을 제외하면 `{...}`는 모두 객체 리터럴이 아니라 Block 구문으로 해석된다. 그래서 [세미콜론을 자동으로 넣어주면](#core.semicolon) 에러가 생길 수 있다. -그리고 JavaScript에는 Namepspace 개념이 없어서 *항상 공유하는* namepace가 딱 하나다. +그리고 JavaScript에는 Namepspace 개념이 없기 때문에 모든 값이 하나의 *전역* 스코프에 정의된다. -변수를 사용할 때마다 JavaScript는 아는 Scope을 상위 방향으로 찾는다. Global Scope에까지 해당 변수를 찾지 못하면 `ReferenceError`가 난다. +변수를 참조 할 때마다 JavaScript는 해당 변수를 찾을 때까지 상위 방향으로 스코프를 탐색한다. 변수 탐색하다가 전역 스코프에서도 찾지 못하면 `ReferenceError`를 발생시킨다. -### Global 변수 지옥. +### 전역 변수 문제. // script A foo = '42'; @@ -23,7 +23,7 @@ JavaScript는 '{}' Block이 배배 꼬여 있어도 문법적으로는 잘 처 // script B var foo = '42' -이 두 스크립트는 전혀 다르다. Script A는 *Global* Scope에 `foo`라는 변수를 정의하는 것이고 Script B는 *현* Scope에 변수 `foo`를 정의하는 것이다. +이 두 스크립트는 전혀 다르다. Script A는 *전역* 스코프에 `foo`라는 변수를 정의하는 것이고 Script B는 *현* 스코프에 변수 `foo`를 정의하는 것이다. 다시 말하지만, 이 둘은 전혀 다르고 `var`가 없을 때 특별한 의미가 있다. @@ -36,7 +36,7 @@ JavaScript는 '{}' Block이 배배 꼬여 있어도 문법적으로는 잘 처 test(); foo; // 21 -Function에서 `var` 구문을 빼버리면 Global Scope의 `foo`의 값을 바꿔버린다. '뭐 이게 뭐가 문제야'라고 생각될 수 있지만 수천 줄인 JavaScript 코드에서 `var`를 빼먹어서 생긴 버그를 해결하는 것은 정말 어렵다. +test 함수 안에 있는 'foo' 변수에 `var` 구문을 빼버리면 Global Scope의 `foo`의 값을 바꿔버린다. '뭐 이게 뭐가 문제야'라고 생각될 수 있지만 수천 줄인 JavaScript 코드에서 `var`를 빼먹어서 생긴 버그를 해결하는 것은 정말 어렵다. // Global Scope var items = [/* some list */]; @@ -51,19 +51,19 @@ Function에서 `var` 구문을 빼버리면 Global Scope의 `foo`의 값을 바 } } -subLoop이 Global 변수 `i`의 값을 변경해버리기 때문에 외부 Loop은 `subLoop`을 한번 호출하고 나면 종료된다. 두 번째 `for` Loop에 `var`를 사용하여 `i`를 정의하면 이 문제는 생기지 않는다. 외부 Scope의 변수를 사용하는 것이 아니라면 `var`를 꼭 넣어야 한다. +subLoop 함수는 전역 변수 `i`의 값을 변경해버리기 때문에 외부에 있는 for문은 `subLoop`을 한번 호출하고 나면 종료된다. 두 번째 `for`문에 `var`를 사용하여 `i`를 정의하면 이 문제는 생기지 않는다. 즉, 의도적으로 외부 스코프의 변수를 사용하는 것이 아니라면 `var`를 꼭 넣어야 한다. -### Local 변수 +### 지역 변수 -JavaScript에서 Local 변수는 [Function 파라미터](#function.general)와 `var`로 정의한 변수뿐이다. +JavaScript에서 지역 변수는 [함수의 파라미터](#function.general)와 `var`로 정의한 변수밖에 없다. - // Global Scope + // 전역 공간 var foo = 1; var bar = 2; var i = 2; function test(i) { - // test Function의 local Scope + // test 함수의 지역 공간 i = 5; var foo = 3; @@ -71,11 +71,11 @@ JavaScript에서 Local 변수는 [Function 파라미터](#function.general)와 ` } test(10); -`foo`, `i`는 `test` Function Scope에 있는 Local 변수라서 Global의 `foo`, `i` 값은 바뀌지 않는다. 하지만 `bar`는 Global 변수이기 때문에 Global의 `bar` 값이 변경된다. +`foo` 변수와 `i` 변수는 `test`함수 스코프에 있는 지역 변수라서 전역 공간에 있는 `foo`, `i` 값은 바뀌지 않는다. 하지만 `bar`는 전역 변수이기 때문에 전역 공간에 있는 `bar`의 값이 변경된다. -### Hoisting +### 호이스팅(Hoisting) -JavaScript는 선언문을 모두 **Hoist**한다. Hoist는 `var` 구문이나 `function`을 선언문을 해당 Scope의 가장 처음으로 옮기는 것을 말한다. +JavaScript는 선언문을 모두 **호이스트(Hoist)**한다. 호이스트란 `var` 구문이나 `function` 선언문을 해당 스코프의 맨 위로 옮기는 것을 말한다. bar(); var bar = function() {}; @@ -94,7 +94,7 @@ JavaScript는 선언문을 모두 **Hoist**한다. Hoist는 `var` 구문이나 ` } } -코드를 본격적으로 실행하기 전에 JavaScript는 `var` 구문과 `function` 선언문을 해당 Scope의 상위로 옮긴다. +코드를 본격적으로 실행하기 전에 JavaScript는 `var` 구문과 `function` 선언문을 해당 스코프의 맨위로 옮긴다. // var 구문이 여기로 옮겨짐. var bar, someValue; // default to 'undefined' @@ -114,23 +114,23 @@ JavaScript는 선언문을 모두 **Hoist**한다. Hoist는 `var` 구문이나 ` } bar(); // bar()가 아직 'undefined'이기 때문에 TypeError가 남 - someValue = 42; // Hoisting은 할당문까지 옮기지 않는다. + someValue = 42; // Hoisting은 할당문은 옮기지 않는다. bar = function() {}; test(); -Block Scope이 없으므로 Loop이나 if의 Block 안에 있는 `var` 구문들까지도 모두 Function Scope의 앞쪽으로 옮겨진다. 그래서 `if` Block의 결과는 좀 이상해진다. +블록 스코프(Block Scope)는 없으므로 for문과 if문 안에 있는 `var` 구문들까지도 모두 함수 스코프 앞쪽으로 옮겨진다. 그래서 `if` Block의 결과는 좀 이상해진다. -원래 코드에서 `if` Block은 *Global 변수* `goo`를 바꾸는 것처럼 보였지만 Hoisting 후에는 *local 변수*를 바꾼다. +원래 코드에서 `if` Block은 *전역 변수* `goo`를 바꾸는 것처럼 보였지만 호이스팅(Hoisting) 후에는 *지역 변수*를 바꾼다. -*Hoisting*을 모르면 다음과 같은 코드는 `ReferenceError`를 낼 것으로 생각할 것이다. +*호이스팅*을 모르면 다음과 같은 코드는 `ReferenceError`를 낼 것으로 생각할 것이다. // SomeImportantThing이 초기화됐는지 검사한다. if (!SomeImportantThing) { var SomeImportantThing = {}; } -`var` 구문은 *Global Scope* 상단으로 옮겨지기 때문에 이 코드는 잘 동작한다. +`var` 구문은 *전역 스코프*의 맨위로 옮겨지기 때문에 이 코드는 잘 동작한다. var SomeImportantThing; @@ -143,11 +143,11 @@ Block Scope이 없으므로 Loop이나 if의 Block 안에 있는 `var` 구문들 ### 이름 찾는 순서 -JavaScript의 모든 Scope은 *현 객체*를 가리키는 [`this`](#function.this)를 가지고 있다. *Global Scope*에도 this가 있다. +JavaScript의 모든 Scope은 *현 객체*를 가리키는 [`this`](#function.this)를 가지고 있다. *전역 스코프*에도 this가 있다. -Function Scope에는 [`arguments`](#function.arguments)라는 변수가 하나 더 있다. 이 변수는 Function에 넘겨진 인자들이 담겨 있다. +함수 스코프에는 [`arguments`](#function.arguments)라는 변수가 하나 더 있다. 이 변수는 함수에 인자로 넘겨진 값들이 담겨 있다. -예를 들어 Function Scope에서 `foo`라는 변수에 접근할 때 JavaScript는 다음과 같은 순서로 찾는다. +예를 들어 함수 스코프에서 `foo`라는 변수에 접근할 때 JavaScript는 다음과 같은 순서로 찾는다. 1. 해당 Scope에서 `var foo` 구문으로 선언된 것을 찾는다. 2. Function 파라미터에서 `foo`라는 것을 찾는다. @@ -156,29 +156,29 @@ Function Scope에는 [`arguments`](#function.arguments)라는 변수가 하나 > **Note:** `arguments`라는 파라미터가 있으면 Function의 기본 객체인 `arguments`가 생성되지 않는다. -### Namespace +### 네임스페이스 -JavaScript에서는 Global Namepspace 하나밖에 없어서 변수 이름이 중복되기 쉽다. 하지만 *Anonymous Wrappers*가 있어서 쉽게 피해갈 수 있다. +JavaScript에서는 전역 공간(Namepspace) 하나밖에 없어서 변수 이름이 중복되기 쉽다. 하지만 *이름없는 랩퍼(Anonymous Wrappers)*를 통해 쉽게 피해갈 수 있다. (function() { - // 일종의 Namepspace라고 할 수 있다. + // 일종의 네임스페이스라고 할 수 있다. window.foo = function() { - // 이 Closure는 Global Scope에 노출된다. + // 이 클로저는 전역 스코프에 노출된다. }; - })(); // Function를 정의하자마자 실행한다. + })(); // 함수를 정의하자마자 실행한다. -Unnamed Function은 [expressions](#function.general)이기 때문에 호출되려면 먼저 Evaluate돼야 한다. +이름없는 함수는 [표현식(expressions)](#function.general)이기 때문에 호출되려면 먼저 평가(Evaluate)돼야 한다. - ( // 소괄호 안에 있는 것을 먼저 Evaluate한다. + ( // 소괄호 안에 있는 것을 먼저 평가한다. function() {} - ) // 그리고 Function 객체를 반환한다. - () // Evaluation된 결과를 호출한다. + ) // 그리고 함수 객체를 반환한다. + () // 평가된 결과를 호출한다. -Function을 Evaluate하고 바로 호출하는 방법이 몇가지 더 있다. 문법은 다르지만 똑같다. +함수를 평가하고 바로 호출하는 방법이 몇가지 더 있다. 문법은 다르지만 똑같다. - // Fucntion을 Evaluate하자마자 호출하는 방법들... + // 함수를 평가하자마자 호출하는 방법들... !function(){}(); +function(){}(); (function(){}()); @@ -186,6 +186,6 @@ Function을 Evaluate하고 바로 호출하는 방법이 몇가지 더 있다. ### 결론 -코드를 캡슐화할 때는 늘 *Anonymous Wrapper*로 Namepspace를 만들어 사용해야 한다. 이 Wrapper는 이름이 중복되는 것을 막아 주고 더 쉽게 모듈화할 수 있도록 해준다. +코드를 캡슐화할 때는 항상 *이름없는 랩퍼(Anonymous Wrapper)*로 네임스페이스를 만들어 사용할 것을 추천한다. 이 래퍼(Wrapper)는 이름이 중복되는 것을 막아 주고 더 쉽게 모듈화할 수 있도록 해준다. -그리고 Global 변수를 사용하는 것은 악질적인 습관이다. 이유야 어쨌든 에러 나기 쉽고 관리하기도 어렵다. +그리고 전역 변수를 사용하는 것은 좋지 못한 습관이다. 이유야 어쨌든 에러 나기 쉽고 관리하기도 어렵다. diff --git a/doc/ko/function/this.md b/doc/ko/function/this.md index 116b1250..b6d57aa6 100644 --- a/doc/ko/function/this.md +++ b/doc/ko/function/this.md @@ -1,4 +1,4 @@ -## `this` +## `this`의 동작 원리 다른 프로그래밍 언어에서 `this`가 가리키는 것과 JavaScript에서 `this`가 가리키는 것과는 좀 다르다. `this`가 가리킬 수 있는 객체는 정확히 5종류나 된다. @@ -42,7 +42,7 @@ Global Scope에서도 this가 사용될 수 있고 이때에는 *Global* 객체 > **Note:** 객체 리터럴에서 this는 그 객체를 가리키지 않는다. 예를 들어 `var obj= {me:this}`에서 `me`가 `obj`를 가리키는 것이 아니라 위에 설명한 5가지 객체 중 하나를 가리킨다. -### 대표적인 결점 +### 대표적인 함정 `this`가 Global 객체를 가리키는 것도 잘못 설계된 부분 중 하나다. 괜찮아 보이지만 실제로는 전혀 사용하지 않는다. @@ -69,14 +69,14 @@ Global Scope에서도 this가 사용될 수 있고 이때에는 *Global* 객체 ### Method할당 하기 -메소드를 변수에 *할당*해 버리기 때문에 Function Aliasing은 JavaScript에서 안된다. +JavaScript의 또다른 함정은 바로 함수의 별칭을 만들수 없다는 점이다. 별칭을 만들기 위해 메소드를 변수에 넣으면 자바스크립트는 별칭을 만들지 않고 바로 *할당*해 버린다. var test = someObject.methodTest; test(); -`test`는 다른 함수를 호출하는 것과 다름없어서 `this`가 someObject를 가리키지 않는다. +첫번째 코드로 인해 이제 `test`는 다른 함수와 똑같이 동작한다. 그래서 test 함수 내부의 `this`도 더이상 someObject를 가리키지 않는다. (역주: test가 methodTest의 별칭이라면 methodTest 함수 내부의 this도 someObject를 똑같이 가리켜야 하지만 test의 this는 더이상 someObject가 아니다.) -처음에는 `this`를 늦게 바인딩하는 것이 나쁜 아이디어라고 생각할 수도 있지만, 이 점이 실제로 [prototypal inheritance](#object.prototype)를 가능케 해준다. +이렇게 `this`를 늦게 바인딩해서 나타나는 약점때문에 늦은 바인딩이 나쁜 거라고 생각할수도 있지만, 사실 이런 특징으로 인해 [프로토타입 상속(prototypal inheritance)](#object.prototype)도 가능해진다. function Foo() {} Foo.prototype.method = function() {}; diff --git a/doc/ko/intro/index.md b/doc/ko/intro/index.md index 16d2ed66..87b72473 100644 --- a/doc/ko/intro/index.md +++ b/doc/ko/intro/index.md @@ -14,9 +14,10 @@ JavaScript Garden은 단순히 JavaScript 언어 자체를 설명하려 만들 - [Andreas Blixt][6] (언어 교정) ## 번역 - - [박창우][] + - [박창우][손병대][] [박창우]: https://github.com/pismute +[손병대]: https://github.com/miconblog ## 호스팅 diff --git a/doc/ko/object/forinloop.md b/doc/ko/object/forinloop.md index 5a619c47..fd05cedb 100644 --- a/doc/ko/object/forinloop.md +++ b/doc/ko/object/forinloop.md @@ -1,10 +1,10 @@ ## `for in` Loop -`in` 연산자와 마찬가지로 `for in`도 객체의 프로퍼티뿐만 아니라 프로토타입 체인까지 Traverse 한다. +객체의 프로퍼티를 탐색할때 `in` 연산자와 마찬가지로 `for in` 문도 프로토타입 체인까지 탐색한다. -> **Note:** `for in`은 Array의 `length`처럼 `enumerable` 속성이 `false`인 프로퍼티는 Iterate 하지 않는다. +> **Note:** `for in`문은 배열의 `length`프로퍼티처럼 `enumerable` 속성이 `false`인 프로퍼티는 탐색하지 않는다. - // 원래는 Object.prototype을 바꾸면 안 된다. + // Object.prototype을 오염시킨다. Object.prototype.bar = 1; var foo = {moo: 2}; @@ -12,9 +12,9 @@ console.log(i); // bar와 moo 둘 다 출력한다. } -선택적으로 Iterate 하려면 `for in`은 바꿀 수 없으니까 Loop 바디에서 하는 수밖에 없다. `Object.prototype`의 [`hasOwnProperty`](#object.hasownproperty)메소드를 사용하면 객체의 프로퍼티만 골라낼 수 있다. +`for in`문에 정의된 기본 동작을 바꿀순 없기 때문에 루프 안에서 불필요한 프로퍼티를 필터링 해야한다. 그래서 `Object.prototype`의 [`hasOwnProperty`](#object.hasownproperty)메소드를 이용해 본래 객체의 프로퍼티만 골라낸다. -> **Note:** `for in`은 프로토타입 체인을 모두 Traverse 한다. 그래서 상속할 때마다 더 느려진다. +> **Note:** `for in`은 프로토타입 체인을 모두 탐색하기 때문에 상속할 때마다 더 느려진다. ### `hasOwnProperty`로 필터링 하기 @@ -25,12 +25,12 @@ } } -실무에 사용할 작정이라면 이렇게 써야 옳다. `hasOwnProperty` 때문에 **오직** `moo`만 출력된다. `hasOwnProperty`가 없으면 `Object.prototype`같은 네이티브 프로토타입이 확장될 때 에러 날 수 있다. +위와 같이 사용해야 올바른 사용법이다. `hasOwnProperty` 때문에 **오직** `moo`만 출력된다. `hasOwnProperty`가 없으면 이 코드는 `Object.prototype`으로 네이티브 객체가 확장될 때 에러가 발생할 수 있다. -네이티브 프로토타입을 확장하는 [Proptotype 라이브러리][1]을 사용하면 `hasOwnProperty`가 없는 `for in` Loop은 꼭 문제를 일으킨다. +따라서 [Proptotype 라이브러리][1]처럼 네이티브 객체를 프로토타입으로 확장한 프레임워크를 사용할 경우 `for in` 문에 `hasOwnProperty`를 사용하지 않을 경우 문제가 발생할 수 있다. ### 결론 -`hasOwnProperty`는 항상 사용해야 한다. 실제로 코드가 동작할 환경에서 네이티브 프로토타입의 확장 여부에 대해 어떠한 가정도 하지 말아야 한다. +`hasOwnProperty`를 항상 사용하길 권한다. 실제 코드가 동작하는 환경에서는 절대로 네이티브 객체가 프로토타입으로 확장됐다 혹은 확장되지 않았다를 가정하면 안된다. [1]: http://www.prototypejs.org/ diff --git a/doc/ko/object/general.md b/doc/ko/object/general.md index 51ae6f60..0e7ae1c6 100644 --- a/doc/ko/object/general.md +++ b/doc/ko/object/general.md @@ -1,6 +1,6 @@ ## 객체와 프로퍼티 -JavaScript에서 [`null`](#core.undefined)과 [`undefined`](#core.undefined)를 제외한 모든 것은 객체다. +JavaScript에서 [`null`](#core.undefined)과 [`undefined`](#core.undefined)를 제외한 모든 것들은 객체처럼 동작한다. false.toString() // 'false' [1, 2, 3].toString(); // '1,2,3' @@ -9,11 +9,11 @@ JavaScript에서 [`null`](#core.undefined)과 [`undefined`](#core.undefined)를 Foo.bar = 1; Foo.bar; // 1 -숫자 리터럴은 객체가 아니라는 오해가 있는데 단지 JavaScript 파서의 문제일 뿐이다. JavaScript 파서는 숫자에 *Dot Notation*이 들어가면 오류라고 생각한다. +숫자 리터럴은 객체처럼 사용되지 못할꺼라는 오해가 있는데 이것은 단지 JavaScript 파서의 문제일 뿐이다. JavaScript 파서는 숫자에 *Dot Notation*이 들어가면 오류라고 생각한다. 2.toString(); // SyntaxError가 난다. -하지만, 숫자를 객체로 인식하는 꼼수가 몇 가지 있다. +하지만, 숫자를 객체처럼 사용할수 있는 꼼수가 몇 가지 있다. 2..toString(); // 두 번째 점은 잘 된다. 2 .toString(); // 왼쪽 공백이 있으면 잘 된다. @@ -21,7 +21,7 @@ JavaScript에서 [`null`](#core.undefined)과 [`undefined`](#core.undefined)를 ### Object 타입 -JavaScript 객체는 name/value 쌍으로 된 프로퍼티로 구성되기 때문에 [*Hashmap*][1]으로도 사용할 수 있다. +JavaScript 객체는 name/value 쌍으로 된 프로퍼티로 구성되기 때문에 [*Hashmap*][1]처럼 사용될 수도 있다. 객체 리터럴인 Object Notation으로 객체를 만들면 `Object.prototype`을 상속받고 [프로퍼티를 하나도 가지지 않은](#object.hasownproperty) 객체가 만들어진다. @@ -30,9 +30,9 @@ JavaScript 객체는 name/value 쌍으로 된 프로퍼티로 구성되기 때 // 값이 12인 'test' 프로퍼티가 있는 객체를 만든다. var bar = {test: 12}; -### 프로퍼티 +### 프로퍼티 접근 -객체의 프로퍼티는 Dot Notation이나 Square Bracket Notation으로 접근할 수 있다. +객체의 프로퍼티는 객체이름 다음에 점을 찍어(Dot Notation) 접근하거나 각괄호를 이용해(Square Bracket Notation) 접근할 수 있다. var foo = {name: 'Kitten'} foo.name; // kitten @@ -44,12 +44,11 @@ JavaScript 객체는 name/value 쌍으로 된 프로퍼티로 구성되기 때 foo.1234; // SyntaxError foo['1234']; // works - -'[]'은 프로퍼티를 동적으로 할당할 수 있고 변수 이름 규칙에도 구애받지 않는다. 그렇지만, 두 가지 방법은 근본적으로 서로 똑같다. +두 방식 모두 거의 동일하게 동작한다. 다만 차이가 있다면 각괄호 방식은 프로퍼티 이름을 동적으로 할당해서 값에 접근 할수 있지만 점을 이용한 방식은 구문 오류를 발생시킨다. ### 프로퍼티 삭제 -객체의 프로퍼티는 `delete`로만 삭제할 수 있다. 프로퍼티에 `undefined`나 `null`을 할당하는 것은 프로퍼티를 삭제하는 것이 아니라 프로퍼티에 할당된 *value*만 지우고 *key*는 그대로 두는 것이다. +객체의 프로퍼티를 삭제하려면 `delete`를 사용해야만 한다. 프로퍼티에 `undefined`나 `null`을 할당하는 것은 프로퍼티를 삭제하는 것이 아니라 프로퍼티에 할당된 *value*만 지우고 *key*는 그대로 두는 것이다. var obj = { bar: 1, @@ -67,7 +66,7 @@ JavaScript 객체는 name/value 쌍으로 된 프로퍼티로 구성되기 때 } -`baz`만 제거했기 때문에 `bar undefined`와 `foo null`은 출력되고 `baz`와 관련된 것은 출력되지 않는다. +위 코드의 출력 결과는 `baz`만 제거했기 때문에 `bar undefined`와 `foo null`은 출력되고 `baz`와 관련된 것은 출력되지 않는다. ### Notation of Keys @@ -76,8 +75,8 @@ JavaScript 객체는 name/value 쌍으로 된 프로퍼티로 구성되기 때 delete: 'I am a keyword, so me too' // SyntaxError가 난다. }; -프로퍼티의 key에 문자열이나 스트링을 사용할 수 있다. 이 부분도 JavaScript 파서의 설계 오류다. ECMAScript 5 이전에는 `SystaxError`가 났었다. +프로퍼티는 따옴표 없는 문자열(plain characters)과 따옴표로 감싼 문자열(strings)을 모두 Key 값으로 사용할 수 있다. 하지만 위와 같은 코드는 JavaScript 파서의 잘못된 설계 때문에 구버전(ECMAScript 5 이전 버전)에서는 `SystaxError`가 발생할 것이다. -이 에러는 `delete`가 키워드이기 때문에 발생하는 것이다. key를 스트링 리터럴로 정의하면 JavaScript 엔진은 언제나 잘 해석한다. +위 코드에서 문제가 되는 `delete` 키워드를 따옴표로 감싸면 구버전의 JavaScript 엔진에서도 제대로 해석될 것이다. [1]: http://en.wikipedia.org/wiki/Hashmap diff --git a/doc/ko/object/hasownproperty.md b/doc/ko/object/hasownproperty.md index b53ad583..fa36645e 100644 --- a/doc/ko/object/hasownproperty.md +++ b/doc/ko/object/hasownproperty.md @@ -1,12 +1,12 @@ ## `hasOwnProperty` -어떤 프로퍼티가 해당 객체 자신의 것인지 아니면 [프로토타입 체인](#object.prototype)에 있는 것인지 확인하려면 `Object.prototype`을 상속받은 `hasOwnProperty` 메소드를 사용해야 한다. +어떤 객체의 프로퍼티가 자기 자신의 프로퍼티인지 아니면 [프로토타입 체인](#object.prototype)에 있는 것인지 확인하려면 `hasOwnProperty` 메소드를 사용한다. 그리고 이 메소드는 `Object.prototype`으로 부터 상속받아 모든 객체가 가지고 있다. -> **Note:** 이 메소드로는 프로퍼티의 값이 `undefined`인지 확인할 수 없다. 프로퍼티가 존재해도 그 값은 `undefined`일 수 있다. +> **Note:** hasOwnProperty 메소드로는 어떤 프로퍼티가 존재하는지 확인하는 용도로는 사용할수 있지만, 그 값이 `undefined`일 수 있기 때문에 어떤 프로퍼티의 값이 `undefined`인지 확인하는 용도로 사용하긴 어렵다. -프로토타입 체인을 Traverse 하지 않으려면 `hasOwnProperty`를 사용하는 방법밖에 없다. +`hasOwnProperty`메소드는 프로토타입 체인을 탐색하지 않고, 프로퍼티를 다룰수있는 유일한 방법이다. - // Object.prototype을 더럽힌다. + // Object.prototype을 오염시킨다. Object.prototype.bar = 1; var foo = {goo: undefined}; @@ -16,11 +16,11 @@ foo.hasOwnProperty('bar'); // false foo.hasOwnProperty('goo'); // true -프로퍼티의 존재 여부를 확인하는 방법은 `hasOwnProperty` 메소드 뿐이다. 이 메소드는 프로토타입 체인의 프로퍼티말고 해당 객체의 프로퍼티만 Iterate할 때 유용하다. 객체 자체의 프로퍼티와 프로토타입 체인 어딘가에 있는 프로퍼티를 골라 주는 다른 방법은 없다. +`hasOwnProperty` 메소드는 어떤 프로퍼티가 자기 자신의 프로퍼티인지 아닌지 정확하게 알려주기 때문에 객체의 프로퍼티를 순회할때 꼭 필요하다. 그리고 프로토타입 체인 어딘가에 정의된 프로퍼티만을 제외하는 방법은 없다. -### `hasOwnProperty`도 프로퍼티 +### `hasOwnProperty` 메소드도 프로퍼티다 -JavaScript는 `hasOwnProperty` 프로퍼티도 보호해주지 않는다. 그래서 객체에 `hasOwnProperty` 프로퍼티가 있으면 다른 객체의 `hasOwnProperty` 메소드를 빌려 사용해야 한다. +JavaScript는 `hasOwnProperty`라는 이름으로 프로퍼티를 덮어 쓸수도 있다. 그래서 객체 안에 같은 이름으로 정의된 `hasOwnProperty`가 있을 경우, 본래 `hasOwnProperty`의 값을 정확하게 얻고 싶다면 다른 객체의 `hasOwnProperty` 메소드를 빌려써야 한다. var foo = { hasOwnProperty: function() { @@ -34,10 +34,10 @@ JavaScript는 `hasOwnProperty` 프로퍼티도 보호해주지 않는다. 그래 // 다른 객체의 hasOwnProperty를 사용하여 foo 객체의 프로퍼티 유무를 확인한다. ({}).hasOwnProperty.call(foo, 'bar'); // true - // Object에 원래 있는 hasOwnProperty를 사용해도 된다. + // Object에 있는 hasOwnProperty를 사용해도 된다. Object.prototype.hasOwnProperty.call(obj, 'bar'); // true ### 결론 -객체에 프로퍼티가 있는지 `hasOwnProperty`로만 확인할 수 있다. [`for in` loop](#object.forinloop)은 항상 `hasOwnProperty`와 함께 사용해야 한다. 네이티브 객체의 [프로토타입](#object.prototype)을 확장하는 사태가 일어나도 안전하게 지켜줄 것이다. +어떤 객체에 원하는 프로퍼티가 있는지 확인하는 가장 확실한 방법은 `hasOwnProperty`를 사용하는 것이다. [`for in` loop](#object.forinloop)에서 네이티브 객체에서 확장된 프로퍼티를 제외하고 순회하려면 `hasOwnProperty`와 함께 사용하길 권한다. diff --git a/doc/ko/object/prototype.md b/doc/ko/object/prototype.md index e2d591cc..9e8ffb2a 100644 --- a/doc/ko/object/prototype.md +++ b/doc/ko/object/prototype.md @@ -2,13 +2,13 @@ Javascript는 클래스 스타일의 상속 모델을 사용하지 않고 *프로토타입* 스타일의 상속 모델을 사용한다. -'이 점이 JavaScript의 약점이다.'라고 말하는 사람들도 있지만 실제로는 prototypal inheritance 모델이 훨씬 더 강력하다. 왜냐하면, 프로토타입 모델에서 클래스 모델을 흉내 내기는 매우 쉽지만, 반대로 클래스 모델에서 프로토타입 모델을 흉내 내기란 너무 어렵다. +'이 점이 JavaScript의 약점이다.'라고 말하는 사람들도 있지만 실제로는 prototypal inheritance 모델이 훨씬 더 강력하다. 그 이유는 프로토타입 모델에서 클래스 모델을 흉내 내기는 매우 쉽지만, 반대로 클래스 모델에서 프로토타입 모델을 흉내 내기란 매우 어렵기 때문이다. -실제로 Prototypal Inheritance 모델을 채용한 언어 중에서 JavaScript만큼 널리 사용되는 언어는 없었기 때문에 너무 늦게 두 모델의 차이점이 정리된 감이 있다. +실제로 Prototypal Inheritance 모델을 채용한 언어 중에서 JavaScript만큼 널리 사용된 언어가 없었기 때문에 두 모델의 차이점이 다소 늦게 정리된 감이 있다. -JavaScript는 *프로토타입 체인*이라는 것으로 상속을 구현한다. +먼저 가장 큰 차이점은 *프로토타입 체인*이라는 것을 이용해 상속을 구현한다는 점이다. -> **Note:** 간단히 말해서 `Bar.prototype = Foo.prototype`은 두 객체가 **하나의 프로토타입**을 공유하는 것이다. 그래서 한 객체의 프로토타입을 변경하면 그 프로토타입 객체를 사용하는 다른 객체에도 영향을 끼친다. 대부분은 나쁜 결과로 이어진다. +> **Note:** 간단히 말해서 `Bar.prototype = Foo.prototype`은 두 객체가 **하나의 프로토타입**을 공유하는 것이다. 그래서 한 객체의 프로토타입을 변경하면 그 프로토타입 객체를 사용하는 다른 객체도 영향을 받는다. 따라서 대부분의 경우 프로토타입을 변경하지는 않는다. function Foo() { this.value = 42; @@ -23,7 +23,7 @@ JavaScript는 *프로토타입 체인*이라는 것으로 상속을 구현한다 Bar.prototype = new Foo(); Bar.prototype.foo = 'Hello World'; - // Bar function을 생성자로 만들고 + // Bar 함수를 생성자로 만들고 Bar.prototype.constructor = Bar; var test = new Bar() // bar 인스턴스를 만든다. @@ -37,42 +37,42 @@ JavaScript는 *프로토타입 체인*이라는 것으로 상속을 구현한다 Object.prototype { toString: ... /* etc. */ } -`Bar.prototype`과 `Foo.prototype`을 둘 다 상속받았기 때문에 `test` 객체는 Foo에 정의한 `method` 함수에 접근할 수 있다. 프로토타입 체인에 있는 `Foo` 인스턴스의 `value` 프로퍼티도 사용할 수 있다. `new Bar()`를 해도 `Foo` 인스턴스는 새로 만들어지지 않고 Bar의 prototype에 있는 것을 재사용한다. 그래서 모든 Bar 인스턴스의 `value` 프로퍼티에 들어 있는 객체는 전부 **같은 객체다**. +위 코드에서 `test` 객체는 `Bar.prototype`과 `Foo.prototype`을 둘 다 상속받았기 때문에 Foo에 정의한 `method` 함수에 접근할 수 있다. 그리고 프로토타입 체인에 있는 `Foo` 인스턴스의 `value` 프로퍼티도 사용할 수 있다. `new Bar()`를 해도 `Foo` 인스턴스는 새로 만들어지지 않고 Bar의 prototype에 있는 것을 재사용한다. 그래서 모든 Bar 인스턴스는 **같은** `value` 프로퍼티를 공유한다. -> **Note:** `Bar.prototype = Foo`라고 하는 것은 `Foo`의 prototype을 가리키는 것이 아니라 Foo라는 Function의 prototype을 가리키는 것이다. 그래서 프로토타입 체인에 `Foo.prototype` 대신 `Function.prototype`이 들어서는 것이기 때문에 `method` 프로퍼티는 못 찾는다. +> **Note:** `Bar.prototype = Foo`라고 하는 것은 `Foo`의 prototype을 가리키는 것이 아니라 Foo라는 Function의 prototype을 가리키는 것이다. 그래서 프로토타입 체인에 `Foo.prototype` 대신 `Function.prototype`이 들어가 있기 때문에 `method` 프로퍼티는 찾지 못한다. -### 프로토타입 찾기 +### 프로토타입 탐색 -객체의 프로퍼티에 접근을 시도하면 JavaScript는 해당 이름의 프로퍼티를 찾을 때까지 위쪽으로 프로토타입 체인을 뒤진다. +객체의 프로퍼티에 접근하려고 하면 JavaScript는 해당 이름의 프로퍼티를 찾을 때까지 프로토타입 체인을 거슬러 올라가면서 탐색하게 된다. -체인의 끝까지 찾았는데도(보통은 `Object.prototype`임) 발견하지 못하면 [undefined](#core.undefined)를 반환한다. +프로토타입 체인을 끝까지 탐색했음에도(보통은 `Object.prototype`임) 불구하고 원하는 프로퍼티를 찾지 못하면 [undefined](#core.undefined)를 반환한다. ### prototype 프로퍼티 -prototype 프로퍼티는 프로토타입 체인을 만드는 데 사용하고 어떤 거라도 할당할 수 있지만, primitive 값을 할당하면 무시된다. +prototype 프로퍼티는 프로토타입 체인을 만드는 데 사용하고 어떤 값이든 할당할 수 있지만, primitive 값을 할당되면 무시한다. function Foo() {} Foo.prototype = 1; // 무시됨 -객체를 할당하면 프로토타입 체인이 동적으로 잘 만들어진다. +반면에 위 예제처럼 객체를 할당하면 프로토타입 체인이 동적으로 잘 만들어진다. ### 성능 -성능이 중요한 부분에서는 프로토타입 체인을 따라 프로퍼티를 찾는 것이 부담일 수 있다. 게다가 없는 프로퍼티에 접근하면 항상 프로토타입 체인 전체를 뒤진다. +프로토타입 체인을 탐색하는 시간이 오래걸릴수록 성능에 부정적인 영향을 줄수있다. 특히 성능이 중요한 코드에서 프로퍼티 탐색시간은 치명적인 문제가 될수있다. 가령, 없는 프로퍼티에 접근하려고 하면 항상 프로토타입 체인 전체를 탐색하게 된다. -객체를 [Iterate](#object.forinloop)하면 프로토타입 체인에 있는 **모든** 프로퍼티가 나열된다. +뿐만아니라 객체를 [순회(Iterate)](#object.forinloop)할때도 프로토타입 체인에 있는 **모든** 프로퍼티를 탐색하게 된다. ### 네이티브 프로토타입의 확장 -JavaScript에서는 `Object.prototype`같이 네이티브 객체들의 프로토타입도 확장할 수 있지만, 이것도 잘못 설계됐다. +종종 `Object.prototype`을 이용해 내장 객체를 확장하는 경우가 있는데, 이것도 역시 잘못 설계된 것중에 하나다. -이것을 [Monkey Patching][1]라고 부르는데 *캡슐화*를 망친다. 굉장히 많이 사용하는 [Prototype][2]도 굳이 기본 타입에 표준도 아닌 것들을 추가하는 이유를 아직 설명하지 못하고 있다. +위와 같이 확장하는 것을 [Monkey Patching][1]라고 부르는데 *캡슐화*를 망친다. 물론 [Prototype][2]같은 유명한 프레임워크들도 이런 확장을 사용하지만, 기본 타입에 표준도 아닌 기능들을 너저분하게 추가하는 이유를 여전히 설명하지 못하고 있다. -기본 타입을 확장하는 것이 좋을 때도 있다. [`Array.forEach`][3]같이 새 JavaScript 엔진에 추가된 기능을 위한 backport를 만들 때는 유용하다. +기본 타입을 확장해야하는 유일한 이유는 [`Array.forEach`][3]같이 새로운 JavaScript 엔진에 추가된 기능을 대비해 미리 만들어 놓는 경우 말고는 없다. ### 결론 -Prototypal Inheritance 모델을 사용하는 코드를 작성하기 전에는 이 모델을 완벽하게 이해해야 한다. 프로토타입 체인과 관련된 성능 문제로 고생하지 않으려면 프로토타입 체인의 길이에 주의하고 너무 길지 않게 적당히 끊어줘야 한다. JavaScript의 새 기능에 대한 호환성을 유지하려는 경우를 제외하고 절대로 네이티브 프로토타입을 확장하면 안 된다. +프로토타입을 이용해 복잡한 코드를 작성하기 전에 반드시 프로토타입 상속 (Prototypal Inheritance) 모델을 완벽하게 이해하고 있어야 한다. 뿐만아니라 프로토타입 체인과 관련된 성능 문제로 고생하지 않으려면 프로토타입 체인이 너무 길지 않도록 항상 주의하고 적당히 끊어줘야 한다. 마지막으로 새로운 JavaScript 기능에 대한 호환성 유지 목적이 아니라면 절대로 네이티브 프로토타입을 확장하지마라. [1]: http://en.wikipedia.org/wiki/Monkey_patch [2]: http://prototypejs.org/ diff --git a/doc/ko/other/timeouts.md b/doc/ko/other/timeouts.md index fb0384ed..2e72036b 100644 --- a/doc/ko/other/timeouts.md +++ b/doc/ko/other/timeouts.md @@ -1,22 +1,22 @@ ### `setTimeout`과 `setInterval` -JavaScript는 비동기이기 때문에 `setTimeout`과 `setInterval` 로 함수의 실행 순서를 조절할 수 있다. +JavaScript는 `setTimeout`과 `setInterval`함수를 이용해 비동기로 함수를 실행시킬수있다. > **Note:** Timeout은 ECMAScript 표준이 아니라 [DOM][1]때문에 구현됐다. function foo() {} var id = setTimeout(foo, 1000); // 0보다 큰 수를 반환한다. -`setTimeout`을 호출하면 timeout의 ID를 반환하고 **대충** 1,000밀리 초 후에 `foo`를 실행시킨다. `foo`는 **딱 한 번만** 실행한다. +`setTimeout`을 호출하면 타이머의 ID를 반환하고 **대략** 1,000밀리 초 후에 `foo`를 실행시킨다. `foo`는 **딱 한 번만** 실행한다. -JavaScript 엔진의 단위 시간(timer resolution)에 따라서 코드를 실행시키고 단일 쓰레드인 JavaScript를 특정 코드가 블록 시켜 버릴 수도 있기 때문에 `setTimeout`으로 코드가 실행돼야 할 시간을 정해줘도 **정확하게 그 시간에 실행되지 않는다.**. +JS엔진은 타이머에 설정한 시간(timer resolution)에 따라서 코드를 실행하지만 단일 쓰레드이기 때문에 특정 코드는 실행이 지연 될수도 있다. 따라서 `setTimeout`으로 코드가 실행돼야 할 시간을 정해줘도 **정확하게 그 시간에 실행되지 않을수도 있다.**. -첫 번째 인자로 넘긴 함수가 실행될 때 컨텍스트인 [`this`](#function.this)는 *Global* 객체를 가리킨다. +첫 번째 인자로 넘긴 함수는 전역 객체가 실행시킨다. 따라서 인자로 넘겨진 함수 내부의 [`this`](#function.this)는 *전역* 객체를 가리키게 된다. function Foo() { this.value = 42; this.method = function() { - // this는 Global 객체를 가리키기 때문에 + // this는 전역 객체를 가리키기 때문에 console.log(this.value); // undefined를 출력한다. }; setTimeout(this.method, 500); @@ -25,24 +25,25 @@ JavaScript 엔진의 단위 시간(timer resolution)에 따라서 코드를 실 > **Note:** `setTimeout`의 첫 번째 파라미터에 **함수** 객체를 넘겨야 하는 데 `setTimeout(foo(), 1000)`처럼 함수의 실행 결과를 넘기는 실수를 저지를 때가 잦다. 이럴 때 `setTimeout`은 그냥 `undefined`를 반환할 뿐이지 에러를 발생시키지 않는다. -### `setInterval`은 계속 함수 호출을 쌓는다(Stacking). +### 함수 호출을 쌓는(Stacking) `setInterval`함수. -`setTimeout`은 딱 한 번 함수를 호출하지만 `setInterval`은 이름처럼 **지정한 시간마다** 함수를 실행해 준다. 이 `setInterval`은 별로다. +`setTimeout`은 딱 한 번 함수를 호출하지만 `setInterval`은 이름처럼 **지정한 시간마다** 함수를 실행시켜준다. 하지만 이 함수의 사용은 좀 생각해봐야한다. -만약 실행하는 코드가 일정시간 동안 블럭되도 `setInterval`은 계속 함수를 호출시키려 든다. 특히 주기가 짧으면 밀리기 쉬워서 함수 호출은 계속 쌓일 수 있다. +`setInterval`은 실행하는 코드가 일정시간 동안 블럭되도 계속해서 함수를 호출하기 때문에 주기가 짧은 경우 함수 호출이 쉽게 쌓여버린다. function foo(){ // 1초 동안 블럭함. } setInterval(foo, 1000); -`foo`는 단순히 호출될 때마다 1초 동안 블럭하는 함수다. +위 코드에서 `foo`함수는 호출될 때마다 1초씩 실행을 지연시킨다. -`foo`가 블럭해도 `setInterval`은 계속 함수 호출을 쌓는다. `foo`의 첫 번째 호출이 끝나도 *10번* 이상의 함수 호출이 쌓여 대기하고 있다. +하지만 `foo`함수가 블럭되더라도 `setInterval`함수는 계속해서 함수 호출을 쌓기 때문에 `foo`함수 호출이 끝나면 *10번* 이상의 함수 호출이 쌓여서 대기하고 있을수도 있다. +(역주: 따라서 함수 호출이 쌓이게 되면 원래 기대했던 실행 주기를 보장받지 못한다.) -### 오래 걸리는 코드 다루기 +### 블럭되는 코드 해결법 -`setTimeout` 으로 함수 자신을 호출하는 방법으로 해결하기가 가장 쉽다. +앞에 문제를 해결하는 가장 쉽고 일반적인 방법은 `setTimeout` 함수에서 자기 자신을 다시 호출하는 방법이다. function foo(){ // something that blocks for 1 second @@ -50,40 +51,40 @@ JavaScript 엔진의 단위 시간(timer resolution)에 따라서 코드를 실 } foo(); -함수 호출이 쌓이지도 않을 뿐만 아니라 `setTimeout` 호출을 해당 함수 안에서 관리하고 `foo` 함수에서 계속 실행할지 말지 조절할 수도 있다. +이 방법은 함수 호출이 쌓이지도 않을 뿐만 아니라 `setTimeout` 호출을 해당 함수 안에서 관리하기 때문에 `foo` 함수에서 계속 실행할지 말지도 조절할 수 있다. -### Timeout 없애기 +### 타이머 없애기 -`clearTimeout`과 `clearInterval` 함수로 setTimeout과 setInterval로 등록한 timeout과 interval을 삭제할 수 있다. `set` 함수들이 반환한 id를 저장했다가 `clear` 함수를 호출하여 삭제한다. +`clearTimeout`과 `clearInterval` 함수로 setTimeout과 setInterval로 등록한 timeout과 interval을 삭제할 수 있다. `set` 함수들이 반환한 id를 저장했다가 `clear` 함수를 호출해서 삭제한다. var id = setTimeout(foo, 1000); clearTimeout(id); -### timeout을 전부 없애기 +### 모든 타이머 없애기 -등록한 timeout과 interval을 한꺼번에 제거하는 메소드는 없다. 구현해서 사용해야 한다. +등록한 timeout과 interval을 한꺼번에 제거하는 내장 함수는 없다. 따라서 좀 무식하지만 직접 구현해야 한다. - // clear "all" timeouts + // "모든" 타이머 지우기 for(var i = 1; i < 1000; i++) { clearTimeout(i); } -Id가 1부터 1000 사이에 있는 timeout들을 제거했지만, 그 외의 것은 아직 남아있다. 또 다른 방법이 있다. `setTimeout`은 항상 호출될 때마다 전보다 1만큼 큰 수를 ID로 반환한다. 이 점을 이용해 1부터 가장최근 ID까지 모두 삭제할 수 있다. +위와 같은 방법은 숫자가 미치지 못하는 타이머는 여전히 남아있을수 있다는 단점이 있다. 또 다른 해결 방법은 타이머가 반환하는 값이 항상 전보다 1만큼 큰 수를 반환한다는 점을 착안한 방법이다. - // clear "all" timeouts + // "모든" 타이머 지우기 var biggestTimeoutId = window.setTimeout(function(){}, 1), i; for(i = 1; i <= biggestTimeoutId; i++) { clearTimeout(i); } -이 방법은 모든 주요 브라우저에서 문제없이 잘 동작한다. 하지만 ID가 항상 순차적이어야 한다고 표준에 명시된 것이 아니다. 그러므로 timeout ID를 모두 저장했다가 삭제하는 것이 가장 안전하다. 그러면 전부 깨끗하게 제거할 수 있다. +이 방법은 모든 주요 브라우저에서 문제없이 잘 동작하지만 ID가 항상 순차적이어야 한다고 표준에 명시된 것이 아니다. 그러므로 timeout ID를 모두 저장했다가 삭제하는 것이 가장 안전하다. 그러면 전부 깨끗하게 제거할 수 있다. -### 숨겨진 `eval` +### 보이지 않게 사용되는 `eval`함수 -`setTimeout`과 `setInterval`의 첫 파라미터에 스트링도 넘길 수 있다. 그렇지만, 내부적으로 `eval`을 사용하는 것이기 때문에 절대 사용하지 말아야 한다. +`setTimeout`과 `setInterval`의 첫 파라미터로 문자열을 넘길 수 있다. 하지만 내부적으로 `eval`을 사용하는 것이기 때문에 절대 사용해서는 안된다. -> **Note:** timeout 함수는 ECMAScript 표준이 아녀서 첫 인자가 스트링 타입일 때에는 JavaScript 구현체마다 다르게 동작한다. 예를 들어, Microsoft의 JScript는 `eval`이 아니라 `Function` 생성자를 사용한다. +> **Note:** timeout 함수는 ECMAScript 표준이 아니기 때문에 문자열로 넘어오는 첫번째 인자에 대한 해석은 구현체마다 다르다. 예를 들어, Microsoft의 JScript는 `eval`이 아니라 `Function` 생성자를 사용한다. function foo() { // 이게 호출됨 @@ -97,7 +98,7 @@ Id가 1부터 1000 사이에 있는 timeout들을 제거했지만, 그 외의 } bar(); -이 경우 `eval`이 [그냥(directly)](#core.eval) 호출되는 것이 아니다. `setTimeout`에 넘겨진 스트링은 *Global* Scope에서 실행되기 때문에 `bar`의 Local 함수 `foo`가 실행되는 것이 아니라 *Global* Scope의 `foo`가 실행된다. +이 경우 `eval`이 [그냥(directly)](#core.eval) 호출되는 것이 아니다. `setTimeout`에 인자로 넘어간 문자열은 *전역* 스코프에서 실행되기 때문에 `bar`함수 영역에 있는 지역 변수 `foo`가 실행되는 것이 아니라 *전역* 스코프에 있는 `foo`가 실행된다. 함수에 파라미터를 넘겨야 하면 스트링을 사용하지 말아야 한다. @@ -115,8 +116,8 @@ Id가 1부터 1000 사이에 있는 timeout들을 제거했지만, 그 외의 ### 결론 -`setTimeout`과 `setInterval`의 파라미터로 스트링은 절대 사용하지 말아야 한다. 핸들러 함수에 인자를 넘겨야 하는 경우도 **분명히** 탈 난다. *익명 함수*을 사용해서 호출해야 한다. +`setTimeout`과 `setInterval`함수에 문자열 인자를 절대 사용해서는 안된다. 핸들러 함수에 인자를 넘기는 코드도 **절대** 좋은 코드가 아니다. *익명 함수*을 사용해서 호출해야 한다. -그리고 `setInterval`은 해당 핸들러가 블럭되든 말든 상관하지 않기 때문에 사용하면 안 된다. +그리고 `setInterval`은 해당 핸들러가 블럭되든 말든 상관하지 않기 때문에 되도록이면 쓰지말자. [1]: http://en.wikipedia.org/wiki/Document_Object_Model "Document Object Model" diff --git a/doc/ko/types/casting.md b/doc/ko/types/casting.md index eb89f546..7a6e28ea 100644 --- a/doc/ko/types/casting.md +++ b/doc/ko/types/casting.md @@ -1,4 +1,4 @@ -## Type Casting +## 타입 캐스팅 JavaScript는 Weak Typing 언어이기 때문에 필요할 때마다 알아서 타입을 변환한다. @@ -15,9 +15,9 @@ JavaScript는 Weak Typing 언어이기 때문에 필요할 때마다 알아서 10 == 010; 10 == '-10'; -> **ES5 Note:** `0`으로 시작하는 숫자 리터럴은 8진수다. 하지만, ECMAScript 5의 strict 모드에서는 더는 8진수로 해석하지 않는다. +> **ES5 Note:** `0`으로 시작하는 숫자 리터럴은 8진수다. 하지만, ECMAScript 5의 strict 모드에서는 8진수로 더이상 해석하지 않는다. -이런 문제들은 [strict equal operator](#types.equality)로 **미리 방지해야** 한다. 이 operator로 JavaScript의 많은 결점을 보완할 수 있지만, 아직도 weak typing 시스템 때문에 생기는 문제가 많다. +위와 같은 문제들은 ***반드시** [삼중 등호 연산자](#types.equality)를 이용해 해결하길 권한다. 물론 삼중 등호로 많은 결점을 보완할 수 있지만, 여전히 weak typing 시스템 때문에 생기는 많은 문제가 남아있다. ### 기본 타입 생성자 diff --git a/doc/ko/types/equality.md b/doc/ko/types/equality.md index 970b2c14..a9daccb5 100644 --- a/doc/ko/types/equality.md +++ b/doc/ko/types/equality.md @@ -1,12 +1,12 @@ ## 객체 비교하기 -JavaScript에서 객체를 비교하는 방법은 두 가지다. +JavaScript에서 객체를 비교하는 방법은 두 가지가 있다. -### Equality Operator +### 이중 등호 연산자 -`==`가 Equality Operator이다. +이중 등호 연산자는 `==`을 말한다. -JavaScript는 Weak Typing을 따르기 때문에 equality operator가 비교할 때 두 객체의 자료형을 **강제로** 변환한다. +JavaScript는 Weak Typing을 따르기 때문에 이중 등호를 이용해 비교할 때 두 객체의 자료형을 **강제로** 변환한다. "" == "0" // false 0 == "" // true @@ -18,15 +18,15 @@ JavaScript는 Weak Typing을 따르기 때문에 equality operator가 비교할 null == undefined // true " \t\r\n" == 0 // true -이 표는 왜 Equality Operator를 사용하면 안 되는지를 보여준다. 이 복잡한 변환 규칙은 실제로 골치 아픈 버그를 만들어 낸다. +이 표는 이중 등호를 사용하면 왜 안되는지를 보여준다. 이 복잡한 변환 규칙은 실제로 골치 아픈 버그를 만들어 낸다. -게다가 강제로 타입을 변환하는 것은 성능 문제도 일으킨다. 예를 들어 스트링과 숫자를 비교하려면 반드시 숫자로 변환해야 한다. +게다가 강제로 타입을 변환하게 되면 성능에도 영향을 준다. 예를 들어 문자와 숫자를 비교하려면 반드시 먼저 문자를 숫자로 변환해야 한다. -### Strict Equality Operator +### 삼중 등호 연산자 -Strict Equality Operator는 `===`이다. +삼중 등호 연산자는 `===`을 말한다. -강제로 타입을 변환하지 않는 것을 제외하고는 Equality Operator와 똑같다. +삼중 등호는 강제로 타입을 변환하지 않는다는 사실을 제외하면 이중 등호와 동일하다. "" === "0" // false 0 === "" // false @@ -38,11 +38,11 @@ Strict Equality Operator는 `===`이다. null === undefined // false " \t\r\n" === 0 // false -이 결과가 훨씬 명확하고 문제를 빨리 발견할 수 있게 해준다. 이 Operator를 사용하면 코드가 좀 더 튼튼하고 비교하는 두 객체의 타입이 다르면 성능도 빠르다. +위 결과가 훨씬 더 명확하고 문제가 쉽게 드러난다. 삼중 등호를 사용하면 코드를 좀 더 튼튼하게 만들수 있고, 비교하는 두 객체의 타입이 다르면 더 좋은 성능을 얻을 수도 있다. ### 객체 비교하기 -`==`와 `===`는 둘 다 **Equality** Operator지만 비교하는 객체 중 적어도 한 개가 Object 타입일 때에는 다르게 동작한다. +이중 등호와(`==`)와 삼중 등호(`===`)는 둘 다 **값을 비교하는** 연산이지만 피연산자중에 Object 타입이 하나라도 있으면 다르게 동작한다. {} === {}; // false new String('foo') === 'foo'; // false @@ -50,8 +50,8 @@ Strict Equality Operator는 `===`이다. var foo = {}; foo === foo; // true -두 Operator 모두 **같은 객체(identity)**인지 비교하는 것이지 객체의 값이 같은지 비교하는 것이 아니다. C에서 포인터를 비교하거나 Python의 is처럼 같은 인스턴스인지 비교하는 것이다. +두 연산자 모두 두 객체의 값이 같은지를 비교하지 않고, 두 객체가 **같은 객체(identity)**인지를 비교한다. C에서 포인터를 비교하거나 Python의 is처럼 같은 인스턴스인지 비교하는 것이다. ### 결론 -반드시 **Strict Equality Operator**를 사용해야 한다. 비교하기 위해서 꼭 타입 변환이 필요하면 언어의 복잡한 변환 규칙에 맡기지 말고 꼭 명시적으로 변환하고 나서 비교해야 한다. +**삼중 등호 연산자**를 사용할 것을 강력하게 권한다. 비교하기 위해서 타입 변환이 필요하면 언어의 복잡한 변환 규칙에 맡기지 말고 꼭 명시적으로 변환한 후에 비교해야 한다. diff --git a/doc/ko/types/instanceof.md b/doc/ko/types/instanceof.md index 560f4435..621f8121 100644 --- a/doc/ko/types/instanceof.md +++ b/doc/ko/types/instanceof.md @@ -1,8 +1,8 @@ -## `instanceof` +## `instanceof` 연산자 -`instanceof`는 두 객체의 생성자를 비교하는 것이고 직접 만든 타입의 객체를 비교할 때 유용하다. 기본 타입만 생각하면 이 연산자는 [typeof](#types.typeof)처럼 거의 쓸모 없다. +`instanceof`연산자는 두 피연산자의 생성자를 비교할때 사용하고 직접 만든 객체를 비교할 때 매우 유용하다. 내장 타입에 쓰는 경우에는 [typeof](#types.typeof)처럼 거의 쓸모가 없다. -### 직접 만든 타입의 객체를 `intanceof`로 비교하기 +### 커스텀 객체를 `intanceof`로 비교하기 function Foo() {} function Bar() {} @@ -11,12 +11,12 @@ new Bar() instanceof Bar; // true new Bar() instanceof Foo; // true - // Bar.prototype에 function 객체인 Foo를 할당하면 + // Bar.prototype에 함수 객체인 Foo를 할당하면 // Bar의 인스턴스는 Foo의 인스턴스가 아니다. Bar.prototype = Foo; new Bar() instanceof Foo; // false -### 기본 타입 객체를 `intanceof`로 비교하기 +### 기본 내장 객체 타입을 `intanceof`로 비교하기 new String('foo') instanceof String; // true new String('foo') instanceof Object; // true diff --git a/doc/ko/types/typeof.md b/doc/ko/types/typeof.md index fb7c6576..a2db9595 100644 --- a/doc/ko/types/typeof.md +++ b/doc/ko/types/typeof.md @@ -1,10 +1,10 @@ -## `typeof` +## `typeof` 연산자 -`typeof`도 [`instanceof`](#types.instanceof)와 함께 JavaScript에서 치명적으로 잘못 설계된 부분이다. 이건 정말 아무짝에 쓸모없다. +`typeof` 연산자도 [`instanceof`](#types.instanceof) 연산자와 함께 JavaScript에서 치명적으로 잘못 설계된 부분이다. 이건 정말이지 아무짝에도 쓸모가 없다. -`instanceof`는 그래도 쓸 데가 좀 있었는데 `typeof`는 딱 한 군데에만 써먹을 수 있다. 객체의 타입을 검사할 일이 없다. +`instanceof` 연산자는 그래도 여전히 쓸만한 데가 좀 있는데 `typeof` 연산자는 객체의 타입을 검사하는 것 외에는 쓸만한데가 없고, 이마저도 거의 쓸일이 없다. -> **Note:** `typeof`는 함수처럼 `typeof(obj)`로 사용할 수 있다. 하지만, 이것은 함수를 호출하는 것이 아니라 단순히 `()`안의 값이 반환되고 `typeof`가 적용되는 것이다. `typeof`라는 함수는 **없다**. +> **Note:** `typeof` 연산자는 함수처럼 `typeof(obj)`로 사용할수 있지만 함수 호출은 아니다. 괄호 안의 값은 `typeof`의 피연산자로 적용되고 그 결과가 반환된다. `typeof`라는 함수는 **없다**. ### JavaScript 타입 표 @@ -26,13 +26,13 @@ {} Object object new Object() Object object -이 표에서 *Type*은 `typeof`가 반환하는 값이다. 표에서 본 것처럼 이 값은 계속 쓸모없다. +위 표에서 *Type*은 `typeof`가 반환하는 값이다. 위 표에서처럼 일치되는 값이 거의 없다. -Class는 객체 내부에 있는 `[[Class]]` 프로퍼티의 값이다. +위 표에서 *Class*는 객체 내부에 있는 `[[Class]]` 프로퍼티의 값을 말한다. > **표준**에는 `[[Class]]`의 값은 `Arguments`, `Array`, `Boolean`, `Date`, `Error`, `Function`, `JSON`, `Math`, `Number`, `Object`, `RegExp`, `String`중 하나라고 나와있다. -`[[Class]]`의 값을 가져다 쓰려면 `Object.prototype`의 `toString` 메소드를 사용해야 한다. +`[[Class]]` 프로퍼티의 값을 가져다 쓰려면 `Object.prototype`의 `toString` 메소드를 사용한다. ### 객체의 클래스 @@ -54,10 +54,10 @@ Class는 객체 내부에 있는 `[[Class]]` 프로퍼티의 값이다. typeof foo !== 'undefined' -이것은 `foo`가 정의됐는지 아닌지를 확인해준다. 정의되지 않은 변수에 접근하면 `ReferenceError` 나는데 이것을 방지할 수 있다. `typeof`가 유용한 건 이때뿐이다. +위 코드는 `foo`가 정의됐는지 아닌지를 확인해준다. 정의되지 않은 변수에 접근하면 `ReferenceError` 나는데 이것을 방지할 수 있다. `typeof`가 유용한 건 이때뿐이다. ### 결론 -객체의 타입을 검사하려면 `Object.prototype.toString`를 사용해야 한다. 다른 방법은 신뢰할 수 없다. 위 표에서 보여준 것처럼 typeof가 반환하는 값은 표준에 나와 있지 않기 때문에 구현마다 다르다. +객체의 타입을 검사하려면 `Object.prototype.toString`를 사용해야 한다. 다른 방법은 신뢰할 수 없다. 위 표에서 보여준 것처럼 typeof가 반환하는 값은 표준에 나와 있지 않기 때문에 구현방법도 제각각이다. -변수가 정의됐는지 확인할 때는 빼고 **목숨을 걸고** `typeof`를 사용하지 못하게 해야 한다. +변수가 정의됐는지 확인할 때를 제외하고 **가급적** `typeof`는 피해야한다. \ No newline at end of file From 48e7a5f49eeac32fa0a54f96b7c9616216b22e6b Mon Sep 17 00:00:00 2001 From: ruben Date: Wed, 21 Nov 2012 10:15:46 +0100 Subject: [PATCH 248/463] fixed a typo --- doc/es/array/general.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/es/array/general.md b/doc/es/array/general.md index 944590b0..3de582bb 100644 --- a/doc/es/array/general.md +++ b/doc/es/array/general.md @@ -31,7 +31,7 @@ para realizar la búsqueda en cada interación del bucle. Y mientras que los úl motores de JavaScript **pueden** aplicar optimizaciones en este caso, no hay manera de saber si el ćodigo se ejecutará en uno de estos nuevos motores nuevos o no. -De hecho, dejando de lado el alamacenamiento en caché puede resultar que el bucle +De hecho, dejando de lado el almacenamiento en caché puede resultar que el bucle inicie sólo la **mitad de rápido** que con la longitud de la caché. ### La propiedad `length` From 5f34e58254739b46e13ab46dc75159c9e1b5b135 Mon Sep 17 00:00:00 2001 From: "ByungDae, Sohn" Date: Wed, 26 Dec 2012 11:14:29 +0900 Subject: [PATCH 249/463] improve transration --- doc/ko/function/arguments.md | 2 +- doc/ko/intro/index.md | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/doc/ko/function/arguments.md b/doc/ko/function/arguments.md index dcc5e8a2..5ea383cb 100644 --- a/doc/ko/function/arguments.md +++ b/doc/ko/function/arguments.md @@ -64,7 +64,7 @@ JavaScript의 모든 함수 스코프에는 `arguments`라는 특별한 변수 ### 성능에 대한 오해와 진실. -`arguments` 객체는 항상 만들어 지지만 예외도 있다. `arguments`라는 이름의 변수를 Function 안에 정의하거나 그 이름으로 파라미터를 만들면 `arguemnts` 객체는 만들어지지 않는다. 그렇지만, 이럴때는 어차피 안쓰겠다는 의미니까 상관 없다. +`arguments` 객체는 항상 만들어지지만 두가지 예외사항이 있다. `arguments`라는 이름으로 변수를 함수 안에 정의하거나 arguments 객체로 넘겨받는 인자중 하나라도 정식 인자로 받아서 사용하면 `arguemnts` 객체는 만들어지지 않는다. 하지만 뭐 이런 경우들은 어차피 arguments 객체를 안쓰겠다는 의미니까 상관 없다. 그리고 *getter*와 *setter*는 항상 생성되기 때문에 getter/setter를 사용하는 것은 성능에 별 영향을 끼치지 않는다. 예제처럼 단순한 코드가 아니라 `arguments` 객체를 다방면으로 활용하는 실제 코드에서도 마찬가지다. diff --git a/doc/ko/intro/index.md b/doc/ko/intro/index.md index 87b72473..2fe16ea7 100644 --- a/doc/ko/intro/index.md +++ b/doc/ko/intro/index.md @@ -14,7 +14,8 @@ JavaScript Garden은 단순히 JavaScript 언어 자체를 설명하려 만들 - [Andreas Blixt][6] (언어 교정) ## 번역 - - [박창우][손병대][] + - [박창우][] + - [손병대][] [박창우]: https://github.com/pismute [손병대]: https://github.com/miconblog From 9c4235052673113663baf58969f9acc98611cf48 Mon Sep 17 00:00:00 2001 From: "ByungDae, Sohn" Date: Wed, 26 Dec 2012 11:37:15 +0900 Subject: [PATCH 250/463] improve translation --- doc/ko/function/arguments.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/ko/function/arguments.md b/doc/ko/function/arguments.md index 5ea383cb..097bec13 100644 --- a/doc/ko/function/arguments.md +++ b/doc/ko/function/arguments.md @@ -64,7 +64,7 @@ JavaScript의 모든 함수 스코프에는 `arguments`라는 특별한 변수 ### 성능에 대한 오해와 진실. -`arguments` 객체는 항상 만들어지지만 두가지 예외사항이 있다. `arguments`라는 이름으로 변수를 함수 안에 정의하거나 arguments 객체로 넘겨받는 인자중 하나라도 정식 인자로 받아서 사용하면 `arguemnts` 객체는 만들어지지 않는다. 하지만 뭐 이런 경우들은 어차피 arguments 객체를 안쓰겠다는 의미니까 상관 없다. +`arguments` 객체는 항상 만들어지지만 두가지 예외사항이 있다. `arguments`라는 이름으로 변수를 함수 안에 정의하거나 arguments 객체로 넘겨받는 인자중 하나라도 정식 인자로 받아서 사용하면 `arguemnts` 객체는 만들어지지 않는다. 사실 arguments 객체를 쓰든 쓰지않든 중요한건 아니므로 신경쓰지 않아도 된다. 그리고 *getter*와 *setter*는 항상 생성되기 때문에 getter/setter를 사용하는 것은 성능에 별 영향을 끼치지 않는다. 예제처럼 단순한 코드가 아니라 `arguments` 객체를 다방면으로 활용하는 실제 코드에서도 마찬가지다. From 1f2bc63402dbfbc1e2804f72ffb7b1a6824d6947 Mon Sep 17 00:00:00 2001 From: PiNotEqual3 Date: Tue, 22 Jan 2013 10:10:25 +0100 Subject: [PATCH 251/463] Update doc/de/intro/index.md German Intro --- doc/de/intro/index.md | 41 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) diff --git a/doc/de/intro/index.md b/doc/de/intro/index.md index 94250e2f..566e3235 100644 --- a/doc/de/intro/index.md +++ b/doc/de/intro/index.md @@ -1,4 +1,43 @@ ## Einführung -Demnächst. +**JavaScript Garden** ist eine wachsende Sammlung von Erklärungen der verzwicktesten Teile von JavaScript. Es gibt +Hinweise um häufige Fehler, Performance Probleme und schlechten Stil zu vermeiden. +JavaScript Garden ist **keine** Anleitung um JavaScript zu lernen. Ein grundlegendes Verständnis der Sprache wird +wärmstens empfohlen. Eine gute [Einführung][1] findet sich zum Beispiel im Mozilla Developer Network. + +## Die Autoren + +Dieses Dokument wurde von zwei liebenswerten [Stack Overflow][2] Benutzern geschrieben: [Ivo Wetzel][3] +(Text) and [Zhang Yi Jiang][4] (Design). + +## Beitragende + + - [Caio Romão][5] (Rechtschreibung) + - [Andreas Blixt][6] (Sprachanpassungen) + +## Hosting + +JavaScript Garden wird von GitHub bereitgestellt, aber es wird auch von [Cramer Development][7] unterstützt durch +einen Mirror auf [JavaScriptGarden.info][8]. + +## Lizenz + +JavaScript Garden wurde unter der [MIT Lizenz][9] veröffentlich und wird von [GitHub][10] veröffentlicht. Wenn du +Fehler findest mach bitte ein [Ticket][11] auf oder einen pull request ins repository. Du kannst uns auch im +[JavaScript Raum][12] des Stack Overflow Chats finden. + +Mehr demnächst. + +[1]: https://developer.mozilla.org/en/JavaScript/Guide +[2]: http://stackoverflow.com/ +[3]: http://stackoverflow.com/users/170224/ivo-wetzel +[4]: http://stackoverflow.com/users/313758/yi-jiang +[5]: https://github.com/caio +[6]: https://github.com/blixt +[7]: http://cramerdev.com/ +[8]: http://javascriptgarden.info/ +[9]: https://github.com/BonsaiDen/JavaScript-Garden/blob/next/LICENSE +[10]: https://github.com/BonsaiDen/JavaScript-Garden +[11]: https://github.com/BonsaiDen/JavaScript-Garden/issues +[12]: http://chat.[stackoverflow.com/rooms/17/javascript From 1546101896aab6a09303fcecbdf18d72726e6b58 Mon Sep 17 00:00:00 2001 From: Bruno Coelho Date: Thu, 24 Jan 2013 09:22:13 -0300 Subject: [PATCH 252/463] Passing the wrong object to hasOwnProperty method. --- doc/en/object/hasownproperty.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/doc/en/object/hasownproperty.md b/doc/en/object/hasownproperty.md index 0033b4ba..03e3feea 100644 --- a/doc/en/object/hasownproperty.md +++ b/doc/en/object/hasownproperty.md @@ -5,26 +5,26 @@ on its [prototype chain](#object.prototype), it is necessary to use the `hasOwnProperty` method which all objects inherit from `Object.prototype`. > **Note:** It is **not** enough to check whether a property is `undefined`. The -> property might very well exist, but its value just happens to be set to +> property might very well exist, but its value just happens to be set to > `undefined`. -`hasOwnProperty` is the only thing in JavaScript which deals with properties and +`hasOwnProperty` is the only thing in JavaScript which deals with properties and does **not** traverse the prototype chain. // Poisoning Object.prototype - Object.prototype.bar = 1; + Object.prototype.bar = 1; var foo = {goo: undefined}; - + foo.bar; // 1 'bar' in foo; // true foo.hasOwnProperty('bar'); // false foo.hasOwnProperty('goo'); // true -Only `hasOwnProperty` will give the correct and expected result; this is -essential when iterating over the properties of any object. There is **no** other -way to exclude properties that are not defined on the object itself, but -somewhere on its prototype chain. +Only `hasOwnProperty` will give the correct and expected result; this is +essential when iterating over the properties of any object. There is **no** other +way to exclude properties that are not defined on the object itself, but +somewhere on its prototype chain. ### `hasOwnProperty` as a Property @@ -45,7 +45,7 @@ necessary to use an *external* `hasOwnProperty` to get correct results. ({}).hasOwnProperty.call(foo, 'bar'); // true // It's also possible to use the hasOwnProperty property from the Object property for this purpose - Object.prototype.hasOwnProperty.call(obj, 'bar'); // true + Object.prototype.hasOwnProperty.call(foo, 'bar'); // true ### In Conclusion From 4a94b223de56462297fa6e018f64ad13bf3abd86 Mon Sep 17 00:00:00 2001 From: Bruno Coelho Date: Fri, 25 Jan 2013 14:08:19 -0300 Subject: [PATCH 253/463] Cosmetic. --- doc/en/object/prototype.md | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/doc/en/object/prototype.md b/doc/en/object/prototype.md index abb67c58..cb053526 100644 --- a/doc/en/object/prototype.md +++ b/doc/en/object/prototype.md @@ -1,23 +1,23 @@ ## The Prototype -JavaScript does not feature a classical inheritance model; instead, it uses a -*prototypal* one. +JavaScript does not feature a classical inheritance model; instead, it uses a +*prototypal* one. -While this is often considered to be one of JavaScript's weaknesses, the +While this is often considered to be one of JavaScript's weaknesses, the prototypal inheritance model is in fact more powerful than the classic model. It is, for example, fairly trivial to build a classic model on top of a prototypal model, while the other way around is a far more difficult task. JavaScript is the only widely used language that features prototypal inheritance, so it can take time to adjust to the differences between the two -models. +models. The first major difference is that inheritance in JavaScript uses *prototype chains*. > **Note:** Simply using `Bar.prototype = Foo.prototype` will result in both objects -> sharing the **same** prototype. Therefore, changes to either object's prototype -> will affect the prototype of the other as well, which in most cases is not the +> sharing the **same** prototype. Therefore, changes to either object's prototype +> will affect the prototype of the other as well, which in most cases is not the > desired effect. function Foo() { @@ -36,11 +36,11 @@ chains*. // Make sure to list Bar as the actual constructor Bar.prototype.constructor = Bar; - var test = new Bar() // create a new bar instance + var test = new Bar(); // create a new bar instance // The resulting prototype chain test [instance of Bar] - Bar.prototype [instance of Foo] + Bar.prototype [instance of Foo] { foo: 'Hello World' } Foo.prototype { method: ... } @@ -48,14 +48,14 @@ chains*. { toString: ... /* etc. */ } In the code above, the object `test` will inherit from both `Bar.prototype` and -`Foo.prototype`; hence, it will have access to the function `method` that was +`Foo.prototype`; hence, it will have access to the function `method` that was defined on `Foo`. It will also have access to the property `value` of the **one** `Foo` instance that is its prototype. It is important to note that `new -Bar()` does **not** create a new `Foo` instance, but reuses the one assigned to +Bar()` does **not** create a new `Foo` instance, but reuses the one assigned to its prototype; thus, all `Bar` instances will share the **same** `value` property. -> **Note:** Do **not** use `Bar.prototype = Foo`, since it will not point to -> the prototype of `Foo` but rather to the function object `Foo`. So the +> **Note:** Do **not** use `Bar.prototype = Foo`, since it will not point to +> the prototype of `Foo` but rather to the function object `Foo`. So the > prototype chain will go over `Function.prototype` and not `Foo.prototype`; > therefore, `method` will not be on the prototype chain. @@ -71,7 +71,7 @@ hasn't found the specified property, it will return the value ### The Prototype Property While the prototype property is used by the language to build the prototype -chains, it is still possible to assign **any** given value to it. However, +chains, it is still possible to assign **any** given value to it. However, primitives will simply get ignored when assigned as a prototype. function Foo() {} @@ -85,9 +85,9 @@ creation of prototype chains. The lookup time for properties that are high up on the prototype chain can have a negative impact on performance, and this may be significant in code where performance is critical. Additionally, trying to access non-existent properties -will always traverse the full prototype chain. +will always traverse the full prototype chain. -Also, when [iterating](#object.forinloop) over the properties of an object +Also, when [iterating](#object.forinloop) over the properties of an object **every** property that is on the prototype chain will be enumerated. ### Extension of Native Prototypes @@ -95,12 +95,12 @@ Also, when [iterating](#object.forinloop) over the properties of an object One mis-feature that is often used is to extend `Object.prototype` or one of the other built in prototypes. -This technique is called [monkey patching][1] and breaks *encapsulation*. While -used by popular frameworks such as [Prototype][2], there is still no good +This technique is called [monkey patching][1] and breaks *encapsulation*. While +used by popular frameworks such as [Prototype][2], there is still no good reason for cluttering built-in types with additional *non-standard* functionality. -The **only** good reason for extending a built-in prototype is to backport -the features of newer JavaScript engines; for example, +The **only** good reason for extending a built-in prototype is to backport +the features of newer JavaScript engines; for example, [`Array.forEach`][3]. ### In Conclusion From 33a89e7857b5b82413af588ac6708117aef3dc4c Mon Sep 17 00:00:00 2001 From: howardchi Date: Wed, 13 Mar 2013 20:08:28 +0800 Subject: [PATCH 254/463] translate to Tranditioin Chinese --- doc/zh(Trandition)/array/constructor.md | 28 +++ doc/zh(Trandition)/array/general.md | 46 ++++ doc/zh(Trandition)/core/delete.md | 85 +++++++ doc/zh(Trandition)/core/eval.md | 42 ++++ doc/zh(Trandition)/core/semicolon.md | 103 +++++++++ doc/zh(Trandition)/core/undefined.md | 70 ++++++ doc/zh(Trandition)/function/arguments.md | 118 ++++++++++ doc/zh(Trandition)/function/closures.md | 98 ++++++++ doc/zh(Trandition)/function/constructors.md | 128 +++++++++++ doc/zh(Trandition)/function/general.md | 48 ++++ doc/zh(Trandition)/function/scopes.md | 233 ++++++++++++++++++++ doc/zh(Trandition)/function/this.md | 111 ++++++++++ doc/zh(Trandition)/index.json | 69 ++++++ doc/zh(Trandition)/intro/index.md | 47 ++++ doc/zh(Trandition)/object/forinloop.md | 51 +++++ doc/zh(Trandition)/object/general.md | 99 +++++++++ doc/zh(Trandition)/object/hasownproperty.md | 57 +++++ doc/zh(Trandition)/object/prototype.md | 118 ++++++++++ doc/zh(Trandition)/other/timeouts.md | 167 ++++++++++++++ doc/zh(Trandition)/types/casting.md | 70 ++++++ doc/zh(Trandition)/types/equality.md | 71 ++++++ doc/zh(Trandition)/types/instanceof.md | 38 ++++ doc/zh(Trandition)/types/typeof.md | 86 ++++++++ 23 files changed, 1983 insertions(+) create mode 100644 doc/zh(Trandition)/array/constructor.md create mode 100644 doc/zh(Trandition)/array/general.md create mode 100644 doc/zh(Trandition)/core/delete.md create mode 100644 doc/zh(Trandition)/core/eval.md create mode 100644 doc/zh(Trandition)/core/semicolon.md create mode 100644 doc/zh(Trandition)/core/undefined.md create mode 100644 doc/zh(Trandition)/function/arguments.md create mode 100644 doc/zh(Trandition)/function/closures.md create mode 100644 doc/zh(Trandition)/function/constructors.md create mode 100644 doc/zh(Trandition)/function/general.md create mode 100644 doc/zh(Trandition)/function/scopes.md create mode 100644 doc/zh(Trandition)/function/this.md create mode 100644 doc/zh(Trandition)/index.json create mode 100644 doc/zh(Trandition)/intro/index.md create mode 100644 doc/zh(Trandition)/object/forinloop.md create mode 100644 doc/zh(Trandition)/object/general.md create mode 100644 doc/zh(Trandition)/object/hasownproperty.md create mode 100644 doc/zh(Trandition)/object/prototype.md create mode 100644 doc/zh(Trandition)/other/timeouts.md create mode 100644 doc/zh(Trandition)/types/casting.md create mode 100644 doc/zh(Trandition)/types/equality.md create mode 100644 doc/zh(Trandition)/types/instanceof.md create mode 100644 doc/zh(Trandition)/types/typeof.md diff --git a/doc/zh(Trandition)/array/constructor.md b/doc/zh(Trandition)/array/constructor.md new file mode 100644 index 00000000..7e768014 --- /dev/null +++ b/doc/zh(Trandition)/array/constructor.md @@ -0,0 +1,28 @@ +## `Array` 的建構函式 + +`Array` 的建構函式在處理參數上一直有模糊的地帶,所以建議使用 `array`的字面語法來使用 - `[]` - 來新增一個的Array + + [1, 2, 3]; // 結果: [1, 2, 3] + new Array(1, 2, 3); // 結果: [1, 2, 3] + + [3]; // 結果: [3] + new Array(3); // 結果: [] + new Array('3') // 結果: ['3'] + +在上面的範例 `new Array(3)` 當只有一個參數傳入到 `Array` 的建構函數 +且那個參數事宜個數字,建構函數會回傳空值 +但是 `Array` 長度的屬性會變成跟那個參數一樣(以此範例來看他回傳的長度為 3) +**注意** 只有他長度的屬性會被設定,整個 Array裡面的數值都不會初始化 + + var arr = new Array(3); + arr[1]; // undefined + 1 in arr; // false, 數值沒有被設定進去 + +被設定用來當做 `Array` 的長度只有少數情況使用 +先設定 `Array` 的長度可以用一下的範例來避免使用 `for loop` 的麻煩 + + new Array(count + 1).join(stringToRepeat); + +### 結語 + +`Array` 的建構函式需要避免,建議使用字面語法。因為他們比較簡短、也更增加閱讀性 diff --git a/doc/zh(Trandition)/array/general.md b/doc/zh(Trandition)/array/general.md new file mode 100644 index 00000000..f4bd9252 --- /dev/null +++ b/doc/zh(Trandition)/array/general.md @@ -0,0 +1,46 @@ +## Array 迴圈和屬性 + +雖然在 Javascript 中 Array 都是 Objects,但是沒有好的理由要使用他 +在 [`for in`](#object.forinloop) 的迴圈中。事實上有很多原因要避免使用 `for in` 在 Array 之中 + +> **注意:** Javascript Arrays **不是** *關連性 Arrays* +> 只有 [objects](#object.general) 來管理建值的相對應關係 +> Arrays 是**保持** 順序的,Objects **則沒有** + +因為 `for in` 迴圈會列舉所有在原型 Array 上的屬性因為他會使用[`hasOwnProperty`](#object.hasownproperty), 這會使得 Array 比原本的 `for` 迴圈慢上二十幾倍 + +### 迴圈 + +為了要達到最好的性能所以最好使用 `for` 迴圈來讀取一個 Array 裡面的數值。 + + var list = [1, 2, 3, 4, 5, ...... 100000000]; + for(var i = 0, l = list.length; i < l; i++) { + console.log(list[i]); + } + +在上面的例子中利用 `l = list.length` 來處理 Array 的長度問題。 + +雖然 `length` 屬性是屬於 Array 中其中一個屬性,但是他還使有一定的性能消耗在每次循環的訪問。 +近期 Javascript 使用 **may** 來解決在這上面的效率問題,但是在現在的引擎上還不一定有支援。 + +實際上,不使用暫存 Array 長度的方式比使用暫存的版本還要慢很多。 + +### `length` 的屬性 + +`length` 屬性中的 *getter* 直接回傳在 Array 之中的程度,而 *setter* 可以用來 **刪除** Array。 + + var foo = [1, 2, 3, 4, 5, 6]; + foo.length = 3; + foo; // [1, 2, 3] + + foo.length = 6; + foo.push(4); + foo; // [1, 2, 3, undefined, undefined, undefined, 4] + +在上面的例子可以看到,如果給的長度比較小他就會去刪除 Array 中的數值。如果比較大的話,他就會自己增加一些 `undefined` 的數值進去 + +### 結語 + +為了達到更好的效率,建議使用 `for` 迴圈還有暫存 `length` 的屬性。 +而 `for in` 迴圈則是會讓程式中有更多的錯誤和性能問題。 + diff --git a/doc/zh(Trandition)/core/delete.md b/doc/zh(Trandition)/core/delete.md new file mode 100644 index 00000000..067fcfdb --- /dev/null +++ b/doc/zh(Trandition)/core/delete.md @@ -0,0 +1,85 @@ +## The `delete` Operator + +In short, it's *impossible* to delete global variables, functions and some other +stuff in JavaScript which have a `DontDelete` attribute set. + +### Global code and Function code + +When a variable or a function is defined in a global or a [function +scope](#function.scopes) it is a property of either the Activation object or +the Global object. Such properties have a set of attributes, one of which is +`DontDelete`. Variable and function declarations in global and function code +always create properties with `DontDelete`, and therefore cannot be deleted. + + // global variable: + var a = 1; // DontDelete is set + delete a; // false + a; // 1 + + // normal function: + function f() {} // DontDelete is set + delete f; // false + typeof f; // "function" + + // reassigning doesn't help: + f = 1; + delete f; // false + f; // 1 + +### Explicit properties + +Explicitly set properties can be deleted normally. + + // explicitly set property: + var obj = {x: 1}; + obj.y = 2; + delete obj.x; // true + delete obj.y; // true + obj.x; // undefined + obj.y; // undefined + +In the example above, `obj.x` and `obj.y` can be deleted because they have no +`DontDelete` atribute. That's why the example below works too. + + // this works fine, except for IE: + var GLOBAL_OBJECT = this; + GLOBAL_OBJECT.a = 1; + a === GLOBAL_OBJECT.a; // true - just a global var + delete GLOBAL_OBJECT.a; // true + GLOBAL_OBJECT.a; // undefined + +Here we use a trick to delete `a`. [`this`](#function.this) here refers +to the Global object and we explicitly declare variable `a` as its property +which allows us to delete it. + +IE (at least 6-8) has some bugs, so the code above doesn't work. + +### Function arguments and built-ins + +Functions' normal arguments, [`arguments` objects](#function.arguments) +and built-in properties also have `DontDelete` set. + + // function arguments and properties: + (function (x) { + + delete arguments; // false + typeof arguments; // "object" + + delete x; // false + x; // 1 + + function f(){} + delete f.length; // false + typeof f.length; // "number" + + })(1); + +### Host objects + +The behaviour of `delete` operator can be unpredictable for hosted objects. Due +to the specification, host objects are allowed to implement any kind of behavior. + +### In conclusion + +The `delete` operator often has unexpected behaviour and can only be safely +used to delete explicitly set properties on normal objects. diff --git a/doc/zh(Trandition)/core/eval.md b/doc/zh(Trandition)/core/eval.md new file mode 100644 index 00000000..e1b14292 --- /dev/null +++ b/doc/zh(Trandition)/core/eval.md @@ -0,0 +1,42 @@ +## 為什麼不要使用 `eval` + +因為 `eval` 函數會在 Javascript 的區域性的區間執行那段程式碼。 + + var foo = 1; + function test() { + var foo = 2; + eval('foo = 3'); + return foo; + } + test(); // 3 + foo; // 1 + +但是, `eval` 只接受直接的呼叫而且那個函數只能叫做 `eval`,才能在一個區段中執行。 + + var foo = 1; + function test() { + var foo = 2; + var bar = eval; + bar('foo = 3'); + return foo; + } + test(); // 2 + foo; // 3 + +所有的 `eval` 都應該去比免試用。有 99.9% 的使用情況都可以 **不必** 使用到而達到同等效果。 + +### 偽裝的 `eval` + +[定時函數](#other.timeouts) `setTimeout` 和 `setInterval` 都可以接受一個字串當做他們第一個參數。這些字串 **永遠** 都會在全域範圍內執行,因此在這種情況下 `eval` 沒有被直接的使用。 + +### 安全上的顧慮 + +`eval` 同樣有安全上的問題,因為所有的程式碼都可以被直接執行。 +而他不應去執行一串未知的字串或是來自不幸任的來源。 + +### 結語 + +`eval` 應該永遠不要去只用它,任何的程式在被他執行後都有性能和安全上的考慮。如果有情況需要去使用他,他都不應該列為第一順位的解決方法。 + +應該有更好的方法能夠去使用,但是最好都不要去使用 `eval`。 + diff --git a/doc/zh(Trandition)/core/semicolon.md b/doc/zh(Trandition)/core/semicolon.md new file mode 100644 index 00000000..02a3ac35 --- /dev/null +++ b/doc/zh(Trandition)/core/semicolon.md @@ -0,0 +1,103 @@ +## 自動插入分號 + +雖然 JavaScript 有 C 語言的語法,但是他不強制一定要加上分號。 +所以分號可以被忽略。 + +Javascript 並 **不是** 一個不需要分號的語言。實際上,它需要分號來讓程式碼更容易被理解。因此 Javascript 的編譯器中遇到了缺少分號的情形,它會自動的在程式碼中插入分號。 + + var foo = function() { + } // 編輯錯誤,因沒分號 + test() + +這時候編譯器在編輯的時候,會自動的加上分號,然後重新編輯。 + + var foo = function() { + }; // 沒有錯誤,編輯繼續 + test() + +自動的加入分號是被認為 **最大** 的設計缺陷之一,因為它能改變程式碼的行為。 + +### 工作原理 + +下面的程式碼中沒有使用任何的分號,所以編譯器需要去決定在哪些地方加入分號。 + + (function(window, undefined) { + function test(options) { + log('testing!') + + (options.list || []).forEach(function(i) { + + }) + + options.value.test( + 'long string to pass here', + 'and another long string to pass' + ) + + return + { + foo: function() {} + } + } + window.test = test + + })(window) + + (function(window) { + window.someLibrary = {} + + })(window) + +下面的程式碼是編譯器 **猜測** 的結果。 + + (function(window, undefined) { + function test(options) { + + // 沒有加入分號,兩行被合併為一行 + log('testing!')(options.list || []).forEach(function(i) { + + }); // <- 插入分號 + + options.value.test( + 'long string to pass here', + 'and another long string to pass' + ); // <- 插入分號 + + return; // <- 插入分號,改變了 return 的表達行為 + { // 作為另一個程式碼的處理 + + // 被當做一個獨立的函數來看 + foo: function() {} + }; // <- 插入分號 + } + window.test = test; // <- 插入分號 + + // 兩行又被合併 + })(window)(function(window) { + window.someLibrary = {}; // <- 插入分號 + + })(window); //<- 插入分號 + +> **注意:** 在這個範例中 Javascript 編譯器沒有正確的處理 `return` ,因為緊接的換行符號。 +> 雖然這不能算是自動分號插入的錯誤,但是它是非常不樂見的效果。 + +編譯器在上面的程式碼中改變了原本程式碼的行為。在一些情況下,會做出 **錯誤的行為** + +### 前置括號 + +在這種前置括號的情況下,編譯器 **不會** 自動的插入分號。 + + log('testing!') + (options.list || []).forEach(function(i) {}) + +上面的程式碼被編譯器轉為只有一行程式 + + log('testing!')(options.list || []).forEach(function(i) {}) + +以上的範例中 `log` 有 **很大** 的可能 **不是** 回傳一個函數。然而這個情況下會出現 `TypeError` 的錯誤或是會出現 `undefined is not a function` . + +### 結語 + +建議永遠 **不要** 忽略分號。同樣的也建議大括號應在他對應的表達式在同一行。在 `if... else...`的表達式中也是如此,不應省略大括號。 +這個習慣可以不僅僅是讓你的程式更一致,也可以避免編譯器因為改變程式而出錯。 + diff --git a/doc/zh(Trandition)/core/undefined.md b/doc/zh(Trandition)/core/undefined.md new file mode 100644 index 00000000..51101912 --- /dev/null +++ b/doc/zh(Trandition)/core/undefined.md @@ -0,0 +1,70 @@ +## `undefined` 和 `null` + +JavaScript 中有兩個表示空值的方式, `null` 和 `undefined` , `undefined`式比較常用的一種。 + +### `undefined` 的值 + +`undefined` 是一個值為 `undefined` 的類型。 + +語言中也定義了一個全域變數,它的值為 `undefined`,這個變數的被稱作 `undefined` 。 +這個變數 **不是** 一個常數,也不是一個關鍵字。這表示它的值可以被輕易的覆蓋。 + +> **ES5 提示: ** `undefined` 在 ECMAScript 5 裡 **不再是** *可寫* 的 +> 但是它的名稱還是可以被隱藏,比如說定義一個函數為 `undefined`。 + +這裡有一些例子會回傳 `undefined` 的值: + + - Accessing the (unmodified) global variable `undefined`. + - Accessing a declared *but not* yet initialized variable. + - Implicit returns of functions due to missing `return` statements. + - `return` statements that do not explicitly return anything. + - Lookups of non-existent properties. + - Function parameters that do not have any explicit value passed. + - Anything that has been set to the value of `undefined`. + - Any expression in the form of `void(expression)` + +### Handling Changes to the Value of `undefined` + +Since the global variable `undefined` only holds a copy of the actual *value* of +`undefined`, assigning a new value to it does **not** change the value of the +*type* `undefined`. + +Still, in order to compare something against the value of `undefined`, it is +necessary to retrieve the value of `undefined` first. + +To protect code against a possible overwritten `undefined` variable, a common +technique used is to add an additional parameter to an [anonymous +wrapper](#function.scopes) that gets no argument passed to it. + + var undefined = 123; + (function(something, foo, undefined) { + // undefined in the local scope does + // now again refer to the value `undefined` + + })('Hello World', 42); + +Another way to achieve the same effect would be to use a declaration inside the +wrapper. + + var undefined = 123; + (function(something, foo) { + var undefined; + ... + + })('Hello World', 42); + +The only difference here is that this version results in 4 more bytes being +used in case it is minified, and there is no other `var` statement inside the +anonymous wrapper. + +### Uses of `null` + +While `undefined` in the context of the JavaScript language is mostly used in +the sense of a traditional *null*, the actual `null` (both a literal and a type) +is more or less just another data type. + +It is used in some JavaScript internals (like declaring the end of the +prototype chain by setting `Foo.prototype = null`), but in almost all cases, it +can be replaced by `undefined`. + + diff --git a/doc/zh(Trandition)/function/arguments.md b/doc/zh(Trandition)/function/arguments.md new file mode 100644 index 00000000..2394177d --- /dev/null +++ b/doc/zh(Trandition)/function/arguments.md @@ -0,0 +1,118 @@ +## The `arguments` Object + +Every function scope in JavaScript can access the special variable `arguments`. +This variable holds a list of all the arguments that were passed to the function. + +> **Note:** In case `arguments` has already been defined inside the function's +> scope either via a `var` statement or being the name of a formal parameter, +> the `arguments` object will not be created. + +The `arguments` object is **not** an `Array`. While it has some of the +semantics of an array - namely the `length` property - it does not inherit from +`Array.prototype` and is in fact an `Object`. + +Due to this, it is **not** possible to use standard array methods like `push`, +`pop` or `slice` on `arguments`. While iteration with a plain `for` loop works +just fine, it is necessary to convert it to a real `Array` in order to use the +standard `Array` methods on it. + +### Converting to an Array + +The code below will return a new `Array` containing all the elements of the +`arguments` object. + + Array.prototype.slice.call(arguments); + +Because this conversion is **slow**, it is **not recommended** to use it in +performance-critical sections of code. + +### Passing Arguments + +The following is the recommended way of passing arguments from one function to +another. + + function foo() { + bar.apply(null, arguments); + } + function bar(a, b, c) { + // do stuff here + } + +Another trick is to use both `call` and `apply` together to create fast, unbound +wrappers. + + function Foo() {} + + Foo.prototype.method = function(a, b, c) { + console.log(this, a, b, c); + }; + + // Create an unbound version of "method" + // It takes the parameters: this, arg1, arg2...argN + Foo.method = function() { + + // Result: Foo.prototype.method.call(this, arg1, arg2... argN) + Function.call.apply(Foo.prototype.method, arguments); + }; + + +### Formal Parameters and Arguments Indices + +The `arguments` object creates *getter* and *setter* functions for both its +properties, as well as the function's formal parameters. + +As a result, changing the value of a formal parameter will also change the value +of the corresponding property on the `arguments` object, and the other way around. + + 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); + +### Performance Myths and Truths + +The only time the `arguments` object is not created is where it is declared as +a name inside of a function or one of its formal parameters. It does not matter +whether it is used or not. + +Both *getters* and *setters* are **always** created; thus, using it has nearly +no performance impact at all, especially not in real world code where there is +more than a simple access to the `arguments` object's properties. + +> **ES5 Note:** These *getters* and *setters* are not created in strict mode. + +However, there is one case which will drastically reduce the performance in +modern JavaScript engines. That case is the use of `arguments.callee`. + + function foo() { + arguments.callee; // do something with this function object + arguments.callee.caller; // and the calling function object + } + + function bigLoop() { + for(var i = 0; i < 100000; i++) { + foo(); // Would normally be inlined... + } + } + +In the above code, `foo` can no longer be a subject to [inlining][1] since it +needs to know about both itself and its caller. This not only defeats possible +performance gains that would arise from inlining, but it also breaks encapsulation +because the function may now be dependent on a specific calling context. + +Making use of `arguments.callee` or any of its properties is **highly discouraged**. + +> **ES5 Note:** In strict mode, `arguments.callee` will throw a `TypeError` since +> its use has been deprecated. + +[1]: http://en.wikipedia.org/wiki/Inlining + + diff --git a/doc/zh(Trandition)/function/closures.md b/doc/zh(Trandition)/function/closures.md new file mode 100644 index 00000000..76f2d078 --- /dev/null +++ b/doc/zh(Trandition)/function/closures.md @@ -0,0 +1,98 @@ +## Closures and References + +One of JavaScript's most powerful features is the availability of *closures*. +With closures, scopes **always** keep access to the outer scope, in which they +were defined. Since the only scoping that JavaScript has is +[function scope](#function.scopes), all functions, by default, act as closures. + +### Emulating private variables + + function Counter(start) { + var count = start; + return { + increment: function() { + count++; + }, + + get: function() { + return count; + } + } + } + + var foo = Counter(4); + foo.increment(); + foo.get(); // 5 + +Here, `Counter` returns **two** closures: the function `increment` as well as +the function `get`. Both of these functions keep a **reference** to the scope of +`Counter` and, therefore, always keep access to the `count` variable that was +defined in that scope. + +### Why Private Variables Work + +Since it is not possible to reference or assign scopes in JavaScript, there is +**no** way of accessing the variable `count` from the outside. The only way to +interact with it is via the two closures. + + var foo = new Counter(4); + foo.hack = function() { + count = 1337; + }; + +The above code will **not** change the variable `count` in the scope of `Counter`, +since `foo.hack` was not defined in **that** scope. It will instead create - or +override - the *global* variable `count`. + +### Closures Inside Loops + +One often made mistake is to use closures inside of loops, as if they were +copying the value of the loop's index variable. + + for(var i = 0; i < 10; i++) { + setTimeout(function() { + console.log(i); + }, 1000); + } + +The above will **not** output the numbers `0` through `9`, but will simply print +the number `10` ten times. + +The *anonymous* function keeps a **reference** to `i`. At the time +`console.log` gets called, the `for loop` has already finished, and the value of +`i` as been set to `10`. + +In order to get the desired behavior, it is necessary to create a **copy** of +the value of `i`. + +### Avoiding the Reference Problem + +In order to copy the value of the loop's index variable, it is best to use an +[anonymous wrapper](#function.scopes). + + for(var i = 0; i < 10; i++) { + (function(e) { + setTimeout(function() { + console.log(e); + }, 1000); + })(i); + } + +The anonymous outer function gets called immediately with `i` as its first +argument and will receive a copy of the **value** of `i` as its parameter `e`. + +The anonymous function that gets passed to `setTimeout` now has a reference to +`e`, whose value does **not** get changed by the loop. + +There is another possible way of achieving this, which is to return a function +from the anonymous wrapper that will then have the same behavior as the code +above. + + for(var i = 0; i < 10; i++) { + setTimeout((function(e) { + return function() { + console.log(e); + } + })(i), 1000) + } + diff --git a/doc/zh(Trandition)/function/constructors.md b/doc/zh(Trandition)/function/constructors.md new file mode 100644 index 00000000..bf9771dc --- /dev/null +++ b/doc/zh(Trandition)/function/constructors.md @@ -0,0 +1,128 @@ +## Constructors + +Constructors in JavaScript are yet again different from many other languages. Any +function call that is preceded by the `new` keyword acts as a constructor. + +Inside the constructor - the called function - the value of `this` refers to a +newly created object. The [prototype](#object.prototype) of this **new** +object is set to the `prototype` of the function object that was invoked as the +constructor. + +If the function that was called has no explicit `return` statement, then it +implicitly returns the value of `this` - the new object. + + function Foo() { + this.bla = 1; + } + + Foo.prototype.test = function() { + console.log(this.bla); + }; + + var test = new Foo(); + +The above calls `Foo` as constructor and sets the `prototype` of the newly +created object to `Foo.prototype`. + +In case of an explicit `return` statement, the function returns the value +specified by that statement, but **only** if the return value is an `Object`. + + function Bar() { + return 2; + } + new Bar(); // a new object + + function Test() { + this.value = 2; + + return { + foo: 1 + }; + } + new Test(); // the returned object + +When the `new` keyword is omitted, the function will **not** return a new object. + + function Foo() { + this.bla = 1; // gets set on the global object + } + Foo(); // undefined + +While the above example might still appear to work in some cases, due to the +workings of [`this`](#function.this) in JavaScript, it will use the +*global object* as the value of `this`. + +### Factories + +In order to be able to omit the `new` keyword, the constructor function has to +explicitly return a value. + + function Bar() { + var value = 1; + return { + method: function() { + return value; + } + } + } + Bar.prototype = { + foo: function() {} + }; + + new Bar(); + Bar(); + +Both calls to `Bar` return the same thing, a newly create object that +has a property called `method`, which is a +[Closure](#function.closures). + +It should also be noted that the call `new Bar()` does **not** affect the +prototype of the returned object. While the prototype will be set on the newly +created object, `Bar` never returns that new object. + +In the above example, there is no functional difference between using and +not using the `new` keyword. + + +### Creating New Objects via Factories + +It is often recommended to **not** use `new` because forgetting its use may +lead to bugs. + +In order to create a new object, one should rather use a factory and construct a +new object inside of that factory. + + function Foo() { + var obj = {}; + obj.value = 'blub'; + + var private = 2; + obj.someMethod = function(value) { + this.value = value; + } + + obj.getPrivate = function() { + return private; + } + return obj; + } + +While the above is robust against a missing `new` keyword and certainly makes +the use of [private variables](#function.closures) easier, it comes with some +downsides. + + 1. It uses more memory since the created objects do **not** share the methods + on a prototype. + 2. In order to inherit, the factory needs to copy all the methods from another + object or put that object on the prototype of the new object. + 3. Dropping the prototype chain just because of a left out `new` keyword + is contrary to the spirit of the language. + +### In Conclusion + +While omitting the `new` keyword might lead to bugs, it is certainly **not** a +reason to drop the use of prototypes altogether. In the end it comes down to +which solution is better suited for the needs of the application. It is +especially important to choose a specific style of object creation and use it +**consistently**. + diff --git a/doc/zh(Trandition)/function/general.md b/doc/zh(Trandition)/function/general.md new file mode 100644 index 00000000..b2788e46 --- /dev/null +++ b/doc/zh(Trandition)/function/general.md @@ -0,0 +1,48 @@ +## Function Declarations and Expressions + +Functions in JavaScript are first class objects. That means they can be +passed around like any other value. One common use of this feature is to pass +an *anonymous function* as a callback to another, possibly an asynchronous function. + +### The `function` Declaration + + function foo() {} + +The above function gets [hoisted](#function.scopes) before the execution of the +program starts; thus, it is available *everywhere* in the scope it was +*defined*, even if called before the actual definition in the source. + + foo(); // Works because foo was created before this code runs + function foo() {} + +### The `function` Expression + + var foo = function() {}; + +This example assigns the unnamed and *anonymous* function to the variable `foo`. + + foo; // 'undefined' + foo(); // this raises a TypeError + var foo = function() {}; + +Due to the fact that `var` is a declaration that hoists the variable name `foo` +before the actual execution of the code starts, `foo` is already defined when +the script gets executed. + +But since assignments only happen at runtime, the value of `foo` will default +to [undefined](#core.undefined) before the corresponding code is executed. + +### Named Function Expression + +Another special case is the assignment of named functions. + + var foo = function bar() { + bar(); // Works + } + bar(); // ReferenceError + +Here, `bar` is not available in the outer scope, since the function only gets +assigned to `foo`; however, inside of `bar`, it is available. This is due to +how [name resolution](#function.scopes) in JavaScript works, the name of the +function is *always* made available in the local scope of the function itself. + diff --git a/doc/zh(Trandition)/function/scopes.md b/doc/zh(Trandition)/function/scopes.md new file mode 100644 index 00000000..879e1e8a --- /dev/null +++ b/doc/zh(Trandition)/function/scopes.md @@ -0,0 +1,233 @@ +## Scopes and Namespaces + +Although JavaScript deals fine with the syntax of two matching curly +braces for blocks, it does **not** support block scope; hence, all that is left +in the language is *function scope*. + + function test() { // a scope + for(var i = 0; i < 10; i++) { // not a scope + // count + } + console.log(i); // 10 + } + +> **Note:** When not used in an assignment, return statement or as a function +> argument, the `{...}` notation will get interpreted as a block statement and +> **not** as an object literal. This, in conjunction with +> [automatic insertion of semicolons](#core.semicolon), can lead to subtle errors. + +There are also no distinct namespaces in JavaScript, which means that everything +gets defined in one *globally shared* namespace. + +Each time a variable is referenced, JavaScript will traverse upwards through all +the scopes until it finds it. In the case that it reaches the global scope and +still has not found the requested name, it will raise a `ReferenceError`. + +### The Bane of Global Variables + + // script A + foo = '42'; + + // script B + var foo = '42' + +The above two scripts do **not** have the same effect. Script A defines a +variable called `foo` in the *global* scope, and script B defines a `foo` in the +*current* scope. + +Again, that is **not** at all the *same effect*: not using `var` can have major +implications. + + // global scope + var foo = 42; + function test() { + // local scope + foo = 21; + } + test(); + foo; // 21 + +Leaving out the `var` statement inside the function `test` will override the +value of `foo`. While this might not seem like a big deal at first, having +thousands of lines of JavaScript and not using `var` will introduce horrible, +hard-to-track-down bugs. + + // global scope + var items = [/* some list */]; + for(var i = 0; i < 10; i++) { + subLoop(); + } + + function subLoop() { + // scope of subLoop + for(i = 0; i < 10; i++) { // missing var statement + // do amazing stuff! + } + } + +The outer loop will terminate after the first call to `subLoop`, since `subLoop` +overwrites the global value of `i`. Using a `var` for the second `for` loop would +have easily avoided this error. The `var` statement should **never** be left out +unless the *desired effect* is to affect the outer scope. + +### Local Variables + +The only source for local variables in JavaScript are +[function](#function.general) parameters and variables declared via the +`var` statement. + + // global scope + var foo = 1; + var bar = 2; + var i = 2; + + function test(i) { + // local scope of the function test + i = 5; + + var foo = 3; + bar = 4; + } + test(10); + +While `foo` and `i` are local variables inside the scope of the function `test`, +the assignment of `bar` will override the global variable with the same name. + +### Hoisting + +JavaScript **hoists** declarations. This means that both `var` statements and +`function` declarations will be moved to the top of their enclosing scope. + + 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]; + } + } + +The above code gets transformed before execution starts. JavaScript moves +the `var` statements, as well as `function` declarations, to the top of the +nearest surrounding scope. + + // var statements got moved here + var bar, someValue; // default to 'undefined' + + // the function declaration got moved up too + function test(data) { + var goo, i, e; // missing block scope moves these here + if (false) { + goo = 1; + + } else { + goo = 2; + } + for(i = 0; i < 100; i++) { + e = data[i]; + } + } + + bar(); // fails with a TypeError since bar is still 'undefined' + someValue = 42; // assignments are not affected by hoisting + bar = function() {}; + + test(); + +Missing block scoping will not only move `var` statements out of loops and +their bodies, it will also make the results of certain `if` constructs +non-intuitive. + +In the original code, although the `if` statement seemed to modify the *global +variable* `goo`, it actually modifies the *local variable* - after hoisting +has been applied. + +Without knowledge of *hoisting*, one might suspect the code below would raise a +`ReferenceError`. + + // check whether SomeImportantThing has been initialized + if (!SomeImportantThing) { + var SomeImportantThing = {}; + } + +But of course, this works due to the fact that the `var` statement is being +moved to the top of the *global scope*. + + var SomeImportantThing; + + // other code might initialize SomeImportantThing here, or not + + // make sure it's there + if (!SomeImportantThing) { + SomeImportantThing = {}; + } + +### Name Resolution Order + +All scopes in JavaScript, including the *global scope*, have the special name +[`this`](#function.this), defined in them, which refers to the *current object*. + +Function scopes also have the name [`arguments`](#function.arguments), defined in +them, which contains the arguments that were passed to the function. + +For example, when trying to access a variable named `foo` inside the scope of a +function, JavaScript will look up the name in the following order: + + 1. In case there is a `var foo` statement in the current scope, use that. + 2. If one of the function parameters is named `foo`, use that. + 3. If the function itself is called `foo`, use that. + 4. Go to the next outer scope, and start with **#1** again. + +> **Note:** Having a parameter called `arguments` will **prevent** the creation +> of the default `arguments` object. + +### Namespaces + +A common problem associated with having only one global namespace is the +likelihood of running into problems where variable names clash. In JavaScript, +this problem can easily be avoided with the help of *anonymous wrappers*. + + (function() { + // a self contained "namespace" + + window.foo = function() { + // an exposed closure + }; + + })(); // execute the function immediately + + +Unnamed functions are considered [expressions](#function.general); so in order to +being callable, they must first be evaluated. + + ( // evaluate the function inside the parentheses + function() {} + ) // and return the function object + () // call the result of the evaluation + +There are other ways to evaluate and directly call the function expression +which, while different in syntax, behave the same way. + + // A few other styles for directly invoking the + !function(){}() + +function(){}() + (function(){}()); + // and so on... + +### In Conclusion + +It is recommended to always use an *anonymous wrapper* to encapsulate code in +its own namespace. This does not only protect code against name clashes, but it +also allows for better modularization of programs. + +Additionally, the use of global variables is considered **bad practice**. **Any** +use of them indicates badly written code that is prone to errors and hard to maintain. + diff --git a/doc/zh(Trandition)/function/this.md b/doc/zh(Trandition)/function/this.md new file mode 100644 index 00000000..48070d2e --- /dev/null +++ b/doc/zh(Trandition)/function/this.md @@ -0,0 +1,111 @@ +## How `this` Works + +JavaScript has a different concept of what the special name `this` refers to +than most other programming languages. There are exactly **five** different +ways in which the value of `this` can be bound in the language. + +### The Global Scope + + this; + +When using `this` in global scope, it will simply refer to the *global* object. + + +### Calling a Function + + foo(); + +Here, `this` will again refer to the *global* object. + +> **ES5 Note:** In strict mode, the global case **no longer** exists. +> `this` will instead have the value of `undefined` in that case. + +### Calling a Method + + test.foo(); + +In this example, `this` will refer to `test`. + +### Calling a Constructor + + new foo(); + +A function call that is preceded by the `new` keyword acts as +a [constructor](#function.constructors). Inside the function, `this` will refer +to a *newly created* `Object`. + +### Explicit Setting of `this` + + function foo(a, b, c) {} + + var bar = {}; + foo.apply(bar, [1, 2, 3]); // array will expand to the below + foo.call(bar, 1, 2, 3); // results in a = 1, b = 2, c = 3 + +When using the `call` or `apply` methods of `Function.prototype`, the value of +`this` inside the called function gets **explicitly set** to the first argument +of the corresponding function call. + +As a result, in the above example the *method case* does **not** apply, and `this` +inside of `foo` will be set to `bar`. + +> **Note:** `this` **cannot** be used to refer to the object inside of an `Object` +> literal. So `var obj = {me: this}` will **not** result in `me` referring to +> `obj`, since `this` only gets bound by one of the five listed cases. + +### Common Pitfalls + +While most of these cases make sense, the first can be considered another +mis-design of the language because it **never** has any practical use. + + Foo.method = function() { + function test() { + // this is set to the global object + } + test(); + } + +A common misconception is that `this` inside of `test` refers to `Foo`; while in +fact, it **does not**. + +In order to gain access to `Foo` from within `test`, it is necessary to create a +local variable inside of `method` that refers to `Foo`. + + Foo.method = function() { + var that = this; + function test() { + // Use that instead of this here + } + test(); + } + +`that` is just a normal variable name, but it is commonly used for the reference to an +outer `this`. In combination with [closures](#function.closures), it can also +be used to pass `this` values around. + +### Assigning Methods + +Another thing that does **not** work in JavaScript is function aliasing, which is +**assigning** a method to a variable. + + var test = someObject.methodTest; + test(); + +Due to the first case, `test` now acts like a plain function call; therefore, +`this` inside it will no longer refer to `someObject`. + +While the late binding of `this` might seem like a bad idea at first, in +fact, it is what makes [prototypal inheritance](#object.prototype) work. + + function Foo() {} + Foo.prototype.method = function() {}; + + function Bar() {} + Bar.prototype = Foo.prototype; + + new Bar().method(); + +When `method` gets called on an instance of `Bar`, `this` will now refer to that +very instance. + + diff --git a/doc/zh(Trandition)/index.json b/doc/zh(Trandition)/index.json new file mode 100644 index 00000000..bffcbf2c --- /dev/null +++ b/doc/zh(Trandition)/index.json @@ -0,0 +1,69 @@ +{ + "title": "JavaScript Garden", + "langTitle": "JavaScript Garden in English", + "description": "A Guide to JavaScript's Quirks and Flaws.", + "sections": [ + { + "title": "Intro", + "dir": "intro", + "articles": [] + }, + { + "title": "Objects", + "dir": "object", + "articles": [ + "general", + "prototype", + "hasownproperty", + "forinloop" + ] + }, + { + "title": "Functions", + "dir": "function", + "articles": [ + "general", + "this", + "closures", + "arguments", + "constructors", + "scopes" + ] + }, + { + "title": "Arrays", + "dir": "array", + "articles": [ + "general", + "constructor" + ] + }, + { + "title": "Types", + "dir": "types", + "articles": [ + "equality", + "typeof", + "instanceof", + "casting" + ] + }, + { + "title": "Core", + "dir": "core", + "articles": [ + "eval", + "undefined", + "semicolon", + "delete" + ] + }, + { + "title": "Other", + "dir": "other", + "articles": [ + "timeouts" + ] + } + ] +} diff --git a/doc/zh(Trandition)/intro/index.md b/doc/zh(Trandition)/intro/index.md new file mode 100644 index 00000000..134bca80 --- /dev/null +++ b/doc/zh(Trandition)/intro/index.md @@ -0,0 +1,47 @@ +## Intro + +**JavaScript Garden** is a growing collection of documentation about the most +quirky parts of the JavaScript programming language. It gives advice to +avoid common mistakes and subtle bugs, as well as performance issues and bad +practices, that non-expert JavaScript programmers may encounter on their +endeavours into the depths of the language. + +JavaScript Garden does **not** aim to teach you JavaScript. Former knowledge +of the language is strongly recommended in order to understand the topics covered +in this guide. In order to learn the basics of the language, please head over to +the excellent [guide][1] on the Mozilla Developer Network. + +## The Authors + +This guide is the work of two lovely [Stack Overflow][2] users, [Ivo Wetzel][3] +(Writing) and [Zhang Yi Jiang][4] (Design). + +## Contributors + + - [Caio Romão][5] (Spelling corrections) + - [Andreas Blixt][6] (Language corrections) + +## Hosting + +JavaScript Garden is hosted on GitHub, but [Cramer Development][7] supports us +with a mirror at [JavaScriptGarden.info][8]. + +## License + +JavaScript Garden is published under the [MIT license][9] and hosted on +[GitHub][10]. If you find errors or typos please [file an issue][11] or a pull +request on the repository. You can also find us in the [JavaScript room][12] on +Stack Overflow chat. + +[1]: https://developer.mozilla.org/en/JavaScript/Guide +[2]: http://stackoverflow.com/ +[3]: http://stackoverflow.com/users/170224/ivo-wetzel +[4]: http://stackoverflow.com/users/313758/yi-jiang +[5]: https://github.com/caio +[6]: https://github.com/blixt +[7]: http://cramerdev.com/ +[8]: http://javascriptgarden.info/ +[9]: https://github.com/BonsaiDen/JavaScript-Garden/blob/next/LICENSE +[10]: https://github.com/BonsaiDen/JavaScript-Garden +[11]: https://github.com/BonsaiDen/JavaScript-Garden/issues +[12]: http://chat.stackoverflow.com/rooms/17/javascript diff --git a/doc/zh(Trandition)/object/forinloop.md b/doc/zh(Trandition)/object/forinloop.md new file mode 100644 index 00000000..3d366f8c --- /dev/null +++ b/doc/zh(Trandition)/object/forinloop.md @@ -0,0 +1,51 @@ +## The `for in` Loop + +Just like the `in` operator, the `for in` loop traverses the prototype +chain when iterating over the properties of an object. + +> **Note:** The `for in` loop will **not** iterate over any properties that +> have their `enumerable` attribute set to `false`; for example, the `length` +> property of an array. + + // Poisoning Object.prototype + Object.prototype.bar = 1; + + var foo = {moo: 2}; + for(var i in foo) { + console.log(i); // prints both bar and moo + } + +Since it is not possible to change the behavior of the `for in` loop itself, it +is necessary to filter out the unwanted properties inside the loop body; +this is done using the [`hasOwnProperty`](#object.hasownproperty) method of +`Object.prototype`. + +> **Note:** Since `for in` always traverses the complete prototype chain, it +> will get slower with each additional layer of inheritance added to an object. + +### Using `hasOwnProperty` for Filtering + + // still the foo from above + for(var i in foo) { + if (foo.hasOwnProperty(i)) { + console.log(i); + } + } + +This version is the only correct one to use. Due to the use of `hasOwnProperty`, it +will **only** print out `moo`. When `hasOwnProperty` is left out, the code is +prone to errors in cases where the native prototypes - e.g. `Object.prototype` - +have been extended. + +One widely used framework that extends `Object.prototype` is [Prototype][1]. +When this framework is included, `for in` loops that do not use +`hasOwnProperty` are guaranteed to break. + +### In Conclusion + +It is recommended to **always** use `hasOwnProperty`. Assumptions should never +be made about the environment the code is running in, or whether the native +prototypes have been extended or not. + +[1]: http://www.prototypejs.org/ + diff --git a/doc/zh(Trandition)/object/general.md b/doc/zh(Trandition)/object/general.md new file mode 100644 index 00000000..9300b18e --- /dev/null +++ b/doc/zh(Trandition)/object/general.md @@ -0,0 +1,99 @@ +## Object Usage and Properties + +Everything in JavaScript acts like an object, with the only two exceptions being +[`null`](#core.undefined) and [`undefined`](#core.undefined). + + false.toString(); // 'false' + [1, 2, 3].toString(); // '1,2,3' + + function Foo(){} + Foo.bar = 1; + Foo.bar; // 1 + +A common misconception is that number literals cannot be used as +objects. That is because a flaw in JavaScript's parser tries to parse the *dot +notation* on a number as a floating point literal. + + 2.toString(); // raises SyntaxError + +There are a couple of workarounds that can be used to make number literals act +as objects too. + + 2..toString(); // the second point is correctly recognized + 2 .toString(); // note the space left to the dot + (2).toString(); // 2 is evaluated first + +### Objects as a Data Type + +Objects in JavaScript can also be used as [*Hashmaps*][1]; they mainly consist +of named properties mapping to values. + +Using an object literal - `{}` notation - it is possible to create a +plain object. This new object [inherits](#object.prototype) from `Object.prototype` and +does not have [own properties](#object.hasownproperty) defined. + + var foo = {}; // a new empty object + + // a new object with a 'test' property with value 12 + var bar = {test: 12}; + +### Accessing Properties + +The properties of an object can be accessed in two ways, via either the dot +notation or the square bracket notation. + + var foo = {name: 'kitten'} + foo.name; // kitten + foo['name']; // kitten + + var get = 'name'; + foo[get]; // kitten + + foo.1234; // SyntaxError + foo['1234']; // works + +The notations work almost identically, with the only difference being that the +square bracket notation allows for dynamic setting of properties and +the use of property names that would otherwise lead to a syntax error. + +### Deleting Properties + +The only way to remove a property from an object is to use the `delete` +operator; setting the property to `undefined` or `null` only removes the +*value* associated with the property, but not the *key*. + + 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]); + } + } + +The above outputs both `bar undefined` and `foo null` - only `baz` was +removed and is therefore missing from the output. + +### Notation of Keys + + var test = { + 'case': 'I am a keyword, so I must be notated as a string', + delete: 'I am a keyword, so me too' // raises SyntaxError + }; + +Object properties can be both notated as plain characters and as strings. Due to +another mis-design in JavaScript's parser, the above will throw +a `SyntaxError` prior to ECMAScript 5. + +This error arises from the fact that `delete` is a *keyword*; therefore, it must be +notated as a *string literal* to ensure that it will be correctly interpreted by +older JavaScript engines. + +[1]: http://en.wikipedia.org/wiki/Hashmap + diff --git a/doc/zh(Trandition)/object/hasownproperty.md b/doc/zh(Trandition)/object/hasownproperty.md new file mode 100644 index 00000000..0033b4ba --- /dev/null +++ b/doc/zh(Trandition)/object/hasownproperty.md @@ -0,0 +1,57 @@ +## `hasOwnProperty` + +To check whether an object has a property defined on *itself* and not somewhere +on its [prototype chain](#object.prototype), it is necessary to use the +`hasOwnProperty` method which all objects inherit from `Object.prototype`. + +> **Note:** It is **not** enough to check whether a property is `undefined`. The +> property might very well exist, but its value just happens to be set to +> `undefined`. + +`hasOwnProperty` is the only thing in JavaScript which deals with properties and +does **not** traverse the prototype chain. + + // Poisoning Object.prototype + Object.prototype.bar = 1; + var foo = {goo: undefined}; + + foo.bar; // 1 + 'bar' in foo; // true + + foo.hasOwnProperty('bar'); // false + foo.hasOwnProperty('goo'); // true + +Only `hasOwnProperty` will give the correct and expected result; this is +essential when iterating over the properties of any object. There is **no** other +way to exclude properties that are not defined on the object itself, but +somewhere on its prototype chain. + +### `hasOwnProperty` as a Property + +JavaScript does not protect the property name `hasOwnProperty`; thus, if the +possibility exists that an object might have a property with this name, it is +necessary to use an *external* `hasOwnProperty` to get correct results. + + var foo = { + hasOwnProperty: function() { + return false; + }, + bar: 'Here be dragons' + }; + + foo.hasOwnProperty('bar'); // always returns false + + // Use another Object's hasOwnProperty and call it with 'this' set to foo + ({}).hasOwnProperty.call(foo, 'bar'); // true + + // It's also possible to use the hasOwnProperty property from the Object property for this purpose + Object.prototype.hasOwnProperty.call(obj, 'bar'); // true + + +### In Conclusion + +Using `hasOwnProperty` is the **only** reliable method to check for the +existence of a property on an object. It is recommended that `hasOwnProperty` +is used in **every** [`for in` loop](#object.forinloop) to avoid errors from +extended native [prototypes](#object.prototype). + diff --git a/doc/zh(Trandition)/object/prototype.md b/doc/zh(Trandition)/object/prototype.md new file mode 100644 index 00000000..abb67c58 --- /dev/null +++ b/doc/zh(Trandition)/object/prototype.md @@ -0,0 +1,118 @@ +## The Prototype + +JavaScript does not feature a classical inheritance model; instead, it uses a +*prototypal* one. + +While this is often considered to be one of JavaScript's weaknesses, the +prototypal inheritance model is in fact more powerful than the classic model. +It is, for example, fairly trivial to build a classic model on top of a +prototypal model, while the other way around is a far more difficult task. + +JavaScript is the only widely used language that features prototypal +inheritance, so it can take time to adjust to the differences between the two +models. + +The first major difference is that inheritance in JavaScript uses *prototype +chains*. + +> **Note:** Simply using `Bar.prototype = Foo.prototype` will result in both objects +> sharing the **same** prototype. Therefore, changes to either object's prototype +> will affect the prototype of the other as well, which in most cases is not the +> desired effect. + + function Foo() { + this.value = 42; + } + Foo.prototype = { + method: function() {} + }; + + function Bar() {} + + // Set Bar's prototype to a new instance of Foo + Bar.prototype = new Foo(); + Bar.prototype.foo = 'Hello World'; + + // Make sure to list Bar as the actual constructor + Bar.prototype.constructor = Bar; + + var test = new Bar() // create a new bar instance + + // The resulting prototype chain + test [instance of Bar] + Bar.prototype [instance of Foo] + { foo: 'Hello World' } + Foo.prototype + { method: ... } + Object.prototype + { toString: ... /* etc. */ } + +In the code above, the object `test` will inherit from both `Bar.prototype` and +`Foo.prototype`; hence, it will have access to the function `method` that was +defined on `Foo`. It will also have access to the property `value` of the +**one** `Foo` instance that is its prototype. It is important to note that `new +Bar()` does **not** create a new `Foo` instance, but reuses the one assigned to +its prototype; thus, all `Bar` instances will share the **same** `value` property. + +> **Note:** Do **not** use `Bar.prototype = Foo`, since it will not point to +> the prototype of `Foo` but rather to the function object `Foo`. So the +> prototype chain will go over `Function.prototype` and not `Foo.prototype`; +> therefore, `method` will not be on the prototype chain. + +### Property Lookup + +When accessing the properties of an object, JavaScript will traverse the +prototype chain **upwards** until it finds a property with the requested name. + +If it reaches the top of the chain - namely `Object.prototype` - and still +hasn't found the specified property, it will return the value +[undefined](#core.undefined) instead. + +### The Prototype Property + +While the prototype property is used by the language to build the prototype +chains, it is still possible to assign **any** given value to it. However, +primitives will simply get ignored when assigned as a prototype. + + function Foo() {} + Foo.prototype = 1; // no effect + +Assigning objects, as shown in the example above, will work, and allows for dynamic +creation of prototype chains. + +### Performance + +The lookup time for properties that are high up on the prototype chain can have +a negative impact on performance, and this may be significant in code where +performance is critical. Additionally, trying to access non-existent properties +will always traverse the full prototype chain. + +Also, when [iterating](#object.forinloop) over the properties of an object +**every** property that is on the prototype chain will be enumerated. + +### Extension of Native Prototypes + +One mis-feature that is often used is to extend `Object.prototype` or one of the +other built in prototypes. + +This technique is called [monkey patching][1] and breaks *encapsulation*. While +used by popular frameworks such as [Prototype][2], there is still no good +reason for cluttering built-in types with additional *non-standard* functionality. + +The **only** good reason for extending a built-in prototype is to backport +the features of newer JavaScript engines; for example, +[`Array.forEach`][3]. + +### In Conclusion + +It is **essential** to understand the prototypal inheritance model before +writing complex code that makes use of it. Also, be aware of the length of the +prototype chains in your code and break them up if necessary to avoid possible +performance problems. Further, the native prototypes should **never** be +extended unless it is for the sake of compatibility with newer JavaScript +features. + +[1]: http://en.wikipedia.org/wiki/Monkey_patch +[2]: http://prototypejs.org/ +[3]: https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/forEach + diff --git a/doc/zh(Trandition)/other/timeouts.md b/doc/zh(Trandition)/other/timeouts.md new file mode 100644 index 00000000..578fad5f --- /dev/null +++ b/doc/zh(Trandition)/other/timeouts.md @@ -0,0 +1,167 @@ +### `setTimeout` and `setInterval` + +Since JavaScript is asynchronous, it is possible to schedule the execution of a +function using the `setTimeout` and `setInterval` functions. + +> **Note:** Timeouts are **not** part of the ECMAScript Standard. They are +> implemented as part of the [DOM][1]. + + function foo() {} + var id = setTimeout(foo, 1000); // returns a Number > 0 + +When `setTimeout` is called, it returns the ID of the timeout and schedule +`foo` to run **approximately** one thousand milliseconds in the future. +`foo` will then be executed **once**. + +Depending on the timer resolution of the JavaScript engine running the code, as +well as the fact that JavaScript is single threaded and other code that gets +executed might block the thread, it is by **no means** a safe bet that one will +get the exact delay specified in the `setTimeout` call. + +The function that was passed as the first parameter will get called by the +*global object*, which means that [`this`](#function.this) inside the called function +refers to the global object. + + function Foo() { + this.value = 42; + this.method = function() { + // this refers to the global object + console.log(this.value); // will log undefined + }; + setTimeout(this.method, 500); + } + new Foo(); + + +> **Note:** As `setTimeout` takes a **function object** as its first parameter, an +> common mistake is to use `setTimeout(foo(), 1000)`, which will use the +> **return value** of the call `foo` and **not** `foo`. This is, most of the time, +> a silent error, since when the function returns `undefined` `setTimeout` will +> **not** raise any error. + +### Stacking Calls with `setInterval` + +While `setTimeout` only runs the function once, `setInterval` - as the name +suggests - will execute the function **every** `X` milliseconds, but its use is +discouraged. + +When code that is being executed blocks the timeout call, `setInterval` will +still issue more calls to the specified function. This can, especially with small +intervals, result in function calls stacking up. + + function foo(){ + // something that blocks for 1 second + } + setInterval(foo, 1000); + +In the above code, `foo` will get called once and will then block for one second. + +While `foo` blocks the code, `setInterval` will still schedule further calls to +it. Now, when `foo` has finished, there will already be **ten** further calls to +it waiting for execution. + +### Dealing with Possible Blocking Code + +The easiest solution, as well as most controllable solution, is to use `setTimeout` within +the function itself. + + function foo(){ + // something that blocks for 1 second + setTimeout(foo, 1000); + } + foo(); + +Not only does this encapsulate the `setTimeout` call, but it also prevents the +stacking of calls and gives additional control. `foo` itself can now decide +whether it wants to run again or not. + +### Manually Clearing Timeouts + +Clearing timeouts and intervals works by passing the respective ID to +`clearTimeout` or `clearInterval`, depending on which `set` function was used +in the first place. + + var id = setTimeout(foo, 1000); + clearTimeout(id); + +### Clearing All Timeouts + +As there is no built-in method for clearing all timeouts and/or intervals, +it is necessary to use brute force in order to achieve this functionality. + + // clear "all" timeouts + for(var i = 1; i < 1000; i++) { + clearTimeout(i); + } + +But there might still be timeouts that are unaffected by this arbitrary number. +Another way of doing this is to consider that the ID given to a timeout is +incremented by one every time you call `setTimeout`. + + // clear "all" timeouts + var biggestTimeoutId = window.setTimeout(function(){}, 1), + i; + for(i = 1; i <= biggestTimeoutId; i++) { + clearTimeout(i); + } + +Even though this works on all major browsers today, it isn't specified that +the IDs should be ordered that way and it may change. Therefore, it is instead +recommended to keep track of all the timeout IDs, so they can be cleared +specifically. + +### Hidden Use of `eval` + +`setTimeout` and `setInterval` can also take a string as their first parameter. +This feature should **never** be used because it internally makes use of `eval`. + +> **Note:** Since the timeout functions are **not** specified by the ECMAScript +> standard, the exact workings when a string is passed to them might differ in +> various JavaScript implementations. For example, Microsoft's JScript uses +> the `Function` constructor in place of `eval`. + + function foo() { + // will get called + } + + function bar() { + function foo() { + // never gets called + } + setTimeout('foo()', 1000); + } + bar(); + +Since `eval` is not getting called [directly](#core.eval) in this case, the string +passed to `setTimeout` will be executed in the *global scope*; thus, it will +not use the local variable `foo` from the scope of `bar`. + +It is further recommended to **not** use a string to pass arguments to the +function that will get called by either of the timeout functions. + + function foo(a, b, c) {} + + // NEVER use this + setTimeout('foo(1, 2, 3)', 1000) + + // Instead use an anonymous function + setTimeout(function() { + foo(a, b, c); + }, 1000) + +> **Note:** While it is also possible to use the syntax +> `setTimeout(foo, 1000, a, b, c)`, it is not recommended, as its use may lead +> to subtle errors when used with [methods](#function.this). + +### In Conclusion + +A string should **never** be used as the parameter of `setTimeout` or +`setInterval`. It is a clear sign of **really** bad code, when arguments need +to be supplied to the function that gets called. An *anonymous function* should +be passed that then takes care of the actual call. + +Furthermore, the use of `setInterval` should be avoided because its scheduler is not +blocked by executing JavaScript. + +[1]: http://en.wikipedia.org/wiki/Document_Object_Model "Document Object Model" + diff --git a/doc/zh(Trandition)/types/casting.md b/doc/zh(Trandition)/types/casting.md new file mode 100644 index 00000000..0dcbc92b --- /dev/null +++ b/doc/zh(Trandition)/types/casting.md @@ -0,0 +1,70 @@ +## Type Casting + +JavaScript is a *weakly typed* language, so it will apply *type coercion* +**wherever** possible. + + // These are true + new Number(10) == 10; // Number.toString() is converted + // back to a number + + 10 == '10'; // Strings gets converted to Number + 10 == '+10 '; // More string madness + 10 == '010'; // And more + isNaN(null) == false; // null converts to 0 + // which of course is not NaN + + // These are false + 10 == 010; + 10 == '-10'; + +> **ES5 Note:** Number literals that start with a `0` are interpreted as octal +> (Base 8). Octal support for these has been **removed** in ECMAScript 5 strict +> mode. + +To avoid the issues above, use of the [strict equal operator](#types.equality) +is **highly** recommended. Although this avoids a lot of common pitfalls, there +are still many further issues that arise from JavaScript's weak typing system. + +### Constructors of Built-In Types + +The constructors of the built in types like `Number` and `String` behave +differently when being used with the `new` keyword and without it. + + new Number(10) === 10; // False, Object and Number + Number(10) === 10; // True, Number and Number + new Number(10) + 0 === 10; // True, due to implicit conversion + +Using a built-in type like `Number` as a constructor will create a new `Number` +object, but leaving out the `new` keyword will make the `Number` function behave +like a converter. + +In addition, passing literals or non-object values will result in even more +type coercion. + +The best option is to cast to one of the three possible types **explicitly**. + +### Casting to a String + + '' + 10 === '10'; // true + +By prepending an empty string, a value can easily be cast to a string. + +### Casting to a Number + + +'10' === 10; // true + +Using the **unary** plus operator, it is possible to cast to a number. + +### Casting to a Boolean + +By using the **not** operator twice, a value can be converted a boolean. + + !!'foo'; // true + !!''; // false + !!'0'; // true + !!'1'; // true + !!'-1' // true + !!{}; // true + !!true; // true + + diff --git a/doc/zh(Trandition)/types/equality.md b/doc/zh(Trandition)/types/equality.md new file mode 100644 index 00000000..e47752a4 --- /dev/null +++ b/doc/zh(Trandition)/types/equality.md @@ -0,0 +1,71 @@ +## Equality and Comparisons + +JavaScript has two different ways of comparing the values of objects for equality. + +### The Equality Operator + +The equality operator consists of two equal signs: `==` + +JavaScript features *weak typing*. This means that the equality operator +**coerces** types in order to compare them. + + "" == "0" // false + 0 == "" // true + 0 == "0" // true + false == "false" // false + false == "0" // true + false == undefined // false + false == null // false + null == undefined // true + " \t\r\n" == 0 // true + +The above table shows the results of the type coercion, and it is the main reason +why the use of `==` is widely regarded as bad practice. It introduces +hard-to-track-down bugs due to its complicated conversion rules. + +Additionally, there is also a performance impact when type coercion is in play; +for example, a string has to be converted to a number before it can be compared +to another number. + +### The Strict Equality Operator + +The strict equality operator consists of **three** equal signs: `===`. + +It works like the normal equality operator, except that strict equality +operator does **not** perform type coercion between its operands. + + "" === "0" // false + 0 === "" // false + 0 === "0" // false + false === "false" // false + false === "0" // false + false === undefined // false + false === null // false + null === undefined // false + " \t\r\n" === 0 // false + +The above results are a lot clearer and allow for early breakage of code. This +hardens code to a certain degree and also gives performance improvements in case +the operands are of different types. + +### Comparing Objects + +While both `==` and `===` are called **equality** operators, they behave +differently when at least one of their operands is an `Object`. + + {} === {}; // false + new String('foo') === 'foo'; // false + new Number(10) === 10; // false + var foo = {}; + foo === foo; // true + +Here, both operators compare for **identity** and **not** equality; that is, they +will compare for the same **instance** of the object, much like `is` in Python +and pointer comparison in C. + +### In Conclusion + +It is highly recommended to only use the **strict equality** operator. In cases +where types need to be coerced, it should be done [explicitly](#types.casting) +and not left to the language's complicated coercion rules. + diff --git a/doc/zh(Trandition)/types/instanceof.md b/doc/zh(Trandition)/types/instanceof.md new file mode 100644 index 00000000..2fe41064 --- /dev/null +++ b/doc/zh(Trandition)/types/instanceof.md @@ -0,0 +1,38 @@ +## The `instanceof` Operator + +The `instanceof` operator compares the constructors of its two operands. It is +only useful when comparing custom made objects. Used on built-in types, it is +nearly as useless as the [typeof operator](#types.typeof). + +### Comparing Custom Objects + + function Foo() {} + function Bar() {} + Bar.prototype = new Foo(); + + new Bar() instanceof Bar; // true + new Bar() instanceof Foo; // true + + // This just sets Bar.prototype to the function object Foo, + // but not to an actual instance of Foo + Bar.prototype = Foo; + new Bar() instanceof Foo; // false + +### Using `instanceof` with Native Types + + new String('foo') instanceof String; // true + new String('foo') instanceof Object; // true + + 'foo' instanceof String; // false + 'foo' instanceof Object; // false + +One important thing to note here is that `instanceof` does not work on objects +that originate from different JavaScript contexts (e.g. different documents +in a web browser), since their constructors will not be the exact same object. + +### In Conclusion + +The `instanceof` operator should **only** be used when dealing with custom made +objects that originate from the same JavaScript context. Just like the +[`typeof`](#types.typeof) operator, every other use of it should be **avoided**. + diff --git a/doc/zh(Trandition)/types/typeof.md b/doc/zh(Trandition)/types/typeof.md new file mode 100644 index 00000000..637ea2bc --- /dev/null +++ b/doc/zh(Trandition)/types/typeof.md @@ -0,0 +1,86 @@ +## The `typeof` Operator + +The `typeof` operator (together with +[`instanceof`](#types.instanceof)) is probably the biggest +design flaw of JavaScript, as it is almost **completely broken**. + +Although `instanceof` still has limited uses, `typeof` really has only one +practical use case, which does **not** happen to be checking the type of an +object. + +> **Note:** While `typeof` can also be called with a function like syntax, i.e. +> `typeof(obj)`, this is not a function call. The parentheses behave as normal +> and the return value will be used as the operand of the `typeof` operator. +> There is **no** `typeof` function. + +### The JavaScript Type Table + + Value Class Type + ------------------------------------- + "foo" String string + new String("foo") String object + 1.2 Number number + new Number(1.2) Number object + true Boolean boolean + new Boolean(true) Boolean object + new Date() Date object + new Error() Error object + [1,2,3] Array object + new Array(1, 2, 3) Array object + new Function("") Function function + /abc/g RegExp object (function in Nitro/V8) + new RegExp("meow") RegExp object (function in Nitro/V8) + {} Object object + new Object() Object object + +In the above table, *Type* refers to the value that the `typeof` operator returns. +As can be clearly seen, this value is anything but consistent. + +The *Class* refers to the value of the internal `[[Class]]` property of an object. + +> **From the Specification:** The value of `[[Class]]` can be one of the +> following strings. `Arguments`, `Array`, `Boolean`, `Date`, `Error`, +> `Function`, `JSON`, `Math`, `Number`, `Object`, `RegExp`, `String`. + +In order to retrieve the value of `[[Class]]`, one has to make use of the +`toString` method of `Object.prototype`. + +### The Class of an Object + +The specification gives exactly one way of accessing the `[[Class]]` value, +with the use of `Object.prototype.toString`. + + function is(type, obj) { + var clas = Object.prototype.toString.call(obj).slice(8, -1); + return obj !== undefined && obj !== null && clas === type; + } + + is('String', 'test'); // true + is('String', new String('test')); // true + +In the above example, `Object.prototype.toString` gets called with the value of +[this](#function.this) being set to the object whose `[[Class]]` value should be +retrieved. + +> **ES5 Note:** For convenience the return value of `Object.prototype.toString` +> for both `null` and `undefined` was **changed** from `Object` to `Null` and +> `Undefined` in ECMAScript 5. + +### Testing for Undefined Variables + + typeof foo !== 'undefined' + +The above will check whether `foo` was actually declared or not; just +referencing it would result in a `ReferenceError`. This is the only thing +`typeof` is actually useful for. + +### In Conclusion + +In order to check the type of an object, it is highly recommended to use +`Object.prototype.toString` because this is the only reliable way of doing so. +As shown in the above type table, some return values of `typeof` are not defined +in the specification; thus, they can differ between implementations. + +Unless checking whether a variable is defined, `typeof` should be avoided. + + From 151456f3bed2db1a99d7e197f3cecdb946acd519 Mon Sep 17 00:00:00 2001 From: howardchi Date: Wed, 13 Mar 2013 22:09:32 +0800 Subject: [PATCH 255/463] finished the part in Array & some in function section --- .gitignore | 1 + doc/zh(Trandition)/core/undefined.md | 70 - doc/zh(Trandition)/function/arguments.md | 118 - .../array/constructor.md | 0 .../array/general.md | 0 doc/{zh(Trandition) => zh-TW}/core/delete.md | 0 doc/{zh(Trandition) => zh-TW}/core/eval.md | 0 .../core/semicolon.md | 0 doc/zh-TW/core/undefined.md | 55 + doc/zh-TW/function/arguments.md | 103 + .../function/closures.md | 0 .../function/constructors.md | 0 .../function/general.md | 0 .../function/scopes.md | 0 .../function/this.md | 0 doc/{zh(Trandition) => zh-TW}/index.json | 0 doc/{zh(Trandition) => zh-TW}/intro/index.md | 0 .../object/forinloop.md | 0 .../object/general.md | 0 .../object/hasownproperty.md | 0 .../object/prototype.md | 0 .../other/timeouts.md | 0 .../types/casting.md | 0 .../types/equality.md | 0 .../types/instanceof.md | 0 doc/{zh(Trandition) => zh-TW}/types/typeof.md | 0 site/zh-TW/index.html | 1913 +++++++++++++++++ 27 files changed, 2072 insertions(+), 188 deletions(-) delete mode 100644 doc/zh(Trandition)/core/undefined.md delete mode 100644 doc/zh(Trandition)/function/arguments.md rename doc/{zh(Trandition) => zh-TW}/array/constructor.md (100%) rename doc/{zh(Trandition) => zh-TW}/array/general.md (100%) rename doc/{zh(Trandition) => zh-TW}/core/delete.md (100%) rename doc/{zh(Trandition) => zh-TW}/core/eval.md (100%) rename doc/{zh(Trandition) => zh-TW}/core/semicolon.md (100%) create mode 100644 doc/zh-TW/core/undefined.md create mode 100644 doc/zh-TW/function/arguments.md rename doc/{zh(Trandition) => zh-TW}/function/closures.md (100%) rename doc/{zh(Trandition) => zh-TW}/function/constructors.md (100%) rename doc/{zh(Trandition) => zh-TW}/function/general.md (100%) rename doc/{zh(Trandition) => zh-TW}/function/scopes.md (100%) rename doc/{zh(Trandition) => zh-TW}/function/this.md (100%) rename doc/{zh(Trandition) => zh-TW}/index.json (100%) rename doc/{zh(Trandition) => zh-TW}/intro/index.md (100%) rename doc/{zh(Trandition) => zh-TW}/object/forinloop.md (100%) rename doc/{zh(Trandition) => zh-TW}/object/general.md (100%) rename doc/{zh(Trandition) => zh-TW}/object/hasownproperty.md (100%) rename doc/{zh(Trandition) => zh-TW}/object/prototype.md (100%) rename doc/{zh(Trandition) => zh-TW}/other/timeouts.md (100%) rename doc/{zh(Trandition) => zh-TW}/types/casting.md (100%) rename doc/{zh(Trandition) => zh-TW}/types/equality.md (100%) rename doc/{zh(Trandition) => zh-TW}/types/instanceof.md (100%) rename doc/{zh(Trandition) => zh-TW}/types/typeof.md (100%) create mode 100644 site/zh-TW/index.html diff --git a/.gitignore b/.gitignore index 237404f0..63b10902 100644 --- a/.gitignore +++ b/.gitignore @@ -15,3 +15,4 @@ /site/es *.md~ *.src.md +*.DS_store diff --git a/doc/zh(Trandition)/core/undefined.md b/doc/zh(Trandition)/core/undefined.md deleted file mode 100644 index 51101912..00000000 --- a/doc/zh(Trandition)/core/undefined.md +++ /dev/null @@ -1,70 +0,0 @@ -## `undefined` 和 `null` - -JavaScript 中有兩個表示空值的方式, `null` 和 `undefined` , `undefined`式比較常用的一種。 - -### `undefined` 的值 - -`undefined` 是一個值為 `undefined` 的類型。 - -語言中也定義了一個全域變數,它的值為 `undefined`,這個變數的被稱作 `undefined` 。 -這個變數 **不是** 一個常數,也不是一個關鍵字。這表示它的值可以被輕易的覆蓋。 - -> **ES5 提示: ** `undefined` 在 ECMAScript 5 裡 **不再是** *可寫* 的 -> 但是它的名稱還是可以被隱藏,比如說定義一個函數為 `undefined`。 - -這裡有一些例子會回傳 `undefined` 的值: - - - Accessing the (unmodified) global variable `undefined`. - - Accessing a declared *but not* yet initialized variable. - - Implicit returns of functions due to missing `return` statements. - - `return` statements that do not explicitly return anything. - - Lookups of non-existent properties. - - Function parameters that do not have any explicit value passed. - - Anything that has been set to the value of `undefined`. - - Any expression in the form of `void(expression)` - -### Handling Changes to the Value of `undefined` - -Since the global variable `undefined` only holds a copy of the actual *value* of -`undefined`, assigning a new value to it does **not** change the value of the -*type* `undefined`. - -Still, in order to compare something against the value of `undefined`, it is -necessary to retrieve the value of `undefined` first. - -To protect code against a possible overwritten `undefined` variable, a common -technique used is to add an additional parameter to an [anonymous -wrapper](#function.scopes) that gets no argument passed to it. - - var undefined = 123; - (function(something, foo, undefined) { - // undefined in the local scope does - // now again refer to the value `undefined` - - })('Hello World', 42); - -Another way to achieve the same effect would be to use a declaration inside the -wrapper. - - var undefined = 123; - (function(something, foo) { - var undefined; - ... - - })('Hello World', 42); - -The only difference here is that this version results in 4 more bytes being -used in case it is minified, and there is no other `var` statement inside the -anonymous wrapper. - -### Uses of `null` - -While `undefined` in the context of the JavaScript language is mostly used in -the sense of a traditional *null*, the actual `null` (both a literal and a type) -is more or less just another data type. - -It is used in some JavaScript internals (like declaring the end of the -prototype chain by setting `Foo.prototype = null`), but in almost all cases, it -can be replaced by `undefined`. - - diff --git a/doc/zh(Trandition)/function/arguments.md b/doc/zh(Trandition)/function/arguments.md deleted file mode 100644 index 2394177d..00000000 --- a/doc/zh(Trandition)/function/arguments.md +++ /dev/null @@ -1,118 +0,0 @@ -## The `arguments` Object - -Every function scope in JavaScript can access the special variable `arguments`. -This variable holds a list of all the arguments that were passed to the function. - -> **Note:** In case `arguments` has already been defined inside the function's -> scope either via a `var` statement or being the name of a formal parameter, -> the `arguments` object will not be created. - -The `arguments` object is **not** an `Array`. While it has some of the -semantics of an array - namely the `length` property - it does not inherit from -`Array.prototype` and is in fact an `Object`. - -Due to this, it is **not** possible to use standard array methods like `push`, -`pop` or `slice` on `arguments`. While iteration with a plain `for` loop works -just fine, it is necessary to convert it to a real `Array` in order to use the -standard `Array` methods on it. - -### Converting to an Array - -The code below will return a new `Array` containing all the elements of the -`arguments` object. - - Array.prototype.slice.call(arguments); - -Because this conversion is **slow**, it is **not recommended** to use it in -performance-critical sections of code. - -### Passing Arguments - -The following is the recommended way of passing arguments from one function to -another. - - function foo() { - bar.apply(null, arguments); - } - function bar(a, b, c) { - // do stuff here - } - -Another trick is to use both `call` and `apply` together to create fast, unbound -wrappers. - - function Foo() {} - - Foo.prototype.method = function(a, b, c) { - console.log(this, a, b, c); - }; - - // Create an unbound version of "method" - // It takes the parameters: this, arg1, arg2...argN - Foo.method = function() { - - // Result: Foo.prototype.method.call(this, arg1, arg2... argN) - Function.call.apply(Foo.prototype.method, arguments); - }; - - -### Formal Parameters and Arguments Indices - -The `arguments` object creates *getter* and *setter* functions for both its -properties, as well as the function's formal parameters. - -As a result, changing the value of a formal parameter will also change the value -of the corresponding property on the `arguments` object, and the other way around. - - 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); - -### Performance Myths and Truths - -The only time the `arguments` object is not created is where it is declared as -a name inside of a function or one of its formal parameters. It does not matter -whether it is used or not. - -Both *getters* and *setters* are **always** created; thus, using it has nearly -no performance impact at all, especially not in real world code where there is -more than a simple access to the `arguments` object's properties. - -> **ES5 Note:** These *getters* and *setters* are not created in strict mode. - -However, there is one case which will drastically reduce the performance in -modern JavaScript engines. That case is the use of `arguments.callee`. - - function foo() { - arguments.callee; // do something with this function object - arguments.callee.caller; // and the calling function object - } - - function bigLoop() { - for(var i = 0; i < 100000; i++) { - foo(); // Would normally be inlined... - } - } - -In the above code, `foo` can no longer be a subject to [inlining][1] since it -needs to know about both itself and its caller. This not only defeats possible -performance gains that would arise from inlining, but it also breaks encapsulation -because the function may now be dependent on a specific calling context. - -Making use of `arguments.callee` or any of its properties is **highly discouraged**. - -> **ES5 Note:** In strict mode, `arguments.callee` will throw a `TypeError` since -> its use has been deprecated. - -[1]: http://en.wikipedia.org/wiki/Inlining - - diff --git a/doc/zh(Trandition)/array/constructor.md b/doc/zh-TW/array/constructor.md similarity index 100% rename from doc/zh(Trandition)/array/constructor.md rename to doc/zh-TW/array/constructor.md diff --git a/doc/zh(Trandition)/array/general.md b/doc/zh-TW/array/general.md similarity index 100% rename from doc/zh(Trandition)/array/general.md rename to doc/zh-TW/array/general.md diff --git a/doc/zh(Trandition)/core/delete.md b/doc/zh-TW/core/delete.md similarity index 100% rename from doc/zh(Trandition)/core/delete.md rename to doc/zh-TW/core/delete.md diff --git a/doc/zh(Trandition)/core/eval.md b/doc/zh-TW/core/eval.md similarity index 100% rename from doc/zh(Trandition)/core/eval.md rename to doc/zh-TW/core/eval.md diff --git a/doc/zh(Trandition)/core/semicolon.md b/doc/zh-TW/core/semicolon.md similarity index 100% rename from doc/zh(Trandition)/core/semicolon.md rename to doc/zh-TW/core/semicolon.md diff --git a/doc/zh-TW/core/undefined.md b/doc/zh-TW/core/undefined.md new file mode 100644 index 00000000..4c9378be --- /dev/null +++ b/doc/zh-TW/core/undefined.md @@ -0,0 +1,55 @@ +## `undefined` 和 `null` + +JavaScript 中有兩個表示空值的方式, `null` 和 `undefined` , `undefined`式比較常用的一種。 + +### `undefined` 的值 + +`undefined` 是一個值為 `undefined` 的類型。 + +語言中也定義了一個全域變數,它的值為 `undefined`,這個變數的被稱作 `undefined` 。 +這個變數 **不是** 一個常數,也不是一個關鍵字。這表示它的值可以被輕易的覆蓋。 + +> **ES5 提示: ** `undefined` 在 ECMAScript 5 裡 **不再是** *可寫* 的 +> 但是它的名稱還是可以被隱藏,比如說定義一個函數為 `undefined`。 + +這裡有一些例子會回傳 `undefined` 的值: + + - 進入尚未修改的全域變數 `undefined`。 + - 進入一個宣告但 **尚未** 初始化的變數。 + - `return` 表示式中沒有返回任何內容。 + - 呼叫不存在的屬性。 + - 函式參數沒有被傳遞數值。 + - 任何被被設定為 `undefined` 的變數。 + - 任何表達式中形式為 `void(expression)` + +### 處理 `undefined` 值的改變 + +由於全域變數 `undefined` 只有保存 `undefined` 類型實際值的一個副本,指定了一個新的值並 **不會** 改變 `undefined`類型裡面的值。 + +為了避免去改變 `undefined` 的值,常用的技巧就是加上一個新的變數到 [匿名包裝器](#function.scopes)。在使用的時候,這個參數不會接受任何的值。 + + var undefined = 123; + (function(something, foo, undefined) { + // undefined 在區域區間內得到了 `undefined` 的值 + + })('Hello World', 42); + +另外一個可以得到同樣的效果就是在內部宣告一個變數 + + var undefined = 123; + (function(something, foo) { + var undefined; + ... + + })('Hello World', 42); + +唯一的不同就是在下者會多 4 個多 bytes 用來壓縮檔案,而且函數內野沒有其他需要使用 `var` + +### 使用 `null` + +JavaScript 中所使用的 `undefined` 類似別的語言中的 *null* , 但實際上在 JavaScript 中的 `null` 算是另外一個類型。 + +它在 JavaScript 有些可以使用的地方 (例如說宣告一個原型的終結,例如 `Foo.prototype = null` )。 +但是在大部分的時候可以用 `undefined`,來取代。 + + diff --git a/doc/zh-TW/function/arguments.md b/doc/zh-TW/function/arguments.md new file mode 100644 index 00000000..428a575d --- /dev/null +++ b/doc/zh-TW/function/arguments.md @@ -0,0 +1,103 @@ +## `arguments` 物件 + +所有函數在 JavaScript 中都可以有個特別的參數 `arguments`。 +這個變數掌握了一列傳入函數中的參數 + +> **注意:** 由於 `arguments` 都已經在函數中被定義了 +> 經過 `var` 定義或是用 `arguments` 宣告參數 +> `arguments` 物件都不會被建立 + +`arguments` 物件 **不是** 一個 `Array`,雖然都有很多 Array 的語法 - 就像是 `length` 屬性 - 但是它沒有繼承來自 `Array.prototype` 事實上它繼承 `object`。 + +由於這些原因,這 **不可能** 用 Array 的一些功能像是 `push`、`pop`或是 `slice` 在 `arguments`。 +但是像 `for` 迴圈這些迴圈都是可以用的,如果真的需要使用一些標準的 `Array` 功能可以先把它轉成真的 `Array` 再去使用。 + +### 轉為 Array + +下面的程式可以回傳一個新的 `Array` 包含所有的元素在 `Arguments`的物件中 + + Array.prototype.slice.call(arguments); + +這種轉化方式比較 **慢** ,不建議使用這種作法如果再追求效率的程式中。 + + +### 傳遞參數 + +下面是建議用這種方式去傳參數到另一個函數 + + function foo() { + bar.apply(null, arguments); + } + function bar(a, b, c) { + // 在這裡做一些事情 + } + +另一個技巧是用 `call` 和 `apply` 放在一起來創造一個更快的解綁定包裝器 + + function Foo() {} + + Foo.prototype.method = function(a, b, c) { + console.log(this, a, b, c); + }; + + // Create an unbound version of "method" + // 輸入的參數: this, arg1, arg2...argN + Foo.method = function() { + + // 結果: Foo.prototype.method.call(this, arg1, arg2... argN) + Function.call.apply(Foo.prototype.method, arguments); + }; + + +### 自動更新 + +在 `Arguments` 物件創造的 *getter* 和 *setter* 的函數方法,可以被視為原本函數的變數。 + +因此,改變了一個變數會跟著改變它的值而且也間接的改變稻香對應的 `arguments` 的物件,反之亦然。 + + 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); + +### 性能 + +`arguments` 總是會被宣告,但除了兩個情況,一個是在一個函式中或是在其中一個參入。而不論他是否有被使用。 + +*getters* 和 *setter* 會永遠被創造。然而,他們對任何性能都沒有影響,除非對它的屬性有多次的訪問 + + +> **ES5 提示:** 那些 *getters* 和 *setters* 在嚴格的模式像不會被建立 + +然而會有一種情況來降低 JavaScript 引擎的效能。就是使用 `arguments.callee`。 + + function foo() { + arguments.callee; // 做一些在這個函數物件 + arguments.callee.caller; // 然後呼叫這個函數物件 + } + + function bigLoop() { + for(var i = 0; i < 100000; i++) { + foo(); // 通常會在內聯 + } + } + +在上面的程式中, `foo` 不再是一個單存的互聯函數 +因為它需要知道他自己和它的調用者。 +這不僅減低了它的性能,而且還破壞的封裝 + +**強烈建議不要使用** `arguments.callee` 或是其他它的屬性 + +> **ES5 Note:** 在嚴格的模式下 `arguments.callee` 會丟出一個 `TypeError`, 因為這種方法已經被廢除了 + +[1]: http://en.wikipedia.org/wiki/Inlining + + diff --git a/doc/zh(Trandition)/function/closures.md b/doc/zh-TW/function/closures.md similarity index 100% rename from doc/zh(Trandition)/function/closures.md rename to doc/zh-TW/function/closures.md diff --git a/doc/zh(Trandition)/function/constructors.md b/doc/zh-TW/function/constructors.md similarity index 100% rename from doc/zh(Trandition)/function/constructors.md rename to doc/zh-TW/function/constructors.md diff --git a/doc/zh(Trandition)/function/general.md b/doc/zh-TW/function/general.md similarity index 100% rename from doc/zh(Trandition)/function/general.md rename to doc/zh-TW/function/general.md diff --git a/doc/zh(Trandition)/function/scopes.md b/doc/zh-TW/function/scopes.md similarity index 100% rename from doc/zh(Trandition)/function/scopes.md rename to doc/zh-TW/function/scopes.md diff --git a/doc/zh(Trandition)/function/this.md b/doc/zh-TW/function/this.md similarity index 100% rename from doc/zh(Trandition)/function/this.md rename to doc/zh-TW/function/this.md diff --git a/doc/zh(Trandition)/index.json b/doc/zh-TW/index.json similarity index 100% rename from doc/zh(Trandition)/index.json rename to doc/zh-TW/index.json diff --git a/doc/zh(Trandition)/intro/index.md b/doc/zh-TW/intro/index.md similarity index 100% rename from doc/zh(Trandition)/intro/index.md rename to doc/zh-TW/intro/index.md diff --git a/doc/zh(Trandition)/object/forinloop.md b/doc/zh-TW/object/forinloop.md similarity index 100% rename from doc/zh(Trandition)/object/forinloop.md rename to doc/zh-TW/object/forinloop.md diff --git a/doc/zh(Trandition)/object/general.md b/doc/zh-TW/object/general.md similarity index 100% rename from doc/zh(Trandition)/object/general.md rename to doc/zh-TW/object/general.md diff --git a/doc/zh(Trandition)/object/hasownproperty.md b/doc/zh-TW/object/hasownproperty.md similarity index 100% rename from doc/zh(Trandition)/object/hasownproperty.md rename to doc/zh-TW/object/hasownproperty.md diff --git a/doc/zh(Trandition)/object/prototype.md b/doc/zh-TW/object/prototype.md similarity index 100% rename from doc/zh(Trandition)/object/prototype.md rename to doc/zh-TW/object/prototype.md diff --git a/doc/zh(Trandition)/other/timeouts.md b/doc/zh-TW/other/timeouts.md similarity index 100% rename from doc/zh(Trandition)/other/timeouts.md rename to doc/zh-TW/other/timeouts.md diff --git a/doc/zh(Trandition)/types/casting.md b/doc/zh-TW/types/casting.md similarity index 100% rename from doc/zh(Trandition)/types/casting.md rename to doc/zh-TW/types/casting.md diff --git a/doc/zh(Trandition)/types/equality.md b/doc/zh-TW/types/equality.md similarity index 100% rename from doc/zh(Trandition)/types/equality.md rename to doc/zh-TW/types/equality.md diff --git a/doc/zh(Trandition)/types/instanceof.md b/doc/zh-TW/types/instanceof.md similarity index 100% rename from doc/zh(Trandition)/types/instanceof.md rename to doc/zh-TW/types/instanceof.md diff --git a/doc/zh(Trandition)/types/typeof.md b/doc/zh-TW/types/typeof.md similarity index 100% rename from doc/zh(Trandition)/types/typeof.md rename to doc/zh-TW/types/typeof.md diff --git a/site/zh-TW/index.html b/site/zh-TW/index.html new file mode 100644 index 00000000..8ae0e924 --- /dev/null +++ b/site/zh-TW/index.html @@ -0,0 +1,1913 @@ +JavaScript Garden +

Intro

JavaScript Garden is a growing collection of documentation about the most +quirky parts of the JavaScript programming language. It gives advice to +avoid common mistakes and subtle bugs, as well as performance issues and bad +practices, that non-expert JavaScript programmers may encounter on their +endeavours into the depths of the language.

+ +

JavaScript Garden does not aim to teach you JavaScript. Former knowledge +of the language is strongly recommended in order to understand the topics covered +in this guide. In order to learn the basics of the language, please head over to +the excellent guide on the Mozilla Developer Network.

+ +

The Authors

+ +

This guide is the work of two lovely Stack Overflow users, Ivo Wetzel +(Writing) and Zhang Yi Jiang (Design).

+ +

Contributors

+ + + +

Hosting

+ +

JavaScript Garden is hosted on GitHub, but Cramer Development supports us +with a mirror at JavaScriptGarden.info.

+ +

License

+ +

JavaScript Garden is published under the MIT license and hosted on +GitHub. If you find errors or typos please file an issue or a pull +request on the repository. You can also find us in the JavaScript room on +Stack Overflow chat.

Objects

Object Usage and Properties

Everything in JavaScript acts like an object, with the only two exceptions being +null and undefined.

+ +
false.toString(); // 'false'
+[1, 2, 3].toString(); // '1,2,3'
+
+function Foo(){}
+Foo.bar = 1;
+Foo.bar; // 1
+
+ +

A common misconception is that number literals cannot be used as +objects. That is because a flaw in JavaScript's parser tries to parse the dot +notation on a number as a floating point literal.

+ +
2.toString(); // raises SyntaxError
+
+ +

There are a couple of workarounds that can be used to make number literals act +as objects too.

+ +
2..toString(); // the second point is correctly recognized
+2 .toString(); // note the space left to the dot
+(2).toString(); // 2 is evaluated first
+
+ +

Objects as a Data Type

+ +

Objects in JavaScript can also be used as Hashmaps; they mainly consist +of named properties mapping to values.

+ +

Using an object literal - {} notation - it is possible to create a +plain object. This new object inherits from Object.prototype and +does not have own properties defined.

+ +
var foo = {}; // a new empty object
+
+// a new object with a 'test' property with value 12
+var bar = {test: 12}; 
+
+ +

Accessing Properties

+ +

The properties of an object can be accessed in two ways, via either the dot +notation or the square bracket notation.

+ +
var foo = {name: 'kitten'}
+foo.name; // kitten
+foo['name']; // kitten
+
+var get = 'name';
+foo[get]; // kitten
+
+foo.1234; // SyntaxError
+foo['1234']; // works
+
+ +

The notations work almost identically, with the only difference being that the +square bracket notation allows for dynamic setting of properties and +the use of property names that would otherwise lead to a syntax error.

+ +

Deleting Properties

+ +

The only way to remove a property from an object is to use the delete +operator; setting the property to undefined or null only removes the +value associated with the property, but not the key.

+ +
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]);
+    }
+}
+
+ +

The above outputs both bar undefined and foo null - only baz was +removed and is therefore missing from the output.

+ +

Notation of Keys

+ +
var test = {
+    'case': 'I am a keyword, so I must be notated as a string',
+    delete: 'I am a keyword, so me too' // raises SyntaxError
+};
+
+ +

Object properties can be both notated as plain characters and as strings. Due to +another mis-design in JavaScript's parser, the above will throw +a SyntaxError prior to ECMAScript 5.

+ +

This error arises from the fact that delete is a keyword; therefore, it must be +notated as a string literal to ensure that it will be correctly interpreted by +older JavaScript engines.

The Prototype

JavaScript does not feature a classical inheritance model; instead, it uses a +prototypal one.

+ +

While this is often considered to be one of JavaScript's weaknesses, the +prototypal inheritance model is in fact more powerful than the classic model. +It is, for example, fairly trivial to build a classic model on top of a +prototypal model, while the other way around is a far more difficult task.

+ +

JavaScript is the only widely used language that features prototypal +inheritance, so it can take time to adjust to the differences between the two +models.

+ +

The first major difference is that inheritance in JavaScript uses prototype +chains.

+ + + +
function Foo() {
+    this.value = 42;
+}
+Foo.prototype = {
+    method: function() {}
+};
+
+function Bar() {}
+
+// Set Bar's prototype to a new instance of Foo
+Bar.prototype = new Foo();
+Bar.prototype.foo = 'Hello World';
+
+// Make sure to list Bar as the actual constructor
+Bar.prototype.constructor = Bar;
+
+var test = new Bar() // create a new bar instance
+
+// The resulting prototype chain
+test [instance of Bar]
+    Bar.prototype [instance of Foo] 
+        { foo: 'Hello World' }
+        Foo.prototype
+            { method: ... }
+            Object.prototype
+                { toString: ... /* etc. */ }
+
+ +

In the code above, the object test will inherit from both Bar.prototype and +Foo.prototype; hence, it will have access to the function method that was +defined on Foo. It will also have access to the property value of the +one Foo instance that is its prototype. It is important to note that new +Bar() does not create a new Foo instance, but reuses the one assigned to +its prototype; thus, all Bar instances will share the same value property.

+ + + +

Property Lookup

+ +

When accessing the properties of an object, JavaScript will traverse the +prototype chain upwards until it finds a property with the requested name.

+ +

If it reaches the top of the chain - namely Object.prototype - and still +hasn't found the specified property, it will return the value +undefined instead.

+ +

The Prototype Property

+ +

While the prototype property is used by the language to build the prototype +chains, it is still possible to assign any given value to it. However, +primitives will simply get ignored when assigned as a prototype.

+ +
function Foo() {}
+Foo.prototype = 1; // no effect
+
+ +

Assigning objects, as shown in the example above, will work, and allows for dynamic +creation of prototype chains.

+ +

Performance

+ +

The lookup time for properties that are high up on the prototype chain can have +a negative impact on performance, and this may be significant in code where +performance is critical. Additionally, trying to access non-existent properties +will always traverse the full prototype chain.

+ +

Also, when iterating over the properties of an object +every property that is on the prototype chain will be enumerated.

+ +

Extension of Native Prototypes

+ +

One mis-feature that is often used is to extend Object.prototype or one of the +other built in prototypes.

+ +

This technique is called monkey patching and breaks encapsulation. While +used by popular frameworks such as Prototype, there is still no good +reason for cluttering built-in types with additional non-standard functionality.

+ +

The only good reason for extending a built-in prototype is to backport +the features of newer JavaScript engines; for example, +Array.forEach.

+ +

In Conclusion

+ +

It is essential to understand the prototypal inheritance model before +writing complex code that makes use of it. Also, be aware of the length of the +prototype chains in your code and break them up if necessary to avoid possible +performance problems. Further, the native prototypes should never be +extended unless it is for the sake of compatibility with newer JavaScript +features.

hasOwnProperty

To check whether an object has a property defined on itself and not somewhere +on its prototype chain, it is necessary to use the +hasOwnProperty method which all objects inherit from Object.prototype.

+ + + +

hasOwnProperty is the only thing in JavaScript which deals with properties and +does not traverse the prototype chain.

+ +
// Poisoning Object.prototype
+Object.prototype.bar = 1; 
+var foo = {goo: undefined};
+
+foo.bar; // 1
+'bar' in foo; // true
+
+foo.hasOwnProperty('bar'); // false
+foo.hasOwnProperty('goo'); // true
+
+ +

Only hasOwnProperty will give the correct and expected result; this is +essential when iterating over the properties of any object. There is no other +way to exclude properties that are not defined on the object itself, but +somewhere on its prototype chain.

+ +

hasOwnProperty as a Property

+ +

JavaScript does not protect the property name hasOwnProperty; thus, if the +possibility exists that an object might have a property with this name, it is +necessary to use an external hasOwnProperty to get correct results.

+ +
var foo = {
+    hasOwnProperty: function() {
+        return false;
+    },
+    bar: 'Here be dragons'
+};
+
+foo.hasOwnProperty('bar'); // always returns false
+
+// Use another Object's hasOwnProperty and call it with 'this' set to foo
+({}).hasOwnProperty.call(foo, 'bar'); // true
+
+// It's also possible to use the hasOwnProperty property from the Object property for this purpose
+Object.prototype.hasOwnProperty.call(obj, 'bar'); // true
+
+ +

In Conclusion

+ +

Using hasOwnProperty is the only reliable method to check for the +existence of a property on an object. It is recommended that hasOwnProperty +is used in every for in loop to avoid errors from +extended native prototypes.

The for in Loop

Just like the in operator, the for in loop traverses the prototype +chain when iterating over the properties of an object.

+ + + +
// Poisoning Object.prototype
+Object.prototype.bar = 1;
+
+var foo = {moo: 2};
+for(var i in foo) {
+    console.log(i); // prints both bar and moo
+}
+
+ +

Since it is not possible to change the behavior of the for in loop itself, it +is necessary to filter out the unwanted properties inside the loop body; +this is done using the hasOwnProperty method of +Object.prototype.

+ + + +

Using hasOwnProperty for Filtering

+ +
// still the foo from above
+for(var i in foo) {
+    if (foo.hasOwnProperty(i)) {
+        console.log(i);
+    }
+}
+
+ +

This version is the only correct one to use. Due to the use of hasOwnProperty, it +will only print out moo. When hasOwnProperty is left out, the code is +prone to errors in cases where the native prototypes - e.g. Object.prototype - +have been extended.

+ +

One widely used framework that extends Object.prototype is Prototype. +When this framework is included, for in loops that do not use +hasOwnProperty are guaranteed to break.

+ +

In Conclusion

+ +

It is recommended to always use hasOwnProperty. Assumptions should never +be made about the environment the code is running in, or whether the native +prototypes have been extended or not.

Functions

Function Declarations and Expressions

Functions in JavaScript are first class objects. That means they can be +passed around like any other value. One common use of this feature is to pass +an anonymous function as a callback to another, possibly an asynchronous function.

+ +

The function Declaration

+ +
function foo() {}
+
+ +

The above function gets hoisted before the execution of the +program starts; thus, it is available everywhere in the scope it was +defined, even if called before the actual definition in the source.

+ +
foo(); // Works because foo was created before this code runs
+function foo() {}
+
+ +

The function Expression

+ +
var foo = function() {};
+
+ +

This example assigns the unnamed and anonymous function to the variable foo.

+ +
foo; // 'undefined'
+foo(); // this raises a TypeError
+var foo = function() {};
+
+ +

Due to the fact that var is a declaration that hoists the variable name foo +before the actual execution of the code starts, foo is already defined when +the script gets executed.

+ +

But since assignments only happen at runtime, the value of foo will default +to undefined before the corresponding code is executed.

+ +

Named Function Expression

+ +

Another special case is the assignment of named functions.

+ +
var foo = function bar() {
+    bar(); // Works
+}
+bar(); // ReferenceError
+
+ +

Here, bar is not available in the outer scope, since the function only gets +assigned to foo; however, inside of bar, it is available. This is due to +how name resolution in JavaScript works, the name of the +function is always made available in the local scope of the function itself.

How this Works

JavaScript has a different concept of what the special name this refers to +than most other programming languages. There are exactly five different +ways in which the value of this can be bound in the language.

+ +

The Global Scope

+ +
this;
+
+ +

When using this in global scope, it will simply refer to the global object.

+ +

Calling a Function

+ +
foo();
+
+ +

Here, this will again refer to the global object.

+ + + +

Calling a Method

+ +
test.foo(); 
+
+ +

In this example, this will refer to test.

+ +

Calling a Constructor

+ +
new foo(); 
+
+ +

A function call that is preceded by the new keyword acts as +a constructor. Inside the function, this will refer +to a newly created Object.

+ +

Explicit Setting of this

+ +
function foo(a, b, c) {}
+
+var bar = {};
+foo.apply(bar, [1, 2, 3]); // array will expand to the below
+foo.call(bar, 1, 2, 3); // results in a = 1, b = 2, c = 3
+
+ +

When using the call or apply methods of Function.prototype, the value of +this inside the called function gets explicitly set to the first argument +of the corresponding function call.

+ +

As a result, in the above example the method case does not apply, and this +inside of foo will be set to bar.

+ + + +

Common Pitfalls

+ +

While most of these cases make sense, the first can be considered another +mis-design of the language because it never has any practical use.

+ +
Foo.method = function() {
+    function test() {
+        // this is set to the global object
+    }
+    test();
+}
+
+ +

A common misconception is that this inside of test refers to Foo; while in +fact, it does not.

+ +

In order to gain access to Foo from within test, it is necessary to create a +local variable inside of method that refers to Foo.

+ +
Foo.method = function() {
+    var that = this;
+    function test() {
+        // Use that instead of this here
+    }
+    test();
+}
+
+ +

that is just a normal variable name, but it is commonly used for the reference to an +outer this. In combination with closures, it can also +be used to pass this values around.

+ +

Assigning Methods

+ +

Another thing that does not work in JavaScript is function aliasing, which is +assigning a method to a variable.

+ +
var test = someObject.methodTest;
+test();
+
+ +

Due to the first case, test now acts like a plain function call; therefore, +this inside it will no longer refer to someObject.

+ +

While the late binding of this might seem like a bad idea at first, in +fact, it is what makes prototypal inheritance work.

+ +
function Foo() {}
+Foo.prototype.method = function() {};
+
+function Bar() {}
+Bar.prototype = Foo.prototype;
+
+new Bar().method();
+
+ +

When method gets called on an instance of Bar, this will now refer to that +very instance.

Closures and References

One of JavaScript's most powerful features is the availability of closures. +With closures, scopes always keep access to the outer scope, in which they +were defined. Since the only scoping that JavaScript has is +function scope, all functions, by default, act as closures.

+ +

Emulating private variables

+ +
function Counter(start) {
+    var count = start;
+    return {
+        increment: function() {
+            count++;
+        },
+
+        get: function() {
+            return count;
+        }
+    }
+}
+
+var foo = Counter(4);
+foo.increment();
+foo.get(); // 5
+
+ +

Here, Counter returns two closures: the function increment as well as +the function get. Both of these functions keep a reference to the scope of +Counter and, therefore, always keep access to the count variable that was +defined in that scope.

+ +

Why Private Variables Work

+ +

Since it is not possible to reference or assign scopes in JavaScript, there is +no way of accessing the variable count from the outside. The only way to +interact with it is via the two closures.

+ +
var foo = new Counter(4);
+foo.hack = function() {
+    count = 1337;
+};
+
+ +

The above code will not change the variable count in the scope of Counter, +since foo.hack was not defined in that scope. It will instead create - or +override - the global variable count.

+ +

Closures Inside Loops

+ +

One often made mistake is to use closures inside of loops, as if they were +copying the value of the loop's index variable.

+ +
for(var i = 0; i < 10; i++) {
+    setTimeout(function() {
+        console.log(i);  
+    }, 1000);
+}
+
+ +

The above will not output the numbers 0 through 9, but will simply print +the number 10 ten times.

+ +

The anonymous function keeps a reference to i. At the time +console.log gets called, the for loop has already finished, and the value of +i as been set to 10.

+ +

In order to get the desired behavior, it is necessary to create a copy of +the value of i.

+ +

Avoiding the Reference Problem

+ +

In order to copy the value of the loop's index variable, it is best to use an +anonymous wrapper.

+ +
for(var i = 0; i < 10; i++) {
+    (function(e) {
+        setTimeout(function() {
+            console.log(e);  
+        }, 1000);
+    })(i);
+}
+
+ +

The anonymous outer function gets called immediately with i as its first +argument and will receive a copy of the value of i as its parameter e.

+ +

The anonymous function that gets passed to setTimeout now has a reference to +e, whose value does not get changed by the loop.

+ +

There is another possible way of achieving this, which is to return a function +from the anonymous wrapper that will then have the same behavior as the code +above.

+ +
for(var i = 0; i < 10; i++) {
+    setTimeout((function(e) {
+        return function() {
+            console.log(e);
+        }
+    })(i), 1000)
+}
+

arguments 物件

所有函數在 JavaScript 中都可以有個特別的參數 arguments。 +這個變數掌握了一列傳入函數中的參數

+ + + +

arguments 物件 不是 一個 Array,雖然都有很多 Array 的語法 - 就像是 length 屬性 - 但是它沒有繼承來自 Array.prototype 事實上它繼承 object

+ +

由於這些原因,這 不可能 用 Array 的一些功能像是 pushpop或是 slicearguments。 +但是像 for 迴圈這些迴圈都是可以用的,如果真的需要使用一些標準的 Array 功能可以先把它轉成真的 Array 再去使用。

+ +

轉為 Array

+ +

下面的程式可以回傳一個新的 Array 包含所有的元素在 Arguments的物件中

+ +
Array.prototype.slice.call(arguments);
+
+ +

這種轉化方式比較 ,不建議使用這種作法如果再追求效率的程式中。

+ +

傳遞參數

+ +

下面是建議用這種方式去傳參數到另一個函數

+ +
function foo() {
+    bar.apply(null, arguments);
+}
+function bar(a, b, c) {
+    // 在這裡做一些事情
+}
+
+ +

另一個技巧是用 callapply 放在一起來創造一個更快的解綁定包裝器

+ +
function Foo() {}
+
+Foo.prototype.method = function(a, b, c) {
+    console.log(this, a, b, c);
+};
+
+// Create an unbound version of "method" 
+// 輸入的參數: this, arg1, arg2...argN
+Foo.method = function() {
+
+    // 結果: Foo.prototype.method.call(this, arg1, arg2... argN)
+    Function.call.apply(Foo.prototype.method, arguments);
+};
+
+ +

自動更新

+ +

Arguments 物件創造的 gettersetter 的函數方法,可以被視為原本函數的變數。

+ +

因此,改變了一個變數會跟著改變它的值而且也間接的改變稻香對應的 arguments 的物件,反之亦然。

+ +
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);
+
+ +

性能

+ +

arguments 總是會被宣告,但除了兩個情況,一個是在一個函式中或是在其中一個參入。而不論他是否有被使用。

+ +

getterssetter 會永遠被創造。然而,他們對任何性能都沒有影響,除非對它的屬性有多次的訪問

+ + + +

然而會有一種情況來降低 JavaScript 引擎的效能。就是使用 arguments.callee

+ +
function foo() {
+    arguments.callee; // 做一些在這個函數物件
+    arguments.callee.caller; // 然後呼叫這個函數物件
+}
+
+function bigLoop() {
+    for(var i = 0; i < 100000; i++) {
+        foo(); // 通常會在內聯
+    }
+}
+
+ +

在上面的程式中, foo 不再是一個單存的互聯函數 +因為它需要知道他自己和它的調用者。 +這不僅減低了它的性能,而且還破壞的封裝

+ +

強烈建議不要使用 arguments.callee 或是其他它的屬性

+ +

Constructors

Constructors in JavaScript are yet again different from many other languages. Any +function call that is preceded by the new keyword acts as a constructor.

+ +

Inside the constructor - the called function - the value of this refers to a +newly created object. The prototype of this new +object is set to the prototype of the function object that was invoked as the +constructor.

+ +

If the function that was called has no explicit return statement, then it +implicitly returns the value of this - the new object.

+ +
function Foo() {
+    this.bla = 1;
+}
+
+Foo.prototype.test = function() {
+    console.log(this.bla);
+};
+
+var test = new Foo();
+
+ +

The above calls Foo as constructor and sets the prototype of the newly +created object to Foo.prototype.

+ +

In case of an explicit return statement, the function returns the value +specified by that statement, but only if the return value is an Object.

+ +
function Bar() {
+    return 2;
+}
+new Bar(); // a new object
+
+function Test() {
+    this.value = 2;
+
+    return {
+        foo: 1
+    };
+}
+new Test(); // the returned object
+
+ +

When the new keyword is omitted, the function will not return a new object.

+ +
function Foo() {
+    this.bla = 1; // gets set on the global object
+}
+Foo(); // undefined
+
+ +

While the above example might still appear to work in some cases, due to the +workings of this in JavaScript, it will use the +global object as the value of this.

+ +

Factories

+ +

In order to be able to omit the new keyword, the constructor function has to +explicitly return a value.

+ +
function Bar() {
+    var value = 1;
+    return {
+        method: function() {
+            return value;
+        }
+    }
+}
+Bar.prototype = {
+    foo: function() {}
+};
+
+new Bar();
+Bar();
+
+ +

Both calls to Bar return the same thing, a newly create object that +has a property called method, which is a +Closure.

+ +

It should also be noted that the call new Bar() does not affect the +prototype of the returned object. While the prototype will be set on the newly +created object, Bar never returns that new object.

+ +

In the above example, there is no functional difference between using and +not using the new keyword.

+ +

Creating New Objects via Factories

+ +

It is often recommended to not use new because forgetting its use may +lead to bugs.

+ +

In order to create a new object, one should rather use a factory and construct a +new object inside of that factory.

+ +
function Foo() {
+    var obj = {};
+    obj.value = 'blub';
+
+    var private = 2;
+    obj.someMethod = function(value) {
+        this.value = value;
+    }
+
+    obj.getPrivate = function() {
+        return private;
+    }
+    return obj;
+}
+
+ +

While the above is robust against a missing new keyword and certainly makes +the use of private variables easier, it comes with some +downsides.

+ +
    +
  1. It uses more memory since the created objects do not share the methods +on a prototype.
  2. +
  3. In order to inherit, the factory needs to copy all the methods from another +object or put that object on the prototype of the new object.
  4. +
  5. Dropping the prototype chain just because of a left out new keyword +is contrary to the spirit of the language.
  6. +
+ +

In Conclusion

+ +

While omitting the new keyword might lead to bugs, it is certainly not a +reason to drop the use of prototypes altogether. In the end it comes down to +which solution is better suited for the needs of the application. It is +especially important to choose a specific style of object creation and use it +consistently.

Scopes and Namespaces

Although JavaScript deals fine with the syntax of two matching curly +braces for blocks, it does not support block scope; hence, all that is left +in the language is function scope.

+ +
function test() { // a scope
+    for(var i = 0; i < 10; i++) { // not a scope
+        // count
+    }
+    console.log(i); // 10
+}
+
+ + + +

There are also no distinct namespaces in JavaScript, which means that everything +gets defined in one globally shared namespace.

+ +

Each time a variable is referenced, JavaScript will traverse upwards through all +the scopes until it finds it. In the case that it reaches the global scope and +still has not found the requested name, it will raise a ReferenceError.

+ +

The Bane of Global Variables

+ +
// script A
+foo = '42';
+
+// script B
+var foo = '42'
+
+ +

The above two scripts do not have the same effect. Script A defines a +variable called foo in the global scope, and script B defines a foo in the +current scope.

+ +

Again, that is not at all the same effect: not using var can have major +implications.

+ +
// global scope
+var foo = 42;
+function test() {
+    // local scope
+    foo = 21;
+}
+test();
+foo; // 21
+
+ +

Leaving out the var statement inside the function test will override the +value of foo. While this might not seem like a big deal at first, having +thousands of lines of JavaScript and not using var will introduce horrible, +hard-to-track-down bugs.

+ +
// global scope
+var items = [/* some list */];
+for(var i = 0; i < 10; i++) {
+    subLoop();
+}
+
+function subLoop() {
+    // scope of subLoop
+    for(i = 0; i < 10; i++) { // missing var statement
+        // do amazing stuff!
+    }
+}
+
+ +

The outer loop will terminate after the first call to subLoop, since subLoop +overwrites the global value of i. Using a var for the second for loop would +have easily avoided this error. The var statement should never be left out +unless the desired effect is to affect the outer scope.

+ +

Local Variables

+ +

The only source for local variables in JavaScript are +function parameters and variables declared via the +var statement.

+ +
// global scope
+var foo = 1;
+var bar = 2;
+var i = 2;
+
+function test(i) {
+    // local scope of the function test
+    i = 5;
+
+    var foo = 3;
+    bar = 4;
+}
+test(10);
+
+ +

While foo and i are local variables inside the scope of the function test, +the assignment of bar will override the global variable with the same name.

+ +

Hoisting

+ +

JavaScript hoists declarations. This means that both var statements and +function declarations will be moved to the top of their enclosing scope.

+ +
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];
+    }
+}
+
+ +

The above code gets transformed before execution starts. JavaScript moves +the var statements, as well as function declarations, to the top of the +nearest surrounding scope.

+ +
// var statements got moved here
+var bar, someValue; // default to 'undefined'
+
+// the function declaration got moved up too
+function test(data) {
+    var goo, i, e; // missing block scope moves these here
+    if (false) {
+        goo = 1;
+
+    } else {
+        goo = 2;
+    }
+    for(i = 0; i < 100; i++) {
+        e = data[i];
+    }
+}
+
+bar(); // fails with a TypeError since bar is still 'undefined'
+someValue = 42; // assignments are not affected by hoisting
+bar = function() {};
+
+test();
+
+ +

Missing block scoping will not only move var statements out of loops and +their bodies, it will also make the results of certain if constructs +non-intuitive.

+ +

In the original code, although the if statement seemed to modify the global +variable goo, it actually modifies the local variable - after hoisting +has been applied.

+ +

Without knowledge of hoisting, one might suspect the code below would raise a +ReferenceError.

+ +
// check whether SomeImportantThing has been initialized
+if (!SomeImportantThing) {
+    var SomeImportantThing = {};
+}
+
+ +

But of course, this works due to the fact that the var statement is being +moved to the top of the global scope.

+ +
var SomeImportantThing;
+
+// other code might initialize SomeImportantThing here, or not
+
+// make sure it's there
+if (!SomeImportantThing) {
+    SomeImportantThing = {};
+}
+
+ +

Name Resolution Order

+ +

All scopes in JavaScript, including the global scope, have the special name +this, defined in them, which refers to the current object.

+ +

Function scopes also have the name arguments, defined in +them, which contains the arguments that were passed to the function.

+ +

For example, when trying to access a variable named foo inside the scope of a +function, JavaScript will look up the name in the following order:

+ +
    +
  1. In case there is a var foo statement in the current scope, use that.
  2. +
  3. If one of the function parameters is named foo, use that.
  4. +
  5. If the function itself is called foo, use that.
  6. +
  7. Go to the next outer scope, and start with #1 again.
  8. +
+ + + +

Namespaces

+ +

A common problem associated with having only one global namespace is the +likelihood of running into problems where variable names clash. In JavaScript, +this problem can easily be avoided with the help of anonymous wrappers.

+ +
(function() {
+    // a self contained "namespace"
+
+    window.foo = function() {
+        // an exposed closure
+    };
+
+})(); // execute the function immediately
+
+ +

Unnamed functions are considered expressions; so in order to +being callable, they must first be evaluated.

+ +
( // evaluate the function inside the parentheses
+function() {}
+) // and return the function object
+() // call the result of the evaluation
+
+ +

There are other ways to evaluate and directly call the function expression +which, while different in syntax, behave the same way.

+ +
// A few other styles for directly invoking the 
+!function(){}()
++function(){}()
+(function(){}());
+// and so on...
+
+ +

In Conclusion

+ +

It is recommended to always use an anonymous wrapper to encapsulate code in +its own namespace. This does not only protect code against name clashes, but it +also allows for better modularization of programs.

+ +

Additionally, the use of global variables is considered bad practice. Any +use of them indicates badly written code that is prone to errors and hard to maintain.

Arrays

Array 迴圈和屬性

雖然在 Javascript 中 Array 都是 Objects,但是沒有好的理由要使用他 +在 for in 的迴圈中。事實上有很多原因要避免使用 for in 在 Array 之中

+ + + +

因為 for in 迴圈會列舉所有在原型 Array 上的屬性因為他會使用hasOwnProperty, 這會使得 Array 比原本的 for 迴圈慢上二十幾倍

+ +

迴圈

+ +

為了要達到最好的性能所以最好使用 for 迴圈來讀取一個 Array 裡面的數值。

+ +
var list = [1, 2, 3, 4, 5, ...... 100000000];
+for(var i = 0, l = list.length; i < l; i++) {
+    console.log(list[i]);
+}
+
+ +

在上面的例子中利用 l = list.length 來處理 Array 的長度問題。

+ +

雖然 length 屬性是屬於 Array 中其中一個屬性,但是他還使有一定的性能消耗在每次循環的訪問。 +近期 Javascript 使用 may 來解決在這上面的效率問題,但是在現在的引擎上還不一定有支援。

+ +

實際上,不使用暫存 Array 長度的方式比使用暫存的版本還要慢很多。

+ +

length 的屬性

+ +

length 屬性中的 getter 直接回傳在 Array 之中的程度,而 setter 可以用來 刪除 Array。

+ +
var foo = [1, 2, 3, 4, 5, 6];
+foo.length = 3;
+foo; // [1, 2, 3]
+
+foo.length = 6;
+foo.push(4);
+foo; // [1, 2, 3, undefined, undefined, undefined, 4]
+
+ +

在上面的例子可以看到,如果給的長度比較小他就會去刪除 Array 中的數值。如果比較大的話,他就會自己增加一些 undefined 的數值進去

+ +

結語

+ +

為了達到更好的效率,建議使用 for 迴圈還有暫存 length 的屬性。 +而 for in 迴圈則是會讓程式中有更多的錯誤和性能問題。

Array 的建構函式

Array 的建構函式在處理參數上一直有模糊的地帶,所以建議使用 array的字面語法來使用 - [] - 來新增一個的Array

+ +
[1, 2, 3]; // 結果: [1, 2, 3]
+new Array(1, 2, 3); // 結果: [1, 2, 3]
+
+[3]; // 結果: [3]
+new Array(3); // 結果: []
+new Array('3') // 結果: ['3']
+
+ +

在上面的範例 new Array(3) 當只有一個參數傳入到 Array 的建構函數 +且那個參數事宜個數字,建構函數會回傳空值 +但是 Array 長度的屬性會變成跟那個參數一樣(以此範例來看他回傳的長度為 3) +注意 只有他長度的屬性會被設定,整個 Array裡面的數值都不會初始化

+ +
var arr = new Array(3);
+arr[1]; // undefined
+1 in arr; // false, 數值沒有被設定進去
+
+ +

被設定用來當做 Array 的長度只有少數情況使用 +先設定 Array 的長度可以用一下的範例來避免使用 for loop 的麻煩

+ +
new Array(count + 1).join(stringToRepeat);
+
+ +

結語

+ +

Array 的建構函式需要避免,建議使用字面語法。因為他們比較簡短、也更增加閱讀性

Types

Equality and Comparisons

JavaScript has two different ways of comparing the values of objects for equality.

+ +

The Equality Operator

+ +

The equality operator consists of two equal signs: ==

+ +

JavaScript features weak typing. This means that the equality operator +coerces types in order to compare them.

+ +
""           ==   "0"           // false
+0            ==   ""            // true
+0            ==   "0"           // true
+false        ==   "false"       // false
+false        ==   "0"           // true
+false        ==   undefined     // false
+false        ==   null          // false
+null         ==   undefined     // true
+" \t\r\n"    ==   0             // true
+
+ +

The above table shows the results of the type coercion, and it is the main reason +why the use of == is widely regarded as bad practice. It introduces +hard-to-track-down bugs due to its complicated conversion rules.

+ +

Additionally, there is also a performance impact when type coercion is in play; +for example, a string has to be converted to a number before it can be compared +to another number.

+ +

The Strict Equality Operator

+ +

The strict equality operator consists of three equal signs: ===.

+ +

It works like the normal equality operator, except that strict equality +operator does not perform type coercion between its operands.

+ +
""           ===   "0"           // false
+0            ===   ""            // false
+0            ===   "0"           // false
+false        ===   "false"       // false
+false        ===   "0"           // false
+false        ===   undefined     // false
+false        ===   null          // false
+null         ===   undefined     // false
+" \t\r\n"    ===   0             // false
+
+ +

The above results are a lot clearer and allow for early breakage of code. This +hardens code to a certain degree and also gives performance improvements in case +the operands are of different types.

+ +

Comparing Objects

+ +

While both == and === are called equality operators, they behave +differently when at least one of their operands is an Object.

+ +
{} === {};                   // false
+new String('foo') === 'foo'; // false
+new Number(10) === 10;       // false
+var foo = {};
+foo === foo;                 // true
+
+ +

Here, both operators compare for identity and not equality; that is, they +will compare for the same instance of the object, much like is in Python +and pointer comparison in C.

+ +

In Conclusion

+ +

It is highly recommended to only use the strict equality operator. In cases +where types need to be coerced, it should be done explicitly +and not left to the language's complicated coercion rules.

The typeof Operator

The typeof operator (together with +instanceof) is probably the biggest +design flaw of JavaScript, as it is almost completely broken.

+ +

Although instanceof still has limited uses, typeof really has only one +practical use case, which does not happen to be checking the type of an +object.

+ + + +

The JavaScript Type Table

+ +
Value               Class      Type
+-------------------------------------
+"foo"               String     string
+new String("foo")   String     object
+1.2                 Number     number
+new Number(1.2)     Number     object
+true                Boolean    boolean
+new Boolean(true)   Boolean    object
+new Date()          Date       object
+new Error()         Error      object
+[1,2,3]             Array      object
+new Array(1, 2, 3)  Array      object
+new Function("")    Function   function
+/abc/g              RegExp     object (function in Nitro/V8)
+new RegExp("meow")  RegExp     object (function in Nitro/V8)
+{}                  Object     object
+new Object()        Object     object
+
+ +

In the above table, Type refers to the value that the typeof operator returns. +As can be clearly seen, this value is anything but consistent.

+ +

The Class refers to the value of the internal [[Class]] property of an object.

+ + + +

In order to retrieve the value of [[Class]], one has to make use of the +toString method of Object.prototype.

+ +

The Class of an Object

+ +

The specification gives exactly one way of accessing the [[Class]] value, +with the use of Object.prototype.toString.

+ +
function is(type, obj) {
+    var clas = Object.prototype.toString.call(obj).slice(8, -1);
+    return obj !== undefined && obj !== null && clas === type;
+}
+
+is('String', 'test'); // true
+is('String', new String('test')); // true
+
+ +

In the above example, Object.prototype.toString gets called with the value of +this being set to the object whose [[Class]] value should be +retrieved.

+ + + +

Testing for Undefined Variables

+ +
typeof foo !== 'undefined'
+
+ +

The above will check whether foo was actually declared or not; just +referencing it would result in a ReferenceError. This is the only thing +typeof is actually useful for.

+ +

In Conclusion

+ +

In order to check the type of an object, it is highly recommended to use +Object.prototype.toString because this is the only reliable way of doing so. +As shown in the above type table, some return values of typeof are not defined +in the specification; thus, they can differ between implementations.

+ +

Unless checking whether a variable is defined, typeof should be avoided.

The instanceof Operator

The instanceof operator compares the constructors of its two operands. It is +only useful when comparing custom made objects. Used on built-in types, it is +nearly as useless as the typeof operator.

+ +

Comparing Custom Objects

+ +
function Foo() {}
+function Bar() {}
+Bar.prototype = new Foo();
+
+new Bar() instanceof Bar; // true
+new Bar() instanceof Foo; // true
+
+// This just sets Bar.prototype to the function object Foo,
+// but not to an actual instance of Foo
+Bar.prototype = Foo;
+new Bar() instanceof Foo; // false
+
+ +

Using instanceof with Native Types

+ +
new String('foo') instanceof String; // true
+new String('foo') instanceof Object; // true
+
+'foo' instanceof String; // false
+'foo' instanceof Object; // false
+
+ +

One important thing to note here is that instanceof does not work on objects +that originate from different JavaScript contexts (e.g. different documents +in a web browser), since their constructors will not be the exact same object.

+ +

In Conclusion

+ +

The instanceof operator should only be used when dealing with custom made +objects that originate from the same JavaScript context. Just like the +typeof operator, every other use of it should be avoided.

Type Casting

JavaScript is a weakly typed language, so it will apply type coercion +wherever possible.

+ +
// These are true
+new Number(10) == 10; // Number.toString() is converted
+                      // back to a number
+
+10 == '10';           // Strings gets converted to Number
+10 == '+10 ';         // More string madness
+10 == '010';          // And more 
+isNaN(null) == false; // null converts to 0
+                      // which of course is not NaN
+
+// These are false
+10 == 010;
+10 == '-10';
+
+ + + +

To avoid the issues above, use of the strict equal operator +is highly recommended. Although this avoids a lot of common pitfalls, there +are still many further issues that arise from JavaScript's weak typing system.

+ +

Constructors of Built-In Types

+ +

The constructors of the built in types like Number and String behave +differently when being used with the new keyword and without it.

+ +
new Number(10) === 10;     // False, Object and Number
+Number(10) === 10;         // True, Number and Number
+new Number(10) + 0 === 10; // True, due to implicit conversion
+
+ +

Using a built-in type like Number as a constructor will create a new Number +object, but leaving out the new keyword will make the Number function behave +like a converter.

+ +

In addition, passing literals or non-object values will result in even more +type coercion.

+ +

The best option is to cast to one of the three possible types explicitly.

+ +

Casting to a String

+ +
'' + 10 === '10'; // true
+
+ +

By prepending an empty string, a value can easily be cast to a string.

+ +

Casting to a Number

+ +
+'10' === 10; // true
+
+ +

Using the unary plus operator, it is possible to cast to a number.

+ +

Casting to a Boolean

+ +

By using the not operator twice, a value can be converted a boolean.

+ +
!!'foo';   // true
+!!'';      // false
+!!'0';     // true
+!!'1';     // true
+!!'-1'     // true
+!!{};      // true
+!!true;    // true
+

Core

為什麼不要使用 eval

因為 eval 函數會在 Javascript 的區域性的區間執行那段程式碼。

+ +
var foo = 1;
+function test() {
+    var foo = 2;
+    eval('foo = 3');
+    return foo;
+}
+test(); // 3
+foo; // 1
+
+ +

但是, eval 只接受直接的呼叫而且那個函數只能叫做 eval,才能在一個區段中執行。

+ +
var foo = 1;
+function test() {
+    var foo = 2;
+    var bar = eval;
+    bar('foo = 3');
+    return foo;
+}
+test(); // 2
+foo; // 3
+
+ +

所有的 eval 都應該去比免試用。有 99.9% 的使用情況都可以 不必 使用到而達到同等效果。

+ +

偽裝的 eval

+ +

定時函數 setTimeoutsetInterval 都可以接受一個字串當做他們第一個參數。這些字串 永遠 都會在全域範圍內執行,因此在這種情況下 eval 沒有被直接的使用。

+ +

安全上的顧慮

+ +

eval 同樣有安全上的問題,因為所有的程式碼都可以被直接執行。 +而他不應去執行一串未知的字串或是來自不幸任的來源。

+ +

結語

+ +

eval 應該永遠不要去只用它,任何的程式在被他執行後都有性能和安全上的考慮。如果有情況需要去使用他,他都不應該列為第一順位的解決方法。

+ +

應該有更好的方法能夠去使用,但是最好都不要去使用 eval

undefinednull

JavaScript 中有兩個表示空值的方式, nullundefinedundefined式比較常用的一種。

+ +

undefined 的值

+ +

undefined 是一個值為 undefined 的類型。

+ +

語言中也定義了一個全域變數,它的值為 undefined,這個變數的被稱作 undefined 。 +這個變數 不是 一個常數,也不是一個關鍵字。這表示它的值可以被輕易的覆蓋。

+ + + +

這裡有一些例子會回傳 undefined 的值:

+ +
    +
  • 進入尚未修改的全域變數 undefined
  • +
  • 進入一個宣告但 尚未 初始化的變數。
  • +
  • return 表示式中沒有返回任何內容。
  • +
  • 呼叫不存在的屬性。
  • +
  • 函式參數沒有被傳遞數值。
  • +
  • 任何被被設定為 undefined 的變數。
  • +
  • 任何表達式中形式為 void(expression)
  • +
+ +

處理 undefined 值的改變

+ +

由於全域變數 undefined 只有保存 undefined 類型實際值的一個副本,指定了一個新的值並 不會 改變 undefined類型裡面的值。

+ +

為了避免去改變 undefined 的值,常用的技巧就是加上一個新的變數到 匿名包裝器。在使用的時候,這個參數不會接受任何的值。

+ +
var undefined = 123;
+(function(something, foo, undefined) {
+    // undefined 在區域區間內得到了 `undefined` 的值
+
+})('Hello World', 42);
+
+ +

另外一個可以得到同樣的效果就是在內部宣告一個變數

+ +
var undefined = 123;
+(function(something, foo) {
+    var undefined;
+    ...
+
+})('Hello World', 42);
+
+ +

唯一的不同就是在下者會多 4 個多 bytes 用來壓縮檔案,而且函數內野沒有其他需要使用 var

+ +

使用 null

+ +

JavaScript 中所使用的 undefined 類似別的語言中的 null , 但實際上在 JavaScript 中的 null 算是另外一個類型。

+ +

它在 JavaScript 有些可以使用的地方 (例如說宣告一個原型的終結,例如 Foo.prototype = null )。 +但是在大部分的時候可以用 undefined,來取代。

自動插入分號

雖然 JavaScript 有 C 語言的語法,但是他不強制一定要加上分號。 +所以分號可以被忽略。

+ +

Javascript 並 不是 一個不需要分號的語言。實際上,它需要分號來讓程式碼更容易被理解。因此 Javascript 的編譯器中遇到了缺少分號的情形,它會自動的在程式碼中插入分號。

+ +
var foo = function() {
+} // 編輯錯誤,因沒分號
+test()
+
+ +

這時候編譯器在編輯的時候,會自動的加上分號,然後重新編輯。

+ +
var foo = function() {
+}; // 沒有錯誤,編輯繼續
+test()
+
+ +

自動的加入分號是被認為 最大 的設計缺陷之一,因為它能改變程式碼的行為。

+ +

工作原理

+ +

下面的程式碼中沒有使用任何的分號,所以編譯器需要去決定在哪些地方加入分號。

+ +
(function(window, undefined) {
+    function test(options) {
+        log('testing!')
+
+        (options.list || []).forEach(function(i) {
+
+        })
+
+        options.value.test(
+            'long string to pass here',
+            'and another long string to pass'
+        )
+
+        return
+        {
+            foo: function() {}
+        }
+    }
+    window.test = test
+
+})(window)
+
+(function(window) {
+    window.someLibrary = {}
+
+})(window)
+
+ +

下面的程式碼是編譯器 猜測 的結果。

+ +
(function(window, undefined) {
+    function test(options) {
+
+        // 沒有加入分號,兩行被合併為一行
+        log('testing!')(options.list || []).forEach(function(i) {
+
+        }); // <- 插入分號
+
+        options.value.test(
+            'long string to pass here',
+            'and another long string to pass'
+        ); // <- 插入分號
+
+        return; // <- 插入分號,改變了 return 的表達行為
+        { // 作為另一個程式碼的處理
+
+            // 被當做一個獨立的函數來看
+            foo: function() {} 
+        }; // <- 插入分號
+    }
+    window.test = test; // <- 插入分號
+
+// 兩行又被合併
+})(window)(function(window) {
+    window.someLibrary = {}; // <- 插入分號
+
+})(window); //<- 插入分號
+
+ + + +

編譯器在上面的程式碼中改變了原本程式碼的行為。在一些情況下,會做出 錯誤的行為

+ +

前置括號

+ +

在這種前置括號的情況下,編譯器 不會 自動的插入分號。

+ +
log('testing!')
+(options.list || []).forEach(function(i) {})
+
+ +

上面的程式碼被編譯器轉為只有一行程式

+ +
log('testing!')(options.list || []).forEach(function(i) {})
+
+ +

以上的範例中 log很大 的可能 不是 回傳一個函數。然而這個情況下會出現 TypeError 的錯誤或是會出現 undefined is not a function .

+ +

結語

+ +

建議永遠 不要 忽略分號。同樣的也建議大括號應在他對應的表達式在同一行。在 if... else...的表達式中也是如此,不應省略大括號。 +這個習慣可以不僅僅是讓你的程式更一致,也可以避免編譯器因為改變程式而出錯。

The delete Operator

In short, it's impossible to delete global variables, functions and some other +stuff in JavaScript which have a DontDelete attribute set.

+ +

Global code and Function code

+ +

When a variable or a function is defined in a global or a function +scope it is a property of either the Activation object or +the Global object. Such properties have a set of attributes, one of which is +DontDelete. Variable and function declarations in global and function code +always create properties with DontDelete, and therefore cannot be deleted.

+ +
// global variable:
+var a = 1; // DontDelete is set
+delete a; // false
+a; // 1
+
+// normal function:
+function f() {} // DontDelete is set
+delete f; // false
+typeof f; // "function"
+
+// reassigning doesn't help:
+f = 1;
+delete f; // false
+f; // 1
+
+ +

Explicit properties

+ +

Explicitly set properties can be deleted normally.

+ +
// explicitly set property:
+var obj = {x: 1};
+obj.y = 2;
+delete obj.x; // true
+delete obj.y; // true
+obj.x; // undefined
+obj.y; // undefined
+
+ +

In the example above, obj.x and obj.y can be deleted because they have no +DontDelete atribute. That's why the example below works too.

+ +
// this works fine, except for IE:
+var GLOBAL_OBJECT = this;
+GLOBAL_OBJECT.a = 1;
+a === GLOBAL_OBJECT.a; // true - just a global var
+delete GLOBAL_OBJECT.a; // true
+GLOBAL_OBJECT.a; // undefined
+
+ +

Here we use a trick to delete a. this here refers +to the Global object and we explicitly declare variable a as its property +which allows us to delete it.

+ +

IE (at least 6-8) has some bugs, so the code above doesn't work.

+ +

Function arguments and built-ins

+ +

Functions' normal arguments, arguments objects +and built-in properties also have DontDelete set.

+ +
// function arguments and properties:
+(function (x) {
+
+  delete arguments; // false
+  typeof arguments; // "object"
+
+  delete x; // false
+  x; // 1
+
+  function f(){}
+  delete f.length; // false
+  typeof f.length; // "number"
+
+})(1);
+
+ +

Host objects

+ +

The behaviour of delete operator can be unpredictable for hosted objects. Due +to the specification, host objects are allowed to implement any kind of behavior.

+ +

In conclusion

+ +

The delete operator often has unexpected behaviour and can only be safely +used to delete explicitly set properties on normal objects.

Other

setTimeout and setInterval

Since JavaScript is asynchronous, it is possible to schedule the execution of a +function using the setTimeout and setInterval functions.

+ + + +
function foo() {}
+var id = setTimeout(foo, 1000); // returns a Number > 0
+
+ +

When setTimeout is called, it returns the ID of the timeout and schedule +foo to run approximately one thousand milliseconds in the future. +foo will then be executed once.

+ +

Depending on the timer resolution of the JavaScript engine running the code, as +well as the fact that JavaScript is single threaded and other code that gets +executed might block the thread, it is by no means a safe bet that one will +get the exact delay specified in the setTimeout call.

+ +

The function that was passed as the first parameter will get called by the +global object, which means that this inside the called function +refers to the global object.

+ +
function Foo() {
+    this.value = 42;
+    this.method = function() {
+        // this refers to the global object
+        console.log(this.value); // will log undefined
+    };
+    setTimeout(this.method, 500);
+}
+new Foo();
+
+ + + +

Stacking Calls with setInterval

+ +

While setTimeout only runs the function once, setInterval - as the name +suggests - will execute the function every X milliseconds, but its use is +discouraged.

+ +

When code that is being executed blocks the timeout call, setInterval will +still issue more calls to the specified function. This can, especially with small +intervals, result in function calls stacking up.

+ +
function foo(){
+    // something that blocks for 1 second
+}
+setInterval(foo, 1000);
+
+ +

In the above code, foo will get called once and will then block for one second.

+ +

While foo blocks the code, setInterval will still schedule further calls to +it. Now, when foo has finished, there will already be ten further calls to +it waiting for execution.

+ +

Dealing with Possible Blocking Code

+ +

The easiest solution, as well as most controllable solution, is to use setTimeout within +the function itself.

+ +
function foo(){
+    // something that blocks for 1 second
+    setTimeout(foo, 1000);
+}
+foo();
+
+ +

Not only does this encapsulate the setTimeout call, but it also prevents the +stacking of calls and gives additional control. foo itself can now decide +whether it wants to run again or not.

+ +

Manually Clearing Timeouts

+ +

Clearing timeouts and intervals works by passing the respective ID to +clearTimeout or clearInterval, depending on which set function was used +in the first place.

+ +
var id = setTimeout(foo, 1000);
+clearTimeout(id);
+
+ +

Clearing All Timeouts

+ +

As there is no built-in method for clearing all timeouts and/or intervals, +it is necessary to use brute force in order to achieve this functionality.

+ +
// clear "all" timeouts
+for(var i = 1; i < 1000; i++) {
+    clearTimeout(i);
+}
+
+ +

But there might still be timeouts that are unaffected by this arbitrary number. +Another way of doing this is to consider that the ID given to a timeout is +incremented by one every time you call setTimeout.

+ +
// clear "all" timeouts
+var biggestTimeoutId = window.setTimeout(function(){}, 1),
+i;
+for(i = 1; i <= biggestTimeoutId; i++) {
+    clearTimeout(i);
+}
+
+ +

Even though this works on all major browsers today, it isn't specified that +the IDs should be ordered that way and it may change. Therefore, it is instead +recommended to keep track of all the timeout IDs, so they can be cleared +specifically.

+ +

Hidden Use of eval

+ +

setTimeout and setInterval can also take a string as their first parameter. +This feature should never be used because it internally makes use of eval.

+ + + +
function foo() {
+    // will get called
+}
+
+function bar() {
+    function foo() {
+        // never gets called
+    }
+    setTimeout('foo()', 1000);
+}
+bar();
+
+ +

Since eval is not getting called directly in this case, the string +passed to setTimeout will be executed in the global scope; thus, it will +not use the local variable foo from the scope of bar.

+ +

It is further recommended to not use a string to pass arguments to the +function that will get called by either of the timeout functions.

+ +
function foo(a, b, c) {}
+
+// NEVER use this
+setTimeout('foo(1, 2, 3)', 1000)
+
+// Instead use an anonymous function
+setTimeout(function() {
+    foo(a, b, c);
+}, 1000)
+
+ + + +

In Conclusion

+ +

A string should never be used as the parameter of setTimeout or +setInterval. It is a clear sign of really bad code, when arguments need +to be supplied to the function that gets called. An anonymous function should +be passed that then takes care of the actual call.

+ +

Furthermore, the use of setInterval should be avoided because its scheduler is not +blocked by executing JavaScript.

\ No newline at end of file From 4a2617698774b12942c24b7411e9088db5f53513 Mon Sep 17 00:00:00 2001 From: howardchi Date: Thu, 14 Mar 2013 02:57:50 +0800 Subject: [PATCH 256/463] finished function/ closures, general --- doc/zh-TW/function/closures.md | 63 ++++++++++++---------------------- doc/zh-TW/function/general.md | 45 +++++++++++------------- 2 files changed, 42 insertions(+), 66 deletions(-) diff --git a/doc/zh-TW/function/closures.md b/doc/zh-TW/function/closures.md index 76f2d078..8c558efa 100644 --- a/doc/zh-TW/function/closures.md +++ b/doc/zh-TW/function/closures.md @@ -1,11 +1,10 @@ -## Closures and References +## Closures 和 References -One of JavaScript's most powerful features is the availability of *closures*. -With closures, scopes **always** keep access to the outer scope, in which they -were defined. Since the only scoping that JavaScript has is -[function scope](#function.scopes), all functions, by default, act as closures. +JavaScript 有一個很重要的特徵就是 **closures** +因為有 Closures,所以作用域 **永遠** 能夠去訪問作用區間外面的變數。 +[函數區間](#function.scopes) 是JavaScript 中唯一擁有自生作用域的結構,因此 Closures 的創立需要依賴函數 -### Emulating private variables +### 模仿私有變數 function Counter(start) { var count = start; @@ -24,30 +23,24 @@ were defined. Since the only scoping that JavaScript has is foo.increment(); foo.get(); // 5 -Here, `Counter` returns **two** closures: the function `increment` as well as -the function `get`. Both of these functions keep a **reference** to the scope of -`Counter` and, therefore, always keep access to the `count` variable that was -defined in that scope. +這裡,`Counter` 返回兩個 Closures,函數 `increment` 還有 `get`。這兩個函數都維持著對外部作用域 `Counter` 的引用,因此總可以訪問作用域的變數 `count`。 -### Why Private Variables Work -Since it is not possible to reference or assign scopes in JavaScript, there is -**no** way of accessing the variable `count` from the outside. The only way to -interact with it is via the two closures. +### 為什麼不可以在外部訪問私有變數 + +因為 Javascript **不可以** 對作用域進行引用或賦值。因此外部的地方沒有辦法訪問 `count` 變數。 +唯一的途徑就是經過那兩個 Closures var foo = new Counter(4); foo.hack = function() { count = 1337; }; -The above code will **not** change the variable `count` in the scope of `Counter`, -since `foo.hack` was not defined in **that** scope. It will instead create - or -override - the *global* variable `count`. +在上面的例子中 `count` **不會** 改變到 `Counter` 裡面的 `count` 的值。因為 `foo.hack` 沒有在 **那個** 作用域內被宣告。它只有會覆蓋或者建立在一個 **全域** 的變數 `count` -### Closures Inside Loops +### 在循環內的 Closures -One often made mistake is to use closures inside of loops, as if they were -copying the value of the loop's index variable. +一個常見的錯誤就是在 Closures 中使用迴圈,假設我們要使用每次迴圈中所使用的進入變數 for(var i = 0; i < 10; i++) { setTimeout(function() { @@ -55,20 +48,14 @@ copying the value of the loop's index variable. }, 1000); } -The above will **not** output the numbers `0` through `9`, but will simply print -the number `10` ten times. - -The *anonymous* function keeps a **reference** to `i`. At the time -`console.log` gets called, the `for loop` has already finished, and the value of -`i` as been set to `10`. - -In order to get the desired behavior, it is necessary to create a **copy** of -the value of `i`. +在上面的例子中它 **不會** 輸出數字從 `0` 到 `9`,但只會出現數字 `10` 十次。 +在 `console.log` 被呼叫的時候,這個 *匿名* 函數中保持一個 **參考** 到 i ,此時 `for`迴圈已經結束, `i` 的值被修改成了 `10`。 +為了要達到想要的結果,需要在每次創造 **副本** 來儲存 `i` 的變數。 -### Avoiding the Reference Problem +### 避免引用錯誤 -In order to copy the value of the loop's index variable, it is best to use an -[anonymous wrapper](#function.scopes). +為了要有達到正確的效果,最好是把它包在一個 +[匿名函數](#function.scopes). for(var i = 0; i < 10; i++) { (function(e) { @@ -78,15 +65,9 @@ In order to copy the value of the loop's index variable, it is best to use an })(i); } -The anonymous outer function gets called immediately with `i` as its first -argument and will receive a copy of the **value** of `i` as its parameter `e`. - -The anonymous function that gets passed to `setTimeout` now has a reference to -`e`, whose value does **not** get changed by the loop. - -There is another possible way of achieving this, which is to return a function -from the anonymous wrapper that will then have the same behavior as the code -above. +匿名外部的函數被呼叫,並把 `i` 作為它第一個參數,此時函數內 `e` 變數就擁有了一個 `i` 的拷貝。 +當傳遞給 `setTimeout` 這個匿名函數執行時,它就擁有了對 `e` 的引用,而這個值 **不會** 被循環改變。 +另外有一個方法也可以完成這樣的工作,那就是在匿名函數中返回一個函數,這和上面的程式碼有同樣的效果。 for(var i = 0; i < 10; i++) { setTimeout((function(e) { diff --git a/doc/zh-TW/function/general.md b/doc/zh-TW/function/general.md index b2788e46..57f4810f 100644 --- a/doc/zh-TW/function/general.md +++ b/doc/zh-TW/function/general.md @@ -1,48 +1,43 @@ -## Function Declarations and Expressions +## 函式的宣告和表達方式 -Functions in JavaScript are first class objects. That means they can be -passed around like any other value. One common use of this feature is to pass -an *anonymous function* as a callback to another, possibly an asynchronous function. +函式在 JavaScript 是第一等物件。這表示他們可以把函式當做值一樣傳遞。 +一個常見的用法是用 *匿名函式* 當做一個回傳去呼叫另一個函式,這是一種非同步函式 -### The `function` Declaration +### 函式的宣告 function foo() {} -The above function gets [hoisted](#function.scopes) before the execution of the -program starts; thus, it is available *everywhere* in the scope it was -*defined*, even if called before the actual definition in the source. +上面的函式在被執行之前會被 [解析(hoisted)](#function.scopes),因此它可以在 **任意** 的地方都是 *有宣告的* ,就算是在比這個函式還早呼叫。 - foo(); // Works because foo was created before this code runs + + foo(); // 可以執行,因為 foo 已經在運行前就被建立 function foo() {} -### The `function` Expression +### `function` 的表達式 var foo = function() {}; -This example assigns the unnamed and *anonymous* function to the variable `foo`. +這個例子把一個 *匿名* 函式賦值給變數 `foo`。 foo; // 'undefined' - foo(); // this raises a TypeError + foo(); // 錯誤: TypeError var foo = function() {}; -Due to the fact that `var` is a declaration that hoists the variable name `foo` -before the actual execution of the code starts, `foo` is already defined when -the script gets executed. +由於 `var` 已經宣告變數 `foo` 在所有的程式碼執行之前。 +所以 `foo`已經在程式運行前就已經被定義過了。 +但是因為賦值只會在運行時去職情,所以在程式碼執行前,`foo` 的值還沒被宣告所以為 [undefined](#core.undefined)。 -But since assignments only happen at runtime, the value of `foo` will default -to [undefined](#core.undefined) before the corresponding code is executed. -### Named Function Expression +### 命名函式的賦值表達式 -Another special case is the assignment of named functions. +另一個特殊狀況就勢將一個命名函式賦值給一個變數。 var foo = function bar() { - bar(); // Works + bar(); // 可以運行 } - bar(); // ReferenceError + bar(); // 錯誤:ReferenceError -Here, `bar` is not available in the outer scope, since the function only gets -assigned to `foo`; however, inside of `bar`, it is available. This is due to -how [name resolution](#function.scopes) in JavaScript works, the name of the -function is *always* made available in the local scope of the function itself. +`bar` 不可以在外部的區域被執行,因為它只有在 `foo` 的函式內才可以去執行。 +然而在 `bar` 內部還是可以看見。這是由於 JavaScript的 [命名處理](#function.scopes)所致。 +函式名在函式內 *都* 可以去使用。 From 5804c903bc52bdd878ea635fbf24b06405fcbf3e Mon Sep 17 00:00:00 2001 From: howardchi Date: Thu, 14 Mar 2013 12:38:22 +0800 Subject: [PATCH 257/463] modify language.json, index.json, constructors.md --- doc/language.json | 2 +- doc/zh-TW/function/constructors.md | 81 +++++++++++------------------- doc/zh-TW/function/scopes.md | 18 +++---- doc/zh-TW/function/this.md | 42 +++++++--------- doc/zh-TW/index.json | 20 ++++---- 5 files changed, 67 insertions(+), 96 deletions(-) diff --git a/doc/language.json b/doc/language.json index 19ef049f..c45b38b6 100644 --- a/doc/language.json +++ b/doc/language.json @@ -1,5 +1,5 @@ { "default": "en", - "listed": ["en", "fi", "ru", "zh", "tr", "pl", "ko", "ja", "es"] + "listed": ["en", "fi", "ru", "zh", "tr", "pl", "ko", "ja", "es", "zh-Tw"] } diff --git a/doc/zh-TW/function/constructors.md b/doc/zh-TW/function/constructors.md index bf9771dc..8c493854 100644 --- a/doc/zh-TW/function/constructors.md +++ b/doc/zh-TW/function/constructors.md @@ -1,15 +1,12 @@ -## Constructors +## 建構函式 -Constructors in JavaScript are yet again different from many other languages. Any -function call that is preceded by the `new` keyword acts as a constructor. - -Inside the constructor - the called function - the value of `this` refers to a -newly created object. The [prototype](#object.prototype) of this **new** -object is set to the `prototype` of the function object that was invoked as the -constructor. +JavaScript 中的建構函式和其他語言中的建構函式是不同的。 +用 `new` 的關鍵字方式調用的函式都被認為是建構函式。 +在建構函式內部 - 被呼叫的函式 - `this` 指向一個新建立的 `object`。[prototype](#object.prototype) 這是一個新的物件一個被指向函式的 `prototype` 的建構函式。 If the function that was called has no explicit `return` statement, then it implicitly returns the value of `this` - the new object. +如果被使用的函式沒有明顯的呼叫 `return` 的表達式,它會回傳一個隱性的 `this` 的新物件。 function Foo() { this.bla = 1; @@ -21,16 +18,13 @@ implicitly returns the value of `this` - the new object. var test = new Foo(); -The above calls `Foo` as constructor and sets the `prototype` of the newly -created object to `Foo.prototype`. - -In case of an explicit `return` statement, the function returns the value -specified by that statement, but **only** if the return value is an `Object`. +在上面的例子中 `Foo` 建立一個建構函式,並設立一個 `prototype` 來創建一個新的物件叫 `Foo.prototype`。 +這個情況下它顯示的 `return` 一個表達式,但他 **只** 返回一個 `Object`。 function Bar() { return 2; } - new Bar(); // a new object + new Bar(); // 返回一個新物件 function Test() { this.value = 2; @@ -39,23 +33,20 @@ specified by that statement, but **only** if the return value is an `Object`. foo: 1 }; } - new Test(); // the returned object + new Test(); // 回傳物件 -When the `new` keyword is omitted, the function will **not** return a new object. +如果 `new` 的關鍵字被忽略,函式就 **不會** 回傳一個新的物件。 function Foo() { - this.bla = 1; // gets set on the global object + this.bla = 1; // 獲取一個全域的參數 } Foo(); // undefined -While the above example might still appear to work in some cases, due to the -workings of [`this`](#function.this) in JavaScript, it will use the -*global object* as the value of `this`. +雖然上面有些情況也能正常運行,但是由於 JavaScript 中 [`this`](#funciton.this) 的工作原理,這裡的 `this` 指向 *全域對象*。 -### Factories +### 工廠模式 -In order to be able to omit the `new` keyword, the constructor function has to -explicitly return a value. +為了不使用 `new` 關鍵字,建構函式必須顯性的返回一個值。 function Bar() { var value = 1; @@ -72,25 +63,17 @@ explicitly return a value. new Bar(); Bar(); -Both calls to `Bar` return the same thing, a newly create object that -has a property called `method`, which is a -[Closure](#function.closures). - -It should also be noted that the call `new Bar()` does **not** affect the -prototype of the returned object. While the prototype will be set on the newly -created object, `Bar` never returns that new object. - -In the above example, there is no functional difference between using and -not using the `new` keyword. +上面兩個呼叫 `Bar` 的方法回傳的值都一樣,一個新創建的擁有 `method` 屬性被返回,這裡創建了一個 [Closure](#function.closures). +還有注意, `new Bar()` 並 **不會** 改變返回物件的原型。 +因為建構函式的原型會指向剛剛創立的新物件,而在這裡的 `Bar` 沒有把這個新物件返回。 +在上面的例子中,使用或者不使用 `new` 關鍵字沒有什麼功能性的區別 -### Creating New Objects via Factories -It is often recommended to **not** use `new` because forgetting its use may -lead to bugs. +### 通過工廠模式創建的新對象 -In order to create a new object, one should rather use a factory and construct a -new object inside of that factory. +常聽到建議 **不要** 使用 `new`,因為如果忘記如何使用它會造成錯誤。 +為了創建一個新的物件,我們可以用工廠方法,來創造一個新的物件在那個方法中。 function Foo() { var obj = {}; @@ -107,22 +90,14 @@ new object inside of that factory. return obj; } -While the above is robust against a missing `new` keyword and certainly makes -the use of [private variables](#function.closures) easier, it comes with some -downsides. +雖然上面的方式比起 `new` 的調用方式更不容易出錯,並且可以充分的使用 [私有變數](#function.closures)所帶來的便利,但是還是有一些不好的地方 - 1. It uses more memory since the created objects do **not** share the methods - on a prototype. - 2. In order to inherit, the factory needs to copy all the methods from another - object or put that object on the prototype of the new object. - 3. Dropping the prototype chain just because of a left out `new` keyword - is contrary to the spirit of the language. -### In Conclusion +1. 會占用更多的記憶體,因為創建的物件 **沒有** 辦法放在在同一個原型上。 +2. 為了要用繼承的方式,工廠方法需要複製所有的屬性或是把一個物件作為新的物件的原型。 +3. 放棄原型鏈僅僅是因為防止遺漏 `new` 所帶來的問題,這與語言本身的思想鄉違背。 -While omitting the `new` keyword might lead to bugs, it is certainly **not** a -reason to drop the use of prototypes altogether. In the end it comes down to -which solution is better suited for the needs of the application. It is -especially important to choose a specific style of object creation and use it -**consistently**. +### 結語 +雖然遺漏 `new` 關鍵字可能會導致問題,但這並 **不是** 放棄只用原型的藉口。 +最終使用哪種方式取決於應用程式的需求,選擇一種程式語言風格並堅持下去才是最重要的。 diff --git a/doc/zh-TW/function/scopes.md b/doc/zh-TW/function/scopes.md index 879e1e8a..00263804 100644 --- a/doc/zh-TW/function/scopes.md +++ b/doc/zh-TW/function/scopes.md @@ -1,12 +1,11 @@ -## Scopes and Namespaces +## 作用域和命名空間 -Although JavaScript deals fine with the syntax of two matching curly -braces for blocks, it does **not** support block scope; hence, all that is left -in the language is *function scope*. +儘管 JavaScript 支持一個大括號創建的程式碼,但並不支持塊級作用域。 +而僅僅支援 *函式作用域* - function test() { // a scope - for(var i = 0; i < 10; i++) { // not a scope - // count + function test() { // 一個作用域 + for(var i = 0; i < 10; i++) { // 不是一個作用域 + // 算數 } console.log(i); // 10 } @@ -16,6 +15,7 @@ in the language is *function scope*. > **not** as an object literal. This, in conjunction with > [automatic insertion of semicolons](#core.semicolon), can lead to subtle errors. + There are also no distinct namespaces in JavaScript, which means that everything gets defined in one *globally shared* namespace. @@ -23,7 +23,7 @@ Each time a variable is referenced, JavaScript will traverse upwards through all the scopes until it finds it. In the case that it reaches the global scope and still has not found the requested name, it will raise a `ReferenceError`. -### The Bane of Global Variables +### 全域變數的壞處 // script A foo = '42'; @@ -222,7 +222,7 @@ which, while different in syntax, behave the same way. (function(){}()); // and so on... -### In Conclusion +### 結語 It is recommended to always use an *anonymous wrapper* to encapsulate code in its own namespace. This does not only protect code against name clashes, but it diff --git a/doc/zh-TW/function/this.md b/doc/zh-TW/function/this.md index 48070d2e..31081883 100644 --- a/doc/zh-TW/function/this.md +++ b/doc/zh-TW/function/this.md @@ -1,50 +1,46 @@ -## How `this` Works +## `this` 的工作原理 -JavaScript has a different concept of what the special name `this` refers to -than most other programming languages. There are exactly **five** different -ways in which the value of `this` can be bound in the language. +JavaScript 有移到完全部屬於其他語言處理 `this` 的處理機制。 +在 **五** 種物同的情況下, `this` 指向的個不相同 -### The Global Scope +### 全域變數 this; -When using `this` in global scope, it will simply refer to the *global* object. +如果再全域範圍內使用 `this`,會指向 *全域* 的物件 -### Calling a Function +### 呼叫一個函式 foo(); -Here, `this` will again refer to the *global* object. +這裡 `this` 也會指向 *全域* 對象。 -> **ES5 Note:** In strict mode, the global case **no longer** exists. -> `this` will instead have the value of `undefined` in that case. +> **ES5 注意:** 在嚴格模式下,不存在全域變數。 +> `this` 將會是 `undefined`。 -### Calling a Method +### 方法調用 test.foo(); -In this example, `this` will refer to `test`. +這個例子中, `this` 指向 `test` 物件。 -### Calling a Constructor +### 呼叫一個建構函式 new foo(); -A function call that is preceded by the `new` keyword acts as -a [constructor](#function.constructors). Inside the function, `this` will refer -to a *newly created* `Object`. +如果函式傾向用 `new` 關鍵詞使用,我們稱這個函式為 [建構函式](#function.constructors)。 +在函式內部, `this` 指向 *新物件的創立* -### Explicit Setting of `this` +### 顯示的設置 `this` function foo(a, b, c) {} var bar = {}; - foo.apply(bar, [1, 2, 3]); // array will expand to the below - foo.call(bar, 1, 2, 3); // results in a = 1, b = 2, c = 3 + foo.apply(bar, [1, 2, 3]); // Array 會被擴展,如下所示 + foo.call(bar, 1, 2, 3); // 傳遞參數 a = 1, b = 2, c = 3 -When using the `call` or `apply` methods of `Function.prototype`, the value of -`this` inside the called function gets **explicitly set** to the first argument -of the corresponding function call. +當使用 `function.prototype` 上的 `call` 或只 `apply` 方法時,函式內的 `this` 將會被 **顯示設置** 為函式調用的第一個參數。 As a result, in the above example the *method case* does **not** apply, and `this` inside of `foo` will be set to `bar`. @@ -53,7 +49,7 @@ inside of `foo` will be set to `bar`. > literal. So `var obj = {me: this}` will **not** result in `me` referring to > `obj`, since `this` only gets bound by one of the five listed cases. -### Common Pitfalls +### 常見誤解 While most of these cases make sense, the first can be considered another mis-design of the language because it **never** has any practical use. diff --git a/doc/zh-TW/index.json b/doc/zh-TW/index.json index bffcbf2c..362fcb44 100644 --- a/doc/zh-TW/index.json +++ b/doc/zh-TW/index.json @@ -1,15 +1,15 @@ { - "title": "JavaScript Garden", - "langTitle": "JavaScript Garden in English", - "description": "A Guide to JavaScript's Quirks and Flaws.", + "title": "JavaScript 庭院", + "langTitle": "JavaScript Garden 繁體中文翻譯", + "description": "JavaScript 語言中古怪用法及缺點的文件總集", "sections": [ { - "title": "Intro", + "title": "簡介", "dir": "intro", "articles": [] }, { - "title": "Objects", + "title": "物件", "dir": "object", "articles": [ "general", @@ -19,7 +19,7 @@ ] }, { - "title": "Functions", + "title": "函式", "dir": "function", "articles": [ "general", @@ -31,7 +31,7 @@ ] }, { - "title": "Arrays", + "title": "陣列", "dir": "array", "articles": [ "general", @@ -39,7 +39,7 @@ ] }, { - "title": "Types", + "title": "類型", "dir": "types", "articles": [ "equality", @@ -49,7 +49,7 @@ ] }, { - "title": "Core", + "title": "核心", "dir": "core", "articles": [ "eval", @@ -59,7 +59,7 @@ ] }, { - "title": "Other", + "title": "其他", "dir": "other", "articles": [ "timeouts" From 3cb2af35117fea202c740ac1708dd8300b3512bc Mon Sep 17 00:00:00 2001 From: howardchi Date: Thu, 14 Mar 2013 15:51:02 +0800 Subject: [PATCH 258/463] finished function/ scope.md --- doc/zh-TW/function/scopes.md | 158 +++++++++------------- site/zh-TW/index.html | 251 ++++++++++++++--------------------- 2 files changed, 161 insertions(+), 248 deletions(-) diff --git a/doc/zh-TW/function/scopes.md b/doc/zh-TW/function/scopes.md index 00263804..3f7c72dd 100644 --- a/doc/zh-TW/function/scopes.md +++ b/doc/zh-TW/function/scopes.md @@ -10,18 +10,13 @@ console.log(i); // 10 } -> **Note:** When not used in an assignment, return statement or as a function -> argument, the `{...}` notation will get interpreted as a block statement and -> **not** as an object literal. This, in conjunction with -> [automatic insertion of semicolons](#core.semicolon), can lead to subtle errors. +> **注意:** 如果不是在賦值語句中,而是在 return 表達式或者函數參數中, `{...}` 將會作為程式碼中的解析,而不是作為物件的字面語法解析。 +> 如果考慮到 [自動分號插入](#core.semicolon),可能會造成一些不易察覺的錯誤。 +JavaScript 中沒有寫示的命名空間定義,這代表著它所有定義的東西都是 *全域共享* 在同一個命名空間下。 -There are also no distinct namespaces in JavaScript, which means that everything -gets defined in one *globally shared* namespace. - -Each time a variable is referenced, JavaScript will traverse upwards through all -the scopes until it finds it. In the case that it reaches the global scope and -still has not found the requested name, it will raise a `ReferenceError`. +每次引用一個變數,JavaScript 會向上找整個作用域直到找到這個變數為止。 +如果在全域中無法找到那個變數,它會拋出 `ReferenceError` 錯誤碼。 ### 全域變數的壞處 @@ -31,17 +26,14 @@ still has not found the requested name, it will raise a `ReferenceError`. // script B var foo = '42' -The above two scripts do **not** have the same effect. Script A defines a -variable called `foo` in the *global* scope, and script B defines a `foo` in the -*current* scope. +上面兩個腳本 *不會* 有同樣的效果。腳本 A 在 *全域* 空間定義了變數 `foo`,腳本 B 定義了 `foo` 在目前的區間內。 -Again, that is **not** at all the *same effect*: not using `var` can have major -implications. +再次強調,上面的效果是 **完全不同**,不使用 `var` 會導致隱性的全域變數。 - // global scope + // 全域作用區 var foo = 42; function test() { - // local scope + // 局部作用區 foo = 21; } test(); @@ -51,38 +43,39 @@ Leaving out the `var` statement inside the function `test` will override the value of `foo`. While this might not seem like a big deal at first, having thousands of lines of JavaScript and not using `var` will introduce horrible, hard-to-track-down bugs. +在函數 `test` 中部使用 `var` 會覆蓋到原本在外面的 `foo`。 +雖然看起來不是什麼大問題,但是當程式有幾千行的時候沒有使用 `var` 會照成難以追蹤的臭蟲。 + - // global scope + // 全域作用域 var items = [/* some list */]; for(var i = 0; i < 10; i++) { subLoop(); } function subLoop() { - // scope of subLoop - for(i = 0; i < 10; i++) { // missing var statement - // do amazing stuff! + // subLoop 的作用域 + for(i = 0; i < 10; i++) { // 缺少了 var + // 做一些事情 } } -The outer loop will terminate after the first call to `subLoop`, since `subLoop` -overwrites the global value of `i`. Using a `var` for the second `for` loop would -have easily avoided this error. The `var` statement should **never** be left out -unless the *desired effect* is to affect the outer scope. +在外面的迴圈在呼叫第一次 `subLoop` 之後就會停止,因為 `subLoop` 全域變數中的 `i` 被覆蓋了。 +在第二次使用 `for` 迴圈的時候,使用 `var` 就可以避免這種錯誤。 +在宣告變數的時候 **絕對不要** 忘記 `var`,除非就是 `希望他的效果` 是取改變外部的作用域。 -### Local Variables +### 局部變數 -The only source for local variables in JavaScript are -[function](#function.general) parameters and variables declared via the -`var` statement. +在 javascript 中能用兩種方式來宣告局部變數。 +[函式](#function.general) 參數和透過 `var` 來宣告變數。 - // global scope + // 全域變數 var foo = 1; var bar = 2; var i = 2; function test(i) { - // local scope of the function test + // 函式 test 內部的局部作用域 i = 5; var foo = 3; @@ -90,13 +83,11 @@ The only source for local variables in JavaScript are } test(10); -While `foo` and `i` are local variables inside the scope of the function `test`, -the assignment of `bar` will override the global variable with the same name. +`foo` 和 `i` 是它的局部變數在 `test` 函式中,但是在 `bar` 的賦值會覆蓋全區域的作用域內的同名變數。 -### Hoisting +### 變數宣告 -JavaScript **hoists** declarations. This means that both `var` statements and -`function` declarations will be moved to the top of their enclosing scope. +JavaScript 會 **提昇** 變數宣告, 這代表著 `var` 和 `function` 的圈告都會被提升到當前作用域的頂端。 bar(); var bar = function() {}; @@ -115,16 +106,14 @@ JavaScript **hoists** declarations. This means that both `var` statements and } } -The above code gets transformed before execution starts. JavaScript moves -the `var` statements, as well as `function` declarations, to the top of the -nearest surrounding scope. +在上面的程式碼會被轉化在執行之前。 JavaScript 會把 `var`,和 `function` 宣告,放到最頂端最接近的作用區間 - // var statements got moved here - var bar, someValue; // default to 'undefined' + // var 被移到這裡 + var bar, someValue; // 值等於 'undefined' - // the function declaration got moved up too + // function 的宣告也被搬上來 function test(data) { - var goo, i, e; // missing block scope moves these here + var goo, i, e; // 沒有作用域的也被搬至頂端 if (false) { goo = 1; @@ -136,87 +125,72 @@ nearest surrounding scope. } } - bar(); // fails with a TypeError since bar is still 'undefined' - someValue = 42; // assignments are not affected by hoisting + bar(); // 出錯:TypeError , bar 還是 'undefined' + someValue = 42; // 賦值語句不會被提昇規則影響 bar = function() {}; test(); -Missing block scoping will not only move `var` statements out of loops and -their bodies, it will also make the results of certain `if` constructs -non-intuitive. +沒有作用域區間不只會把 `var` 放到迴圈之外,還會使得 `if` 表達式更難看懂。 -In the original code, although the `if` statement seemed to modify the *global -variable* `goo`, it actually modifies the *local variable* - after hoisting -has been applied. +在一般的程式中,雖然 `if` 表達式中看起來修改了 *全域變數* `goo`,但實際上在提昇規則被運用後,卻是在修改 *局部變數* -Without knowledge of *hoisting*, one might suspect the code below would raise a -`ReferenceError`. +如果沒有提昇規則的話,可能會出現像下面的看起來會出現 `ReferenceError` 的錯誤。 - // check whether SomeImportantThing has been initialized + // 檢查 SomeImportantThing 是否已經被初始化 if (!SomeImportantThing) { var SomeImportantThing = {}; } -But of course, this works due to the fact that the `var` statement is being -moved to the top of the *global scope*. +但是它沒有錯誤,因為 `var` 的表達式會被提升到 *全域作用域* 的頂端。 var SomeImportantThing; - // other code might initialize SomeImportantThing here, or not + // 有些程式,可能會初始化。 + SomeImportantThing here, or not - // make sure it's there + // 檢查是否已經被初始化。 if (!SomeImportantThing) { SomeImportantThing = {}; } -### Name Resolution Order - -All scopes in JavaScript, including the *global scope*, have the special name -[`this`](#function.this), defined in them, which refers to the *current object*. +### 名稱解析順序 + +JavaScript 中所有的作用區,包括 *全域作用域*,都有一個特殊的名字 [`this`](#function.this), 在它們裡面被定義,指向當前的物件 -Function scopes also have the name [`arguments`](#function.arguments), defined in -them, which contains the arguments that were passed to the function. +函式作用域也有一個名稱叫做 [`arguments`](#function.arguments), 定義它們,其中包括傳到函式內的參數。 -For example, when trying to access a variable named `foo` inside the scope of a -function, JavaScript will look up the name in the following order: +例如,它們開始試著進入到 `foo` 的作用域裡面, JavaScript 會依照下面的順序去查詢: - 1. In case there is a `var foo` statement in the current scope, use that. - 2. If one of the function parameters is named `foo`, use that. - 3. If the function itself is called `foo`, use that. - 4. Go to the next outer scope, and start with **#1** again. + 1. 當作用域內是否有 `var foo` 的定義。 + 2. 函式形式參數是否有使用 `foo` 名稱定義。 + 3. 函式自身是剖叫做 `foo`。 + 4. 回溯到上一個層級然後再從第一個開始往下去查。 -> **Note:** Having a parameter called `arguments` will **prevent** the creation -> of the default `arguments` object. +> **注意: ** 自定義 `arguments` 參數會阻止原生的 `arguments` 的物件創立 -### Namespaces +### 命名空間 -A common problem associated with having only one global namespace is the -likelihood of running into problems where variable names clash. In JavaScript, -this problem can easily be avoided with the help of *anonymous wrappers*. +只有一個全域作用域會導致常見的錯誤是命名衝突。在 JavaScript 中可以透過 *匿名包裝器* 來解決。 (function() { - // a self contained "namespace" + // 自己本身的匿名空間 window.foo = function() { - // an exposed closure + // 對外公開的函式 }; - })(); // execute the function immediately + })(); // 馬上執行這個匿名函式 +匿名函式被認為是 [表達式](#function.general)因此為了要可以調用,它們會先被執行。 -Unnamed functions are considered [expressions](#function.general); so in order to -being callable, they must first be evaluated. - - ( // evaluate the function inside the parentheses + ( // 小括號內的先被執行 function() {} - ) // and return the function object - () // call the result of the evaluation + ) // 回傳函數對象 + () // 調用上面的執行結果 -There are other ways to evaluate and directly call the function expression -which, while different in syntax, behave the same way. +還有其他方式也可以像上面一樣調用函式的方式達到 - // A few other styles for directly invoking the !function(){}() +function(){}() (function(){}()); @@ -224,10 +198,6 @@ which, while different in syntax, behave the same way. ### 結語 -It is recommended to always use an *anonymous wrapper* to encapsulate code in -its own namespace. This does not only protect code against name clashes, but it -also allows for better modularization of programs. - -Additionally, the use of global variables is considered **bad practice**. **Any** -use of them indicates badly written code that is prone to errors and hard to maintain. +建議最好是都用 *匿名包裝器* 來封裝你的程式碼在自己的命名區間內。這不僅是要防止命名衝突也可以使得程序更有模組化。 +另外,全域變數是個 **不好的** 習慣,因為它會帶來錯誤和更難去維護。 \ No newline at end of file diff --git a/site/zh-TW/index.html b/site/zh-TW/index.html index 8ae0e924..94c2d741 100644 --- a/site/zh-TW/index.html +++ b/site/zh-TW/index.html @@ -1,7 +1,7 @@ -JavaScript Garden -

Intro

JavaScript Garden is a growing collection of documentation about the most +

簡介

JavaScript Garden is a growing collection of documentation about the most quirky parts of the JavaScript programming language. It gives advice to avoid common mistakes and subtle bugs, as well as performance issues and bad practices, that non-expert JavaScript programmers may encounter on their @@ -34,7 +34,7 @@

License

JavaScript Garden is published under the MIT license and hosted on GitHub. If you find errors or typos please file an issue or a pull request on the repository. You can also find us in the JavaScript room on -Stack Overflow chat.

Objects

Object Usage and Properties

Everything in JavaScript acts like an object, with the only two exceptions being +Stack Overflow chat.

物件

Object Usage and Properties

Everything in JavaScript acts like an object, with the only two exceptions being null and undefined.

false.toString(); // 'false'
@@ -357,105 +357,94 @@ 

License

It is recommended to always use hasOwnProperty. Assumptions should never be made about the environment the code is running in, or whether the native -prototypes have been extended or not.

Functions

Function Declarations and Expressions

Functions in JavaScript are first class objects. That means they can be -passed around like any other value. One common use of this feature is to pass -an anonymous function as a callback to another, possibly an asynchronous function.

+prototypes have been extended or not.

函式

函式的宣告和表達方式

函式在 JavaScript 是第一等物件。這表示他們可以把函式當做值一樣傳遞。 +一個常見的用法是用 匿名函式 當做一個回傳去呼叫另一個函式,這是一種非同步函式

-

The function Declaration

+

函式的宣告

function foo() {}
 
-

The above function gets hoisted before the execution of the -program starts; thus, it is available everywhere in the scope it was -defined, even if called before the actual definition in the source.

+

上面的函式在被執行之前會被 解析(hoisted),因此它可以在 任意 的地方都是 有宣告的 ,就算是在比這個函式還早呼叫。

-
foo(); // Works because foo was created before this code runs
+
foo(); // 可以執行,因為 foo 已經在運行前就被建立
 function foo() {}
 
-

The function Expression

+

function 的表達式

var foo = function() {};
 
-

This example assigns the unnamed and anonymous function to the variable foo.

+

這個例子把一個 匿名 函式賦值給變數 foo

foo; // 'undefined'
-foo(); // this raises a TypeError
+foo(); // 錯誤: TypeError
 var foo = function() {};
 
-

Due to the fact that var is a declaration that hoists the variable name foo -before the actual execution of the code starts, foo is already defined when -the script gets executed.

+

由於 var 已經宣告變數 foo 在所有的程式碼執行之前。 +所以 foo已經在程式運行前就已經被定義過了。 +但是因為賦值只會在運行時去職情,所以在程式碼執行前,foo 的值還沒被宣告所以為 undefined

-

But since assignments only happen at runtime, the value of foo will default -to undefined before the corresponding code is executed.

+

命名函式的賦值表達式

-

Named Function Expression

- -

Another special case is the assignment of named functions.

+

另一個特殊狀況就勢將一個命名函式賦值給一個變數。

var foo = function bar() {
-    bar(); // Works
+    bar(); // 可以運行
 }
-bar(); // ReferenceError
+bar(); // 錯誤:ReferenceError
 
-

Here, bar is not available in the outer scope, since the function only gets -assigned to foo; however, inside of bar, it is available. This is due to -how name resolution in JavaScript works, the name of the -function is always made available in the local scope of the function itself.

How this Works

JavaScript has a different concept of what the special name this refers to -than most other programming languages. There are exactly five different -ways in which the value of this can be bound in the language.

+

bar 不可以在外部的區域被執行,因為它只有在 foo 的函式內才可以去執行。 +然而在 bar 內部還是可以看見。這是由於 JavaScript的 命名處理所致。 +函式名在函式內 可以去使用。

this 的工作原理

JavaScript 有移到完全部屬於其他語言處理 this 的處理機制。 +在 種物同的情況下, this 指向的個不相同

-

The Global Scope

+

全域變數

this;
 
-

When using this in global scope, it will simply refer to the global object.

+

如果再全域範圍內使用 this,會指向 全域 的物件

-

Calling a Function

+

呼叫一個函式

foo();
 
-

Here, this will again refer to the global object.

+

這裡 this 也會指向 全域 對象。

-

Calling a Method

+

方法調用

test.foo(); 
 
-

In this example, this will refer to test.

+

這個例子中, this 指向 test 物件。

-

Calling a Constructor

+

呼叫一個建構函式

new foo(); 
 
-

A function call that is preceded by the new keyword acts as -a constructor. Inside the function, this will refer -to a newly created Object.

+

如果函式傾向用 new 關鍵詞使用,我們稱這個函式為 建構函式。 +在函式內部, this 指向 新物件的創立

-

Explicit Setting of this

+

顯示的設置 this

function foo(a, b, c) {}
 
 var bar = {};
-foo.apply(bar, [1, 2, 3]); // array will expand to the below
-foo.call(bar, 1, 2, 3); // results in a = 1, b = 2, c = 3
+foo.apply(bar, [1, 2, 3]); // Array 會被擴展,如下所示
+foo.call(bar, 1, 2, 3); // 傳遞參數 a = 1, b = 2, c = 3
 
-

When using the call or apply methods of Function.prototype, the value of -this inside the called function gets explicitly set to the first argument -of the corresponding function call.

+

當使用 function.prototype 上的 call 或只 apply 方法時,函式內的 this 將會被 顯示設置 為函式調用的第一個參數。

As a result, in the above example the method case does not apply, and this inside of foo will be set to bar.

@@ -466,7 +455,7 @@

License

obj, since this only gets bound by one of the five listed cases.

-

Common Pitfalls

+

常見誤解

While most of these cases make sense, the first can be considered another mis-design of the language because it never has any practical use.

@@ -523,12 +512,11 @@

License

When method gets called on an instance of Bar, this will now refer to that -very instance.

Closures and References

One of JavaScript's most powerful features is the availability of closures. -With closures, scopes always keep access to the outer scope, in which they -were defined. Since the only scoping that JavaScript has is -function scope, all functions, by default, act as closures.

+very instance.

Closures 和 References

JavaScript 有一個很重要的特徵就是 closures +因為有 Closures,所以作用域 永遠 能夠去訪問作用區間外面的變數。 +函數區間 是JavaScript 中唯一擁有自生作用域的結構,因此 Closures 的創立需要依賴函數

-

Emulating private variables

+

模仿私有變數

function Counter(start) {
     var count = start;
@@ -548,16 +536,12 @@ 

License

foo.get(); // 5
-

Here, Counter returns two closures: the function increment as well as -the function get. Both of these functions keep a reference to the scope of -Counter and, therefore, always keep access to the count variable that was -defined in that scope.

+

這裡,Counter 返回兩個 Closures,函數 increment 還有 get。這兩個函數都維持著對外部作用域 Counter 的引用,因此總可以訪問作用域的變數 count

-

Why Private Variables Work

+

為什麼不可以在外部訪問私有變數

-

Since it is not possible to reference or assign scopes in JavaScript, there is -no way of accessing the variable count from the outside. The only way to -interact with it is via the two closures.

+

因為 Javascript 不可以 對作用域進行引用或賦值。因此外部的地方沒有辦法訪問 count 變數。 +唯一的途徑就是經過那兩個 Closures

var foo = new Counter(4);
 foo.hack = function() {
@@ -565,14 +549,11 @@ 

License

};
-

The above code will not change the variable count in the scope of Counter, -since foo.hack was not defined in that scope. It will instead create - or -override - the global variable count.

+

在上面的例子中 count 不會 改變到 Counter 裡面的 count 的值。因為 foo.hack 沒有在 那個 作用域內被宣告。它只有會覆蓋或者建立在一個 全域 的變數 count

-

Closures Inside Loops

+

在循環內的 Closures

-

One often made mistake is to use closures inside of loops, as if they were -copying the value of the loop's index variable.

+

一個常見的錯誤就是在 Closures 中使用迴圈,假設我們要使用每次迴圈中所使用的進入變數

for(var i = 0; i < 10; i++) {
     setTimeout(function() {
@@ -581,20 +562,14 @@ 

License

}
-

The above will not output the numbers 0 through 9, but will simply print -the number 10 ten times.

- -

The anonymous function keeps a reference to i. At the time -console.log gets called, the for loop has already finished, and the value of -i as been set to 10.

+

在上面的例子中它 不會 輸出數字從 09,但只會出現數字 10 十次。 +在 console.log 被呼叫的時候,這個 匿名 函數中保持一個 參考 到 i ,此時 for迴圈已經結束, i 的值被修改成了 10。 +為了要達到想要的結果,需要在每次創造 副本 來儲存 i 的變數。

-

In order to get the desired behavior, it is necessary to create a copy of -the value of i.

+

避免引用錯誤

-

Avoiding the Reference Problem

- -

In order to copy the value of the loop's index variable, it is best to use an -anonymous wrapper.

+

為了要有達到正確的效果,最好是把它包在一個 +匿名函數.

for(var i = 0; i < 10; i++) {
     (function(e) {
@@ -605,15 +580,9 @@ 

License

}
-

The anonymous outer function gets called immediately with i as its first -argument and will receive a copy of the value of i as its parameter e.

- -

The anonymous function that gets passed to setTimeout now has a reference to -e, whose value does not get changed by the loop.

- -

There is another possible way of achieving this, which is to return a function -from the anonymous wrapper that will then have the same behavior as the code -above.

+

匿名外部的函數被呼叫,並把 i 作為它第一個參數,此時函數內 e 變數就擁有了一個 i 的拷貝。 +當傳遞給 setTimeout 這個匿名函數執行時,它就擁有了對 e 的引用,而這個值 不會 被循環改變。 +另外有一個方法也可以完成這樣的工作,那就是在匿名函數中返回一個函數,這和上面的程式碼有同樣的效果。

for(var i = 0; i < 10; i++) {
     setTimeout((function(e) {
@@ -724,16 +693,13 @@ 

License

強烈建議不要使用 arguments.callee 或是其他它的屬性

Constructors

Constructors in JavaScript are yet again different from many other languages. Any -function call that is preceded by the new keyword acts as a constructor.

- -

Inside the constructor - the called function - the value of this refers to a -newly created object. The prototype of this new -object is set to the prototype of the function object that was invoked as the -constructor.

+

建構函式

JavaScript 中的建構函式和其他語言中的建構函式是不同的。 +用 new 的關鍵字方式調用的函式都被認為是建構函式。 +在建構函式內部 - 被呼叫的函式 - this 指向一個新建立的 objectprototype 這是一個新的物件一個被指向函式的 prototype 的建構函式。

If the function that was called has no explicit return statement, then it -implicitly returns the value of this - the new object.

+implicitly returns the value of this - the new object. +如果被使用的函式沒有明顯的呼叫 return 的表達式,它會回傳一個隱性的 this 的新物件。

function Foo() {
     this.bla = 1;
@@ -746,16 +712,13 @@ 

License

var test = new Foo();
-

The above calls Foo as constructor and sets the prototype of the newly -created object to Foo.prototype.

- -

In case of an explicit return statement, the function returns the value -specified by that statement, but only if the return value is an Object.

+

在上面的例子中 Foo 建立一個建構函式,並設立一個 prototype 來創建一個新的物件叫 Foo.prototype。 +這個情況下它顯示的 return 一個表達式,但他 返回一個 Object

function Bar() {
     return 2;
 }
-new Bar(); // a new object
+new Bar(); // 返回一個新物件
 
 function Test() {
     this.value = 2;
@@ -764,25 +727,22 @@ 

License

foo: 1 }; } -new Test(); // the returned object +new Test(); // 回傳物件
-

When the new keyword is omitted, the function will not return a new object.

+

如果 new 的關鍵字被忽略,函式就 不會 回傳一個新的物件。

function Foo() {
-    this.bla = 1; // gets set on the global object
+    this.bla = 1; // 獲取一個全域的參數
 }
 Foo(); // undefined
 
-

While the above example might still appear to work in some cases, due to the -workings of this in JavaScript, it will use the -global object as the value of this.

+

雖然上面有些情況也能正常運行,但是由於 JavaScript 中 this 的工作原理,這裡的 this 指向 全域對象

-

Factories

+

工廠模式

-

In order to be able to omit the new keyword, the constructor function has to -explicitly return a value.

+

為了不使用 new 關鍵字,建構函式必須顯性的返回一個值。

function Bar() {
     var value = 1;
@@ -800,24 +760,16 @@ 

License

Bar();
-

Both calls to Bar return the same thing, a newly create object that -has a property called method, which is a -Closure.

+

上面兩個呼叫 Bar 的方法回傳的值都一樣,一個新創建的擁有 method 屬性被返回,這裡創建了一個 Closure.

-

It should also be noted that the call new Bar() does not affect the -prototype of the returned object. While the prototype will be set on the newly -created object, Bar never returns that new object.

+

還有注意, new Bar()不會 改變返回物件的原型。 +因為建構函式的原型會指向剛剛創立的新物件,而在這裡的 Bar 沒有把這個新物件返回。 +在上面的例子中,使用或者不使用 new 關鍵字沒有什麼功能性的區別

-

In the above example, there is no functional difference between using and -not using the new keyword.

+

通過工廠模式創建的新對象

-

Creating New Objects via Factories

- -

It is often recommended to not use new because forgetting its use may -lead to bugs.

- -

In order to create a new object, one should rather use a factory and construct a -new object inside of that factory.

+

常聽到建議 不要 使用 new,因為如果忘記如何使用它會造成錯誤。 +為了創建一個新的物件,我們可以用工廠方法,來創造一個新的物件在那個方法中。

function Foo() {
     var obj = {};
@@ -835,32 +787,23 @@ 

License

}
-

While the above is robust against a missing new keyword and certainly makes -the use of private variables easier, it comes with some -downsides.

+

雖然上面的方式比起 new 的調用方式更不容易出錯,並且可以充分的使用 私有變數所帶來的便利,但是還是有一些不好的地方

    -
  1. It uses more memory since the created objects do not share the methods -on a prototype.
  2. -
  3. In order to inherit, the factory needs to copy all the methods from another -object or put that object on the prototype of the new object.
  4. -
  5. Dropping the prototype chain just because of a left out new keyword -is contrary to the spirit of the language.
  6. +
  7. 會占用更多的記憶體,因為創建的物件 沒有 辦法放在在同一個原型上。
  8. +
  9. 為了要用繼承的方式,工廠方法需要複製所有的屬性或是把一個物件作為新的物件的原型。
  10. +
  11. 放棄原型鏈僅僅是因為防止遺漏 new 所帶來的問題,這與語言本身的思想鄉違背。
-

In Conclusion

+

結語

-

While omitting the new keyword might lead to bugs, it is certainly not a -reason to drop the use of prototypes altogether. In the end it comes down to -which solution is better suited for the needs of the application. It is -especially important to choose a specific style of object creation and use it -consistently.

Scopes and Namespaces

Although JavaScript deals fine with the syntax of two matching curly -braces for blocks, it does not support block scope; hence, all that is left -in the language is function scope.

- -
function test() { // a scope
-    for(var i = 0; i < 10; i++) { // not a scope
-        // count
+

雖然遺漏 new 關鍵字可能會導致問題,但這並 不是 放棄只用原型的藉口。 +最終使用哪種方式取決於應用程式的需求,選擇一種程式語言風格並堅持下去才是最重要的。

作用域和命名空間

儘管 JavaScript 支持一個大括號創建的程式碼,但並不支持塊級作用域。 +而僅僅支援 函式作用域

+ +
function test() { // 一個作用域
+    for(var i = 0; i < 10; i++) { // 不是一個作用域
+        // 算數
     }
     console.log(i); // 10
 }
@@ -880,7 +823,7 @@ 

License

the scopes until it finds it. In the case that it reaches the global scope and still has not found the requested name, it will raise a ReferenceError.

-

The Bane of Global Variables

+

全域變數的壞處

// script A
 foo = '42';
@@ -1093,14 +1036,14 @@ 

License

// and so on...
-

In Conclusion

+

結語

It is recommended to always use an anonymous wrapper to encapsulate code in its own namespace. This does not only protect code against name clashes, but it also allows for better modularization of programs.

Additionally, the use of global variables is considered bad practice. Any -use of them indicates badly written code that is prone to errors and hard to maintain.

Arrays

Array 迴圈和屬性

雖然在 Javascript 中 Array 都是 Objects,但是沒有好的理由要使用他 +use of them indicates badly written code that is prone to errors and hard to maintain.

陣列

Array 迴圈和屬性

雖然在 Javascript 中 Array 都是 Objects,但是沒有好的理由要使用他 在 for in 的迴圈中。事實上有很多原因要避免使用 for in 在 Array 之中

結語

-

Array 的建構函式需要避免,建議使用字面語法。因為他們比較簡短、也更增加閱讀性

Types

Equality and Comparisons

JavaScript has two different ways of comparing the values of objects for equality.

+

Array 的建構函式需要避免,建議使用字面語法。因為他們比較簡短、也更增加閱讀性

類型

Equality and Comparisons

JavaScript has two different ways of comparing the values of objects for equality.

The Equality Operator

@@ -1440,7 +1383,7 @@

License

!!'-1' // true !!{}; // true !!true; // true -

Core

為什麼不要使用 eval

因為 eval 函數會在 Javascript 的區域性的區間執行那段程式碼。

+

核心

為什麼不要使用 eval

因為 eval 函數會在 Javascript 的區域性的區間執行那段程式碼。

var foo = 1;
 function test() {
@@ -1728,7 +1671,7 @@ 

License

In conclusion

The delete operator often has unexpected behaviour and can only be safely -used to delete explicitly set properties on normal objects.

Other

setTimeout and setInterval

Since JavaScript is asynchronous, it is possible to schedule the execution of a +used to delete explicitly set properties on normal objects.

其他

setTimeout and setInterval

Since JavaScript is asynchronous, it is possible to schedule the execution of a function using the setTimeout and setInterval functions.