diff --git a/.gitignore b/.gitignore index 83ec89a6..c37ad084 100644 --- a/.gitignore +++ b/.gitignore @@ -1,22 +1,16 @@ -/site/index.html /build /html /log /node_modules -/site/de -/site/ru -/site/zh -/site/en -/site/fi -/site/pl -/site/tr -/site/ko -/site/ja -/site/es -/site/hu -/site/zhtw -/site/it -/site/hu +/.idea/* + +/site +!/site/favicon.ico +!/site/image +!/site/javascript +!/site/style +!/site/style + *.md~ *.src.md *.DS_store diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index c4b42c85..fe3c6b6f 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -6,3 +6,14 @@ 1. Contributing to JS Garden makes you a fantastic person, and Brendan Eich will find you immensely attractive. Thank you for being kind enough to help out! + +## Testing locally + +1. Run `npm run build` to build +1. Run a webserver from the root of the repo to view + +## Getting changes merged + +1. Squash your changes into one commit +1. Make sure the site still works :) +1. Make a PR diff --git a/JavaScript-Garden b/JavaScript-Garden new file mode 120000 index 00000000..dcc6db5e --- /dev/null +++ b/JavaScript-Garden @@ -0,0 +1 @@ +./site \ No newline at end of file diff --git a/README.md b/README.md index cb9cb3d4..be02cfd5 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,18 @@ JavaScript Garden ================= +2024 update: this project has not been actively maintained in years. The original author +[took the site down](https://github.com/BonsaiDen/JavaScript-Garden/commit/93278fbcafa569fd193f8784abc267e9db09c645) +in 2022 (no judgement - updating it would be a big project!). At that point it was already long out of date, e.g. missing +the new language features from ES6 onwards. + +Many excellent modern guides exist, e.g. [Eloquent Javascript](https://eloquentjavascript.net/), or +the [MDN guide](https://developer.mozilla.org/en-US/docs/Web/JavaScript). + +Thanks for all the maintainers and translators over the years! + +----- + **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 @@ -19,7 +31,7 @@ This guide is the work of two lovely Stack Overflow users, [Ivo Wetzel][6] [many others](https://github.com/BonsaiDen/JavaScript-Garden/graphs/contributors) who've worked hard to provide translations or fixes. -It's currently maintained by [Tim Ruffles](http://twitter.com/timruffles). +It was maintained by [Tim Ruffles](http://twitter.com/timruffles) from 2013-2020ish. ## Contributing diff --git a/doc/by/array/constructor.md b/doc/by/array/constructor.md new file mode 100644 index 00000000..6eaa5f2a --- /dev/null +++ b/doc/by/array/constructor.md @@ -0,0 +1,31 @@ +## Канструктар `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'] + +У выпадку, калі канструктару `Array` перадаецца толькі адзін параметр, і калі гэты +аргумент тыпу `Number`, канструктар верне *разрэджаны* масіў, які мае уласціваць +`length` са значэннем аргумента. Варта адзначыць, што такім чынам будзе зменена +**толькі** значэнне ўласцівасці `length` масіва; індэксы масіва не будуць +праініцыялізаваныя. + + var arr = new Array(3); + arr[1]; // undefined + 1 in arr; // false, індэкс не праініцыялізаваны + +Магчымасць загадзя вызначыць даўжыню масіва карысна толькі ў рэдкіх выпадках, +напрыклад, паўтор радка без выкарыстання цыкла. + + new Array(count + 1).join(stringToRepeat); + +### У заключэнне + +Літэралы маюць перавагі над канструктарам Array. Яны карацейшыя, маюць больш чысты +сінтаксіс і робяць код больш чытэльным. diff --git a/doc/by/array/general.md b/doc/by/array/general.md new file mode 100644 index 00000000..3e358d5a --- /dev/null +++ b/doc/by/array/general.md @@ -0,0 +1,56 @@ +## Ітэрацыі па масівам і ўласцівасці + +Хоць масівы ў JavaScript — аб'екты, няма добрых падставаў для таго, каб +выкарыстоўваць [цыкл `for in`](#object.forinloop) для ітэрацыі па масівах. +Фактычна, ёсць шэраг добрых падстаў **супраць** гэтага. + +> **Заўвага:** масівы JavaScript **не** *асацыятыўныя масівы*. JavaScript мае +> [аб'екты](#object.general) для структуры ключ-значэнне. Але калі асацыятыўныя +> масівы **захоўваюць** парадак, аб'екты — **не**. + +З той прычыны, што цыкл `for in` пералічвае ўсе ўласцівасці, якія ёсць у ланцужку прататыпаў, +і таму, што адзіны спосаб выключыць гэтыя значэнні — [`hasOwnProperty`](#object.hasownproperty), +ітэрацыя атрымліваецца ў **20 разоў** марудней за звычайны цыкл `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`. + +Негледзячы на тое, што ўласцівасць `length` вызначана ў самім масіве, пошук +гэтай уласцівасці накладвае выдаткі на пошук пры кожнай ітэрацыі цыкла. І хоць +новыя рухавікі JavaScript **могуць** прымяніць аптымізацыю у гэтым выпадку, няма +магчымасці дакладна ведаць, ці будзе код выкананы на гэтых новых рухавіках. + +Фактычна, адсутнасць кэшавання можа зрабіць выкананне цыкла **ў два разы больш +марудным**, чым з кэшаваным 'length'. + +### Уласцівасць `length` + +Хоць *гэтэр* уласцівасці `length` проста вяртае колькасць элементаў, што +знаходзяцца у масіве, *сэтэр* можа быць выкарыстаны для **абразання** масіва. + + var arr = [1, 2, 3, 4, 5, 6]; + arr.length = 3; + arr; // [1, 2, 3] + + arr.length = 6; + arr.push(4); + arr; // [1, 2, 3, undefined, undefined, undefined, 4] + +Прысвойванне ўласцівасці 'length' меншага значэння абразае масіў. Прысваенне большага +значэнне створыць разрэджаны масіў. + +### У заключэнне + +Для лепшай прадукцыйнасці рэкамендуецца заўсёды выкарыстоўваць звычайны цыкл `for`, +і кэшаваць уласціваць `length`. Выкарыстоўванне `for in` для ітэрацыі па масіву — +прыкмета дрэнна напісанага коду, схільнага да памылак і дрэннай прадукцыйнасці. diff --git a/doc/by/core/delete.md b/doc/by/core/delete.md new file mode 100644 index 00000000..07e2c1ce --- /dev/null +++ b/doc/by/core/delete.md @@ -0,0 +1,81 @@ +## Аператар `delete` + +У JavaScript *немагчыма* выдаліць глабальныя пераменныя, функцыі і некаторыя іншыя +рэчы, што маюць атрыбут `DontDelete`. + +### Глабальны код і код функцый. + +Калі пераменная або функцыя аб'яўленыя ў глабальнай зоне бачнасці, або [зоне бачнасці +функцыі](#function.scopes) то яна будзе ўласцівасцю або аб'екта актывацыі, або +глабальнай зоны бачнасці. Такія ўласцівасці маюць набор атрыбутаў, адзін з іх — +`DontDelete`. Пераменныя і функцыі, аб'яўленыя ў глабальнай зоне бачнасці і зоне +бачнасці функцыі, заўсёды ствараюцца з уласцівасцю `DontDelete`, а таму не могуць +быць выдаленыя. + + // глабальная пераменная: + var a = 1; // мае ўласцівасць DontDelete + delete a; // false + a; // 1 + + // звычайная функцыя: + function f() {} // мае ўласціваць DontDelete + delete f; // false + typeof f; // "function" + + // перапрызначэнне не дапамагае: + f = 1; + delete f; // false + f; // 1 + +### Яўна прызначаныя ўласцівасці + +Яўна прызначаныя ўласцівасці могуць быць лёгка выдаленыя. + + // яўна прызначаныя ўласцівасці: + var obj = {x: 1}; + obj.y = 2; + delete obj.x; // true + delete obj.y; // true + obj.x; // undefined + obj.y; // undefined + +У вышэйпрыведзеным прыкладзе, `obj.x` і `obj.y` могуць быць выдаленыя, бо не маюць +атрыбута `DontDelete`. Таму і прыкад ніжэй працуе: + + // Гэта працуе правільна, акрамя IE: + var GLOBAL_OBJECT = this; + GLOBAL_OBJECT.a = 1; + a === GLOBAL_OBJECT.a; // true — глабальная пераменная + delete GLOBAL_OBJECT.a; // true + GLOBAL_OBJECT.a; // undefined + +Гэта прыём, каб выдаліць `a`. [`this`](#function.this) спасылаецца на глабальны +аб'ект, і мы яўна аб'яўляем пераменную `a` як яго ўласцівасць, што дазваляе нам +выдаліць яе. + +IE (прынамсі 6-8) мае хібы, таму вышэйпрыведзены код там працаваць не будзе. + +### Аргументы функцый і ўбудаваныя ўласцівасці + +Звычайныя аргументы функцыі, [аб'ект `arguments`](#function.arguments), а таксама +убудаваныя ўласцівасці таксама маюць атрыбут `DontDelete`. + + // аргументы функцыі і ўласцівасці: + (function (x) { + + delete arguments; // false + typeof arguments; // "object" + + delete x; // false + x; // 1 + + function f(){} + delete f.length; // false + typeof f.length; // "number" + + })(1); + +### У заключэнне + +Аператар `delete` часта паводзіць сябе нечакана, таму адзінае надзейнае выкарыстанне +`delete` — выдаленне яўна прызначаных уласцівасцяў. diff --git a/doc/by/core/eval.md b/doc/by/core/eval.md new file mode 100644 index 00000000..7e07dbcd --- /dev/null +++ b/doc/by/core/eval.md @@ -0,0 +1,47 @@ +## Чаму не варта выкарыстоўваць `eval` + +Функцыя `eval` выконвае радок JavaScript коду ў лакальнай зоне бачнасці. + + var number = 1; + function test() { + var number = 2; + eval('number = 3'); + return number; + } + test(); // 3 + number; // 1 + +Тым не менш, `eval` выконваецца ў лакальнай прасторы імён толькі ў тым выпадку, калі +яна была выклікана наўпрост *і* імя выкліканай функцыі — `eval`. + + var number = 1; + function test() { + var number = 2; + var copyOfEval = eval; + copyOfEval('number = 3'); + return number; + } + test(); // 2 + number; // 3 + +Лепш пазбягаць выкарыстоўвання `eval`. 99,9% яе «выкарыстанняў» можа быць дасягнута +**без** яе. + +### Схаваны `eval` + +Абедзве [функцыі тайм-аўты](#other.timeouts) `setTimeout` і `setInterval` могуць +прымаць радок у якасці першага аргумента. Гэты радок будзе **заўсёды** выконвацца +ў глабальнай прасторы імёнаў, бо `eval` не выклікаецца наўпрост у дадзеным выпадку. + +### Праблемы з бяспекаю + +Таксама `eval` мае праблемы з бяспекаю, бо ён выконвае **любы** перададзены код. +Таму яе **ніколі** не варта выкарыстоўваць з радкамі, што паходзяць з ненадзейных +крыніцаў. + +### Заключэнне + +Лепш ніколі не выкарыстоўваць `eval`. Любы код, што выкарыстоўвае яе, спрэчны ў +плане якасці, карэктнасці, прадукцыйнасці і бяспекі. Калі для таго, каб нешта +працавала, патрэбны `eval`, **не** трэба прымаць гэта рашэнне ў першую чаргу. +*Лепшым рашэннем* будзе тое, што не будзе выкарыстоўваць `eval`. diff --git a/doc/by/core/semicolon.md b/doc/by/core/semicolon.md new file mode 100644 index 00000000..db78ed7d --- /dev/null +++ b/doc/by/core/semicolon.md @@ -0,0 +1,109 @@ +## Аўтаматычная ўстаўка кропкі з коскай + +Хаця 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` не з'яўляецца функцыяй. + +### Заключэнне + +Крайне рэкамендуецца **ніколі** не прапускаць кропку з коскай. Таксама заўсёды +рэкамендуецца ставіць дужкі на той жа лініі, што і адпаведныя канструкцыі, і ніколі +не прапускаць іх у аднарадковых канструкцыях `if` / `else`. Гэтыя меры не толькі +павысяць кансістэнтнасць кода, але таксама прадухіляць ад таго, што парсер +JavaScript зменіць паводзіны кода. diff --git a/doc/by/core/undefined.md b/doc/by/core/undefined.md new file mode 100644 index 00000000..18af0f2d --- /dev/null +++ b/doc/by/core/undefined.md @@ -0,0 +1,69 @@ +## `undefined` і `null` + +JavaScript мае два розныя значэнні для 'нічога' - гэта `null` і `undefined`, пры +гэтым апошняе больш карыснае. + +### Значэнне `undefined` + +`undefined` — гэта тып з роўна адным значэннем: `undefined`. + +Мова таксама аб'яўляе глабальную пераменную, што мае значэнне `undefined`; Гэта +пераменная таксама называецца `undefined`. Тым не менш, гэта пераменная, а **не** +канстанта, ці ключавое слова. Гэта азначае, што яе *значэнне* можа быць +з лёгкасцю перазапісаным. + +> **Заўвага для ES5:** у ECMAScript 5 `undefined` **больш** *нельга запісваць* у +> строгім рэжыме, але гэта імя можа ўся яшчэ быць перакрыта праз выкарыстанне +> функцыі з іменем `undefined`. + +Ніжэй пералічаныя некалькі выпадкаў, калі вяртаецца `undefined`: + + - Доступ да (немадыфікаванай) глабальнай пераменнай `undefined`. + - Доступ да аб'яўленай, *але яшчэ не* ініцыалізаванай пераменнай. + - Няяўна вернутае значэнне функцыі праз адсутнасць аператара `return`. + - З аператара `return`, які нічога яўна не вяртае. + - У выніку пошуку неіснуючай уласцівасці аб'екта. + - Параметры функцыі, якім яўна не было прысвоена значэнне. + - Усё, чаму было прысвоена значэнне `undefined`. + - Любы выраз у форме `void(expression)`. + +### Апрацоўка зменаў значэння `undefined` + +З той прычыны, што глабальная пераменная `undefined` утрымлівае толькі копію +актуальнага *значэння* `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 байты пры +мініфікацыі, а ў першым унутры ананімнай абгорткі не будзе аператара `var`. + +### Выкарыстоўванне `null` + +Хаця `undefined` у кантэксце мовы JavaScript у асноўным выкарыстоўваецца ў сэнсе +традыйнага *null*, сам `null` (і літэрал і тып) з'яўляецца яшчэ адным тыпам дадзеных. + +Выкарыстоўваецца ў некаторых унутранных механізмах JavaScript (напрыклад аб'яўленне +канца ланцужка прататыпаў пазначаючы `Foo.prototype = null`), але амаль што ва ўсіх +выпадках ён можа быць заменены на `undefined`. diff --git a/doc/by/function/arguments.md b/doc/by/function/arguments.md new file mode 100644 index 00000000..98ac3d2b --- /dev/null +++ b/doc/by/function/arguments.md @@ -0,0 +1,130 @@ +## Аб'ект `arguments` + +У зоне бачнасці любой функцыі JavaScript ёсць доступ да адмысловай пераменнай +`arguments`. Гэтая пераменная утрымлівае спіс усіх аргументаў, што былі +перададзеныя функцыі. + +> **Заўвага:** У выпадку, калі `arguments` ужо быў створаны ўнутры зоны бачнасці +> функцыі праз выраз `var`, або з'яўляецца фармальным параметрам, +> аб'ект `arguments` не будзе створаны. + +Аб'ект `arguments` **не з'яўляецца** спадкаемцам `Array`. Ён мае падабенствы +з масівам, напрыклад уласцівасць `length`. Але ён не ўспадкоўвае `Array.prototype`, +а ўяўляе з сябе `Object`. + +Таму **не**магчыма выклікаць стандартныя метады `push`, `pop` або `slice` +у аб'екта `arguments`. Тым не менш, ітэрацыя з звычайным цыклам `for` працуе карэктна. +Неабходна канвертаваць яго ў сапраўдны аб'ект `Array`, каб прымяніць стандартныя +метады масіваў. + +### Канвертацыя ў масіў + +Ніжэйпрыведезны код верне новы масіў, які будзе ўтрымліваць усе элементы аб'екта +`arguments`. + + Array.prototype.slice.call(arguments); + +Такая канвертацыя **марудная**, яе **не рэкамендуецца** выкарыстоўваць у крытычных +у плане прадукцыйнасці частках кода. + +### Перадача `arguments` + +Ніжэй прадстаўлены рэкамендаваны спосаб перадачы аргументаў з адной функцыі ў іншую. + + function foo() { + bar.apply(null, arguments); + } + function bar(a, b, c) { + // тут робім што-небудзь + } + +Яшчэ адзін прыём — гэта выкарыстанне `call` і `apply` разам, каб ператварыць метады, +што выкарыстоўваюць значэнне `this` як і свае аргументы, у звычайныя функцыі, +што выкарыстоўваюць толькі аргументы. + + function Person(first, last) { + this.first = first; + this.last = last; + } + + Person.prototype.fullname = function(joiner, options) { + options = options || { order: "western" }; + var first = options.order === "western" ? this.first : this.last; + var last = options.order === "western" ? this.last : this.first; + return first + (joiner || " ") + last; + }; + + // Ствараем незвязаную версію "fullname", што можа быць выкарыстана з любым + // аб'ектам, які мае ўласцівасці 'first' і 'last', перададзеным у якасці + // першага параметра. Гэтую абгортку не трэба будзе мяняць, калі колькасць або + // парадак аргументаў fullname зменяцца. + Person.fullname = function() { + // Result: Person.prototype.fullname.call(this, joiner, ..., argN); + return Function.call.apply(Person.prototype.fullname, arguments); + }; + + var grace = new Person("Grace", "Hopper"); + + // 'Grace Hopper' + grace.fullname(); + + // 'Turing, Alan' + Person.fullname({ first: "Alan", last: "Turing" }, ", ", { order: "eastern" }); + + +### Фармальныя параметры і індэксы аргументаў + +Аб'ект `arguments` стварае *гэтэр* і *сэтэр* як да кожнай са сваіх уласцівасцяў, +так і да фармальных параметраў функцыі. + +У выніку змена значэння фармальнага параметра зменіць таксама адпаведную ўласцівасць +аб'екта `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` не ствараецца, — гэта калі ёсць фармальны аргумент функцыі +або пераменная ўнутры яе з такім іменем. Не важна, выкарыстоўваюцца яны ці не. + +Як *гэтэры*, так і *сэтэры* ствараюцца **заўсёды**, таму іх выкарыстоўванне не +мае амаль ніякага ўплыву на прадукцыйнасць. + +> **Заўвага для ES5:** *гэтэры* і *сэтэры* не ствараюцца ў строгім рэжыме. + +Тым не менш, ёсць адна рэч, якая можа жахліва знізіць прадукцыйнасць у сучасных +рухавіках JavaScript — гэта выкарыстанне `arguments.callee`. + + function foo() { + arguments.callee; // робім што-небудзь з функцыяй foo + arguments.callee.caller; // і з функцыяй, якая выклікала foo + } + + function bigLoop() { + for(var i = 0; i < 100000; i++) { + foo(); // Звычайна ўстаўляецца... + } + } + +У вышэйпрыведзеным кодзе `foo` больш не можа быць [устаўлена][1], бо ёй трэба +ведаць аб сабе і аб функцыі, што яе выклікала. Гэта не толькі знішчае павышэнне +прадукцыйнасці, якое магло адбыцца дзякуючы ўстаўцы, але і парушае інкапсуляцыю, бо +функцыя цяпер залежыць ад спецыфічнага кантэксту, які яе выклікае. + +Выкарыстоўванне `arguments.callee` або яго ўласцівасцяў **вельмі непажадана**. + +> **Заўвага для ES5:** У строгім рэжыме `arguments.callee` кіне памылку `TypeError`, +> бо яго выкарыстанне аб'яўлена састарэлым. + +[1]: http://en.wikipedia.org/wiki/Inlining diff --git a/doc/by/function/closures.md b/doc/by/function/closures.md new file mode 100644 index 00000000..23911e6a --- /dev/null +++ b/doc/by/function/closures.md @@ -0,0 +1,113 @@ +## Замыканні і спасылкі + +Адна з найбольш магутных магчымасцяў JavaScript — магчымасць ствараць *замыканні*. +Зона бачнасці замыканняў **заўсёды** мае доступ да знешняй зоны бачнасці, у якой +замыканне было аб'яўлена. З той прычыны, што ў JavaScript адзіны механізм працы +з зонай бачнасці — гэта [зоны бачнасці функцыі](#function.scopes), усе функцыі +выступаюць у якасці замыканняў. + +### Эмуляцыя прыватных пераменных + + function Counter(start) { + var count = start; + return { + increment: function() { + count++; + }, + + get: function() { + return count; + } + } + } + + var foo = Counter(4); + foo.increment(); + foo.get(); // 5 + +Тут `Counter` вяртае **два** замыканні: функцыю `increment` і функцыю `get`. +Абедзьве функцыі маюць **спасылку** на зону бачнасці `Counter` і таму заўсёды +маюць доступ да пераменнай `count`, што была аб'яўлена ў гэтай зоне бачнасці. + +### Якім чынам гэта працуе + +З той прычыны, што ў JavaScript немагчыма спасылацца або прысвойваць зоны бачнасці, +**немагчыма** атрымаць доступ да пераменнай `count` звонку. Адзіны спосаб +узаемадзейнічаць з ім — выкарыстоўваць два замыканні. + + var foo = new Counter(4); + foo.hack = function() { + count = 1337; + }; + +Вышэйпрыведзены код **не** памяняе значэнне пераменнай `count` у зоне бачнасці +`Counter`, бо `foo.hack` не быў аб'яўлены у **гэтай** зоне бачнасці. Замест гэтага +ён створыць або перазапіша *глабальную* пераменную `count`. + +### Замыканні ўнутры цыклаў + +Частая памылка - выкарыстанне замыканняў унутры цыклаў, як быццам бы яны капіруюць +значэнне пераменнай індэксу цыкла. + + for(var i = 0; i < 10; i++) { + setTimeout(function() { + console.log(i); + }, 1000); + } + +Вышэйпрыведзены код **не** выведзе нумары ад `0` да `9`, ён проста выведзе +нумар `10` дзесяць разоў. + +*Ананімная* функцыя захоўвае **спасылку** на `i`. У той час, калі функцыя `console.log` +выклікаецца, `цыкл for` ужо адпрацаваў, а значэнне `i` ўжо стала `10`. + +Каб атрымаць пажаданыя паводзіны, неабходна стварыць **копію** значэння `i`. + +### Як абыйсці праблемы спасылкі + +Каб стварыць копію значэння пераменнай індэкса цыкла, лепшы спосаб — стварэнне +[ананімнай абгорткі](#function.scopes). + + for(var i = 0; i < 10; i++) { + (function(e) { + setTimeout(function() { + console.log(e); + }, 1000); + })(i); + } + +Знешняя ананімная функцыя выконваецца імгненна з `i` ў якасці першага аргумента +і атрымае копію **значэння** `i` ў якасці параметра `e`. + +Ананімная функцыя, што перадаецца метаду `setTimeout`, цяпер мае спасылку на +`e`, чыё значэнне **не** мяняецца на працягу цыкла. + +Яшчэ адзін спосаб атрымаць такі вынік — вяртаць функцыю з ананімнай абгорткі, +што будзе паводзіць сябе такім жа чынам, як і папярэдні прыклад. + + for(var i = 0; i < 10; i++) { + setTimeout((function(e) { + return function() { + console.log(e); + } + })(i), 1000) + } + +Яшчэ адзін папулярны спосаб дасягнуць гэтага — дадаць яшчэ адзін аргумент выкліку +функцыі `setTimeout`, якая перадасць агрумент функцыі зваротнага выкліку. + + for(var i = 0; i < 10; i++) { + setTimeout(function(e) { + console.log(e); + }, 1000, i); + } + +Некаторыя старыя асяродкі JS (Internet Explorer 9 і ніжэй) не падтрымліваюць +гэтую магчымасць. + +Таксама магчыма выканаць гэта выкарыстоўваючы `.bind`, якая можа звязаць +`this` і аргументы функцыі. Ніжэйпрыведзены прыклад працуе як папярэднія. + + for(var i = 0; i < 10; i++) { + setTimeout(console.log.bind(console, i), 1000); + } diff --git a/doc/by/function/constructors.md b/doc/by/function/constructors.md new file mode 100644 index 00000000..1da70bf5 --- /dev/null +++ b/doc/by/function/constructors.md @@ -0,0 +1,122 @@ +## Канструктары + +Канструктары ў JavaScript таксама адрозніваюцца ад большасці іншых моваў. Любы +выклік функцыі, якому папярэднічае ключавое слова `new` з'яўляецца канструктарам. + +Унутры канструктара (выкліканай функцыі) - значэнне `this` спасылаецца на +новаствораны аб'ект. [Прататыпам](#object.prototype) **новага** +аб'екта прызначаецца `prototype` функцыі, што была выклікана ў якасці канструктара. + +У выпадку, калі выкліканая функцыя не вяртае яўнага значэння праз `return`, будзе +не яўна вернута значэнне `this`, то бок новы аб'ект. + + function Person(name) { + this.name = name; + } + + Person.prototype.logName = function() { + console.log(this.name); + }; + + var sean = new Person(); + +У гэтым прыкладзе `Person` выклікаецца ў якасці канструктара, адпаведна `prototype` +створанага аб'екта будзе прывязаны да `Person.prototype`. + +Вярнуць яўнае значэнне праз `return`, можна **толькі** калі гэта значэнне - `Object`. + + function Car() { + return 'ford'; + } + new Car(); // новы аб'ект, не 'ford' + + function Person() { + this.someValue = 2; + + return { + name: 'Charles' + }; + } + new Person(); // вяртае аб'ект ({name:'Charles'}), які не ўтрымлівае someValue + +Калі ключавое слова `new` прапушчана, функцыя **не** верне аб'ект. + + function Pirate() { + // пазначыць значэнне ў глабальным аб'екце! + this.hasEyePatch = true; + } + var somePirate = Pirate(); // somePirate == undefined + +Гэты прыклад можа спрацаваць у некаторых выпадках, праз тое як працуе +[`this`](#function.this) у JavaScript. Значэннем `this` тут будзе +*глабальны аб'ект*. + +### Фабрыкі + +Каб мець магчымасць прапусціць ключавое слова `new`, канструктар функцыі мае яўна +вяртаць значэнне. + + function Robot() { + var color = 'gray'; + return { + getColor: function() { + return color; + } + } + } + + new Robot(); + Robot(); + +Абодва выклікі `Robot` вернуць тое ж самае, новы аб'ект, які мае ўласцівасць +`getColor`, што з'яўляецца [замыканнем](#function.closures). + +Таксама варта адзначыць, што выклік `new Robot()` **не** ўплывае на прататып +вернутага аб'екта. Хаця прататып будзе прызначаны новастворанаму аб'екту, `Robot` +ніколі не верне гэты аб'ект. + +У прыкладзе вышэй, няма розніцы паміж выклікам функцыі з аператарам `new` або +без яго. + + +### Стварэнне новых аб'ектаў з выкарыстаннем фабрык + +Часта рэкамендуюць **не** выкарыстоўваць `new` бо забыўшыся выкарыстаць яго, можна +стварыць памылку. + +Каб стварыць новы аб'ект, лепш выкарыстоўваць фабрыку і стварыць новы аб'ект +*унутры фабрыкі*. + + function CarFactory() { + var car = {}; + car.owner = 'nobody'; + + var milesPerGallon = 2; + + car.setOwner = function(newOwner) { + this.owner = newOwner; + } + + car.getMPG = function() { + return milesPerGallon; + } + + return car; + } + +Хоць гэты прыклад і спрацуе негледзячы на забытае `new`, і бясспрэчна выкарыстоўвае +[прыватныя пераменныя](#function.closures), ён мае некалькі недахопаў. + + 1. Ён выкарыстоўвае больш памяці, бо функцыі створаных аб'ектаў **не** захоўваюццца + у прататыпе, а ствараюцца на нова для кожнага аб'екта. + 2. Каб эмуляваць спадкаемства, фабрыка мае скапіраваць метады іншага аб'екта, або + пазначыць прататыпам новага аб'екта стары. + 3. Разрыў ланцужка прататыпаў, проста па прычыне забытага ключавога слова `new`, + не адпавядае духу мовы JavaScript. + +### У заключэнне + +Негледзячы на тое, што прапушчанае `new` можа выліцца ў памылку, гэта **не** +прычына адмовіцца ад выкарыстання прататыпаў. У выніку лепш высвятліць якое рашэнне +больш адпавядае патрабаванням праграмы. Асабліва важна выбраць пэўны стыль і +**паслядоўна** выкарыстоўваць яго. diff --git a/doc/by/function/general.md b/doc/by/function/general.md new file mode 100644 index 00000000..da5f4ba3 --- /dev/null +++ b/doc/by/function/general.md @@ -0,0 +1,48 @@ +## Выразы і аб'яўленне функцый + +У JavaScript функцыі таксама з'яўляюцца аб'ектамі. Гэта значыць іх можна перадаваць +і прысвойваць як і любыя іншыя аб'екты. Адзін, часта выкарыстоўваемы варыянт, +гэтай магчымасці - перадача *ананімнага метада* як функцыі зваротнага выкліку +іншай, магчыма асінхроннай функцыі. + +### Аб'яўленне `function` + + function foo() {} + +У вышэй прыведзеным прыкладзе функцыя [уздымаецца](#function.scopes) перад тым +як пачынаецца выконванне праграмы; Такім чынам, яна даступная *паўсюль* у зоне +бачнасці, у якой яна была *аб'яўлена*, нават калі выклік адбываецца да фактычнага +аб'яўлення ў кодзе. + + foo(); // Працуе, бо функцыя будзе створана да выконвання кода + function foo() {} + +### `function` як выраз + + var foo = function() {}; + +У гэтым прыкладзе пераменнай `foo` прысвойваецца *ананімная* функцыя. + + foo; // 'undefined' + foo(); // уздыме TypeError + var foo = function() {}; + +Праз тое, што `var` - гэта аб'яўленне якое уздымае імя пераменнай `foo` перад тым +як код будзе выкананы, `foo` будзе ўжо аб'яўленым калі ён пачне выконвацца. + +Але так як прысвойванні адбываюцца толькі пад час выконвання, значэнне `foo` +будзе змоўчанным ([undefined](#core.undefined)) да выконвання адпаведнага кода. + +### Выразы з іменаванымі функцыямі + +Яшчэ адзін выбітны выпадак - прысвойванне іменавай функцыі. + + var foo = function bar() { + bar(); // працуе + } + bar(); // ReferenceError + +Тут, `bar` не даступны ў знешнім скоўпе, бо функцыя толькі прысвойваецца пераменнай +`foo`; аднак, унутры `bar`, імя даступнае. Так адбываецца праз асаблівасці працы +з [прастранствамі імён](#function.scopes) у JavaScript - імя функцыі *заўсёды* +даступнае ў лакальным скоўпе функцыі. diff --git a/doc/by/function/scopes.md b/doc/by/function/scopes.md new file mode 100644 index 00000000..7ade2cfd --- /dev/null +++ b/doc/by/function/scopes.md @@ -0,0 +1,230 @@ +## Зоны бачнасці і прасторы імёнаў + +Негледзячы на тое, што JavaScript добра працуе з сінтаксісам фігурных дужак для +блокаў, у ім **няма** падтрымкі блочнай зоны бачнасці; усё што ёсць на гэты конт +у мове - *зона бачнасці функцыі*. + + function test() { // зона бачнасці + for(var i = 0; i < 10; i++) { // не зона бачнасці + // лічым + } + console.log(i); // 10 + } + +> **Заўвага:** Калі не выкарыстана ў прысвойванні, аператары return або аргуменце +> функцыі, натацыя `{...}` будзе інтэрпрэтавана як блочны выраз, а **не** як літэрал +> аб'екта. Гэта з'ява, сумесна з [аўтаматычнай устаўкай коскі з кропкай](#core.semicolon), +> можа прывесці да хітрых памылак. + +Таксама JavaScript не падтрымлівае выразныя прасторы імёнаў, усё аб'яўляецца ў +агульнадаступнай прасторы імёнаў. + +Для кожнай спасылкі на пераменную, JavaScript пойдзе ўверх па ўсіх зонах бачнасці, +пакуль не знойдзе яе. У выпадку, калі ён дойдзе да глабальнай прасторы імён і ўсё +яшчэ не знойдзе неабходнае імя, ён уздыме `ReferenceError`. + +### Атрута глабальнымі пераменнымі + + // скрыпт A + foo = '42'; + + // скрыпт B + var foo = '42' + +Вышэйпрыведзеныя скрыпты маюць **розныя** вынікі. Скрыпт A аб'яўляе пераменную +`foo` у *глабальнай* зоне бачнасці, скрыпт B аб'яўляе `foo` у *актуальнай* зоне +бачнасці. + +Паўторымся, гэта абсалютна **не** *той жа самы вынік*: не выкарыстоўваенне `var` +можа мець сур'ёзныя наступствы. + + // глабальная зона бачнасці + var foo = 42; + function test() { + // лакальная зона бачнасці + foo = 21; + } + test(); + foo; // 21 + +З-за таго, што аператар `var` прапушчаны ўнутры функцыі `test`, значэнне `foo` +у глабальнай прасторы імён будзе перазапісаным. Хаця першапачаткова гэта можа +падацца невялікай праблемай, не выкарыстоўванне `var` у кодзе на тысячы радкоў, +прывядзе да жахлівых, цяжкіх для адладкі памылак. + + // глабальная прастора імёнаў + for(var i = 0; i < 10; i++) { + subLoop(); + } + + function subLoop() { + // прастора імёнаў subLoop + for(i = 0; i < 10; i++) { // аператар var прапушчаны + // робім чароўныя рэчы! + } + } + +Знешні цыкл скончыцца пасля першага выкліка `subLoop`, бо `subLoop` перазапісвае +глабальную пераменную `i`. Выкарыстоўваючы `var` для другога цыкла `for` можна +было б пазбегнуць памылкі. **Ніколі** не прапускайце аператар `var`, акрамя +выпадкаў, калі змена дадзеных у знешняй зоне бачнасці ёсць *пажаданым вынікам*. + +### Лакальныя пераменныя + +Адзіная крыніца лакальных пераменных у JavaScript гэта параметры [функцыі](#function.general) +і пераменныя аб'яўленыя праз аператар `var`. + + // глабальная зона бачнасці + var foo = 1; + var bar = 2; + var i = 2; + + function test(i) { + // лакальная зона бачнасці функцыі test + i = 5; + + var foo = 3; + bar = 4; + } + test(10); + +`foo` і `i` гэта лакальныя пераменныя унутры зоны бачнасці функцыі `test`, +а вось прызначэнне `bar` перазапіша глабальныю пераменную з тым жа іменем. + +### Падыманне + +JavaScript **падымае** аб'яўленні. Гэта азначае, што абодва аб'яўленні аператараў +`var` і `function` падымуцца на верх іх зоны бачнасці. + + 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]; + } + } + +Вышэйпрыведзены код трансфармуецца перад пачаткам выконвання. JavaScript падымае +аператары `var`, як і аб'яўленне `function`, наверх бліжэйшай зоны бачнасці. + + // аператар var перамяшчаецца сюды + var bar, someValue; // па змоўчванню - 'undefined' + + // аб'яўленне функцыі таксама падымаецца наверх + function test(data) { + var goo, i, e; // адсутная блочная зона бачнасці перайшла сюды + if (false) { + goo = 1; + + } else { + goo = 2; + } + for(i = 0; i < 100; i++) { + e = data[i]; + } + } + + bar(); // падае з TypeError бо ўсё яшчэ 'undefined' + someValue = 42; // прысвойванні не падымаюцца + bar = function() {}; + + test(); + +Адсутнасць блочнай зоны бачнасці не толькі падыме аператар `var` па-за межы цыкла +і яго цела, але таскама зробіць вынік некаторых канструкцый `if` не-інтуітыўным. + +Хоць у арыгінальным кодзе падаецца што канструкцыя `if` змяняе *глабальную +пераменную* `goo`, на дадзены момант гэта мяняе *лакальную пераменную* - пасля +таго, як было прыменена падыманне. + +Без ведаў аб *падыманні*, можна падумаць што код ніжэй кіне `ReferenceError`. + + // правярае ці было SomeImportantThing праініцыалізавана + if (!SomeImportantThing) { + var SomeImportantThing = {}; + } + +Але канешне, гэта працуе праз тое, што аператар `var` быў падняты на верх +глабальнай *зоны бачнасці*. + + var SomeImportantThing; + + // тут нейкі код можа ініцыалізаваць SomeImportantThing, або не + + // тут у гэтым можна ўпэўніцца + if (!SomeImportantThing) { + SomeImportantThing = {}; + } + +### Парадак доступу да пераменных + +Усе зоны бачнасці ў JavaScript, уключаючы *глабальную зону бачнасці*, маюць +адмысловае імя [`this`](#function.this), аб'яўленае ўнутры іх, якое спасылаецца +на *актуальны аб'ект*. + +Зоны бачнасці функцый таксама маюць імя [`arguments`](#function.arguments), +аб'яўленае ў іх, якое спасылаецца на аргументы, што былі перададзеныя ў функцыю. + +Напрыклад, калі паспрабаваць атрымаць доступ да пераменнай `foo` унутры зоны +бачнасці функцыі, JavaScript будзе шукаць імя ў наступным парадку: + + 1. У выпадку калі прысутнічае канструкцыя `var foo` у актуальнай зоне бачнасці, + ёна і выкарыстоўваецца. + 2. Калі параметр функцыі мае імя `foo`, ён будзе выкарыстаны. + 3. Калі сама функцыя называецца `foo`, яна будзе выкарыстана. + 4. Пераходзіць у знешнюю зону бачнасці, і пачынае з пункта **#1**. + +> **Заўвага:** Наява параметра названага `arguments` **перадухіліць** стварэнне +> параметра `arguments` па змоўчванні. + +### Прасторы імёнаў + +Вялікая праблема, звязаная з выкарыстоўваннем глабальнай прасторы імёнаў, гэта +высокая верагоднасць перасячэння імёнаў пераменных. У JavaScript, гэта праблема +можа быць лёгка пазбегнута праз выкарыстанне *ананімных абгортак*. + + (function() { + // аўтаномная "прастора імён" + + window.foo = function() { + // адкрытае замыканне + }; + + })(); // імгненнае выкананне функцыі + + +Ананімныя функцыі з'яўляюцца [выразамі](#function.general); таму каб быць выкліканымі, +яны спачатку маюць быць ацэненымі. + + ( // ацэньваем функцыю ўнутры дужак + function() {} + ) // вяртаем аб'ект функцыі + () // выклік выніку ацэнкі + +Ёсць і іншыя спосабы ацаніць і імгненна выклікаць выраз функцыі, хаця яны і +адрозніваюцца па сінтаксісу, паводзяць сябе аднолькава. + + // Яшчэ некалькі спосабаў наўпрост выклікаць функцыю + !function(){}() + +function(){}() + (function(){}()); + // і так далей... + +### Заключэнне + +Рэкамендуецца заўсёды выкарыстоўваць *ананімную абгортку* каб інкапсуліраваць код +у яго асабістай прасторы імёнаў. Гэта не толькі абараняе код ад перасячэння імёнаў, +але і дапамагае падзяляць праграму на модулі. + +Таксама выкарыстанне глабальных пераменных лічыцца **дрэннай практыкай**. **Любое** +іх выкарыстоўванне - прыкмета дрэнна напісанага кода, схільнага да памылак, і цяжага +ў падтрымцы. diff --git a/doc/by/function/this.md b/doc/by/function/this.md new file mode 100644 index 00000000..0a85ef5f --- /dev/null +++ b/doc/by/function/this.md @@ -0,0 +1,118 @@ +## Як працуе `this` + +У JavaScript `this` азначае канцэптуальна іншую рэч, чым у іншых мовах праграмавання. +Існуе роўна **пяць** варыянтаў таго, да чаго можа быць прывязана `this`. + +### Глабальна зона бачнасці + + this; + +Калі `this` выкарыстоўваецца ў глабальнай зоне бачнасці - яна спасылаецца на *глабальны* аб'ект + + +### Выклік функцыі + + foo(); + +Тут, `this` усё яшчэ спасылаецца на *глабальны* аб'ект. + +> **Заўвага для ES5:** У строгім рэжыме, паняцця глабальнасці **больш не існуе**. +> `this` у такім выпадку будзе мець значэнне `undefined`. + +### Выклік метада + + test.foo(); + +У гэтым выпадку, `this` будзе спасылацца на аб'ект `test`. + +### Выклік канструктара + + new foo(); + +Выклік функцыі, перад якім прысутнічае ключавое слова `new`, выступае ў якасці +[канструктара](#function.constructors). Унутры функцыі, `this` будзе спасылацца +на *новаствораны* аб'ект. + +### Яўная ўстаноўка `this` + + function foo(a, b, c) {} + + var bar = {}; + foo.apply(bar, [1, 2, 3]); // масіў разгорнецца ў ніжэйпрыведзенае + foo.call(bar, 1, 2, 3); // вынікам будзе a = 1, b = 2, c = 3 + +Пры выкарыстоўванні метадаў `call` або `apply` з `Function.prototype`, значэнню +`this` унутры выкліканай функцыі **яўна прысвойваецца** значэнне першага +аргумента адпаведнага выкліка функцыі. + +Як вынік, у вышэйпрыведзеным прыкладзе *правіла метада* **не** працуе, і `this` +унутры `foo` будзе мець значэнне `bar`. + +> **Заўвага:** `this` **не можа** быць выкарыстаны як спасылка ўнутры літэрала +> `Object`. Таму ў кодзе `var obj = {me: this}` `me` **не** будзе спасылацца на +> `obj`, бо `this` прывязваецца толькі па пяці вышэйапісаных правілах. + +### Магчымыя пасткі + +Не гледзячы на тое, што большасць гэтых прыкладаў лагічныя, першы можна лічыць +яшчэ адным недаглядам мовы, бо ён **ніколі** не мае практычнага прымянення. + + Foo.method = function() { + function test() { + // this спасылаецца на глабальны аб'ект + } + test(); + }; + +Памылковым меркаваннем будзе тое, што `this` унутры `test` будзе спасылацца на +`Foo`; Але на самрэч **гэта не так**. + +Каб атрымаць доступ да `Foo` з цела `test`, вы можаце стварыць лакальную +пераменную унутры `метада` што будзе спасылацца на `Foo`. + + Foo.method = function() { + var self = this; + function test() { + // Тут выкарыстоўвайце self замест this + } + test(); + }; + +`self` гэта звычайнае імя пераменнай, але яно часта выкарыстоўваецца для спасылкі +на знешні `this`. У камбінацыі з [замыканнямі](#function.closures), яно можа быць +выкарыстана для перадачы `this` навокал. + +У ECMAScript 5 можна выкарыстаць метад `bind` у камбінацыі з ананімнай функцыяй, +дзеля таго каб атрымаць аналагічны вынік. + + Foo.method = function() { + var test = function() { + // this цяпер спасылаецца на Foo + }.bind(this); + test(); + }; + +### Прысвойванне метадаў + +Яшчэ адна рэч якая **не** працуе ў JavaScript - гэта стварэнне псэўданімаў функцый, +то бок **прысвойванне** значэння метада пераменнай. + + var test = someObject.methodTest; + test(); + +Паводле першага правіла, `test` цяпер працуе як звычайны выклік функцыі; +адпаведна, `this` унутры больш не будзе спасылацца на `someObject`. + +Поздняе звязванне `this` можа падацца дрэннай ідэяй, але насамрэч якраз дзякуючы +гэтаму працуе [спадкаемства прататыпаў](#object.prototype). + + function Foo() {} + Foo.prototype.method = function() {}; + + function Bar() {} + Bar.prototype = Foo.prototype; + + new Bar().method(); + +Калі выклікаецца `method` новага экзэмпляра `Bar`, `this` будзе спасылацца на гэты +экзэмпляр. diff --git a/doc/by/index.json b/doc/by/index.json new file mode 100644 index 00000000..1ed0abaa --- /dev/null +++ b/doc/by/index.json @@ -0,0 +1,69 @@ +{ + "title": "JavaScript Garden", + "langTitle": "JavaScript Garden па Беларуску", + "description": "Мануал па недахопаў і дзівосах JavaScript", + "sections": [ + { + "title": "Уводзіны", + "dir": "intro", + "articles": ["index"] + }, + { + "title": "Аб'екты", + "dir": "object", + "articles": [ + "general", + "prototype", + "hasownproperty", + "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" + ] + }, + { + "title": "Ядро", + "dir": "core", + "articles": [ + "eval", + "undefined", + "semicolon", + "delete" + ] + }, + { + "title": "Рэшта", + "dir": "other", + "articles": [ + "timeouts" + ] + } + ] +} diff --git a/doc/by/intro/index.md b/doc/by/intro/index.md new file mode 100644 index 00000000..ea82a31e --- /dev/null +++ b/doc/by/intro/index.md @@ -0,0 +1,56 @@ +## Уступ + +**JavaScript Garden** гэта растучы набор дакументацыі аб найбольш +цікавых частках мовы праграмавання JavaScript. Ён дае парады аб тым як прадухіліць +частыя і непрадказальныя памылкі, а таксама праблемы з хуткасцю выконвання і +дрэннымі практыкамі, якія праграмісты, не з'яўляючыяся экспертамі у JavaScript +маглі сустрэць падчас сваіх пошукаў у глыбіні мовы. + +JavaScript Garden **не** ставіць сваёй мэтай навучыць вас мове JavaScript. Былыя +веды мовы рэкамендаваныя, каб вы змаглі зразумець пытанні разглядаемыя ў гэтым +мануале. Каб зразумець базавыя рэчы мовы, калі ласка прачытайце цудоўны [мануал][1] +у сетцы распрацоўшчыкаў Mozilla. + +## Аўтары + +Гэты мануал - праца двух выбітных карыстальнікаў [Stack Overflow][2] , [Ivo Wetzel][3] +(Тэкст) і [Zhang Yi Jiang][4] (Дызайн). + +На дадзены момант падтрымліваецца [Tim Ruffles](http://truffles.me.uk). + +## Удзельнікі + +- Зашмат каб пералічыць тут, [паглядзіце спіс](https://github.com/BonsaiDen/JavaScript-Garden/graphs/contributors). + + +## Хостынг + +JavaScript Garden хосціцца на GitHub, але [Cramer Development][7] падтрымлівае нас +люстэркам на [JavaScriptGarden.info][8]. У Беларускамоўнай версіі таксама ёсць +сваё [люстэрка на GitHub][13] + +## Пераклад + +Перакладзена на Беларускую мову супольнасцю [it-mova][14]. + +## Ліцэнзія + +JavaScript Garden апублікаваны пад [MIT ліцэнзіяй][9] і хосціцца на +[GitHub][10]. Калі вы знойдзеце апячатку або памылку - [пазначце памылку][11] або +адпраўце pull request у сховішча. Вы таксама можаце знайсці нас у +[JavaScript room][12] на чаце 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/it-na-move/JavaScript-Garden/ +[11]: https://github.com/it-na-move/JavaScript-Garden/issues +[12]: http://chat.stackoverflow.com/rooms/17/javascript +[13]: http://it-na-move.github.io/JavaScript-Garden/ +[14]: https://github.com/it-na-move diff --git a/doc/by/object/forinloop.md b/doc/by/object/forinloop.md new file mode 100644 index 00000000..fbe52f15 --- /dev/null +++ b/doc/by/object/forinloop.md @@ -0,0 +1,63 @@ +## Цыкл `for in` + +Як і аператар `in`, цыкл `for in` праходзіць па ўсім ланцужку прататыпаў +пры ітэрацыі па ўласцівасцях аб'екта. + +> **Заўвага:** Цыкл `for in` **не** ітэруе па уласцівасцях, у якіх атрыбут +> `enumerable` мае значэнне `false`; напрыклад, уласцівасць `length` +> масіва (Array). + + // Атруцім Object.prototype + Object.prototype.bar = 1; + + var foo = {moo: 2}; + for(var i in foo) { + console.log(i); // вывядзе і bar і moo + } + +Праз тое, што немагчыма памяняць паводзіны самаго цыкла `for in`, неабходна фільтраваць +непажаданыя ўласцівасці аб'екта ўнутры цыкла. У версіях ECMAScript 3 і пазней, +гэта можна зрабіць праз метад [`hasOwnProperty`](#object.hasownproperty). + +Пачынаючы з ECMAScript 5, `Object.defineProperty` можа быць выкарыстана з +`enumerable` роўным `false`, каб дадаць уласцівасці аб'екту такім чынам, што яны +не будуць пералічаны. У такім выпадку было б справядлівым меркаваць, што любая +`enumerable` уласціваць была дададзена адмыслова і прапусціць `hasOwnProperty`, бо +гэта робіць код больш шматслоўным і цяжэйшым для чытання. У бібліятэчным кодзе +`hasOwnProperty` мае быць усё роўна выкарыстаны, бо не варта рабіць здагадкі аб +тым, якія `enumerable` уласцівасці могуць пражываць у ланцужку прататыпаў. + +> **Заўвага:** праз тое, што `for in` заўсёды праходзіць праз увесць ланцужок прататыпаў, +> ён будзе працаваць усё марудней з кожным новым слоем спадкаемства. + +### Выкарыстоўванне `hasOwnProperty` для фільтрацыі + + // возьмем foo з прыкладу + for(var i in foo) { + if (foo.hasOwnProperty(i)) { + console.log(i); + } + } + +Гэта адзіная правільная версія выкарыстоўвання цыкла. Дзякуючы выкарыстоўванню +`hasOwnProperty`, быдзе выведзена **толькі** `moo`. +Калі прыбраць `hasOwnProperty`, код будзе схільны да памылак у выпадку, калі +натыўныя прататыпы — напрыклад, `Object.prototype` — былі змененыя. + +У новых версіях ECMAScript уласцівасці, пазначаныя як не enumerable, могуць быць +вызначыныя праз `Object.defineProperty`, змяншаючы рызыку ітэрацыі праз іх без +выкарыстання `hasOwnProperty`. Тым не менш, трэба быць уважлівым пры выкарыстанні +старых бібліятэк, такіх як [Prototype][1], якая не выкарыстроўвае новымя магчымасці +ECMAScript. +Пры выкарыстоўванні гэтай бібліятэкі, цыклы `for in`, якія не выкарыстоўваюць +`hasOwnProperty`, гарантавана не будуць працаваць. + +### У заключэнне + +Рэкамендавана **заўсёды** выкарыстоўваць `hasOwnProperty` як у ECMAScript 3 або +ніжэй, так і ў бібліятэчным кодзе. У гэтых асяродках ніколі не варта рабіць +здагадкі аб тым, быў зменены натыўны прататып ці не. Пачынаючы з ECMAScript 5, +`Object.defineProperty` дазваляе пазначаць уласцівасці як не `enumerable` і прапускаць +выкарыстоўванне `hasOwnProperty` у кодзе праграмы. + +[1]: http://www.prototypejs.org/ diff --git a/doc/by/object/general.md b/doc/by/object/general.md new file mode 100644 index 00000000..6977d8a3 --- /dev/null +++ b/doc/by/object/general.md @@ -0,0 +1,98 @@ +## Выкарыстанне і ўласцівасці аб'ектаў + +Усё ў 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 + +Часта распрацоўшчыкі думаюць, што лічбавыя літэралы не могуць быць выкарыстаны як +аб'екты. Гэта праз тое, што сінтаксічны аналізатар JavaScript стараецца прывесці +*натацыю кропка* пасля нумара да літэрала з плаваючай кропкай. + + 2.toString(); // уздымае SyntaxError + +Ёсць некалькі падыходаў, якія могуць дазволіць выкарыстаць лікавыя літэралы як +аб'екты'. + + 2..toString(); // другая кропка распазнаецца слушна + 2 .toString(); // заўважце прабел з лева ад кропкі + (2).toString(); // 2 распазнаецца першым чынам + +### Аб'ект як тып дадзеных + +Аб'екты ў JavaScript таксама могуць быць выкарыстаныя як [*хэш-табліцы*][1]; яны ў асноўным +складаюцца з іменаваных уласцівасцяў з адпаведнымі значэннямі. + +Выкарыстоўваючы натацыю літэрала аб'екта — `{}` — магчыма стварыць +просты аб'ект. Гэты новы аб'ект [пашырае](#object.prototype) `Object.prototype` і +не мае [сваіх уласцівасцяў](#object.hasownproperty) якія былі б вызначыныя. + + var foo = {}; // новы пусты аб'ект + + // новы аб'ект з уласціваццю 'test', якая мае значэнне 12 + var bar = {test: 12}; + +### Доступ да ўласцівасцяў + +Доступ да ўласцівасцяў аб'екта можа быць здейснены двумя спосабамі, праз кропкавую +натацыю або натацыю з квадратнымі дужкамі. + + var foo = {name: 'кацяня'} + foo.name; // кацяня + foo['name']; // кацяня + + var get = 'name'; + foo[get]; // кацяня + + foo.1234; // SyntaxError + foo['1234']; // працуе + +Натацыі працуюць амаль што ідэнтычна, з адзінай розніцай у тым, што +натацыя з квадратнымі дужкамі дазваляе дынамічную устаноўку ўласцівасцяў і +выкарыстанне імёнаў уласцівасцяў, якія інакш прывялі б да сінтаксічных памылак. + +### Выдаленне ўласцівасцяў + +Адзіны спосаб выдаліць уласціваць з аб'екта — гэта выкарыстаць аператар `delete`; +пазначэнне уласціваці як `undefined` або `null` толькі прыбірае +*значэнне* звязанае з уласцівацю, але не *ключ*. + + 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]); + } + } + +Вышэй прыведзены код вывядзе `bar undefined` і `foo null` — толькі `baz` быў +выдалены і таму адсутнічае ў вывадзе. + +### Натацыя ключэй + + var test = { + 'case': 'Я ключавое слова, таму я павінна быць пазначана як радок', + delete: 'Я таксама ключавое слова, таму і я' // уздымае SyntaxError + }; + +Уласцівасці аб'ектаў могуць быць пазначаныя як сімваламі, так і ў выглядзе радкоў. +Праз яшчэ адну хібу сінтаксічнага аналізатара JavaScript, вышэй прыведзены код +кіне `SyntaxError` у весіях ранейшых за ECMAScript 5. + +Гэта памылка ўздымаецца праз тое, што `delete` - гэта *ключавое слова*; такім чынам, +яно мае быць пазначана як *літэрал радка* каб забяспечыць, што яно будзе какрэктна +інтэрпрэтавана старымі рухавікамі JavaScript. + +[1]: http://en.wikipedia.org/wiki/Hashmap diff --git a/doc/by/object/hasownproperty.md b/doc/by/object/hasownproperty.md new file mode 100644 index 00000000..730ce942 --- /dev/null +++ b/doc/by/object/hasownproperty.md @@ -0,0 +1,55 @@ +## Метад `hasOwnProperty` + +Каб праверыць, ці ёсць у аб'екта ўласцівасць, вызначаная ў *ім самім*, а не дзе-небудзь +у яго [ланцужку прататыпаў](#object.prototype), неабходна выкарыстаць метад +`hasOwnProperty`, які ўсе аб'екты ўспадкоўваюць ад `Object.prototype`. + +> **Заўвага:** **недастаткова** праверыць, ці значэнне уласцівасці — `undefined`. +> Уласцівасць можа існаваць, але яе значэнне было пазначана як `undefined`. + +`hasOwnProperty` — адзіная функцыя ў JavaScript, якая дазваляе атрымаць уласцівасці +аб'екта **без** зварота да ланцужка прататыпаў. + + // Сапсуем 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 + +Толькі `hasOwnProperty` дасць правільны чаканы вынік. Паглядзіце секцыю аб +[цыкле `for in`](#object.forinloop) для падрабязнейшых звестак аб тым, як +выкарыстоўваць `hasOwnProperty` падчас ітэрацыі па ўласцівасцях аб'екта. + +### `hasOwnProperty` як уласцівасць + +JavaScript не абараняе ўласцівасць `hasOwnProperty`; такім чынам, ёсць верагоднасць +што ў аб'екта можа быць уласцівасць з такім імем, неабходна выкарыстаць +*знешні* `hasOwnProperty` для карэктнага выніку. + + var foo = { + hasOwnProperty: function() { + return false; + }, + bar: 'Тут жывуць драконы' + }; + + foo.hasOwnProperty('bar'); // заўсёды верне false + + // выкарыстайце hasOwnProperty іншага аб'екта + // і перадайце foo у якасці this + ({}).hasOwnProperty.call(foo, 'bar'); // true + + // Такасама магчыма выкарыстаць hasOwnProperty з Object.prototype + Object.prototype.hasOwnProperty.call(foo, 'bar'); // true + + +### Заключэнне + +Выкарыстоўванне `hasOwnProperty` ёсць **адзіным** надзейным спосабам, каб +праверыць існаванне ўласцівасці ў аб'екце. Рэкамендуецца выкарыстоўваць +`hasOwnProperty` пры ітэрацыі па ўласцівасцях аб'екта, як апісана ў секцыі +[цыкла `for in` ](#object.forinloop). diff --git a/doc/by/object/prototype.md b/doc/by/object/prototype.md new file mode 100644 index 00000000..ec80e801 --- /dev/null +++ b/doc/by/object/prototype.md @@ -0,0 +1,115 @@ +## Прататып + +JavaScript не прадастаўляе класічную мадэль спадкаемства; замест гэтага, ён +выкарыстоўвае *прататыпную* мадэль. + +Негледзячы на тое, што гэта лічыцца адной з слабасцяў JavaScript, мадэль +прататыпнага спадкаемства больш эфэктыўная за класічную. +Напрыклад, даволі трывіальна пабудаваць класічную мадэль паверх прататыпнай мадэлі, +у той час як адваротнае было б значна больш складаным. + +JavaScript гэта адзіная шырока выкарыстоўваемая мова, якая падтрымлівае +прататыпнае спадкаемства, таму можа спатрэбіцца час, каб прызвычаіцца да гэтай мадэлі. + +Першая вялікая розніца заключаецца ў тым, што JavaScript выкастроўвае *прататыпныя +ланужкі*. + +> **Заўвага:** простае выкарыстоўванне `Bar.prototype = Foo.prototype` прывядзе +> да таго, што абодва аб'екта будуць выкарыстоўваць **той жа** прататып. +> Такім чынам, змены ў прататыпе любога з аб'ектаў паўплываюць на прататып іншага, +> што звычайна не ёсць пажаданым эфэктам. + + function Foo() { + this.value = 42; + } + Foo.prototype = { + method: function() {} + }; + + function Bar() {} + + // Пазначае прататыпам Bar новы асобнік Foo + Bar.prototype = new Foo(); + Bar.prototype.foo = 'Hello World'; + + // Упэнімся, што Bar з'яўляецца дзейсным канструктарам + Bar.prototype.constructor = Bar; + + var test = new Bar(); // стварае новы асобнік Bar + + // Выніковы ланцужок прататыпаў + test [instance of Bar] + Bar.prototype [instance of Foo] + { foo: 'Hello World', value: 42 } + Foo.prototype + { method: ... } + Object.prototype + { toString: ... /* і г.д. */ } + +У вышэй прыведзеным кодзе аб'ект `test` атрымае спадчыну і ад `Bar.prototype`, +і ад `Foo.prototype`; такім чынам, ён будзе мець доступ да функцыі `method`, якая +вызначана ў `Foo`. А таксама доступ да ўласцівасці `value` +**аднаго унікальнага асобніка** `Foo`, які з'яўляецца яго прататыпам. Важна заўважыць, +што `new Bar()` **не** стварае новы асобнік `Foo`, але выкарыстоўвае функцыю, +пазначаную яго прататыпам; такім чынам, усе асобнікі `Bar` будуць выкарыстоўваць +**тую ж** уласціваць `value`. + +> **Заўвага:** **не** выкарыстоўвайце `Bar.prototype = Foo`, бо гэта будзе +> ўказваць не на прататып `Foo`, а на аб'ект фукцыі `Foo`. Таму ланцужок +> прататыпаў будзе праходзіць праз `Function.prototype`, а не `Foo.prototype`; +> па гэтай прычыне `method` не будзе прысутнічаць у ланцужку прататыпаў. + +### Пошук уласцівасцяў + +Калі адбываецца зварот да ўласцівасці, JavaScript пройдзе па ўсім +ланцужку прататыпаў **уверх** да таго моманту, як знойдзе ўласціваць з запытаным імем. + +У той момант, калі дасягнуты верх ланцужка - а менавіта `Object.prototype` - і ўсё яшчэ +не знойдзена адпаведная ўласцівасць, будзе вернута значэнне [undefined](#core.undefined). + +### Уласцівасць prototype + +Нягледзячы на тое, што ўласцівасць prototype выкарыстоўваецца мовай, каб пабудаваць +ланцужок прататыпаў, магчыма прызначыць яму **любое** значэнне. Аднак, прызначэнне +прымітываў будузе праігнараваным. + + function Foo() {} + Foo.prototype = 1; // без эфекту + +Прызначэнне аб'ектаў, як паказана ў прыкладзе вышэй, будзе працаваць, і дазволіць +дынамічна ствараць ланцужкі прататыпаў. + +### Хуткасць выканання + +Пошук уласцівасцяў, якія знаходзяцца высока ў ланцужку прататыпаў, можа +негатыўна адбіцца на хуткасці выканання, і гэта можа быць прыкметным у кодзе, у якім +чыннік хуткасці крытычны. У выпадку спробы доступа да неіснуючых уласцівасцяў +будзе пройдзены ўвесь ланцужок прататыпаў. + +У дадатак, пры [ітэрацыі](#object.forinloop) па ўласцівасцях аб'екта +**кожная** уласціваць, што ёсць у ланцужку прататыпаў будзе апрацавана. + +### Расшырэнне ўбудаваных прататыпаў + +Адна з дрэнных магчымасцяў, што сустракаецца даволі часта — расшырэнне прататыпа +`Object.prototype` або аднаго з іншых убудаваных тыпаў. + +Такая практыка называецца [monkey patching][1] і парушае *інкапсуляцыю*. Хаця +папулярныя фрэймворкі, такія як [Prototype][2] шырока выкарыстоўваюць гэтую +мачымасць, няма добрых матываў для нагрувашчвання ўбудаваных тыпаў дадатковай +*нестандартнай* функцыянальнасцю. + +**Адзіным** добрым матывам расшырэння убудаваных прататыпаў — гэта дадаванне функцыянала, +што з'явіўся у новых рухавіках JavaScript; напрыклад, [`Array.forEach`][3]. + +### У завяршэнне + +**Вельмі важна** разумець, як працуе мадэль прататыпнага спадкаемства да таго, як +пісаць код, які яе выкарыстоўвае. Таксама сачыце за даўжынёй ланцужка прататыпаў +і драбіце іх, калі ёсць магчымасць, каб пазбегнуць праблем з прадукцыйнасцю. +Таксама ўбудаваныя прататыпы **ніколі** не павінны расшырацца, акрамя як для +таго, каб падтрымаць новыя магчымасці 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/by/other/timeouts.md b/doc/by/other/timeouts.md new file mode 100644 index 00000000..1ed49dc4 --- /dev/null +++ b/doc/by/other/timeouts.md @@ -0,0 +1,168 @@ +### `setTimeout` і `setInterval` + +Дзякуючы асінхроннасці JavaScript магчыма запланаваць выкананне функцыі з дапамогай +метадаў `setTimeout` і `setInterval`. + +> **Заўвага:** Таймаўты **не** з'яўляюцца часткай стандарта ECMAScript. Яны былі +> распрацаваны ў [BOM, ці DOM Узровень 0][1], якія ніколі не былі аб'яўлены ці +> задакументаваны фармальна. Да гэтага часу няма рэкамендацыйных спецыфікацый, +> аднак, у дадзены момант яны стандартызаваны ў [HTML5][2]. У сувязі з гэтым +> рэалізацыя можа адрознівацца ў залежнасці ад браўзера і рухавіка + + function foo() {} + var id = setTimeout(foo, 1000); // вяртае Number > 0 + +Калі функцыя `setTimeout` выклікана, яна вяртае ID таймаўта і плануе выкананне +`foo` **прыблізна** праз тысячу мілісекунд. +`foo` будзе выканана **аднойчы**. + +Улічваючы вырашэнні таймера рухавіка Javascript, які выконвае код, +аднапаточнасць JavaScript і тое, што іншы код, які выконваецца +можа блакаваць паток, **нельга** быць упэўненым, што вы атрымаеце затрымку, +пазначанаю ў выкліку `setTimeout`. + +Функцыя, якая была перададзена як першы параметр, будзе выклікана +*глабальным аб'ектам*, гэта азначае, што [`this`](#function.this) унутры выкліканай функцыі +спасылаецца на глабальны аб'ект. + + function Foo() { + this.value = 42; + this.method = function() { + // this спасылаецца на глабальны аб'ект + console.log(this.value); // выведзе undefined + }; + setTimeout(this.method, 500); + } + new Foo(); + + +> **Заўвага:** Так як `setTimeout` прымае **функцыю** як першы параметр, +> распаўсюджанай з'яўляецца памылка выкарыстоўвання `setTimeout(foo(), 1000)`, у гэтым выпадку +> будзе выкарыстоўвацца **вернутае значэнне** выкліка `foo`, а **не** `foo`. Гэта, у большасці выпадкаў, +> маўклівая памылка, так як калі функцыя вяртае `undefined`, `setTimeout` +> **не** выклікае памылкі. + +### Паслядоўныя выклікі з дапамогай `setInterval` + +У той час калі `setTimeout` выконвае функцыю толькі адзін раз, `setInterval` - як бачна з назвы - +выконвае функцыю **кожныя** `X` milliseconds, але яе выкарыстанне не пажадана. + +Код, які выконваецца, блакуе выклік з таймаўтам, у той час `setInterval` будзе +планаваць выклікі зададзенай функцыі. Гэта можа, асабліва з маленькімі інтэрваламі, +прывесці да стварэння чаргі выклікаў функцый. + + function foo(){ + // нешта, што блакуе на 1 секунду + } + setInterval(foo, 100); + +У прыведзеным кодзе `foo` будзе выклікана аднойчы і заблакуе выкананне на адну секунду. + +У той час калі `foo` блакуе код, `setInterval` будзе планаваць наступныя яе выклікі +А калі выкананне `foo` скончана, ужо **дзесяць** наступных выклікаў будуць чакаць выканання. + +### Праца з магчыма блакуючым кодам + +Найбольш простае і кіруемае рашэнне гэта выкарыстоўваць `setTimeout` унутры самой функцыі. + + function foo(){ + // нешта, што блакуе на 1 секунду + setTimeout(foo, 100); + } + foo(); + +Гэты падыход не толькі інкапсулюе выклік `setTimeout`, але таксама прадухіляе +стварэнне чаргі выклікаў і дае дадатковы кантроль. Цяпер `foo` можа сама вырашыць +хоча яна выконвацца яшчэ раз ці не. + +### Ручная чыстка таймаўтаў + +Чыстка таймаўтаў і інтэрвалаў здзяйсняецца перадачай адпаведнага ID у +`clearTimeout` або `clearInterval`, гледзячы якая `set` функцыя была выкарыстана +да гэтага. + + var id = setTimeout(foo, 1000); + clearTimeout(id); + +### Чыстка ўсіх таймаўтаў + +Так як няма ўбудаванага метада для выдалення ўсіх таймаўтаў і/або інтэрвалаў, +для гэтага неабходна выкарыстоўваць брутфорс. + + // выдаліць "усе" таймаўты + for(var i = 1; i < 1000; i++) { + clearTimeout(i); + } + +Але могуць быць таймаўты, якія не закрануты гэтым адвольным нумарам. +Іншы шлях ажыццяўлення гэтага - прыняць, што ID таймаўта павялічваецца на +адзін пасля кожнага выкліку `setTimeout`. + + // выдаліць "усе" таймаўты + var biggestTimeoutId = window.setTimeout(function(){}, 1), + i; + for(i = 1; i <= biggestTimeoutId; i++) { + clearTimeout(i); + } + +Не гледзячы на тое, што зараз гэта працуе на ўсіх асноўных браўзерах, тое, што ID +павінны быць арганізаваны такім шляхам не пазначана ў спецыфікацыі і можа змяніцца. Таму +замест гэтага рэкамендуецца сачыць за ўсімі ID таймаўтаў, каб яны маглі быць выдалены паасобку. + +### Схаванае выкарыстанне `eval` + +`setTimeout` і `setInterval` таксама могуць прымаць радок у якасці першага параметра. +Гэту магчымасць **ніколі** не трэба выкарыстоўваць, бо ўнутрана вызываецца `eval`. + +> **Заўвага:** Дакладны механізм работы пры перадачы радка можа адрозніваецца ў +> розных JavaScript рэалізацыях. Напрыклад, JScript ад Microsoft выкарыстоўвае +> канструктар `Function` замест `eval`. + + function foo() { + // будзе выклікана + } + + function bar() { + function foo() { + // ніколі не будзе выклікана + } + setTimeout('foo()', 1000); + } + bar(); + +Паколькі `eval` не выклікана [напрамую](#core.eval), радок, які перададзены +`setTimeout` будзе выкананы ў *глабальным скоўпе*; такім чынам, не будзе выкарыстана +лакальная пераменная `foo` са скоўпа `bar`. + +Адсюль вынікае рэкамендацыя **не** выкарыстоўваць радок для перадачы аргументаў у +функцыю, якая будзе вызывацца адной з таймаўт функцый. + + function foo(a, b, c) {} + + // НІКОЛІ так не рабіце + setTimeout('foo(1, 2, 3)', 1000) + + // Замест выкарыстоўвайце ананімныя функцыі + setTimeout(function() { + foo(1, 2, 3); + }, 1000) + +> **Заўвага:** Нягледзячы на тое, што сінтаксіс `setTimeout(foo, 1000, 1, 2, 3)` можна выкарыстоўваць, +> гэта не рэкамендуецца, так як можа прывесці да +> непрыкметных памылак пры выкарыстанні з [метадамі](#function.this). +> Больш таго, сінтаксіс можа не працаваць у некаторых рэалізацыях JavaScript. +> Напрыклад, Internet Explorer ад Microsoft [**не** перадае аргументы напрамую зваротнаму выкліку](3). + +### У заключэнне + +Радок **ніколі** не павінен быць выкарыстаны як параметр `setTimeout` ці +`setInterval`. Відавочны знак **сапраўды** благога кода гэта калі функцыя, якая будзе выклікана, +патрабуе аргументы. Трэба перадаваць *ананімную функцыю*, якая будзе адказваць за +выклік патрэбнай функцыі. + +Больш таго, трэба пазбягаць выкарыстання `setInterval`, таму што яе планавальнік не блакуецца +выкананнем JavaScript. + +[1]: http://www.nczonline.net/blog/2009/09/29/web-definitions-dom-ajax-and-more/ "Web definitions: DOM, Ajax, and more" +[2]: http://www.w3.org/TR/2014/WD-html5-20140617/webappapis.html#timers "6 Web application APIs - HTML5" +[3]: http://msdn.microsoft.com/en-us/library/ie/ms536753(v=vs.85).aspx "setTimeout method (Internet Explorer)" diff --git a/doc/by/types/casting.md b/doc/by/types/casting.md new file mode 100644 index 00000000..763bf3a1 --- /dev/null +++ b/doc/by/types/casting.md @@ -0,0 +1,71 @@ +## Прывядзенне тыпаў + +JavaScript - *слаба тыпізаваная* мова, таму *прывядзенне тыпаў* адбываецца +**паўсюль** дзе магчыма. + + // Гэтыя равенствы - праўдзівыя + new Number(10) == 10; // аб'ект тыпа Number пераўтвараецца у + // лікавы прымітыў, праз няяўны выклік + // метада Number.prototype.valueOf + + 10 == '10'; // Strings пераўтвараецца ў Number + 10 == '+10 '; // Троху вар'яцтва з радкамі + 10 == '010'; // і яшчэ + isNaN(null) == false; // null пераўтвараецца ў 0 + // які вядома ж не NaN + + // Гэтыя равенствы - ілжывыя + 10 == 010; + 10 == '-10'; + +> **Заўвага для ES5:** Лічбавыя літэралы, што пачынаюцца з `0` інтэрпрэтуюцца як +> васьмірычныя (Base 8). Падтрымка васьмірычнай сістэмы была **прыбраная** у +> ECMAScript 5 strict mode. + +Каб пазбегнуць вышэйпрыведзеных праблемаў, **настойліва** ракамендуецца выкарыстоўваць +[аператар строгай роўнасці](#types.equality). Зрэшты, хоць гэта і пазбаўляе ад +многіх распаўсюджаных праблемаў, існуе яшчэ шмат праблемаў, які ўзнікаюць праз +слабую тыпізацыю JavaScript. + +### Канструктары ўбудаваных тыпаў + +Канструктары ўбудаваных тыпаў, напрыклад, `Number` і `String` паводзяць сябе +па рознаму, у залежнасці ад таго, выклікаюцца яны з ключавым словам `new` або без яго. + + new Number(10) === 10; // False, Object і Number + Number(10) === 10; // True, Number і Number + new Number(10) + 0 === 10; // True, праз неяўнае прывядзенне + +Выкарыстанне ўбудаванага тыпу, такога як `Number` у якасці канструкта створыць новы +экзэмпляр аб'екта `Number`, але пры адсутнасці ключавога слова `new` функцыя +`Number` будзе паводзіць сябе як канвертар. + +У дадатак, выкарытоўванне літэралаў, або значэнняў якія не з'яўляюцца аб'ектамі +прывядзе да дадатковых прывядзенняў тыпаў. + +Лепшы варыянт - гэта **яўнае** прывядзенне да аднаго з трох магчымых тыпаў. + +### Прывядзенне да радка + + '' + 10 === '10'; // true + +Праз даданне да значэння пустога радка, яно лёгка прыводзіцца да радка. + +### Прывядзенне да лікавага тыпу + + +'10' === 10; // true + +Выкарыстоўваючы **унарны** аператар плюс, магчыма пераўтварыць значэнне ў нумар. + +### Прывядзенне да булевага тыпу + +Выкарыстоўваючы аператар **адмаўленне (!)** двойчы, значэнне можна прыведзена +да лагічнага (булевага) тыпу. + + !!'foo'; // true + !!''; // false + !!'0'; // true + !!'1'; // true + !!'-1' // true + !!{}; // true + !!true; // true diff --git a/doc/by/types/equality.md b/doc/by/types/equality.md new file mode 100644 index 00000000..0859ce03 --- /dev/null +++ b/doc/by/types/equality.md @@ -0,0 +1,70 @@ +## Роўнасць і параўнанне + +У JavaScript роўнасць значэнняў аб'ектаў можна вызначыць двумя спосабамі. + +### Аператар роўнасці + +Аператар роўнасці складаецца з двух сімвалаў 'роўна': `==` + +JavaScript мае *слабую тыпізацыю*. Гэта значыць што аператар роўнасці +**прыводзіць** тыпы аб'ектаў, каб параўнаць іх. + + "" == "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 + +Вышэй прыведзеная табліца паказвае вынікі прывядзення тыпаў, і гэта галоўная прычына +па якой выкаростоўванне `==` лічыцца дрэннай практыкай. Яно прыводзіць да памылак +якія цяжка адсачыць праз складаны механізм прывядзення тыпаў. + +Акрамя гэтага, прывядзенне тыпаў таксама ўплывае на вытворчасць; +напрыклад, радок мае быць ператвораны ў нумар, перад тым як быць параўнаным з +іншым нумарам. + +### Аператар строгай роўнасці + +Аператар строгай роўнасці складаецца з **трох** сімвалаў 'роўна': `===`. + +Ён дзейнічае як звычайны аператар роўнасці, за выключэннем таго, што строгая +роўнасць **не** прыводзіць аперанды да агульнага тыпу. + + "" === "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 + +Вышэй прыведзеныя вынікі значна больш зразумелыя і даюць магчымасць хутчэй выявіць +памылкі ў кодзе. Гэта паляпшае код, а таксама дае прырост вытворчасці, у выпадку +калі аперанды розных тыпаў. + +### Параўнанне аб'ектаў + +Хоць абодва аператар `==` і `===` называюцца аператарамі **роўнасці**, яны паводзяць +сабе па рознаму калі хоць адзін аперанд тыпа `Object`. + + {} === {}; // false + new String('foo') === 'foo'; // false + new Number(10) === 10; // false + var foo = {}; + foo === foo; // true + +Тут абодва аператанда параўноўваюцца на **ідэнтычнасць**, а **не** на роўнасць; +то бок будзе праверана, ці з'яўляюцца яны адным **экзэмплярам** аб'екта. Гэтак жа, +як `is` у Python, або параўнанне ўказальнікаў у C. + +### У заключэнне + +Настойліва рэкамендуецца выкарыстоўваць толькі аператар **строгай роўнасці**. +У выпадку, калі тыпы маюць быць прыведзеныя, гэта варта рабіць [яўна](#types.casting), +а не пакідаць іх на сумленні складаных правілаў прывядзення мовы праграмавання. diff --git a/doc/by/types/instanceof.md b/doc/by/types/instanceof.md new file mode 100644 index 00000000..220bc3c3 --- /dev/null +++ b/doc/by/types/instanceof.md @@ -0,0 +1,37 @@ +## Аператар `instanceof` + +Аператар `instanceof` параўноўвае канструктары двух аперандаў. Гэта карысна толькі +для параўнання аб'ектаў не ўбудаваных тыпаў. Выкарыстоўванне на ўбудаваных тыпах не +мае сэнсу, як і [аператар typeof](#types.typeof). + +### Параўнанне адвольных аб'ектаў + + function Foo() {} + function Bar() {} + Bar.prototype = new Foo(); + + new Bar() instanceof Bar; // true + new Bar() instanceof Foo; // true + + // Калі толькі прысвоім Bar.prototype аб'ект функцыі Foo, + // але не самаго экзэмпляра Foo + Bar.prototype = Foo; + new Bar() instanceof Foo; // false + +### Выкарыстоўванне `instanceof` з убудаванымі тыпамі + + new String('foo') instanceof String; // true + new String('foo') instanceof Object; // true + + 'foo' instanceof String; // false + 'foo' instanceof Object; // false + +Варта адзначыць, што `instanceof` не працуе на аб'ектах, якія паходзяць з розных +кантэкстаў JavaScript (напрыклад, розных дакументаў у web-браузеры), бо іх канструктары +насамрэч не будуць канструктарамі тых самых аб'ектаў. + +### У заключэнне + +Аператар `instanceof` мае быць выкарыстаны **толькі** для працы з аб'ектамі не +ўбудаваных тыпаў якія паходзяць з аднаго кантэкста JavaScript. Як і ў выпадку з +[аператарам `typeof`](#types.typeof), трэба **пазбягаць** любога іншага яго выкарыстання. diff --git a/doc/by/types/typeof.md b/doc/by/types/typeof.md new file mode 100644 index 00000000..7fb16ba9 --- /dev/null +++ b/doc/by/types/typeof.md @@ -0,0 +1,80 @@ +## Аператар `typeof` + +Аператар `typeof` (разам з [`instanceof`](#types.instanceof)) магчыма найбольшая +хіба мовы JavaScript, таму што ён амаль што **цалкам зламаны**. + +Хаця `instanceof` усё яшчэ мае абмежаванае ўжыванне, `typeof` можа быць выкарыстаны +толькі з адной мэтай, і гэта дарэчы **не** праверка тыпа. + +> **Заўвага:** Хаця для выкліка `typeof` можна выкарыстаць сінтаксіс функцыі, то бок +> `typeof(obj)`, гэта не выклік функцыі. Дужкі будуць апрацоўвацца нармальна +> і вернутае значэнне будзе выкарыстана як аперанд аператара `typeof`. +> **Не існуе** функцыі `typeof`. + +### Табліца тыпаў JavaScript + + Значэнне Клас Тып + ------------------------------------- + "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 + +У вышэй прыведзенай табыліцы, *Тып* паказвае значэнне вернутае аператарам `typeof`. +Як можна пабачыць, гэта значэнне абсалютна не кансістэнтнае. + +*Клас* паказвае значэнне ўнутраннай уласцівасці `[[Class]]` аб'екта. + +> **З спецыфікацыі:** значэнне `[[Class]]` можа быць быць адным з наступных +> радкоў. `Arguments`, `Array`, `Boolean`, `Date`, `Error`, +> `Function`, `JSON`, `Math`, `Number`, `Object`, `RegExp`, `String`. + +### Клас аб'екта + +Адзіны спосаб атрымаць значэнне `[[Class]]` аб'екта - выклікаць метад `Object.prototype.toString`. +Ён верне радок у наступным фармаце: `'[object ' + valueOfClass + ']'`, напрыклад +`[object String]` або `[object Array]`: + + 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 + +У вышэйпрыведзеным прыкладзе, `Object.prototype.toString` выклікаецца са значэннем +[this](#function.this) пазначаным як аб'ект чыё значэнне `[[Class]]` мае быць +атрыманым. + +> **Заўвага для ES5:** у ECMAScript 5, для зручнасці, значэнне `Object.prototype.toString` +> для `null` і `undefined` было **зменена** з `Object` на `Null` і +> `Undefined` адпаведна. + +### Праверка вызначанасці пераменных + + typeof foo !== 'undefined' + +Вышэйпрыведзены код праверыць ці было вызначана `foo`; просты зварот да пераменнай +прывядзе да `ReferenceError`. Гэта адзінае для чаго карысны `typeof`. + +### У заключэнне + +Каб праверыць тып аб'екта, настойліва рэкамендуецца выкарыстоўваць +`Object.prototype.toString` - гэта адзіны надзейны спосаб. +Як паказана ў вышэйпрыведзенай табліцы, некаторыя значэнні вернутыя аператарам +`typeof` не вызначаныя ў спецыфікацыі; такім чынам, яны могуць быць рознымі ў +розных рэалізацыях. + +Акрамя як для праверкі вызначанасці пераменнай, `typeof` мае быць пазбегнуты. diff --git a/doc/en/function/closures.md b/doc/en/function/closures.md index a5fbc91e..aef633b9 100644 --- a/doc/en/function/closures.md +++ b/doc/en/function/closures.md @@ -36,12 +36,12 @@ Since it is not possible to reference or assign scopes in JavaScript, there is interact with it is via the two closures. var foo = new Counter(4); - foo.hack = function() { + foo.hackFail = 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 +since `foo.hackFail` was not defined in **that** scope. It will instead create - or override - the *global* variable `count`. ### Closures Inside Loops @@ -97,7 +97,7 @@ above. } The other popular way to achieve this is to add an additional argument to -the setTimeout function, which passes these arguments to the callback. +the `setTimeout` function, which passes these arguments to the callback. for(var i = 0; i < 10; i++) { setTimeout(function(e) { diff --git a/doc/en/function/constructors.md b/doc/en/function/constructors.md index 2fa3bda4..e84a6cf8 100644 --- a/doc/en/function/constructors.md +++ b/doc/en/function/constructors.md @@ -65,15 +65,12 @@ explicitly return a value. } } } - Robot.prototype = { - someFunction: function() {} - }; new Robot(); Robot(); Both calls to `Robot` return the same thing, a newly created object that -has a property called `method`, which is a +has a property called `getColor`, which is a [Closure](#function.closures). It should also be noted that the call `new Robot()` does **not** affect the diff --git a/doc/en/function/scopes.md b/doc/en/function/scopes.md index 28caddbd..33d525e1 100644 --- a/doc/en/function/scopes.md +++ b/doc/en/function/scopes.md @@ -220,6 +220,7 @@ which, while different in syntax, behave the same way. !function(){}() +function(){}() (function(){}()); + void function(){}(); // and so on... ### In Conclusion diff --git a/doc/en/function/this.md b/doc/en/function/this.md index f123f336..83abff00 100644 --- a/doc/en/function/this.md +++ b/doc/en/function/this.md @@ -63,7 +63,7 @@ mis-design of the language because it **never** has any practical use. // 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**. @@ -77,7 +77,7 @@ local variable inside of `method` that refers to `Foo`. // Use self instead of this here } test(); - } + }; `self` 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 @@ -90,7 +90,7 @@ As of ECMAScript 5 you can use the `bind` method combined with an anonymous func // this now refers to Foo }.bind(this); test(); - } + }; ### Assigning Methods diff --git a/doc/en/object/general.md b/doc/en/object/general.md index 9300b18e..89589229 100644 --- a/doc/en/object/general.md +++ b/doc/en/object/general.md @@ -6,9 +6,9 @@ Everything in JavaScript acts like an object, with the only two exceptions being false.toString(); // 'false' [1, 2, 3].toString(); // '1,2,3' - function Foo(){} - Foo.bar = 1; - Foo.bar; // 1 + function sayHello(){} + sayHello.count = 1; + sayHello.count; // 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 @@ -20,7 +20,7 @@ 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(); // note the space left of the dot (2).toString(); // 2 is evaluated first ### Objects as a Data Type @@ -32,25 +32,25 @@ 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 + var names = {}; // a new empty object - // a new object with a 'test' property with value 12 - var bar = {test: 12}; + // a new object with a 'name' property with value 'Rob' + var rob = {name: 'Rob'}; ### 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 pet = {name: 'kitten'} + pet.name; // kitten + pet['name']; // kitten var get = 'name'; - foo[get]; // kitten + pet[get]; // kitten - foo.1234; // SyntaxError - foo['1234']; // works + pet.1234; // SyntaxError + pet['1234']; // works The notations work almost identically, with the only difference being that the square bracket notation allows for dynamic setting of properties and @@ -63,13 +63,13 @@ 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 + a: 1, + b: 2, + c: 3 }; - obj.bar = undefined; - obj.foo = null; - delete obj.baz; + obj.a = undefined; + obj.b = null; + delete obj.c; for(var i in obj) { if (obj.hasOwnProperty(i)) { @@ -77,7 +77,7 @@ operator; setting the property to `undefined` or `null` only removes the } } -The above outputs both `bar undefined` and `foo null` - only `baz` was +The above outputs both `a undefined` and `b null` - only `c` was removed and is therefore missing from the output. ### Notation of Keys diff --git a/doc/en/object/prototype.md b/doc/en/object/prototype.md index cb053526..f63abaa9 100644 --- a/doc/en/object/prototype.md +++ b/doc/en/object/prototype.md @@ -41,7 +41,7 @@ chains*. // The resulting prototype chain test [instance of Bar] Bar.prototype [instance of Foo] - { foo: 'Hello World' } + { foo: 'Hello World', value: 42 } Foo.prototype { method: ... } Object.prototype diff --git a/doc/en/other/timeouts.md b/doc/en/other/timeouts.md index 8fe66d81..e27ccacf 100644 --- a/doc/en/other/timeouts.md +++ b/doc/en/other/timeouts.md @@ -55,7 +55,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. @@ -70,7 +70,7 @@ the function itself. function foo(){ // something that blocks for 1 second - setTimeout(foo, 100); + setTimeout(foo, 1000); } foo(); diff --git a/doc/en/types/typeof.md b/doc/en/types/typeof.md index 637ea2bc..9eb3fbdc 100644 --- a/doc/en/types/typeof.md +++ b/doc/en/types/typeof.md @@ -42,13 +42,11 @@ 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 -`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`. +The only way to determine an object's `[[Class]]` value is using `Object.prototype.toString`. It +returns a string in the following format: `'[object ' + valueOfClass + ']'`, e.g `[object String]` or +`[object Array]`: function is(type, obj) { var clas = Object.prototype.toString.call(obj).slice(8, -1); diff --git a/doc/es/function/constructors.md b/doc/es/function/constructors.md index 0850cb4b..9c4e2946 100644 --- a/doc/es/function/constructors.md +++ b/doc/es/function/constructors.md @@ -48,7 +48,7 @@ Cuando una `nueva` keyword es omitidad, la función **no** devuelve un nuevo obj } Foo(); // undefined -Auqnue el ejemplo anterior puede parecer que trabaja en algunos casos, debido +Aunque 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`. diff --git a/doc/es/function/general.md b/doc/es/function/general.md index d9621bc5..c051373a 100644 --- a/doc/es/function/general.md +++ b/doc/es/function/general.md @@ -1,7 +1,7 @@ ## 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 +Las funciones en JavaScript son funciones de primera clase `(first class functions)`. +Esto significa que se pueden tratar como objetos. Un uso común de esta 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` diff --git a/doc/es/function/scopes.md b/doc/es/function/scopes.md index d641a939..00ed940c 100644 --- a/doc/es/function/scopes.md +++ b/doc/es/function/scopes.md @@ -47,7 +47,7 @@ mayor implicación. test(); foo; // 21 -Dejando de lador la sentencia `var` dentro de la función `test` sobre escribiría el +Dejando de lado 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. @@ -68,7 +68,7 @@ horrible y difícil detección de errores. 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. +el *efecto deseado* es afectado por el ámbito exterior. ### Variables locales diff --git a/doc/es/function/this.md b/doc/es/function/this.md index 7b1c0554..4fed1e35 100644 --- a/doc/es/function/this.md +++ b/doc/es/function/this.md @@ -17,7 +17,7 @@ Cuando se utiliza `this` en el ámbito global, simplemente se refiere al objeto Aquí `this` se refiere al objeto *global*. -> **Nota ES5:** En modo estricto (strict mode), global **ya no** existe. +> **Nota ES5:** En modo estricto (strict mode), el objeto global **ya no** es accesible a través de this. > `this` tendrá el valor de `undefined` en este caso. ### Llamar a un método @@ -63,7 +63,7 @@ mal diseño del lenguaje, ya que **nunca** tiene un uso práctico. // 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í**. @@ -77,7 +77,7 @@ dentro del `método` para referirse a `Foo`. // 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 diff --git a/doc/es/index.json b/doc/es/index.json index 54d54e1c..1367f527 100644 --- a/doc/es/index.json +++ b/doc/es/index.json @@ -39,7 +39,7 @@ ] }, { - "title": "Types", + "title": "Tipos", "dir": "types", "articles": [ "equality", diff --git a/doc/es/object/general.md b/doc/es/object/general.md index b06264ec..da48e138 100644 --- a/doc/es/object/general.md +++ b/doc/es/object/general.md @@ -91,7 +91,7 @@ Las propiedades de los objetos puede ser simbolizados como caracteres planos y c 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 +Este error se produce porque `delete` es una *keyword*; por lo tanto, debe ser anotado como un *string literal* para asegurarse que será interpretado correctamente por diversos motores de JavaScript. diff --git a/doc/es/object/prototype.md b/doc/es/object/prototype.md index 363c4d48..0461d1ff 100644 --- a/doc/es/object/prototype.md +++ b/doc/es/object/prototype.md @@ -41,7 +41,7 @@ llamadas de *cadenas de prototipo* (*prototype chains*). // Resultado de cadena de prototipos (prototype chain) test [instance of Bar] Bar.prototype [instance of Foo] - { foo: 'Hello World' } + { foo: 'Hello World', value: 42 } Foo.prototype { method: ... } Object.prototype diff --git a/doc/es/types/equality.md b/doc/es/types/equality.md index 5665917f..f933d495 100644 --- a/doc/es/types/equality.md +++ b/doc/es/types/equality.md @@ -1,13 +1,13 @@ -## Equality and Comparisons +## Igualdad y Comparación -JavaScript has two different ways of comparing the values of objects for equality. +JavaScript posee 2 maneras diferentes para comparar valores entre objetos para comprobar igualdad. -### The Equality Operator +### El Operador de Igualdad -The equality operator consists of two equal signs: `==` +El operador de igualdad consiste en 2 signos es igual: `==` -JavaScript features *weak typing*. This means that the equality operator -**coerces** types in order to compare them. +JavaScript utiliza *tipado débil*. Esto significa que el operador de igualdad +**obliga** una conversión de tipos para poder compararlos. "" == "0" // false 0 == "" // true @@ -19,20 +19,20 @@ 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. +La tabla anterior muestra los resultados de la conversión de tipos, éste es el motivo principal +de por qué el uso de `==` es ampliamente considerado una mala práctica. Introduce errores +difíciles de identificar debido a la complejidad de sus reglas de conversión. -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. +Además, existe un impacto en el rendimiento cuando entra en juego la conversión de tipos; +por ejemplo, una cadena debe ser convertida a número antes de poder ser comparada +con otro número. -### The Strict Equality Operator +### El Operador de Igualdad Estricto -The strict equality operator consists of **three** equal signs: `===`. +El operador de igualdad estricto consiste en **tres** signos es igual: `===`: -It works exactly like the normal equality operator, except that strict equality -operator does **not** perform type coercion between its operands. +Funciona exactamente igual que el operador de igualdad, excepto que el operador de igualdad +estricto **no** utiliza conversión de tipos entre sus operandos. "" === "0" // false 0 === "" // false @@ -44,14 +44,14 @@ 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. +Los resultados anteriores son mucho más claros y permiten una detección de errores temprana. +Esto permite un código más sólido en cierto grado y también mejora el rendimiento +en el caso que los operandos sean de tipos diferentes. -### Comparing Objects +### Comparando Objetos -While both `==` and `===` are stated as **equality** operators, they behave -differently when at least one of their operands happens to be an `Object`. +Aunque `==` como `===` son considerados operadores de **igualdad**, se comportan +de maneras diferentes cuando al menos uno de sus operandos es `Object`. {} === {}; // false new String('foo') === 'foo'; // false @@ -59,13 +59,13 @@ 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. +En este caso, los dos operadores comparan por **referencia** y **no** por igualdad; esto es, +comparan por la misma **instancia** del objeto, parecido +al operador `is` en Python y la comparación entre punteros en C. -### In Conclusion +### En Conclusión -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. +Es altamente recomendable usar sólo el operador de **igualdad estricta**. En los casos +donde los tipos de datos necesitan ser convertidos, debe hacerse [explícitamente](#types.casting) +y no dejárselo a las complicadas reglas de conversión del lenguaje. diff --git a/doc/fi/function/this.md b/doc/fi/function/this.md index 3ebf0a7b..3e2b09d2 100644 --- a/doc/fi/function/this.md +++ b/doc/fi/function/this.md @@ -51,7 +51,7 @@ Useimmat näistä tapauksista ovat järkeviä. Ensimmäistä niistä tosin voida // this asettuu globaaliin olioon } test(); - } + }; Yleisesti luullaan, että test-funktion sisältämä `this` viittaa tässä tapauksessa `Foo`-olioon. Todellisuudessa se **ei** kuitenkaan tee näin. @@ -63,7 +63,7 @@ Jotta `Foo`-olioon voidaan päästä käsiksi `test`-funktion sisällä, tulee m // Käytä thatia thissin sijasta } test(); - } + }; `that` on normaali nimi, jota käytetään yleisesti viittaamaan ulompaan `this`-muuttujaan. [Sulkeumia](#function.closures) käytettäessä `this`-arvoa voidaan myös välittää edelleen. diff --git a/doc/fi/object/prototype.md b/doc/fi/object/prototype.md index 4ecdae89..f2497e05 100644 --- a/doc/fi/object/prototype.md +++ b/doc/fi/object/prototype.md @@ -31,7 +31,7 @@ Ensimmäinen suuri ero liittyy siihen, kuinka perintä toimii. JavaScriptissä s // Prototyyppiketju test [Bar-olio] Bar.prototype [Foo-olio] - { foo: 'Terve maailma' } + { foo: 'Terve maailma', value: 42 } Foo.prototype { method: ... } Object.prototype diff --git a/doc/fr/array/general.md b/doc/fr/array/general.md index ab9183a0..aecec798 100644 --- a/doc/fr/array/general.md +++ b/doc/fr/array/general.md @@ -1,7 +1,7 @@ ## Tableaux: iteration et propriétés Bien que les tableaux soient des objets en JavaScript, il n'y a pas de bonnes raisons d'utiliser la boucle [`for in`](#object.forinloop). -En fait, il un certain nombre de bonnes raisons **contre** l'utilisation de `for in` sur les tableaux. +En fait, il y a un certain nombre de bonnes raisons **contre** l'utilisation de `for in` sur les tableaux. **Remarque:** Les tableaux JavaScript ne sont **pas** *associatifs*. JavaScript n'offre que les [objets](#object.general) pour associer des clés à des valeurs. Contrairement aux tableaux associatifs, les objets ne préservent **pas** l'ordre. diff --git a/doc/fr/function/this.md b/doc/fr/function/this.md index 723c0255..aed2301c 100644 --- a/doc/fr/function/this.md +++ b/doc/fr/function/this.md @@ -52,7 +52,7 @@ Bien que la plupart de ces cas ont du sens, le premier cas peut être considér // this réfère à l'objet global } test(); - } + }; Une autre erreur souvent commise est que `this` l'intérieur de `test` se réfère à `foo`; ce qui n'est **pas** du tout le cas. @@ -64,7 +64,7 @@ Pour accéder à `foo` de l'intérieur de `test`, vous pouvez créer une variabl // Utilisez self au lieu de this ici } test(); - } + }; `self` est juste une variable normale, couramment utilisée pour référencer un `this` extérieur. Combiné avec des [fermetures](# function.closures) "closures", on peut l'utiliser pour passer les valeurs de `this`. @@ -75,7 +75,7 @@ Pour accéder à `foo` de l'intérieur de `test`, vous pouvez créer une variabl // maintenant, this réfère à Foo }.bind(this); test(); - } + }; ### Assignement de méthodes diff --git a/doc/fr/object/prototype.md b/doc/fr/object/prototype.md index 50b21f23..c1a471aa 100644 --- a/doc/fr/object/prototype.md +++ b/doc/fr/object/prototype.md @@ -33,7 +33,7 @@ La première différence majeure est que l'héritage en JavaScript utilise des * // La chaîne de prototypes qui en résulte test [instance of Bar] Bar.prototype [instance of Foo] - { foo: 'Hello World' } + { foo: 'Hello World', value: 42 } Foo.prototype { method: ... } Object.prototype diff --git a/doc/hu/array/constructor.md b/doc/hu/array/constructor.md index 444644a0..57a5a9ca 100644 --- a/doc/hu/array/constructor.md +++ b/doc/hu/array/constructor.md @@ -10,7 +10,7 @@ ajánlott mindig a tömb literált - `[]` jelölés - használni új tömbök l new Array(3); // Eredmény: [] new Array('3') // Eredmény: ['3'] -Abban az esetben, hogyha ez a konstruktor csak egy `szám` paramétert kap, akkor +Abban az esetben, ha ez a konstruktor csak egy `szám` paramétert kap, akkor visszatérési értékül egy olyan tömböt fog létrehozni amelynek a `length` mezője akkorára van beállítva, ahogy azt megadtuk az argumentumban. Megjegyzendő hogy **csak** a `length` tulajdonság lesz ekkor beállítva; az egyes indexek külön-külön diff --git a/doc/hu/array/general.md b/doc/hu/array/general.md index 660bb3b3..f7fa98e4 100644 --- a/doc/hu/array/general.md +++ b/doc/hu/array/general.md @@ -13,7 +13,7 @@ lassabb mint egy sima `for` ciklus. ### Iteráció -Annak érdekébern hogy a legjobb teljesítményt érjük el a tömbökön való iteráció során, +Annak érdekében, hogy a legjobb teljesítményt érjük el a tömbökön való iteráció során, a legjobb hogyha a klasszikus `for` ciklust használjuk. var list = [1, 2, 3, 4, 5, ...... 100000000]; @@ -27,7 +27,7 @@ a `l = list.length` kifejezés használatával. Habár a `length` tulajdonság mindig magán a tömbön van definiálva, még mindig lehet egy kis teljesítmény kiesés amiatt hogy minden iterációban újra meg kell keresni ezt a tulajdonságot. Persze a legújabb JavaScript motorok **talán** -használnak erre optimalizációt, de nem lehet biztosan megmondani hogy ahol a kódunk +használnak erre optimalizációt, de nem lehet biztosan megmondani, hogy ahol a kódunk futni fog, az egy ilyen motor-e vagy sem. Valójában, a cachelés kihagyása azt eredményezheti, hogy a ciklusunk csak diff --git a/doc/hu/core/delete.md b/doc/hu/core/delete.md index 859a3537..89b95b41 100644 --- a/doc/hu/core/delete.md +++ b/doc/hu/core/delete.md @@ -41,7 +41,7 @@ Az expliciten beállított mezőket persze normálisan lehet törölni. obj.y; // undefined -A fenti példábna az `obj.x` és `obj.y` törölhető, mivel nincs `DontDelete` +A fenti példában az `obj.x` és `obj.y` törölhető, mivel nincs `DontDelete` attribútuma egyik mezőnek sem. Ezért működik az alábbi példa is. // működik, kivéve IE-ben @@ -52,7 +52,7 @@ attribútuma egyik mezőnek sem. Ezért működik az alábbi példa is. GLOBAL_OBJECT.a; // undefined Itt egy trükköt használunk az `a` törlésére. A [`this`](#function.this) itt -a Globális objektumra mutat, és expliciten bezetjük rajta az `a` változót, mint +a Globális objektumra mutat, és expliciten bevezetjük rajta az `a` változót, mint egy mezőjét, így törölni is tudjuk. Mint az szokás, a fenti kód egy kicsit bugos IE-ben (legalábbis 6-8-ig). @@ -88,4 +88,4 @@ meghatározva az ES aktuális verziójú specifikációjában, pl. a window) ### Összegzésképp A `delete` működése helyenként megjósolhatatlan, így biztonsággal csak olyan -objektumok mezőin használhatjuk amelyeket expliciten mi állítottunk be. \ No newline at end of file +objektumok mezőin használhatjuk, amelyeket expliciten mi állítottunk be. \ No newline at end of file diff --git a/doc/hu/core/eval.md b/doc/hu/core/eval.md index b2c83d45..9de5d3b3 100644 --- a/doc/hu/core/eval.md +++ b/doc/hu/core/eval.md @@ -44,6 +44,6 @@ nem megbízható/ismeretlen. ### Összegzésül Soha ne használjunk `eval`t. Bármilyen kód működése, teljesítménye, ill. biztonsága -megkérdőjelezhető amely használja ezt a nyelvi elemet. Semmilyen megoldás +megkérdőjelezhető, amely használja ezt a nyelvi elemet. Semmilyen megoldás használata **nem ajánlott** amely első sorban `eval`ra épül. Ekkor egy *jobb megoldás* szükségeltetik, amely nem függ az `eval`tól. \ No newline at end of file diff --git a/doc/hu/core/semicolon.md b/doc/hu/core/semicolon.md index 0241234f..fddd1acf 100644 --- a/doc/hu/core/semicolon.md +++ b/doc/hu/core/semicolon.md @@ -93,7 +93,7 @@ Az értelmező drasztikusan megváltoztatta a fenti kódot. A legtöbb esetben a beillesztő **rosszul** tippel. (A ford.: Semmilyen nyelvben sem jó, hogyha hagyjuk hogy a gép találja ki mit -szerettünk volna írni. Néma gyereknek az anyja sem érti a kódját ugye) +szerettünk volna írni. Néma gyereknek az anyja sem érti a kódját ugye.) ### Kezdő Zárójelek diff --git a/doc/hu/function/arguments.md b/doc/hu/function/arguments.md index d7b77ec0..0a0a1e6f 100644 --- a/doc/hu/function/arguments.md +++ b/doc/hu/function/arguments.md @@ -22,12 +22,12 @@ Ez a kódrészlet egy új `Array` objektummá varázsolja az emlegetett `argumen Array.prototype.slice.call(arguments); -De, ez a konverzió meglehetősen **lassú** így egyáltalán **nem ajánlott** teljesítmény kirtikus +De, ez a konverzió meglehetősen **lassú**, így egyáltalán **nem ajánlott** teljesítmény kirtikus alkalmazások írásakor. ### Argumentumok kezelése -A következő módszer ajánlott arra az esetre hogyha az egyik függvény paramétereit egy-az-egyben +A következő módszer ajánlott arra az esetre, hogy ha az egyik függvény paramétereit egy-az-egyben át szeretnénk adni egy másik függvény számára. function foo() { @@ -37,7 +37,7 @@ A következő módszer ajánlott arra az esetre hogyha az egyik függvény param // sok okos kód ide } -Egy másik trükk arra hogy teljesen független wrapper függvényeket gyártsunk, a `call` +Egy másik trükk arra, hogy teljesen független wrapper függvényeket gyártsunk, a `call` és `apply` együttes használata. function Foo() {} @@ -83,7 +83,7 @@ egyik paraméterének ezt a nevet választjuk. Azonban a *getterek* és *setterek* mindig létrejönnek, de ez ne zavarjon meg minket, mert semmiféle befolyása nincs a teljesítményre, pláne olyan kódban ahol sokkal több mindennel -is foglalkozunk mint az `arguments` objetkumhoz való hozzáférés. +is foglalkozunk, mint az `arguments` objetkumhoz való hozzáférés. > **ES5 Megjegyzés:** Ezek a **getterek** és **setterek** nem jönnek létre strict módban. diff --git a/doc/hu/function/closures.md b/doc/hu/function/closures.md index 436f58e2..33d4e3bd 100644 --- a/doc/hu/function/closures.md +++ b/doc/hu/function/closures.md @@ -3,7 +3,7 @@ A JavaScript nyelv egyik legerőteljesebb tulajdonsága a *closure*-ök használatában rejlik. Ezek használatával a hatókörök egymásba ágyazhatóak, és egy belső hatókör mindig hozzáfér az őt körülvevő, külső hatókör változóihoz. Miután JavaScriptben egyetlen dologgal lehet -hatóköröket kifejezni, és ez a [funkció](#function.scopes) (bizony az if, try/catch és hasonló blokkok **nem** jelentenek új hatókört, mint pl. a Javaban), az összes funkció closure-ként szerepel. +hatóköröket kifejezni, és ez a [függvény](#function.scopes) (bizony az if, try/catch és hasonló blokkok **nem** jelentenek új hatókört, mint pl. a Javaban), az összes funkció closure-ként szerepel. ### Privát változók emulálása @@ -25,7 +25,7 @@ hatóköröket kifejezni, és ez a [funkció](#function.scopes) (bizony az if, t foo.get(); // 5 Ebben a példában a `Counter` **két** closure-rel tér vissza: az `increment` és -a `get` funkcióval. Mind a két funkció **referenciát** tárol a `Counter` hatókörre, +a `get` függvénnyel. Mind a két függvény **referenciát** tárol a `Counter` hatókörre, és így mindketten hozzáférnek a `count` változóhoz, ami ebben a hatókörben lett definiálva. @@ -46,7 +46,7 @@ létre fogja hozni, vagy felül fogja írni a *globális* `count` változót (wi ### Closure-ök használata ciklusokban -Az egyik leggyakoribb hiba amit el lehet követni, az a closure-ök ciklusokban való használata. +Az egyik leggyakoribb hiba, amit el lehet követni, az a closure-ök ciklusokban való használata. Annak is azon speciális esete amikor a ciklus indexváltozóját szeretnénk lemásolni a closure-ön belül. for(var i = 0; i < 10; i++) { @@ -82,7 +82,7 @@ függvénnyel](#function.scopes). A külső (wrapper) névtelen függvény így azonnal meghívódik az `i` ciklusváltozóval, mint paraméterrel, és így mindig egy másolatot fog kapni az `i` változó **értékéről**, amit ő `e` néven emészt tovább. -Így a `setTimeout`ban lévő névtelen fgv. mindig az `e` nevű referenciára fog mutatni, aminek az értéke így már **nem** változik meg a ciklus futása során. +Így a `setTimeout`ban lévő névtelen függvény mindig az `e` nevű referenciára fog mutatni, aminek az értéke így már **nem** változik meg a ciklus futása során. Egy másik lehetséges út a megoldáshoz az, hogy egy wrapper függvényt visszatérítünk a setTimeoutból, aminek ugyanaz lesz a hatása, mint a fentebbi példának. diff --git a/doc/hu/function/constructors.md b/doc/hu/function/constructors.md index e48e0b60..c955cce1 100644 --- a/doc/hu/function/constructors.md +++ b/doc/hu/function/constructors.md @@ -1,6 +1,6 @@ ## Konstruktorok -Csak úgy mint minden más, a konstruktorok működése szintén különbözik +Csak úgy, mint minden más, a konstruktorok működése szintén különbözik a megszokottól. Itt minden függvényhívás amelyet a `new` kulcsszó előz meg, konstruktor hívásnak számít. @@ -19,7 +19,7 @@ Ha a konstruktor függvényben nincs `return` utasítás, akkor automatikusan a var test = new Foo(); -A fenti kódban a `Foo` függvényt mint konstruktort hívjuk meg, ami a test változóban +A fenti kódban a `Foo` függvényt, mint konstruktort hívjuk meg, ami a test változóban egy új objektumot fog eredményezni. Ennek az objektumnak a `prototípusa` a Foo prototípusa lesz. Trükkös ugyan, de ha mégis van `return` utasítás az éppen konstruált függvényben, akkor @@ -47,12 +47,12 @@ Hogyha kihagyjuk a `new` kulcsszó használatát, a függvény **nem** egy új o } Foo(); // undefined -A [`this`](#function.this) JavaScript beli működésének köszönhetően, mégha le is +A [`this`](#function.this) JavaScript beli működésének köszönhetően, még ha le is fut az előbbi kód, akkor a `this` helyére a *globális objektumot* képzeljük. ### Gyárak (Factory-k) -Ahhoz, hogy teljesen eltudjuk hagyni a `new` kulcsszó használatát, a konstruktor +Ahhoz, hogy teljesen el tudjuk hagyni a `new` kulcsszó használatát, a konstruktor függvény explicit értékkel kell visszatérjen. function Bar() { diff --git a/doc/hu/function/general.md b/doc/hu/function/general.md index 4392060e..9b62b0ee 100644 --- a/doc/hu/function/general.md +++ b/doc/hu/function/general.md @@ -1,7 +1,7 @@ ## Függvény deklarációk és kifejezések A függvények JavaScriptben egyben objektumok is. Ez azt jelenti, hogy -ugyanúgy lehet őket passzolgatni mint bármelyik más értékeket. Ezt a featuret +ugyanúgy lehet őket passzolgatni, mint bármelyik más értékeket. Ezt a featuret gyakran használják arra, hogy egy *névtelen (callback) függvényt* átadjunk egy másik -aszinkron- függvény paramétereként. @@ -9,7 +9,7 @@ egy másik -aszinkron- függvény paramétereként. function foo() {} -Ez a függvény felkerül a scope tetejére ([hoisting](#function.scopes)), mielőtt a kód végrehajtása megtörténne. Így abban a scopeban ahol *definiálták*, *mindenhol* elérhető, +Ez a függvény felkerül a scope tetejére ([hoisting](#function.scopes)), mielőtt a kód végrehajtása megtörténne. Így abban a scope-ban, ahol *definiálták*, *mindenhol* elérhető, még abban a trükkös esetben is, hogyha a kód azon pontján hívjuk ezt a függvényt, mielőtt definiáltuk volna (látszólag). @@ -30,7 +30,7 @@ Habár ebben a példában a `var` deklaráció futás előtt a kód tetejére k ettől függetlenül a foo mint függvény meghívásakor hibát fogunk kapni. Ugyanis a deklaráció felkúszott, azonban az értékadás csak futásidőben fog megtörténni, -addig is a foo változó értéke [undefined](#core.undefined) marad. Az undefinedet pedig hiába hívjuk függvényként, TypeErrort kapunk végeredményül. +addig is a foo változó értéke [undefined](#core.undefined) marad. Az undefinedot pedig hiába hívjuk függvényként, TypeErrort kapunk végeredményül. ### Névvel ellátott függvény kifejezés @@ -41,7 +41,7 @@ Egy másik érdekes eset, amikor névvel ellátott függvényeket adunk érték } bar(); // ReferenceError -Ebben a példában a `bar`t önmagában nem lehet elérni egy külső scopeból (utolsó sor), +Ebben a példában a `bar`t önmagában nem lehet elérni egy külső scope-ból (utolsó sor), mivel egyből értékül adtuk a `foo` változónak. Ennek ellenére a `bar`on belül elérhető a `bar` név. A tanulság az, hogy a függvény önmagát *mindig* eléri a saját scopeján belül, és ez a JavaScriptben található [névfeloldásnak](#function.scopes) köszönhető. diff --git a/doc/hu/function/scopes.md b/doc/hu/function/scopes.md index 71c99902..7e75a0b5 100644 --- a/doc/hu/function/scopes.md +++ b/doc/hu/function/scopes.md @@ -214,8 +214,8 @@ ahhoz hogy meghívhatóak legyenek, először ki kell értékelni őket. ) // a függvény objektum visszatérítése () // az eredmény meghívása -Persze más kifejezések is használhatóak arra hogy kiértékeljük és meghívjuk -a függvény kifejezést, amelyek habár szintaxisukban eltérnek, ugyanazt eredményezik. +Persze más kifejezések is használhatóak arra, hogy kiértékeljük és meghívjuk +a függvény kifejezést, amelyek habár szintaxisukban eltérnek, ugyan azt eredményezik. // Még több stílus anonymus függvények azonnali hívásához... !function(){}() diff --git a/doc/hu/function/this.md b/doc/hu/function/this.md index 938385f4..8c363873 100644 --- a/doc/hu/function/this.md +++ b/doc/hu/function/this.md @@ -1,20 +1,20 @@ ## A `this` mágikus működése -A `this` kicsit másképp működik a JavaScriptben mint ahogy azt megszokhattuk -más nyelvekben. Ugyanis pontosan **ötféle** módja lehet annak hogy a `this` +A `this` kicsit másképp működik a JavaScriptben, mint ahogy azt megszokhattuk +más nyelvekben. Ugyanis pontosan **öt féle** módja lehet annak, hogy a `this` éppen mire utal a nyelvben. ### A Globális hatókör this; -Amikor globális hatókörben van használva a this, akkor pontosan a *globális* objektumra utal. +Amikor globális hatókörben van használva a `this`, akkor pontosan a *globális* objektumra utal. ### Függvény híváskor foo(); -Itt, a `this` megint a *globális* objektumra fog utalni. +Itt a `this` megint a *globális* objektumra fog utalni. > **ES5 Megjegyzés:** Strict módban a globális eset **nem létezik** többé. > Ezekben az esetekben a `this` értéke undefined lesz. @@ -40,7 +40,7 @@ az *újonnan létrehozott* `Objektumra` fog hivatkozni. foo.apply(bar, [1, 2, 3]); // ugyanaz mint egy sorral lejjebb foo.call(bar, 1, 2, 3); // argumentumok: a = 1, b = 2, c = 3 -A `Function.prototype`-ban levő `call` vagy `apply` használatakor aztán elszabadul a pokol :). +A `Function.prototype`-ban levő `call` vagy `apply` használatakor aztán elszabadul a pokol 😀. Ezekben az esetekben ugyanis a this a foo hívásakor **egzaktan** be lesz állítva az apply/call első argumentumára. @@ -63,7 +63,7 @@ praktikus felhasználási módja. // A this itt a globális ojjektum. } test(); - } + }; Gyakori hiba, hogy úgy gondolják a fenti példában az emberek, hogy a `this` a `test` függvényen belül az őt körülvevő `Foo`-ra fog mutatni, pedig **nem**. @@ -77,11 +77,11 @@ lokálisan elhelyezni a `method`-on belül, ami már valóban a kívánt `this`- // Használjuk a that-et a this helyett } test(); - } + }; A `that` tuladjonképpen egy mezei változónév (nem kulcsszó), de sokszor használják arra, -hogy egy másik `this`-re hivatkozzanak vele. A [colsureökkel](#function.closures) kombinálva -ez a módszer arra is használható hogy `this`-eket passzolgassunk a vakvilágban és mégtovább. +hogy egy másik `this`-re hivatkozzanak vele. A [closure-ökkel](#function.closures) kombinálva +ez a módszer arra is használható, hogy `this`-eket passzolgassunk a vakvilágban és még tovább. ### Eljárások értékül adása @@ -107,4 +107,4 @@ ami a nyelv egyik fő erőssége. new Bar().method(); Amikor a `method` meghívódik a `Bar` példányaként, a `this` pontosan a `Bar` -megfelelő példányára fog mutatni. \ No newline at end of file +megfelelő példányára fog mutatni. diff --git a/doc/hu/intro/index.md b/doc/hu/intro/index.md index 911baf61..83bb9b94 100644 --- a/doc/hu/intro/index.md +++ b/doc/hu/intro/index.md @@ -2,7 +2,7 @@ A **JavaScript Garden** egy folytonosan növekvő kódgyűjtemény amely a nyelv kihívást okozó részeit hivatott tisztázni. Itt tanácsokat kaphatsz afelől, hogyan kerüld el a leggyakoribb programozási- valamint nyelvi hibákat, hogyan írj gyorsabb kódot, és mik a legsűrűbben elkövetett *bad practice*k amelyekkel egy átlagos JavaScript programozó (nem) mindennapi útján találkozhat a nyelv megismerése közben. -A JavaScript Gardennek **nem** célja hogy megtanítsa a JavaScript nyelvet! +A JavaScript Gardennek **nem** célja, hogy megtanítsa a JavaScript nyelvet! Az itt felsorolt témák megértéséhez mindenképp szükséges némi tapasztalat. Ha a nyelv alapjait szeretnéd elsajátítani, először nézd át ezt a kiváló [tutorialt][1] a Mozilla Developer Networkön. ## Szerzők diff --git a/doc/hu/object/forinloop.md b/doc/hu/object/forinloop.md index b004e557..642dc265 100644 --- a/doc/hu/object/forinloop.md +++ b/doc/hu/object/forinloop.md @@ -1,13 +1,13 @@ ## A `for in` ciklus -Csak úgy mint a jó öreg `in` operátor, a `for in` is bejárja az egész +Csak úgy, mint a jó öreg `in` operátor, a `for in` is bejárja az egész prototípus láncot, amikor egy objektum mezőin próbálnánk iterálni. > **Megjegyzés:** A `for in` ciklus **nem** fog iterálni azokon a mezőkön, > amelyeknek az `enumerable` tulajdonsága `false`-ra van állítva. Például a > `length` mező nem kerül az iterációba amikor egy tömbön iterálnánk végig. - // Mérgezzük Object.prototypeot! + // Mérgezzük Object.prototype-ot! Object.prototype.bar = 1; var foo = {moo: 2}; @@ -32,10 +32,10 @@ lakó [`hasOwnProperty`](#object.hasownproperty) függvény használatával érh } } -Ez az egyetlen helyes útja annak hogy az objektum saját mezőin iteráljunk csak végig. +Ez az egyetlen helyes útja annak, hogy az objektum saját mezőin iteráljunk csak végig. Mivel a `hasOwnProperty`-t használjuk, így csak a várt `moo`-t fogja kiírni. Tehén jó kódunk van! Hogyha a `hasOwnProperty`-t kihagynánk, a kódunk ki lenne téve nem várt -hibáknak, amik pl. abból fakadnak hogy valaki ocsmányul kiterjesztette az +hibáknak, amik pl. abból fakadnak, hogy valaki ocsmányul kiterjesztette az `Object.prototype`-t. Például, ha a [Prototype][1] frameworköt használjuk, és nem ilyen stílusban írjuk a diff --git a/doc/hu/object/general.md b/doc/hu/object/general.md index 8f396de4..0032e735 100644 --- a/doc/hu/object/general.md +++ b/doc/hu/object/general.md @@ -1,8 +1,8 @@ ## Objektumok és mezők használata -A JavaSciprtben minden objektumként működik, a [`null`](#core.undefined) és az [`undefined`](#core.undefined) kivételével. +A JavaScriptben minden objektumként működik, a [`null`](#core.undefined) és az [`undefined`](#core.undefined) kivételével. - false.toString(); // 'hamis' + false.toString(); // 'false' [1, 2, 3].toString(); // '1,2,3' function Foo(){} @@ -47,11 +47,11 @@ Egy objektum mezői kétféle módon érhetőek el, vagy az 'objektum.mezőnév' foo.1234; // SyntaxError foo['1234']; // működik -A két jelölés majdnem egyenértékűen használható, kivéve, hogy a szögletes zárójelekkel dinamkusan állíthatunk be mezőket és olyan neveket is választhatunk, amik amúgy szintaxis hibához vezetnének (Fordító: mivel a neveket stringbe kell rakni, megadhatunk a JS által "lefoglalt" kulcsszavakat is mezőnévként, habár ennek használata erősen kerülendő). +A két jelölés majdnem egyenértékűen használható, kivéve, hogy a szögletes zárójelekkel dinamikusan állíthatunk be mezőket és olyan neveket is választhatunk, amik amúgy szintaxis hibához vezetnének (Fordító: mivel a neveket stringbe kell rakni, megadhatunk a JS által "lefoglalt" kulcsszavakat is mezőnévként, habár ennek használata erősen kerülendő). ### Mezők törlése -Egyetlen módon lehet mezőt törölni egy objektumból ez pedig a `delete` operátor +Egyetlen módon lehet mezőt törölni egy objektumból, ez pedig a `delete` operátor használata; a mező értékének `undefined`-ra vagy `null`-ra való állítása csak magára az értékre van kihatással, de a kulcs ugyanúgy megmarad az objektumban. @@ -84,7 +84,7 @@ Az objektumok mezőnevei mind stringként, mind egyszerű szövegként (Ford.: a leírhatóak. A JavaScript értelmező hibája miatt, a fenti kód azonban `SyntaxErrort` eredményez ECMAScript 5 előtti verzió esetén. Ez a hiba onnan ered, hogy a `delete` egy *kulcsszó*, viszont érdemes *string literálként* -leírni hogy helyesen megértsék a régebbi JavaScript motorok is. +leírni, hogy helyesen megértsék a régebbi JavaScript motorok is. [1]: http://en.wikipedia.org/wiki/Hashmap diff --git a/doc/hu/object/hasownproperty.md b/doc/hu/object/hasownproperty.md index 46d713e8..245a3287 100644 --- a/doc/hu/object/hasownproperty.md +++ b/doc/hu/object/hasownproperty.md @@ -1,8 +1,8 @@ ## `hasOwnProperty` -Hogy megtudjuk nézni egy adott objektum saját mezőit - azokat a mezőket amelyek +Hogy meg tudjuk nézni egy adott objektum saját mezőit - azokat a mezőket, amelyek az objektumon *közvetlenül* vannak definiálva, és nem valahol a -[prototípus láncon](#object.prototype) -, a `hasOwnProperty` függvényt használata +[prototípus láncon](#object.prototype) -, a `hasOwnProperty` függvény használata ajánlott, amelyet az összes objektum amúgy is örököl az `Object.prototype`-ból. > **Megj.:** Vicces programozók miatt, **nem** biztos hogy elég lesz megnézni hogy @@ -58,4 +58,4 @@ A `hasOwnProperty` használata az **egyetlen** megbízható módszer annak eldö hogy egy mező közvetlenül az objektumon lett-e létrehozva. Melegen ajánlott a `hasOwnProperty`-t **minden** [`for in` ciklusban](#object.forinloop) használni. Használatával ugyanis elkerülhetjük a kontár módon kiegészített natív prototípusokból -fakadó esetleges hibákat, amire példát az imént láttunk. \ No newline at end of file +fakadó esetleges hibákat, amire az imént láttunk példát. \ No newline at end of file diff --git a/doc/hu/object/prototype.md b/doc/hu/object/prototype.md index 2822188e..27a533b4 100644 --- a/doc/hu/object/prototype.md +++ b/doc/hu/object/prototype.md @@ -4,7 +4,7 @@ A JavaScript nem a klasszikus öröklődést használja, hanem egy ún. *protot származtatást használ. Míg ezt gyakran a JavaScript legnagyobb hibái között tartják számon, valójában -ez a származtatási modell jóval kifejezőbb mint klasszikus barátja. +ez a származtatási modell jóval kifejezőbb, mint klasszikus barátja. Ezt jelzi, hogy például sokkal könnyebb megépíteni a klasszikus modellt, alapul véve a prototípusos modellt, míg a fordított irány kivitelezése igencsak nehézkes lenne. @@ -40,7 +40,7 @@ használ. // A kapott prototípus lánc test [instance of Bar] Bar.prototype [instance of Foo] - { foo: 'Hello World' } + { foo: 'Hello World', value: 42 } Foo.prototype { method: ... } Object.prototype @@ -73,7 +73,7 @@ visszatérni. Alapjáraton, a JavaScript a prototype nevű mezőt használja a prototípus láncok kialakításához, de ettől függetlenül ez is ugyanolyan mező mint a többi, és -**bármilyen** értéket belehet neki állítani. Viszont a primitív típusokat egyszerűen +**bármilyen** értéket be lehet neki állítani. Viszont a primitív típusokat egyszerűen figyelmen kívül fogja hagyni a feldolgozó. function Foo() {} @@ -84,9 +84,9 @@ mezőkre és ezeknek az átállításával bele lehet szólni a prototípus lán ### Teljesítmény -Értelemszerűen, minnél nagyobb a prototípus lánc, annál tovább tart egy-egy mező +Értelemszerűen, minél nagyobb a prototípus lánc, annál tovább tart egy-egy mező felkeresése, és ez rossz hatással lehet a kód teljesítményére. Emellett, ha egy -olyan mezőt próbálunk elérni amely nincs az adott objektum példányban, az mindig +olyan mezőt próbálunk elérni, amely nincs az adott objektum példányban, az mindig a teljes lánc bejárását fogja eredményezni. Vigyázat! Akkor is bejárjuk a teljes láncot, amikor egy objektum mezőin próbálunk [iterálni](#object.forinloop). @@ -98,7 +98,7 @@ definiált prototípust próbálunk kiegészíteni új kóddal. Ezt [monkey patching][1]-nek is hívják, és aktívan kerülendő, mivel megtöri az *egységbe zárás* elvét. Habár ezt a technikát olyan népszerű framework-ök -is használják mint a [Prototype][2], ettől függetlenül ne hagyjuk magunkat csőbe húzni; +is használják, mint a [Prototype][2], ettől függetlenül ne hagyjuk magunkat csőbe húzni; nincs ésszerű indok arra, hogy összezavarjuk a beépített típusokat, további *nem standard* saját funkcionalitással. diff --git a/doc/hu/other/timeouts.md b/doc/hu/other/timeouts.md index 36c17e56..7ad37665 100644 --- a/doc/hu/other/timeouts.md +++ b/doc/hu/other/timeouts.md @@ -3,16 +3,16 @@ Mivel a JavaScript aszinkron, a `setTimeout` és `setInterval` használatával lehetséges késleltetni a kódok lefutási idejét. -> **Megjegyzés:** A timeout fv.-ek **nem** részei az ECMAScript Standardnek. +> **Megjegyzés:** A timeout függvények **nem** részei az ECMAScript Standardnek. > Mivel a [DOM][1] részeként lettek implementálva. function foo() {} var id = setTimeout(foo, 1000); // Egy számmal (> 0) tér vissza -Amikor a `setTimeout` függvényt meghívjuk, válaszul egy timeout ID-t kapunk +Amikor a `setTimeout` függvényt meghívjuk, válaszul egy timeout ID-t kapunk, valamint be lesz ütemezve a `foo` függvényhívás, hogy **körülbelül** 1000 miliszekundum múlva fusson le a jövőben. A `foo` **egyszer** lesz végrehajtva. -Az aktuális JavaScript motor időzítésétől függően, és annak figyelembe vételével +Az aktuális JavaScript motor időzítésétől függően, és annak figyelembe vételével, hogy a JavaScript mindig egyszálú, tehát a megelőző kódok blokkolhatják a szálat, **soha** nem lehet biztonságosan meghatározni hogy valóban a kért időzítéssel fog lefutni a kód amit megadtunk a `setTimeout`ban. Erre semmilyen biztosíték nincs. @@ -40,8 +40,8 @@ utal. ### Híváshalmozás a `setInterval`al -Míg a `setTimeout` csak egyszer futtatja le a megadott függvényt, a `setInterval` -- ahogy a neve is mutatja - **minden** `X` miliszekundumban végrehajtja a +Míg a `setTimeout` csak egyszer futtatja le a megadott függvényt, a `setInterval` - +ahogy a neve is mutatja - **minden** `X` miliszekundumban végrehajtja a neki átadott kódot, használata pedig erősen kerülendő. Nagy hátulütője, hogy még akkor is ütemezi az újabb és újabb @@ -62,7 +62,7 @@ futtatása először végzett. ### Hogyan Bánjunk El a Blokkolással -A legkönnyebb és kontrollálhatóbb megoldásnak az bizonyul, hogyha a `setTimeout` +A legkönnyebb és kontrollálhatóbb megoldásnak az bizonyul, ha a `setTimeout` függvényt a rögtön a foo-n belül használjuk. function foo(){ @@ -72,13 +72,13 @@ függvényt a rögtön a foo-n belül használjuk. foo(); Ez nem csak egységbe zárja a `setTimeout` hívást, de meggátolja a felesleges hívások -felhalmozását, és több irányítást ad a kezünkbe. A `foo` így magától eltudja +felhalmozását, és több irányítást ad a kezünkbe. A `foo` így magától el tudja dönteni, hogy akarja-e újra futtatni önmagát vagy sem. ### Timeout Tisztogatás Kézzel A `clearTimeout` vagy `clearInterval` hívással tudjuk a timeoutjainkat -megszüntetni, természetesen attól függ hogy melyiket használjuk, +megszüntetni, természetesen attól függ, hogy melyiket használjuk, hogy melyik `set` függvénnyel indítottuk útjára a timeoutunkat. var id = setTimeout(foo, 1000); @@ -94,7 +94,7 @@ hívás törlésére, ezért bruteforce módszerekhez kell folyamodjunk. clearTimeout(i); } -Persze ez csak véletlenszerű lövöldözés, semmi sem garantálja hogy a fenti +Persze ez csak véletlenszerű lövöldözés, semmi sem garantálja, hogy a fenti módszerrel nem marad timeout a rendszerben (A ford.: például az ezredik timeout vagy afelett). Szóval egy másik módszer ennek megoldására, hogy feltételezzük hogy minden `setTimeout` hívással az azonosítók száma egyel növekszik. @@ -106,8 +106,8 @@ minden `setTimeout` hívással az azonosítók száma egyel növekszik. clearTimeout(i); } -Habár ez a megoldás minden böngészőben megy (egyenlőre), ez az azonosítókról született mondás nincs specifikációban rögzítve, és ennek megfelelően változhat. -Az ajánlott módszer továbbra is az, hogy kövessük nyomon az összes timeout azonosítót amit generáltunk, és így ki is tudjuk őket rendesen törölni. +Habár ez a megoldás minden böngészőben megy (egyelőre), ez az azonosítókról született mondás nincs specifikációban rögzítve, és ennek megfelelően változhat. +Az ajánlott módszer továbbra is az, hogy kövessük nyomon az összes timeout azonosítót, amit generáltunk, és így ki is tudjuk őket rendesen törölni. ### `eval` A Színfalak Mögött @@ -158,7 +158,7 @@ a timeout függvények által meg lesz hívva a későbbiekben. **Soha** ne használjunk stringeket a `setTimeout` vagy `setInterval` első paramétereiként. Ha argumentumokat kell átadni a meghívandó függvénynek, az egyértelműen **rossz** kódra utal. Ebben az esetben a függvényhívás -lebonyolításához egy *anoním* függvény használata ajánlott. +lebonyolításához egy *anonim* függvény használata ajánlott. Továbbá, mivel az ütemező kódja nem blokkolódik a JavaScript futás által, a `setInterval` használata úgy általában kerülendő. diff --git a/doc/hu/types/casting.md b/doc/hu/types/casting.md index b5066ca5..ee604410 100644 --- a/doc/hu/types/casting.md +++ b/doc/hu/types/casting.md @@ -26,14 +26,14 @@ meglepetéseket. ### Natív típusok konstruktorai -A jó hír az, hogy a natív típusok mint a `Number` és a `String` különféle -módon viselkednek hogyha a `new` kulcsszóval avagy anélkül vannak inicializálva. +A jó hír az, hogy a natív típusok, mint a `Number` és a `String` különféle +módon viselkednek, hogy ha a `new` kulcsszóval avagy anélkül vannak inicializálva. new Number(10) === 10; // Hamis, Objektum vs. Szám Number(10) === 10; // Igaz, Szám vs. szám new Number(10) + 0 === 10; // Igaz, az implicit konverziónak hála -Ha egy natív típust mint a `Number` konstruktorként kezelünk, akkor egy új +Ha egy natív típust, mint a `Number` konstruktorként kezelünk, akkor egy új `Number` objektumot kapunk. De ha kihagyjuk a `new` kulcsszót akkor a `Number` egy egyszerű konverter függvényként fog viselkedni. diff --git a/doc/hu/types/equality.md b/doc/hu/types/equality.md index 0b503294..d627e86c 100644 --- a/doc/hu/types/equality.md +++ b/doc/hu/types/equality.md @@ -7,7 +7,7 @@ vizsgálatára Az egyenlőség vizsgálatot végző (egyik) operátort így jelöljük: `==` -A JavaScript egy *gyengén típusos* nyelv. Ez azt jelenti hogy az egyenlőség +A JavaScript egy *gyengén típusos* nyelv. Ez azt jelenti, hogy az egyenlőség operátor **típuskényszerítést** alkalmaz ahhoz, hogy össze tudjon hasonlítani két értéket. @@ -21,9 +21,9 @@ két értéket. null == undefined // igaz " \t\r\n" == 0 // igaz -A fenti táblázat szépen mutatja hogy mi a típuskényszerítés eredménye, és egyben +A fenti táblázat szépen mutatja, hogy mi a típuskényszerítés eredménye, és egyben azt is, hogy miért rossz szokás a `==` használata. Szokás szerint, ez megint -olyan fícsör ami nehezen követhető kódhoz vezethet a komplikált konverziós +olyan fícsör, ami nehezen követhető kódhoz vezethet a komplikált konverziós szabályai miatt. Pláne, hogy a kényszerítés teljesítmény problémákhoz is vezet; ugyanis, mielőtt @@ -34,7 +34,7 @@ a megfelelő típusra. Ez az operátor már **három** egyenlőségjelből áll: `===`. -Ugyanúgy működik mint az előbbi, kivéve hogy ez a változat **nem** alkalmaz +Ugyanúgy működik, mint az előbbi, kivéve hogy ez a változat **nem** alkalmaz típuskényszerítést az operandusai között. "" === "0" // hamis @@ -49,12 +49,12 @@ típuskényszerítést az operandusai között. A felső eredmények sokkal egyértelműbbek és ennek köszönhetően sokkal hamarabb eltörik a kód egy-egy ellenőrzésen. Ettől sokkal hibatűrőbb lesz -a produktumunk, és ráadásul teljesítménybeli gondjaink sem lesznek. +a produktumunk, ráadásul teljesítménybeli gondjaink sem lesznek. ### Objektumok összehasonlítása Habár mind a `==`-t és a `===`-t is egyenlőség operátornak hívjuk, eltérően -viselkednek hogyha legalább az egyik operandusuk egy objektum. +viselkednek, hogy ha legalább az egyik operandusuk egy objektum. {} === {}; // hamis new String('foo') === 'foo'; // hamis diff --git a/doc/hu/types/instanceof.md b/doc/hu/types/instanceof.md index 82f5942d..50dbd489 100644 --- a/doc/hu/types/instanceof.md +++ b/doc/hu/types/instanceof.md @@ -2,7 +2,7 @@ Az `instanceof` operátor a két operandusának konstruktorait hasonlítja össze. Csak akkor bizonyul hasznosnak, amikor saját készítésű objektumokon alkalmazzuk. -Beépített típusokon ugyanolyan hasztalan alkalmazni mint a [typeof operátort](#types.typeof). +Beépített típusokon ugyanolyan hasztalan alkalmazni, mint a [typeof operátort](#types.typeof). ### Saját objektumok összehasonlítása @@ -32,4 +32,4 @@ a böngészőn belül), mivel a konstruktoruk nem pontosan ugyanaz az objektum l ### Összegzésül -Az `instanceof`-ot tehát **csak** megegyező JS kontextusból származó, saját készítésű objektumoknál használjuk. Minden más felhasználása kerülendő, csak úgy mint a [`typeof`](#types.typeof) operátor esetén. \ No newline at end of file +Az `instanceof`-ot tehát **csak** megegyező JS kontextusból származó, saját készítésű objektumoknál használjuk. Minden más felhasználása kerülendő, csak úgy, mint a [`typeof`](#types.typeof) operátor esetén. \ No newline at end of file diff --git a/doc/hu/types/typeof.md b/doc/hu/types/typeof.md index b39070fd..556543dc 100644 --- a/doc/hu/types/typeof.md +++ b/doc/hu/types/typeof.md @@ -5,7 +5,7 @@ lehetőség szerint a JavaScript nyelv egyik legnagyobb buktatója, mivel majdne teljesen **rosszul működik**. Habár az `instanceof`-nak korlátozottan még lehet értelme, a `typeof` operátor -tényleg csak egyetlen praktikus use case-zel rendelkezik és ez **nem** az hogy egy +tényleg csak egyetlen praktikus use case-el rendelkezik és ez **nem** az, hogy egy objektum típusvizsgálatát elvégezzük. > **Megjegyzés:** Mivel a `typeof` vizsgálatot ravaszul úgy is le lehet írni, diff --git a/doc/it/function/constructors.md b/doc/it/function/constructors.md index 45983b2c..1273e87c 100644 --- a/doc/it/function/constructors.md +++ b/doc/it/function/constructors.md @@ -41,7 +41,7 @@ specificato da quell'istruzione, ma **solo** se il valore di ritorno è un name: 'Charles' }; } - new Test(); // l'oggetto ritornato ({name: 'Charles'}), escluso someValue + new Person(); // l'oggetto ritornato ({name: 'Charles'}), escluso someValue Quando la parola chiave `new` viene omessa, la funzione **non** ritornerà un nuovo oggetto. @@ -116,7 +116,7 @@ esso ha alcuni aspetti negativi. 1. Usa più memoria dal momento che gli oggetti creati **non** condividono i metodi di un prototipo. 2. Per poter ereditare, la factory deve copiare tutti i metodi da un altro - oggetto oppure mettere quell'oggetto nel proptotipo del nuovo oggetto. + oggetto oppure mettere quell'oggetto nel prototipo del nuovo oggetto. 3. Perdere la catena di prototipi solo perché si vuole tralasciare la parola chiave `new` è contrario allo spirito del linguaggio. diff --git a/doc/it/function/general.md b/doc/it/function/general.md index f78ef846..9181ad88 100644 --- a/doc/it/function/general.md +++ b/doc/it/function/general.md @@ -3,7 +3,7 @@ Le funzioni in JavaScript sono oggetti di prima classe. Ciò significa che possono essere usate come ogni altro valore. Un uso comune di questa caratteristica è quello di passare una *funzione anonima* come funzione di -callback ad un'altra, possibilmente asincrona, funzione. +callback ad un'altra funzione, possibilmente asincrona. ### La dichiarazione di `function` diff --git a/doc/it/function/scopes.md b/doc/it/function/scopes.md index 812e4fbd..24f6d250 100644 --- a/doc/it/function/scopes.md +++ b/doc/it/function/scopes.md @@ -127,7 +127,7 @@ vicino scope che le racchiude. // le istruzioni var vengono spostate qui var bar, someValue; // di default a 'undefined' - // la dichiarazione function viene spostate qui + // la dichiarazione function viene spostata qui function test(data) { var goo, i, e; // il blocco scope mancante sposta qui queste istruzioni if (false) { diff --git a/doc/it/function/this.md b/doc/it/function/this.md index 5bee4398..258086a3 100644 --- a/doc/it/function/this.md +++ b/doc/it/function/this.md @@ -66,7 +66,7 @@ uso pratico. // this viene impostato all'oggetto globale } test(); - } + }; Una comune credenza è che `this` all'interno di `test` faccia riferimento a `Foo` mentre, invece, **non** è così. @@ -80,7 +80,7 @@ una variabile locale all'interno di `method` che faccia riferimento a `Foo`. // Qui viene usato self invece di this } test(); - } + }; `self` è solo un normale nome di variabile, ma viene comunemente usato come riferimento ad un `this` più esterno. Abbinato alle [closures](#function.closures) @@ -94,7 +94,7 @@ con una funziona anonima // this ora fa riferimento a Foo }.bind(this); test(); - } + }; ### Metodi di asseganzione diff --git a/doc/it/object/prototype.md b/doc/it/object/prototype.md index 4c34fada..8f8111d1 100644 --- a/doc/it/object/prototype.md +++ b/doc/it/object/prototype.md @@ -43,7 +43,7 @@ La prima grande differenza è che l'ereditarietà in JavaScript utilizza le // La catena di prototipi finale test [istanza di Bar] Bar.prototype [istanza di Foo] - { foo: 'Hello World' } + { foo: 'Hello World', value: 42 } Foo.prototype { method: ... } Object.prototype diff --git a/doc/it/types/casting.md b/doc/it/types/casting.md index 743ee317..5da767f0 100644 --- a/doc/it/types/casting.md +++ b/doc/it/types/casting.md @@ -25,7 +25,7 @@ una *conversione di tipo* **ovunque** sia possibile. Per evitare i problemi appena visti, l'uso dell'[operatore di uguaglianza stretta](#types.equality) è **altamente** raccomandato. Sebbene questo eviti molti dei comuni problemi, ci sono ancora -molti ulteriori problemi che possono essere generati dal sistema debolemente +molti ulteriori problemi che possono essere generati dal sistema debolmente tipizzato di JavaScript. ### Costruttori di tipi interni diff --git a/doc/it/types/instanceof.md b/doc/it/types/instanceof.md index 04ba1e93..8ff454f4 100644 --- a/doc/it/types/instanceof.md +++ b/doc/it/types/instanceof.md @@ -34,7 +34,7 @@ esattamente lo stesso oggetto. ### In conclusione -L'operatore `instanceof` dovrebbe essere usto **solo** quando si ha a che fare +L'operatore `instanceof` dovrebbe essere usato **solo** quando si ha a che fare con oggetti personalizzati creati dal programmatore, che provengono dallo stesso contesto JavaScript. Proprio come per l'operatore [`typeof`](#types.typeof), ogni altro tipo di utilizzo dovrebbe essere **evitato**. diff --git a/doc/ja/function/this.md b/doc/ja/function/this.md index 4e6e27aa..88a35390 100644 --- a/doc/ja/function/this.md +++ b/doc/ja/function/this.md @@ -55,7 +55,7 @@ JavaScriptの`this`と名付けられた特殊なキーワードは他のプロ // このファンクションはグローバルオブジェクトに設定される } test(); - } + }; 良くある誤解として`test`の中の`this`が`Foo`を参照しているというものがありますが、そのような事実は**一切**ありません。 @@ -67,7 +67,7 @@ JavaScriptの`this`と名付けられた特殊なキーワードは他のプロ // ここでthisの代わりに使用する } test(); - } + }; `that`は通常の変数名ですが、外部の`this`の参照の為に良く使われます。[クロージャ](#function.closures)と組み合わせる事で`this`の値を渡す事ができるようになります。 diff --git a/doc/ja/object/prototype.md b/doc/ja/object/prototype.md index 4a5ad300..a38ff3f5 100644 --- a/doc/ja/object/prototype.md +++ b/doc/ja/object/prototype.md @@ -33,7 +33,7 @@ JavaScriptはプロトタイプベースが採用されている唯一の広範 // プロトタイプチェーンの結果 test [instance of Bar] Bar.prototype [instance of Foo] - { foo: 'Hello World' } + { foo: 'Hello World', value: 42 } Foo.prototype { method: ... } Object.prototype diff --git a/doc/ko/array/general.md b/doc/ko/array/general.md index 1a665fa3..12f66100 100644 --- a/doc/ko/array/general.md +++ b/doc/ko/array/general.md @@ -25,14 +25,15 @@ JavaScript에서는 배열(Array)도 객체(Object)지만 객체 순회(Iterate) `length` 프로퍼티의 *getter*는 단순히 Array 안에 있는 엘리먼트의 개수를 반환하고 *setter*는 배열을 할당한 수만큼 잘라 버린다. - var foo = [1, 2, 3, 4, 5, 6]; - foo.length = 3; - foo; // [1, 2, 3] + var arr = [1, 2, 3, 4, 5, 6]; + arr.length = 3; + arr; // [1, 2, 3] - foo.length = 6; - foo; // [1, 2, 3] + arr.length = 6; + arr.push(4); + arr; // [1, 2, 3, undefined, undefined, undefined, 4] -현재 크기보다 더 작은 값을 할당하면 배열을 자르지만, 현재 크기보다 더 큰 값을 할당한다고 해서 배열을 늘리진 않는다. +현재 크기보다 더 작은 값을 할당하면 배열을 자른다. 배열의 크기를 증가시키면 드문드문(sparse)한 배열을 생성한다. ### 결론 diff --git a/doc/ko/core/eval.md b/doc/ko/core/eval.md index 528b1883..2a97ebea 100644 --- a/doc/ko/core/eval.md +++ b/doc/ko/core/eval.md @@ -2,26 +2,26 @@ `eval` 함수는 JavaScript 문자열을 지역 스코프에서 실행한다. - var foo = 1; + var number = 1; function test() { - var foo = 2; - eval('foo = 3'); - return foo; + var number = 2; + eval('number = 3'); + return number; } test(); // 3 - foo; // 1 + number; // 1 `eval`함수는 `eval`이라는 이름으로 **직접** 실행할 때에만 지역 스코프에서 실행된다. 그리고 `eval`이라는 이름에 걸맞게 악명또한 높다. - var foo = 1; + var number = 1; function test() { - var foo = 2; - var bar = eval; - bar('foo = 3'); - return foo; + var number = 2; + var copyOfEval = eval; + copyOfEval('number = 3'); + return number; } test(); // 2 - foo; // 3 + number; // 3 어쨌든 `eval`은 사용하지 말아야 한다. eval을 사용하는 99.9%는 사실 eval 없이도 만들수있다. diff --git a/doc/ko/function/arguments.md b/doc/ko/function/arguments.md index 5ea383cb..288928f5 100644 --- a/doc/ko/function/arguments.md +++ b/doc/ko/function/arguments.md @@ -27,22 +27,37 @@ JavaScript의 모든 함수 스코프에는 `arguments`라는 특별한 변수 // 내곡동에 땅이라도 산다. } -또 다른 방법으로는 함수를 랩핑하지 않고, 풀어서 `call`과 `apply`를 함께 사용하는 방법이 있다. (역주: 프로토타입에 있는 method를 호출하기 전에 Foo 객체 안에 있는 method로 한번더 필터링하는 효과가 있다. ) +또 다른 트릭은 `call`과 `apply`를 함께 사용하여 메소드(`this`의 값과 인자들을 사용하는 함수)를 +단지 인자들만 사용하는 일반 함수로 바꾸는 것이다. - function Foo() {} + function Person(first, last) { + this.first = first; + this.last = last; + } - Foo.prototype.method = function(a, b, c) { - console.log(this, a, b, c); + Person.prototype.fullname = function(joiner, options) { + options = options || { order: "western" }; + var first = options.order === "western" ? this.first : this.last; + var last = options.order === "western" ? this.last : this.first; + return first + (joiner || " ") + last; }; - // "method"를 풀어 쓴(unbound) 버전 - // 이 Function의 인자: this, arg1, arg2...argN - Foo.method = function() { - - // 결과: Foo.prototype.method.call(this, arg1, arg2... argN) - Function.call.apply(Foo.prototype.method, arguments); + // "fullname" 메소드의 비결합(unbound) 버전을 생성한다. + // 첫번째 인자로 'first'와 'last' 속성을 가지고 있는 어떤 객체도 사용 가능하다. + // "fullname"의 인자 개수나 순서가 변경되더라도 이 랩퍼를 변경할 필요는 없을 것이다. + Person.fullname = function() { + // 결과: Person.prototype.fullname.call(this, joiner, ..., argN); + return Function.call.apply(Person.prototype.fullname, arguments); }; + var grace = new Person("Grace", "Hopper"); + + // 'Grace Hopper' + grace.fullname(); + + // 'Turing, Alan' + Person.fullname({ first: "Alan", last: "Turing" }, ", ", { order: "eastern" }); + ### 일반 파라미터와 arguments 객체의 인덱스 일반 파라미터와 `arguments` 객체의 프로퍼티는 모두 *getter*와 *setter*를 가진다. diff --git a/doc/ko/function/closures.md b/doc/ko/function/closures.md index 4d7463a6..4e5631fa 100644 --- a/doc/ko/function/closures.md +++ b/doc/ko/function/closures.md @@ -75,3 +75,21 @@ JavaScript에서는 스코프(Scope)를 어딘가에 할당해두거나 참조 } })(i), 1000) } + +즐겨 쓰이는 또 하나의 방법은 `setTimeout` 함수에 세번째 인자를 추가하는 방법이다. +추가된 인자는 콜백 함수에 전달된다. + + for(var i = 0; i < 10; i++) { + setTimeout(function(e) { + console.log(e); + }, 1000, i); + } + +레거시 JS 환경(Internet Explorer 9 이하)은 이 방법을 지원하지 않는다. + +`.bind`를 사용하는 방법도 있다. `.bind`는 `this` 컨텍스트와 인자들을 함수에 결속(bind)시킨다. +아래 코드는 위 코드와 동일하게 동작한다. + + for(var i = 0; i < 10; i++) { + setTimeout(console.log.bind(console, i), 1000); + } diff --git a/doc/ko/function/constructors.md b/doc/ko/function/constructors.md index 1aa6de4a..2b26dc24 100644 --- a/doc/ko/function/constructors.md +++ b/doc/ko/function/constructors.md @@ -6,40 +6,40 @@ JavaScript의 생성자는 다른 언어들과 다르게 `new` 키워드로 호 그리고 생성자에 명시적인 `return` 구문이 없으면 this가 가리키는 객체를 반환한다. - function Foo() { - this.bla = 1; + function Person(name) { + this.name = name; } - Foo.prototype.test = function() { - console.log(this.bla); + Person.prototype.logName = function() { + console.log(this.name); }; - var test = new Foo(); + var sean = new Person(); -위 코드는 `new` 키워드가 실행되는 시점에 `Foo`를 생성자로 호출하고 `Foo.prototype`을 새 객체의 prototype에 할당한다. +위 코드는 `Person`을 생성자로 호출하고 새로 생성된 객체의 `prototype`을 `Person.prototype`으로 설정한다. 아래 코드와 같이 생성자에 명시적인 `return` 문이 있는 경우에는 반환하는 값이 객체인 경우에만 그 값을 반환한다. - function Bar() { - return 2; + function Car() { + return 'ford'; } - new Bar(); // 새 객체를 만들어 반환 + new Car(); // 'ford'가 아닌 새로운 객체를 반환 - function Test() { - this.value = 2; + function Person() { + this.someValue = 2; return { - foo: 1 + name: 'Charles' }; } - new Test(); // 명시한 객체를 반환 + new Person(); // someValue가 포함되지 않은 ({name:'Charles'}) 객체 반환 new 키워드가 없으면 그 함수는 객체를 반환하지 않는다. - function Foo() { - this.bla = 1; // 전역객체에 할당된다. + function Pirate() { + this.hasEyePatch = true; // 전역 객체를 준비! } - Foo(); // undefined + var somePirate = Pirate(); // somePirate = undefined 위 예제는 그때그때 다르게 동작한다. 그리고 [`this`](#function.this) 객체의 동작 원리에 따라서 Foo 함수안의 `this`의 값은 *Global 객체*를 가리키게된다. (역주: 결국 new 키워드를 빼고, 코드를 작성할 경우 원치 않은 this 참조 오류가 발생할 수 있다.) @@ -48,24 +48,24 @@ new 키워드가 없으면 그 함수는 객체를 반환하지 않는다. 생성자가 객체를 반환하면 `new` 키워드를 생략할 수 있다. - function Bar() { - var value = 1; + function Robot() { + var color = 'gray'; return { - method: function() { - return value; + getColor: function() { + return color; } } } - Bar.prototype = { - foo: function() {} + Robot.prototype = { + someFunction: function() {} }; - new Bar(); - Bar(); + new Robot(); + Robot(); -new 키워드의 유무과 관계없이 `Bar` 생성자의 동작은 동일한다. 즉 [클로저](#function.closures)가 할당된 method 프로퍼티가 있는 새로운 객체를 만들어 반환한다. +new 키워드의 유무과 관계없이 `Robot` 생성자의 동작은 동일하다. 즉 [클로저](#function.closures)가 할당된 method 프로퍼티가 있는 새로운 객체를 만들어 반환한다. -`new Bar()`로 호출되는 생성자는 반환되는 객체의 prototype 프로퍼티에 아무런 영향을 주지 않는다. 객체를 반환하지 않는 생성자로 만들어지는 경우에만 객체의 prototype이 생성자의 것으로 할당된다. +`new Robot()`으로 호출되는 생성자는 반환되는 객체의 prototype 프로퍼티에 아무런 영향을 주지 않는다. 객체를 반환하지 않는 생성자로 만들어지는 경우에만 객체의 prototype이 생성자의 것으로 할당된다. 그러니까 이 예제에서 `new` 키워드의 유무는 아무런 차이가 없다. (역주: 생성자에 객체를 만들어 명시적으로 반환하면 new 키워드에 관계없이 잘 동작하는 생성자를 만들수있다. 즉, new 키워드가 빠졌을때 발생하는 this 참조 오류를 방어해준다.) @@ -76,19 +76,21 @@ new 키워드의 유무과 관계없이 `Bar` 생성자의 동작은 동일한 객체를 만들고 반환해주는 팩토리를 사용하여 `new` 키워드 문제를 회피할 수 있다. - function Foo() { - var obj = {}; - obj.value = 'blub'; + function CarFactory() { + var car = {}; + car.owner = 'nobody'; - var private = 2; - obj.someMethod = function(value) { - this.value = value; + var milesPerGallon = 2; + + car.setOwner = function(newOwner) { + this.owner = newOwner; } - obj.getPrivate = function() { - return private; + car.getMPG = function() { + return milesPerGallon; } - return obj; + + return car; } `new` 키워드가 없어도 잘 동작하고 [private 변수](#function.closures)를 사용하기도 쉽다. 그렇지만, 단점도 있다. diff --git a/doc/ko/function/scopes.md b/doc/ko/function/scopes.md index 7792ee65..b94dc10e 100644 --- a/doc/ko/function/scopes.md +++ b/doc/ko/function/scopes.md @@ -1,4 +1,4 @@ - ## 스코프와 네임스페이스 +## 스코프와 네임스페이스 JavaScript는 '{}' Block이 배배 꼬여 있어도 문법적으로는 잘 처리하지만, Block Scope은 지원하지 않는다. 그래서 JavaScript에서는 항상 *함수 스코프*를 사용한다. diff --git a/doc/ko/function/this.md b/doc/ko/function/this.md index b6d57aa6..0ad51ad9 100644 --- a/doc/ko/function/this.md +++ b/doc/ko/function/this.md @@ -51,23 +51,33 @@ Global Scope에서도 this가 사용될 수 있고 이때에는 *Global* 객체 // 여기에서 this는 Global 객체를 가리킨다. } test(); - } + }; `test` 에서 `this`가 `Foo`를 가리킬 것으로 생각할 테지만 틀렸다. 실제로는 그렇지 않다. `test`에서 `Foo`에 접근하려면 method에 Local 변수를 하나 만들고 `Foo`를 가리키게 하여야 한다. Foo.method = function() { - var that = this; + var self = this; function test() { - // 여기에서 this 대신에 that을 사용하여 Foo에 접근한다. + // 여기에서 this 대신에 self를 사용하여 Foo에 접근한다 } test(); - } + }; -`that`은 this에 접근하기 위해 만든 변수다. [closures](#function.closures)와 함께 `this`의 값을 넘기는 데 사용할 수 있다. +`self`는 통상적인 변수 이름이지만, 바깥쪽의 `this`를 참조하기 위해 일반적으로 사용된다. +또한 [클로저](#function.closures)와 결합하여 `this`의 값을 주고 받는 용도로 사용할 수도 있다. -### Method할당 하기 +ECMAScript 5부터는 익명 함수와 결합된 `bind` 메소드를 사용하여 같은 결과를 얻을 수 있다. + + Foo.method = function() { + var test = function() { + // this는 이제 Foo를 참조한다 + }.bind(this); + test(); + }; + +### Method 할당하기 JavaScript의 또다른 함정은 바로 함수의 별칭을 만들수 없다는 점이다. 별칭을 만들기 위해 메소드를 변수에 넣으면 자바스크립트는 별칭을 만들지 않고 바로 *할당*해 버린다. diff --git a/doc/ko/object/prototype.md b/doc/ko/object/prototype.md index 9e8ffb2a..606d8105 100644 --- a/doc/ko/object/prototype.md +++ b/doc/ko/object/prototype.md @@ -31,7 +31,7 @@ Javascript는 클래스 스타일의 상속 모델을 사용하지 않고 *프 // 결과적으로 만들어진 프로토타입 체인은 다음과 같다. test [instance of Bar] Bar.prototype [instance of Foo] - { foo: 'Hello World' } + { foo: 'Hello World', value: 42 } Foo.prototype { method: ... } Object.prototype diff --git a/doc/language.json b/doc/language.json index af707fb6..df12ab7d 100644 --- a/doc/language.json +++ b/doc/language.json @@ -1,4 +1,4 @@ { "default": "en", - "listed": ["en","es","fi","fr","hu","it","ja","ko","pl","ptbr","ru","tr","zh","zhtw"] -} + "listed": ["by","en","es","fi","fr","hu","it","ja","ko","pl","ptbr","ru","tr","zh","zhtw"] +} diff --git a/doc/pl/function/this.md b/doc/pl/function/this.md index 3819cac7..adf7e1d0 100644 --- a/doc/pl/function/this.md +++ b/doc/pl/function/this.md @@ -63,7 +63,7 @@ w praktyce. // 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**. @@ -77,7 +77,7 @@ metody lokalnej zmiennej, która będzie wskazywała na `Foo`. // 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)](#function.closures), diff --git a/doc/pl/object/prototype.md b/doc/pl/object/prototype.md index c538ee8a..3cabc20e 100644 --- a/doc/pl/object/prototype.md +++ b/doc/pl/object/prototype.md @@ -41,14 +41,14 @@ tak zwanych *łańcuchów prototypów*. // The resulting prototype chain test [instance of Bar] Bar.prototype [instance of Foo] - { foo: 'Hello World' } + { foo: 'Hello World', value: 42 } 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`, +`Bar.prototype` i `Foo.prototype`, 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 jedyną instancją `Foo` i stała się jego prototypem. Należy pamiętać, że `new Bar` **nie** tworzy nowej instancji `Foo`, diff --git a/doc/ptbr/core/eval.md b/doc/ptbr/core/eval.md index 0579953d..e7608cd9 100644 --- a/doc/ptbr/core/eval.md +++ b/doc/ptbr/core/eval.md @@ -11,8 +11,8 @@ A função `eval` executará uma string de código JavaScript no escopo local. test(); // 3 foo; // 1 -Entreranto, `eval` somente é executado no escopo local quando é chamado diretamente -*e* quanto o nome da função chamada é `eval`. +Entretanto, `eval` somente é executado no escopo local quando é chamado diretamente +*e* quando o nome da função chamada é `eval`. var foo = 1; function test() { @@ -40,6 +40,6 @@ Ele **nunca** deve ser utilizado com strings de origens duvidosas ou desconhecid ### Conclusão `eval` nunca deve ser utilizado. Qualquer código que faça uso de `eval` seve ser questionado -em sua utilizade, performance e segurança. Se algo necessita de `eval` para funcionar, então **não** deve ser utilizado. +em sua utilidade, performance e segurança. Se algo necessita de `eval` para funcionar, então **não** deve ser utilizado. Um *design melhor* deve ser utilizado, um que não faça uso de `eval`. diff --git a/doc/ptbr/core/semicolon.md b/doc/ptbr/core/semicolon.md index 38375017..843d7db4 100644 --- a/doc/ptbr/core/semicolon.md +++ b/doc/ptbr/core/semicolon.md @@ -2,7 +2,7 @@ Apesar do JavaScript possuir uma sintaxe no estilo C, o uso do ponto e vírgula **não** é obrigatório. -JavaScript não é uma linguagem 'semicolon-less'. De fato, o ponto e vírgula é necessário para o interpretação do código. Entretanto, o parser do JavaScript insere o **automaticamente** ponto e vírgula sempre que ocorrer um error de parser, decorrente da falta do ponto e vírgula. +JavaScript não é uma linguagem 'semicolon-less'. De fato, o ponto e vírgula é necessário para o interpretação do código. Entretanto, o parser do JavaScript insere o **ponto e vírgula** automaticamente sempre que ocorrer um error de parser, decorrente da falta do ponto e vírgula. var foo = function() { } // parse error, semicolon expected @@ -96,11 +96,5 @@ As chances de `log` não retornar uma função são **muito** altas; portanto, o ### Conclusão -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. - É **fortemente** recomendado que nunca se omita o ponto e vírgula. Também é recomendado que chaves sejam mantidas na mesma linha que seus statements e que nunca sejam omitadas em declações de uma só linha como `if` / `else` statements. Tais medidas não somente melhorarão a consistência do código, como também irão previnir alteração no comportamento do código por má interpretação do parser do JavaScript. diff --git a/doc/ptbr/core/undefined.md b/doc/ptbr/core/undefined.md index 463a9618..cbaedcc6 100644 --- a/doc/ptbr/core/undefined.md +++ b/doc/ptbr/core/undefined.md @@ -28,10 +28,10 @@ Aqui estão alguns exemplos de quando o valor `undefined` é retornado: ### Manipulando mudanças no valor de `undefined` -Uma que a variável global `undefined` apenas mantém uma cópia do valor *atual* de `undefined`, atribuir-lhe +Uma vez que a variável global `undefined` apenas mantém uma cópia do valor *atual* de `undefined`, atribuir-lhe um novo valor **não** muda o valor do tipo `undefined`. -Ainda, a fim de comparar alguma coisa com o valor de `undefined`, é ncessário que +Ainda, a fim de comparar alguma coisa com o valor de `undefined`, é necessário que primeiro se retorne o `undefined`. A fim de proteger o código contra uma possível sobrescrtia da variável `undefined`, uma @@ -54,7 +54,7 @@ Outra maneira de atingir o mesmo efeito seria utilizar uma declaração dentro d })('Hello World', 42); -A única diferença aqui é a que a última versão resulta na redução de 4 bytes, e nã existe +A única diferença aqui é a que a última versão resulta na redução de 4 bytes, e não existe outro `var` statement dentro do wrapper anônimo. ### Usos do `null` diff --git a/doc/ptbr/function/arguments.md b/doc/ptbr/function/arguments.md index 099ecf02..33c3214f 100644 --- a/doc/ptbr/function/arguments.md +++ b/doc/ptbr/function/arguments.md @@ -1,6 +1,6 @@ ## O objeto `arguments` -Todo escopo de uma função em JavaScript em acesso à variável especial `arguments`. +Todo escopo de uma função em JavaScript tem acesso à variável especial `arguments`. Esta variável armazena uma lista de todos os argumentos que foram passados para a função. > **Nota:** No caso em que `arguments` tenha sido definido dentro do escopo da função por meio @@ -12,7 +12,7 @@ e é de fato um `Object`. Devido a isto, **não** é possível usar os métodos padrões de array como `push`, `pop` ou `slice` no `arguments`. Enquanto que a iteração com um simples `for` loop funciona bem, -é necessário convertê-lo para um `Array` a fim de usar os métodos padrões de `Array`. +é necessário convertê-lo para um `Array` a fim de usar os métodos padrões de `Array`. ### Convertendo em um Array @@ -96,10 +96,7 @@ em engines modernas de JavaScript. Este caso é o uso de `arguments.callee` foo(); // Would normally be inlined... } } - -No código acima, `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. + Isto não somente acaba com possíveis ganhos de performance que resultariam de inlining, mas também quebram o encapsulamento pois a função agora depende de uma chamada específica de contexto. diff --git a/doc/ptbr/function/this.md b/doc/ptbr/function/this.md index 6f8c45d9..daacb9a9 100644 --- a/doc/ptbr/function/this.md +++ b/doc/ptbr/function/this.md @@ -61,7 +61,7 @@ como um engano de concepção da linguagem, já que **nunca** se mostrou útil. // this referencia o objeto global } test(); - } + }; Um erro comum é achar que `this` dentro de `test` referencia `Foo`; enquanto que, na realidade **não é isto que acontece**. @@ -75,7 +75,7 @@ uma variável global dentro do método para se referir à `Foo`. // Utilize that no lugar de this aqui } test(); - } + }; `that` trata-se de uma variável normal, porém é normalmente utilizada para referências externas de `this`. Quando combinadas com [closures](#function.closures), também podem ser utilizadas para repassar `this` como valor. diff --git a/doc/ptbr/object/forinloop.md b/doc/ptbr/object/forinloop.md index fc35f5b2..e3e09efa 100644 --- a/doc/ptbr/object/forinloop.md +++ b/doc/ptbr/object/forinloop.md @@ -31,7 +31,7 @@ Esta é única forma correta de usar. Devido ao uso de `hasOwnProperty`, o exemp Um framework largamente utilizado que estende o `Object.prototype` é [Prototype][1]. Quando este framework é utilizado, laços `for in` que não utilizam -`hasOwnProperty` ficam protegidos contra erros. +`hasOwnProperty` ficam desprotegidos contra erros. ### Conclusão diff --git a/doc/ptbr/object/general.md b/doc/ptbr/object/general.md index a5e88626..12452e7f 100644 --- a/doc/ptbr/object/general.md +++ b/doc/ptbr/object/general.md @@ -14,7 +14,7 @@ Um equívoco muito comum é a idéia de que números não podem ser manipulados 2.toString(); // raises SyntaxError -Existem duas soluções para contornar este problema e permtir que números se comportem como objetos. +Existem três soluções para contornar este problema e permtir que números se comportem como objetos. 2..toString(); // o segundo ponto é reconhecido corretamente 2 .toString(); // perceba o espaço deixado à esquerda do ponto diff --git a/doc/ptbr/object/hasownproperty.md b/doc/ptbr/object/hasownproperty.md index 2ff0589f..858e052c 100644 --- a/doc/ptbr/object/hasownproperty.md +++ b/doc/ptbr/object/hasownproperty.md @@ -27,7 +27,7 @@ em outro lugar na cadeia prototype. ### `hasOwnProperty` como propriedade -JavaScript não protege o nome do propriedade `hasOwnProperty`; assim, se +JavaScript não protege o nome da propriedade `hasOwnProperty`; assim, se existe a possibilidade de algum objeto possuir uma propriedade com este mesmo nome, torna-se necessário utilizar um `hasOwnProperty` **externo** a fim de obter resultados corretos. @@ -50,7 +50,7 @@ torna-se necessário utilizar um `hasOwnProperty` **externo** a fim de obter res ### Conclusão -O método é a **única** maneira confiável `hasOwnProperty` para verificar a existência da propriedade em um objeto. +O método `hasOwnProperty` é a **única** maneira confiável para verificar a existência da propriedade em um objeto. É recomendado que `hasOwnProperty` seja utilizado em **cada** interação de um [laço `for in`](#object.forinloop) a fim de evitar erros de extensão do [prototype](#object.prototype). diff --git a/doc/ptbr/object/prototype.md b/doc/ptbr/object/prototype.md index a44bb25e..c9411640 100644 --- a/doc/ptbr/object/prototype.md +++ b/doc/ptbr/object/prototype.md @@ -37,7 +37,7 @@ A primeira grande diferença é que herança em JavaScript utiliza o conceito de // A cadeia prototype resultante test [instance of Bar] Bar.prototype [instance of Foo] - { foo: 'Hello World' } + { foo: 'Hello World', value: 42 } Foo.prototype { method: ... } Object.prototype diff --git a/doc/ptbr/other/timeouts.md b/doc/ptbr/other/timeouts.md index 8d522c4e..74ec2081 100644 --- a/doc/ptbr/other/timeouts.md +++ b/doc/ptbr/other/timeouts.md @@ -13,7 +13,7 @@ Quando `setTimeout` é chamado, ele retorna o ID do timeout e agenda a execuçã para **aproximadamente** mil milissegundos no futuro. `foo` será executado uma **única** vez. -Dependendo de como a enine JavaScript que está rodando o código resolve o timer, bem como +Dependendo de como a engine JavaScript que está rodando o código resolve o timer, bem como o fato de que o JavaScript é single threaded e outro código que é executado pode bloquear a thread, **não há como** garantir a precisão dos intervalos especificados nas chamadas `setTimeout`. @@ -44,7 +44,7 @@ o nome sugere - irá executar a função a **cada** `X` milisegundos, porém se desencorajado. Quando um código em execução bloqueia a chamada do timeout, `setInterval` continuará -emitindo chamads para a função em questão. Isto pode, especialmente com intervalos curtos, +emitindo chamadas para a função em questão. Isto pode, especialmente com intervalos curtos, resultar em uma pilha de chamadas de função. function foo(){ @@ -129,7 +129,7 @@ Esta funcionalidade **nunca** deve ser utilizada pois internamente faz uso de `e Uma vez que `eval` não é chamado [diretamente](#core.eval) neste caso, a string passada como argumento para `setTimeout` será executada no *escopo global*; assim, ela -não usará a variávle local `foo` do escopo de `bar`. +não usará a variável local `foo` do escopo de `bar`. Também é recomendado **não** usar uma string para passar argumentos para a função que será chamada por qualquer uma das funções de timeout. diff --git a/doc/ru/array/constructor.md b/doc/ru/array/constructor.md index 0bfec314..13f58846 100644 --- a/doc/ru/array/constructor.md +++ b/doc/ru/array/constructor.md @@ -15,7 +15,7 @@ arr[1]; // не определён, undefined 1 in arr; // false, индекс не был установлен -Поведение, которое позволяет изначально установить только размер массива, может пригодиться лишь в нескольких случаях, таких как повторение строк, за счёт чего избегается использование цикла `for loop`. +Поведение, которое позволяет изначально установить только размер массива, может пригодиться лишь в нескольких случаях, таких как повторение строк, за счёт чего избегается использование цикла `for`. new Array(count + 1).join(stringToRepeat); diff --git a/doc/ru/function/constructors.md b/doc/ru/function/constructors.md index 33f62bf2..7a322aff 100644 --- a/doc/ru/function/constructors.md +++ b/doc/ru/function/constructors.md @@ -70,7 +70,7 @@ ### Создание объектов с использованием фабрик -Часто рекомендуют **не** использовать `new`, поскольку если вы его забудете, это может привести к ошибкам. +Часто **не** рекомендуют использовать `new`, поскольку если вы его забудете, это может привести к ошибкам. Чтобы создать новый объект, лучше использовать фабрику и создать новый объект *внутри* этой фабрики. @@ -89,13 +89,13 @@ return obj; } -Хотя данный пример и сработает, если вы забыли ключевое слово `new` и благодаря ему легче работать с [приватными переменными](#function.closures), у него есть несколько недостатков +Хотя данный пример и сработает, если вы забыли ключевое слово `new`, и благодаря ему легче работать с [приватными переменными](#function.closures), у него есть несколько недостатков 1. Он использует больше памяти, поскольку созданные объекты **не** хранят методы в прототипе и соответственно для каждого нового объекта создаётся копия каждого метода. 2. Чтобы эмулировать наследование, фабрике нужно скопировать все методы из другого объекта или установить прототипом нового объекта старый. - 3. Разрыв цепочки прототипов просто по причине забытого ключевого слова `new` идёт в разрез с духом языка. + 3. Разрыв цепочки прототипов просто по причине забытого ключевого слова `new` идёт вразрез с духом языка. ### Заключение -Хотя забытое ключевое слово `new` и может привести к багам, это точно **не** причина отказываться от использования прототипов. В конце концов, полезнее решить какой из способов лучше совпадает с требованиями приложения: очень важно выбрать один из стилей создания объектов и после этого **не изменять** ему. +Хотя забытое ключевое слово `new` и может привести к багам, это точно **не** причина отказываться от использования прототипов. В конце концов, полезнее решить, какой из способов лучше совпадает с требованиями приложения: очень важно выбрать один из стилей создания объектов и после этого **не изменять** ему. diff --git a/doc/ru/function/scopes.md b/doc/ru/function/scopes.md index 8883e3f7..0cf88caa 100644 --- a/doc/ru/function/scopes.md +++ b/doc/ru/function/scopes.md @@ -73,9 +73,9 @@ В то время как `foo` и `i` — локальные переменные в области видимости функции `test`, присвоение `bar` переопределит значение одноимённой глобальной переменной. -### Высасывание +### Всплытие -JavaScript **высасывает** определения. Это значит, что оба определения с использованием `var` и определение `function` будут перенесены наверх заключающей их области видимости. +В JavaScript действует механизм **всплытия** определения. Это значит, что оба определения с использованием `var` и определение `function` будут перенесены наверх заключающей их области видимости. bar(); var bar = function() {}; @@ -116,16 +116,16 @@ JavaScript **высасывает** определения. Это значит, bar(); // вылетает с ошибкой TypeError, // поскольку bar всё ещё 'undefined' - someValue = 42; // присвоения не подвержены высасыванию + someValue = 42; // присвоения не подвержены всплытию bar = function() {}; test(); Потерянная область видимости блока не только переместит операторы `var` вовне циклов и их тел, но и сделает результаты некоторых конструкций с `if` неинтуитивными. -В исходном коде оператор `if` изменял *глобальную переменную* `goo`, когда, как оказалось, он изменяет *локальную переменную* — в результате работы высасывания. +В исходном коде оператор `if` изменял *глобальную переменную* `goo`, когда, как оказалось, он изменяет *локальную переменную* — в результате работы всплытия. -Если вы не знакомы с *высасываниями*, то можете посчитать, что нижеприведённый код должен породить +Если вы не знакомы со *всплытием*, то можете посчитать, что нижеприведённый код должен породить `ReferenceError`. // проверить, проинициализована ли SomeImportantThing @@ -162,7 +162,7 @@ JavaScript **высасывает** определения. Это значит, ### Пространства имён -Нередкое последствие наличия только одного глобального пространства имён — проблемы с перекрытием имён переменных. В JavaScript эту проблему легко избежать, используя *анонимные обёртки*. +Нередкое последствие наличия только одного глобального пространства имён — проблема с перекрытием имён переменных. В JavaScript эту проблему легко избежать, используя *анонимные обёртки*. (function() { // самостоятельно созданное "пространство имён" diff --git a/doc/ru/function/this.md b/doc/ru/function/this.md index d50f9403..6883a546 100644 --- a/doc/ru/function/this.md +++ b/doc/ru/function/this.md @@ -51,7 +51,7 @@ // this ссылается на глобальный объект } test(); - } + }; Распространенным заблуждением будет то, что `this` внутри `test` ссылается на `Foo`, но это **не так**. @@ -63,7 +63,7 @@ // Здесь используем that вместо this } test(); - } + }; Подходящее имя для переменной - `that`, его часто используют для ссылки на внешний `this`. В комбинации с [замыканиями](#function.closures) `this` можно пробрасывать в глобальную область или в любой другой объект. diff --git a/doc/ru/object/forinloop.md b/doc/ru/object/forinloop.md index 0b097259..3bc5c8d4 100644 --- a/doc/ru/object/forinloop.md +++ b/doc/ru/object/forinloop.md @@ -25,7 +25,7 @@ } } -Это единственная версия правильного использования цикла. Благодаря использованию `hasOwnPropery` будет выведено **только** свойство `moo`. Если же убрать `hasOwnProperty`, код становится нестабилен и могут возникнуть ошибки, особенно если кто-то изменил встроенные прототипы, такие как `Object.prototype`. +Это единственная версия правильного использования цикла. Благодаря использованию `hasOwnProperty` будет выведено **только** свойство `moo`. Если же убрать `hasOwnProperty`, код становится нестабилен и могут возникнуть ошибки, особенно если кто-то изменил встроенные прототипы, такие как `Object.prototype`. Один из самых популярных фреймворков [Prototype][1] как раз этим и славится, и если вы его подключаете, то не забудьте использовать `hasOwnProperty` внутри цикла `for in`, иначе у вас гарантированно возникнут проблемы. diff --git a/doc/ru/object/general.md b/doc/ru/object/general.md index 9490570f..aa5ad534 100644 --- a/doc/ru/object/general.md +++ b/doc/ru/object/general.md @@ -73,7 +73,7 @@ var test = { 'case': 'Я — ключевое слово, поэтому меня надо записывать строкой', - delete: 'Я тоже ключевое слово, так что я' // бросаю SyntaxError + delete: 'Я тоже ключевое слово, так что я' // не является ошибкой, бросает SyntaxError только в версиях ECMAScript ниже 5ой версии }; Свойства объектов могут записываться как явно символами, так и в виде закавыченных строк. В связи с другим упущением в парсере JavaScript, этот код выбросит `SyntaxError` во всех версиях ранее ECMAScript 5. diff --git a/doc/ru/object/hasownproperty.md b/doc/ru/object/hasownproperty.md index d46d7f10..89b950ca 100644 --- a/doc/ru/object/hasownproperty.md +++ b/doc/ru/object/hasownproperty.md @@ -16,7 +16,7 @@ foo.hasOwnProperty('bar'); // false foo.hasOwnProperty('goo'); // true -Только используя `hasOwnProperty` можно гарантировать правильный результат при переборе свойств объекта. И **нет** иного способа для определения свойств, которые определены в *самом* объекте, а не где-то в цепочке его прототипов. +Только используя `hasOwnProperty` можно гарантировать правильный результат при переборе свойств объекта. И **нет** иного способа для определения свойств, которые определены в *самом* объекте, а не где-то в цепочке его прототипов. ### `hasOwnProperty` как свойство @@ -38,4 +38,3 @@ JavaScript **не** резервирует свойство с именем `has ### Заключение **Единственным** способом проверить существование свойства у объекта является использование метода `hasOwnProperty`. При этом рекомендуется использовать этот метод в **каждом** [цикле `for in`](#object.forinloop) вашего проекта, чтобы избежать возможных ошибок с ошибочным заимствованием свойств из [прототипов](#object.prototype) родительских объектов. Также вы можете использовать конструкцию `{}.hasOwnProperty.call(...)` на случай, если кто-то вздумает расширить [прототипы](#object.prototype) встроенных объектов. - diff --git a/doc/ru/object/prototype.md b/doc/ru/object/prototype.md index 7ae8ed99..a8e75129 100644 --- a/doc/ru/object/prototype.md +++ b/doc/ru/object/prototype.md @@ -10,17 +10,19 @@ > **Замечание:** В результате выполнения конструкции `Bar.prototype = Foo.prototype` оба объекта будут делить друг с другом **один и тот же** прототип. Так что изменение прототипа одного из объектов повлечёт за собой изменение прототипа другого и наоборот — вряд ли это окажется тем, чего вы ожидали. +> **Замечание:** Для объявления наследования вместо `Bar.prototype = Object.create(Foo.prototype)` можно воспользоваться конструкций `Bar.prototype = new Foo()`, но у нее есть пару недостатков: 1) как правило требуется унаследовать только методы и свойства прототипа, а не создавать для этого новый объект; 2) создание объекта может требовать обязательные аргументы. + +> **Примечание:** Метод `Object.create` отсутствует в IE8 и ниже, но его легко реализовать созданием своей такой функции или же можно подключить библиотеку для поддержки старых IE [*es5-shim*][5] + function Foo() { this.value = 42; } - Foo.prototype = { - method: function() {} - }; + Foo.prototype.method = function() {} function Bar() {} - // Установим значением прототипа Bar новый экземпляр Foo - Bar.prototype = new Foo(); + // Зададим наследование от Foo + Bar.prototype = Object.create(Foo.prototype); Bar.prototype.foo = 'Hello World'; // Убедимся, что Bar является действующим конструктором @@ -31,7 +33,7 @@ // Цепочка прототипов, которая получится в результате test [instance of Bar] Bar.prototype [instance of Foo] - { foo: 'Hello World' } + { foo: 'Hello World', value: 42 } Foo.prototype { method: ... } Object.prototype @@ -81,4 +83,5 @@ [2]: http://en.wikipedia.org/wiki/Monkey_patch [3]: http://prototypejs.org/ [4]: https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/forEach +[5]: https://github.com/es-shims/es5-shim diff --git a/doc/tr/function/scopes.md b/doc/tr/function/scopes.md index d826f1aa..211c45f7 100644 --- a/doc/tr/function/scopes.md +++ b/doc/tr/function/scopes.md @@ -178,7 +178,7 @@ adında bir özel değişken tanımlanmıştır, bu değişken *geçerli nesneyi Fonksiyon kapsamlarında aynı zamanda [`arguments`](#function.arguments) adında bir değişken tanımlanmıştır ve fonksiyonun argümanlarını içerir. -Örnek olarak bir fonksiyon kapsamında `foo` değişkenine eriğildiğinde JavaScript +Örnek olarak bir fonksiyon kapsamında `foo` değişkenine erişildiğinde JavaScript isim çözümlemeyi aşağıdaki sıra ile yapacaktır: 1. Geçerli kapsamda bir `var foo` ifadesi mevcutsa bu kullanılır. diff --git a/doc/tr/function/this.md b/doc/tr/function/this.md index de24190a..b589dc42 100644 --- a/doc/tr/function/this.md +++ b/doc/tr/function/this.md @@ -65,7 +65,7 @@ kullanılımı yoktur. // this genel nesneye işaret eder } test(); - } + }; Bir başka yanılgı `test` fonksiyonunun içinde `this` 'in `Foo` 'ya işaret edeceğinin sanılmasıdır, ama bu **doğru değildir**. @@ -79,7 +79,7 @@ değişken oluşturmaktır. // Burada this yerine that kullanın } test(); - } + }; `that` kelimesinin dilde özel bir anlamı yoktur, ama sıklıkla dış kapsamdaki `this` 'e işaret etmek için kullanılır. Bu yöntem [`closure`](#function.closures) diff --git a/doc/tr/object/prototype.md b/doc/tr/object/prototype.md index 1a2d09a1..d8b8522a 100644 --- a/doc/tr/object/prototype.md +++ b/doc/tr/object/prototype.md @@ -39,7 +39,7 @@ yapılmasıdır. // Sonuçta ortaya çıkan prototip zinciri test [bir Bar sınıfı nesnesi] Bar.prototype [bir Foo sınıfı nesnesi] - { foo: 'Hello World' } + { foo: 'Hello World', value: 42 } Foo.prototype { method: ... } Object.prototype diff --git a/doc/zh/function/arguments.md b/doc/zh/function/arguments.md index d6f7f9db..ac6967eb 100755 --- a/doc/zh/function/arguments.md +++ b/doc/zh/function/arguments.md @@ -9,7 +9,7 @@ JavaScript 中每个函数内都能访问一个特别变量 `arguments`。这个 `arguments` 变量**不是**一个数组(`Array`)。 尽管在语法上它有数组相关的属性 `length`,但它不从 `Array.prototype` 继承,实际上它是一个对象(`Object`)。 -因此,无法对 `arguments` 变量使用标准的数组方法,比如 `push`, `pop` 或者 `slice`。 +因此,无法对 `arguments` 变量使用标准的数组方法,比如 `push`、`pop` 或者 `slice`。 虽然使用 `for` 循环遍历也是可以的,但是为了更好的使用数组方法,最好把它转化为一个真正的数组。 ###转化为数组 @@ -93,19 +93,19 @@ JavaScript 中每个函数内都能访问一个特别变量 `arguments`。这个 return [a, arguments[0]]; } var pair = f(17); - assert(pair[0] === 42); - assert(pair[1] === 17); + console.assert(pair[0] === 42); + console.assert(pair[1] === 17); 然而,的确有一种情况会显著的影响现代 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(); // 通常情况会作为内联函数... } } diff --git a/doc/zh/function/closures.md b/doc/zh/function/closures.md index 77f69e4c..df474a65 100755 --- a/doc/zh/function/closures.md +++ b/doc/zh/function/closures.md @@ -3,6 +3,8 @@ 闭包是 JavaScript 一个非常重要的特性,这意味着当前作用域**总是**能够访问外部作用域中的变量。 因为 [函数](#function.scopes) 是 JavaScript 中唯一拥有自身作用域的结构,因此闭包的创建依赖于函数。 +> 译者注:ES2015 中增加了块级作用域。 + ###模拟私有变量 function Counter(start) { @@ -23,7 +25,7 @@ foo.get(); // 5 这里,`Counter` 函数返回两个闭包,函数 `increment` 和函数 `get`。 这两个函数都维持着 -对外部作用域 `Counter` 的引用,因此总可以访问此作用域内定义的变量 `count`. +对外部作用域 `Counter` 的引用,因此总可以访问此作用域内定义的变量 `count`。 ###为什么不可以在外部访问私有变量 @@ -44,13 +46,13 @@ for(var i = 0; i < 10; i++) { setTimeout(function() { - console.log(i); + console.log(i); }, 1000); } 上面的代码不会输出数字 `0` 到 `9`,而是会输出数字 `10` 十次。 -当 `console.log` 被调用的时候,*匿名*函数保持对外部变量 `i` 的引用,此时 `for`循环已经结束, `i` 的值被修改成了 `10`. +当 `console.log` 被调用的时候,*匿名*函数保持对外部变量 `i` 的引用,此时 `for`循环已经结束, `i` 的值被修改成了 `10`。 为了得到想要的结果,需要在每次循环中创建变量 `i` 的**拷贝**。 @@ -61,7 +63,7 @@ for(var i = 0; i < 10; i++) { (function(e) { setTimeout(function() { - console.log(e); + console.log(e); }, 1000); })(i); } @@ -76,8 +78,8 @@ setTimeout((function(e) { return function() { console.log(e); - } - })(i), 1000) + }; + })(i), 1000); } diff --git a/doc/zh/function/general.md b/doc/zh/function/general.md index 6269ee16..04414900 100755 --- a/doc/zh/function/general.md +++ b/doc/zh/function/general.md @@ -1,6 +1,6 @@ ##函数声明与表达式 -函数是JavaScript中的一等对象,这意味着可以把函数像其它值一样传递。 +函数是 JavaScript 中的一等对象,这意味着可以把函数像其它值一样传递。 一个常见的用法是把*匿名函数*作为回调函数传递到异步函数中。 ###函数声明 @@ -8,9 +8,9 @@ function foo() {} 上面的方法会在执行前被 [解析(hoisted)](#function.scopes),因此它存在于当前上下文的*任意*一个地方, -即使在函数定义体的上面被调用也是对的。 +即使在函数定义体的上面被调用也是对的。 - foo(); // 正常运行,因为foo在代码运行前已经被创建 + foo(); // 正常运行,因为 foo 在代码运行前已经被创建 function foo() {} ### 函数赋值表达式 @@ -39,7 +39,6 @@ `bar` 函数声明外是不可见的,这是因为我们已经把函数赋值给了 `foo`; 然而在 `bar` 内部依然可见。这是由于 JavaScript 的 [命名处理](#function.scopes) 所致, 函数名在函数内*总是*可见的。 -> **注意:**在IE8及IE8以下版本浏览器bar在外部也是可见的,是因为浏览器对命名函数赋值表达式进行了错误的解析, +> **注意: **在 IE8 及 IE8 以下版本浏览器 bar 在外部也是可见的,是因为浏览器对命名函数赋值表达式进行了错误的解析, > 解析成两个函数 `foo` 和 `bar` -[30]: http://cnblogs.com/sanshi/ diff --git a/doc/zh/function/this.md b/doc/zh/function/this.md index 0930ef26..967c9dfb 100755 --- a/doc/zh/function/this.md +++ b/doc/zh/function/this.md @@ -9,7 +9,8 @@ JavaScript 有一套完全不同于其它语言的对 `this` 的处理机制。 当在全部范围内使用 `this`,它将会指向*全局*对象。 -> **[译者注][30]:**浏览器中运行的 JavaScript 脚本,这个全局对象是 `window`。 +> **[译者注][30]:**浏览器中运行的 JavaScript 脚本,这个全局对象是 `window`; +> 在 nodejs 环境中运行的 Javascript 脚本,这个全局对象是 `global`。 ###函数调用 @@ -22,13 +23,13 @@ JavaScript 有一套完全不同于其它语言的对 `this` 的处理机制。 ###方法调用 - test.foo(); + test.foo(); 这个例子中,`this` 指向 `test` 对象。 ###调用构造函数 - new foo(); + new foo(); 如果函数倾向于和 `new` 关键词一块使用,则我们称这个函数是 [构造函数](#function.constructors)。 在函数内部,`this` 指向*新创建*的对象。 @@ -39,7 +40,7 @@ JavaScript 有一套完全不同于其它语言的对 `this` 的处理机制。 var bar = {}; foo.apply(bar, [1, 2, 3]); // 数组将会被扩展,如下所示 - foo.call(bar, 1, 2, 3); // 传递到foo的参数是:a = 1, b = 2, c = 3 + foo.call(bar, 1, 2, 3); // 传递到 foo 的参数是:a = 1, b = 2, c = 3 当使用 `Function.prototype` 上的 `call` 或者 `apply` 方法时,函数内的 `this` 将会被 **显式设置**为函数调用的第一个参数。 @@ -53,14 +54,14 @@ JavaScript 有一套完全不同于其它语言的对 `this` 的处理机制。 ###常见误解 尽管大部分的情况都说的过去,不过第一个规则(**[译者注][30]:**这里指的应该是第二个规则,也就是直接调用函数时,`this` 指向全局对象) -被认为是JavaScript语言另一个错误设计的地方,因为它**从来**就没有实际的用途。 +被认为是 JavaScript 语言另一个错误设计的地方,因为它**从来**就没有实际的用途。 Foo.method = function() { function test() { // this 将会被设置为全局对象(译者注:浏览器环境中也就是 window 对象) } test(); - } + }; 一个常见的误解是 `test` 中的 `this` 将会指向 `Foo` 对象,实际上**不是**这样子的。 @@ -72,7 +73,7 @@ JavaScript 有一套完全不同于其它语言的对 `this` 的处理机制。 // 使用 that 来指向 Foo 对象 } test(); - } + }; `that` 只是我们随意起的名字,不过这个名字被广泛的用来指向外部的 `this` 对象。 在 [闭包](#function.closures) 一节,我们可以看到 `that` 可以作为参数传递。 diff --git a/doc/zh/intro/license.md b/doc/zh/intro/license.md index 33aa7406..057dd8a6 100755 --- a/doc/zh/intro/license.md +++ b/doc/zh/intro/license.md @@ -1,7 +1,7 @@ ##许可 JavaScript 秘密花园在 [MIT license][1] 许可协议下发布,并存放在 [GitHub][2] 开源社区。 -如果你发现错误或者打字错误,请[新建一个任务单][3]或者发一个抓取请求。 +如果你发现错误,请[新建一个任务单][3]或者发一个抓取请求(Pull Request)。 你也可以在 Stack Overflow 的 [JavaScript 聊天室][4]找到我们。 [1]: https://github.com/BonsaiDen/JavaScript-Garden/blob/next/LICENSE diff --git a/doc/zh/object/forinloop.md b/doc/zh/object/forinloop.md index a0360e7e..16f9faaa 100755 --- a/doc/zh/object/forinloop.md +++ b/doc/zh/object/forinloop.md @@ -37,5 +37,4 @@ 推荐**总是**使用 `hasOwnProperty`。不要对代码运行的环境做任何假设,不要假设原生对象是否已经被扩展了。 [1]: http://www.prototypejs.org/ -[30]: http://cnblogs.com/sanshi/ diff --git a/doc/zh/object/general.md b/doc/zh/object/general.md index 58f20810..3ada17fa 100755 --- a/doc/zh/object/general.md +++ b/doc/zh/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,7 +9,7 @@ JavaScript 中所有变量都是对象,除了两个例外 [`null`](#core.undef Foo.bar = 1; Foo.bar; // 1 -一个常见的误解是数字的字面值(literal)不是对象。这是因为 JavaScript 解析器的一个错误, +一个常见的误解是数字的字面值(literal)不能当作对象使用。这是因为 JavaScript 解析器的一个错误, 它试图将*点操作符*解析为浮点数字面值的一部分。 2.toString(); // 出错:SyntaxError @@ -25,7 +25,7 @@ JavaScript 中所有变量都是对象,除了两个例外 [`null`](#core.undef JavaScript 的对象可以作为[*哈希表*][1]使用,主要用来保存命名的键与值的对应关系。 使用对象的字面语法 - `{}` - 可以创建一个简单对象。这个新创建的对象从 `Object.prototype` -[继承](#object.prototype)下面,没有任何[自定义属性](#object.hasownproperty)。 +[继承](#object.prototype)下来,没有任何[自定义属性](#object.hasownproperty)。 var foo = {}; // 一个空对象 @@ -34,7 +34,7 @@ JavaScript 的对象可以作为[*哈希表*][1]使用,主要用来保存命 ### 访问属性 -有两种方式来访问对象的属性,点操作符或者中括号操作符。 +有两种方式来访问对象的属性,点操作符和中括号操作符。 var foo = {name: 'kitten'} foo.name; // kitten diff --git a/doc/zh/object/hasownproperty.md b/doc/zh/object/hasownproperty.md index 2466f8c5..c9b3fc21 100755 --- a/doc/zh/object/hasownproperty.md +++ b/doc/zh/object/hasownproperty.md @@ -8,8 +8,8 @@ `hasOwnProperty` 是 JavaScript 中唯一一个处理属性但是**不**查找原型链的函数。 - // 修改Object.prototype - Object.prototype.bar = 1; + // 修改 Object.prototype + Object.prototype.bar = 1; var foo = {goo: undefined}; foo.bar; // 1 @@ -18,8 +18,8 @@ foo.hasOwnProperty('bar'); // false foo.hasOwnProperty('goo'); // true -只有 `hasOwnProperty` 可以给出正确和期望的结果,这在遍历对象的属性时会很有用。 -**没有**其它方法可以用来排除原型链上的属性,而不是定义在对象*自身*上的属性。 +只有 `hasOwnProperty` 可以给出正确和期望的结果。可以查看 [`for in` 循环](#object.forinloop) +章节来获取关于在迭代遍历对象属性的时候,何时使用 `hasOwnProperty` 的更多信息。 ###`hasOwnProperty` 作为属性 @@ -35,7 +35,7 @@ JavaScript **不会**保护 `hasOwnProperty` 被非法占用,因此如果一 foo.hasOwnProperty('bar'); // 总是返回 false - // 使用其它对象的 hasOwnProperty,并将其上下文设置为foo + // 使用其它对象的 hasOwnProperty,并将其上下文设置为 foo ({}).hasOwnProperty.call(foo, 'bar'); // true ###结论 @@ -44,4 +44,3 @@ JavaScript **不会**保护 `hasOwnProperty` 被非法占用,因此如果一 同时在使用 [`for in` loop](#object.forinloop) 遍历对象时,推荐**总是**使用 `hasOwnProperty` 方法, 这将会避免[原型](#object.prototype)对象扩展带来的干扰。 -[30]: http://cnblogs.com/sanshi/ diff --git a/doc/zh/object/prototype.md b/doc/zh/object/prototype.md index 0d0079c4..25a1d89d 100755 --- a/doc/zh/object/prototype.md +++ b/doc/zh/object/prototype.md @@ -3,7 +3,7 @@ JavaScript 不包含传统的类继承模型,而是使用 *prototype* 原型模型。 虽然这经常被当作是 JavaScript 的缺点被提及,其实基于原型的继承模型比传统的类继承还要强大。 -实现传统的类继承模型是很简单,但是实现 JavaScript 中的原型继承则要困难的多。 +例如,很容易通过原型继承实现传统的类继承模型,但是反过来,通过传统的类继承模型来实现原型继承模型就困难得多。 (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.) @@ -23,19 +23,19 @@ other way around is a far more difficult task.) function Bar() {} - // 设置Bar的prototype属性为Foo的实例对象 + // 设置 Bar 的 prototype 属性为 Foo 的实例对象 Bar.prototype = new Foo(); Bar.prototype.foo = 'Hello World'; - // 修正Bar.prototype.constructor为Bar本身 + // 修正 Bar.prototype.constructor 为 Bar 本身 Bar.prototype.constructor = Bar; - var test = new Bar() // 创建Bar的一个新实例 + var test = new Bar(); // 创建Bar的一个新实例 // 原型链 test [Bar的实例] Bar.prototype [Foo的实例] - { foo: 'Hello World' } + { foo: 'Hello World', value: 42 } Foo.prototype {method: ...}; Object.prototype @@ -46,7 +46,7 @@ other way around is a far more difficult task.) 需要注意的是 `new Bar()` **不会**创造出一个新的 `Foo` 实例,而是 重复使用它原型上的那个实例;因此,所有的 `Bar` 实例都会共享**相同**的 `value` 属性。 -> **注意:** **不要**使用 `Bar.prototype = Foo`,因为这不会执行 `Foo` 的原型,而是指向函数 `Foo`。 +> **注意:** **不要**使用 `Bar.prototype = Foo`,因为这不会指向 `Foo` 的原型,而是指向函数 `Foo`。 > 因此原型链将会回溯到 `Function.prototype` 而不是 `Foo.prototype`,因此 `method` 将不会在 Bar 的原型链上。 ###属性查找 @@ -58,7 +58,7 @@ other way around is a far more difficult task.) ###原型属性 当原型属性用来创建原型链时,可以把**任何**类型的值赋给它(prototype)。 -然而将原子类型赋给 prototype 的操作将会被忽略。 +然而将原子类型(primitives)赋给 prototype 的操作将会被忽略。 function Foo() {} Foo.prototype = 1; // 无效 @@ -67,16 +67,16 @@ other way around is a far more difficult task.) ###性能 -如果一个属性在原型链的上端,则对于查找时间将带来不利影响。特别的,试图获取一个不存在的属性将会遍历整个原型链。 +如果一个属性在原型链的上端,则对于查找时间将带来不利影响。注意,试图获取一个不存在的属性将会遍历整个原型链。 并且,当使用 [`for in`](#object.forinloop) 循环遍历对象的属性时,原型链上的**所有**属性都将被访问。 ###扩展内置类型的原型 -一个错误特性被经常使用,那就是扩展 `Object.prototype` 或者其他内置类型的原型对象。 +扩展 `Object.prototype` 或者其他内置类型的原型对象,作为一个错误特性,经常被使用。 这种技术被称之为 [monkey patching][1] 并且会破坏*封装*。虽然它被广泛的应用到一些 JavaScript 类库中比如 [Prototype][2], -但是我仍然不认为为内置类型添加一些*非标准*的函数是个好主意。 +但是我仍然不赞同为内置类型添加一些*非标准*的函数。 扩展内置类型的**唯一**理由是为了和新的 JavaScript 保持一致,比如 [`Array.forEach`][3]。 diff --git a/doc/zh/other/timeouts.md b/doc/zh/other/timeouts.md index 7810b39f..4b2cc5d0 100755 --- a/doc/zh/other/timeouts.md +++ b/doc/zh/other/timeouts.md @@ -101,7 +101,7 @@ } bar(); -由于 `eval` 在这种情况下不是被[直接](#core.eval)调用,因此传递到 `setTimeout` 的字符串会自*全局作用域*中执行; +由于 `eval` 在这种情况下不是被[直接](#core.eval)调用,因此传递到 `setTimeout` 的字符串会到*全局作用域*中执行; 因此,上面的回调函数使用的不是定义在 `bar` 作用域中的局部变量 `foo`。 建议**不要**在调用定时器函数时,为了向回调函数传递参数而使用字符串的形式。 diff --git a/doc/zh/types/typeof.md b/doc/zh/types/typeof.md index f7a6cc1e..fec6fcf7 100755 --- a/doc/zh/types/typeof.md +++ b/doc/zh/types/typeof.md @@ -75,7 +75,7 @@ JavaScript 标准文档只给出了一种获取 `[[Class]]` 值的方法,那 Object.prototype.toString.call(undefined) // "[object Undefined]" -###测试为定义变量 +###测试未定义变量 typeof foo !== 'undefined' diff --git a/doc/zhtw/array/constructor.md b/doc/zhtw/array/constructor.md index 6c66656d..fd952497 100644 --- a/doc/zhtw/array/constructor.md +++ b/doc/zhtw/array/constructor.md @@ -10,7 +10,7 @@ new Array('3') // 結果: ['3'] 在上面的範例 `new Array(3)` 當只有一個參數傳入到 `Array` 的建構函數 -且那個參數事宜個數字,建構函數會回傳空值 +且那個參數是一個數字,建構函數會回傳空值 但是 `Array` 長度的屬性會變成跟那個參數一樣(以此範例來看他回傳的長度為 3) **注意** 只有他長度的屬性會被設定,整個 Array裡面的數值都不會初始化 diff --git a/doc/zhtw/array/general.md b/doc/zhtw/array/general.md index e9de8782..1a59d72e 100644 --- a/doc/zhtw/array/general.md +++ b/doc/zhtw/array/general.md @@ -7,7 +7,7 @@ > 只有 [objects](#object.general) 來管理建值的相對應關係 > Arrays 是**保持** 順序的,Objects **則沒有** -因為 `for in` 迴圈會列舉所有在原型 Array 上的屬性因為他會使用[`hasOwnProperty`](#object.hasownproperty), 這會使得 Array 比原本的 `for` 迴圈慢上二十幾倍 +因為 `for in` 迴圈會使用[`hasOwnProperty`](#object.hasownproperty),所以它會列舉所有在原型 Array 上的屬性,這會使得 Array 比原本的 `for` 迴圈慢上二十幾倍 ### 迴圈 @@ -20,8 +20,8 @@ 在上面的例子中利用 `l = list.length` 來處理 Array 的長度問題。 -雖然 `length` 屬性是屬於 Array 中其中一個屬性,但是他還使有一定的性能消耗在每次循環的訪問。 -近期 Javascript 使用 **may** 來解決在這上面的效率問題,但是在現在的引擎上還不一定有支援。 +雖然 `length` 屬性是屬於 Array 中其中一個屬性,但是他在每次循環還是有一定的性能消耗。 +近期 Javascript **可能**使用來解決在這上面的效率問題,但是在現在的引擎上還不一定有支援。 實際上,不使用暫存 Array 長度的方式比使用暫存的版本還要慢很多。 diff --git a/doc/zhtw/core/eval.md b/doc/zhtw/core/eval.md index fb9e36bb..26b7d332 100644 --- a/doc/zhtw/core/eval.md +++ b/doc/zhtw/core/eval.md @@ -32,7 +32,7 @@ ### 安全上的顧慮 `eval` 同樣有安全上的問題,因為所有的程式碼都可以被直接執行。 -而他不應去執行一串未知的字串或是來自不幸任的來源。 +而他不應去執行一串未知的字串或是來自不信任的來源。 ### 結語 diff --git a/doc/zhtw/core/undefined.md b/doc/zhtw/core/undefined.md index 491f8528..501dfb95 100644 --- a/doc/zhtw/core/undefined.md +++ b/doc/zhtw/core/undefined.md @@ -1,6 +1,6 @@ ## `undefined` 和 `null` -JavaScript 中有兩個表示空值的方式, `null` 和 `undefined` , `undefined`式比較常用的一種。 +JavaScript 中有兩個表示空值的方式, `null` 和 `undefined` , `undefined`是比較常用的一種。 ### `undefined` 的值 diff --git a/doc/zhtw/function/arguments.md b/doc/zhtw/function/arguments.md index 7cb76032..39aa58f0 100644 --- a/doc/zhtw/function/arguments.md +++ b/doc/zhtw/function/arguments.md @@ -18,7 +18,7 @@ Array.prototype.slice.call(arguments); -這種轉化方式比較 **慢** ,不建議使用這種作法如果再追求效率的程式中。 +這種轉化方式比較 **慢** ,如果在追求效率的程式中,不建議使用這種作法。 ### 傳遞參數 @@ -53,7 +53,7 @@ 在 `Arguments` 物件創造的 *getter* 和 *setter* 的函數方法,可以被視為原本函數的變數。 -因此,改變了一個變數會跟著改變它的值而且也間接的改變稻香對應的 `arguments` 的物件,反之亦然。 +因此,改變了一個形式參將數會跟著改變對應的 `arguments` 的屬性,反之亦然。 function foo(a, b, c) { arguments[0] = 2; diff --git a/doc/zhtw/function/general.md b/doc/zhtw/function/general.md index 84a2bb3c..fe400880 100644 --- a/doc/zhtw/function/general.md +++ b/doc/zhtw/function/general.md @@ -25,19 +25,19 @@ 由於 `var` 已經宣告變數 `foo` 在所有的程式碼執行之前。 所以 `foo`已經在程式運行前就已經被定義過了。 -但是因為賦值只會在運行時去職情,所以在程式碼執行前,`foo` 的值還沒被宣告所以為 [undefined](#core.undefined)。 +但是因為賦值只會在運行時去執行,所以在程式碼執行前,`foo` 的值還沒被宣告所以為 [undefined](#core.undefined)。 ### 命名函式的賦值表達式 -另一個特殊狀況就勢將一個命名函式賦值給一個變數。 +另一個特殊狀況是將一個命名函式賦值給一個變數。 var foo = function bar() { bar(); // 可以運行 } bar(); // 錯誤:ReferenceError -`bar` 不可以在外部的區域被執行,因為它只有在 `foo` 的函式內才可以去執行。 +`bar` 不可以在外部的區域被執行,因為它只有在 `foo` 的函式內才可以執行。 然而在 `bar` 內部還是可以看見。這是由於 JavaScript的 [命名處理](#function.scopes)所致。 -函式名在函式內 *都* 可以去使用。 +函式名在函式內 *都* 可以使用。 diff --git a/doc/zhtw/function/scopes.md b/doc/zhtw/function/scopes.md index 3e151282..d443656f 100644 --- a/doc/zhtw/function/scopes.md +++ b/doc/zhtw/function/scopes.md @@ -160,7 +160,7 @@ JavaScript 中所有的作用區,包括 *全域作用域*,都有一個特殊 1. 當作用域內是否有 `var foo` 的定義。 2. 函式形式參數是否有使用 `foo` 名稱定義。 - 3. 函式自身是剖叫做 `foo`。 + 3. 函式自身是否叫做 `foo`。 4. 回溯到上一個層級然後再從第一個開始往下去查。 > **注意: ** 自定義 `arguments` 參數會阻止原生的 `arguments` 的物件創立 diff --git a/doc/zhtw/function/this.md b/doc/zhtw/function/this.md index d919c228..361a06c4 100644 --- a/doc/zhtw/function/this.md +++ b/doc/zhtw/function/this.md @@ -1,7 +1,7 @@ ## `this` 的工作原理 -JavaScript 有移到完全部屬於其他語言處理 `this` 的處理機制。 -在 **五** 種物同的情況下, `this` 指向的個不相同 +JavaScript 有一道完全不屬於其他語言處理 `this` 的處理機制。 +在 **五** 種不同的情況下, `this` 指向的各不相同 ### 全域變數 @@ -14,12 +14,12 @@ JavaScript 有移到完全部屬於其他語言處理 `this` 的處理機制。 foo(); -這裡 `this` 也會指向 *全域* 對象。 +這裡 `this` 也會指向 *全域* 物件。 > **ES5 注意:** 在嚴格模式下,不存在全域變數。 > `this` 將會是 `undefined`。 -### 方法調用 +### 呼叫一個方法 test.foo(); @@ -42,8 +42,7 @@ JavaScript 有移到完全部屬於其他語言處理 `this` 的處理機制。 當使用 `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`. +因此,在以上的例子中已不適用*函式調用*的原則,而且`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 @@ -51,47 +50,48 @@ inside of `foo` will be set to `bar`. ### 常見誤解 -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 + // this 設定為全域 } 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` that refers to `Foo`. +為了在 `test` 中使用 `Foo` 物件,我們需要在 `method` 函式内部建立一個區域變數指向 `Foo`。 Foo.method = function() { var that = this; function test() { - // Use that instead of this here + // 這裡使用 that 而非 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`。 在 [閉包](#function.closures) 一節,可以看到它(`that`)可以取代 `this` 傳遞。 -### Assigning Methods +在 ECMAScript 5 ,你可以使用 `bind` 結合匿名函式達到相同結果。 -Another thing that does **not** work in JavaScript is function aliasing, which is -**assigning** a method to a variable. + Foo.method = function() { + var test = function() { + // this 指向 Foo + }.bind(this); + test(); + }; + +### 函式表達式 + +另一個在 JavaScript 中**不會**運作的就是 function aliasing,也就是函式**賦值**給一個變數。 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` 的绑定特性似乎像是個壞主意,但事實上,它使得 [原型繼承](#object.prototype)得以運作。 function Foo() {} Foo.prototype.method = function() {}; @@ -101,7 +101,5 @@ fact, it is what makes [prototypal inheritance](#object.prototype) work. new Bar().method(); -When `method` gets called on an instance of `Bar`, `this` will now refer to that -very instance. - +當 `method` 被呼叫時,`this` 將會指向 `Bar` 的實體物件。 diff --git a/doc/zhtw/object/forinloop.md b/doc/zhtw/object/forinloop.md index 67fa8915..06b248a6 100644 --- a/doc/zhtw/object/forinloop.md +++ b/doc/zhtw/object/forinloop.md @@ -27,10 +27,10 @@ } 這個版本的程式碼是唯一正確的寫法。由於我們使用了 `hasOwnProperty`,這次 **只** 輸出 `moo`。 -如果不只用這個程式碼在原型物件中(比如 `Object.prototype`)被擴展可能會出錯。 +如果不使用這個程式碼在原型物件中(比如 `Object.prototype`)被擴展可能會出錯。 -一個廣泛的模組 [Prototype][1]就礦展了圓型的 JavaScript 物件。 -因此,但這模組包含在頁面中時,不使用 `hasOwnProperty` 過濾的 `for in` 尋難免會出問題。 +一個廣泛使用的舊函式庫 [Prototype][1]就擴展了原型的 JavaScript 物件。 +因此,當這個函式庫包含在頁面中時,不使用 `hasOwnProperty` 過濾的 `for in` 迴圈難免會出問題。 ### 總結 diff --git a/doc/zhtw/object/general.md b/doc/zhtw/object/general.md index 01c98bc5..6cd56600 100644 --- a/doc/zhtw/object/general.md +++ b/doc/zhtw/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' @@ -23,7 +23,7 @@ JavaScript 的物件可以作為 [*Hashmaps*][1]使用,主要用來保存命名的鍵與值的對應關係。 -使用物件的字面語法 - `{}` - 可以創建一個簡單的物件。 這個新創建的物件從 `Object.prototype` [繼承](#object.prototype),下面,沒有任何 [自定義屬性](#object.hasownproperty)。 +使用物件的字面語法 - `{}` - 可以創建一個簡單的物件。 這個新創建的物件[繼承](#object.prototype) 自 `Object.prototype` ,沒有任何 [自定義屬性](#object.hasownproperty)。 var foo = {}; // 一個空的物件 @@ -32,7 +32,7 @@ JavaScript 的物件可以作為 [*Hashmaps*][1]使用,主要用來保存命 ### 訪問屬性 -有兩種訪問物件的屬性,點操作或是中括號操作。 +有兩種方式來訪問物件的屬性,點操作或是中括號操作。 var foo = {name: 'kitten'} foo.name; // kitten @@ -69,14 +69,14 @@ JavaScript 的物件可以作為 [*Hashmaps*][1]使用,主要用來保存命 只有 `baz` 真正被刪除而已,所以從輸出結果中消失。 -### 屬姓名的語法 +### 屬性名的語法 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 }; -物件的屬性名可以使用字符串或是普通的宣告。但是由於 JavaScript 編譯器有個另外一個錯誤設計。 +物件的屬性名可以使用字符串或是普通的宣告。但是由於 JavaScript 編譯器存在一個錯誤設計。 上面的兩種方式在 ECMAScript 5之前都會拋出 `SyntaxError` 的錯誤。 這個錯誤的原因是 `delete` 是 JavaScript 語言的一個 *關鍵字* 因此為了在更低的版本能執行最好用 *string literal* diff --git a/doc/zhtw/object/hasownproperty.md b/doc/zhtw/object/hasownproperty.md index d35d49e2..5d8403b4 100644 --- a/doc/zhtw/object/hasownproperty.md +++ b/doc/zhtw/object/hasownproperty.md @@ -1,6 +1,6 @@ ## `hasOwnProperty` -為了判斷一個物件是否包含 *自定義* 屬性而 *不是* [原形](#object.prototype)上的屬性,我們需要使用繼承 `Object.prototype` 的 `hasOwnProperty` 方法。 +為了判斷一個物件是否包含 *自定義* 屬性而 *不是* [原型](#object.prototype)上的屬性,我們需要使用繼承 `Object.prototype` 的 `hasOwnProperty` 方法。 > **注意:** 判斷一個屬性是否 `undefined` 是 **不夠的**。 > 因為一個屬性可能存在,但是它的值被設成 `undefined`。 @@ -42,4 +42,4 @@ JavaScript **不會** 保護 `hasOwnProperty`被占用,因此如果碰到存 當檢查一個物件是否存在的時候, `hasOwnProperty` 是 **唯一** 可用的方法。 同時在使用 [`for in loop`](#object.forinloop) -建議使用 `hasOwnProperty` 避免 [原型](#object.prototype)所帶來的干擾。 \ No newline at end of file +建議使用 `hasOwnProperty` 避免 [原型](#object.prototype)所帶來的干擾。 diff --git a/doc/zhtw/object/prototype.md b/doc/zhtw/object/prototype.md index f2bcaff3..83ad784a 100644 --- a/doc/zhtw/object/prototype.md +++ b/doc/zhtw/object/prototype.md @@ -1,9 +1,9 @@ ## Prototype -JavaScript 不包含原本繼承的模型。然而它使用的是*原型*模型。 +JavaScript 不包含傳統繼承的模型,它使用的是*原型*模型。 -然而常常有人提及 JavaScript 的缺點,就是基於原本繼承模型比類繼承更強大。 -現實傳統的類繼承模型是很簡單。但是在 JavaScript 中實現元繼承則要困難很多。 +儘管常常有人提及 JavaScript 的缺點,但基於原型的繼承模型比傳統繼承更強大。 +實現傳統的類繼承模型是很簡單。但是在 JavaScript 中實現原型的繼承模型則要困難很多。 由於 JavaScript 是唯一一個被廣泛使用的基於原型繼承的語言,所以我們必須要花時間來理解這兩者的不同。 @@ -33,7 +33,7 @@ JavaScript 不包含原本繼承的模型。然而它使用的是*原型*模型 // 原型鏈 test [instance of Bar] Bar.prototype [instance of Foo] - { foo: 'Hello World' } + { foo: 'Hello World', value: 42 } Foo.prototype { method: ... } Object.prototype @@ -72,14 +72,14 @@ JavaScript 不包含原本繼承的模型。然而它使用的是*原型*模型 一個經常發生的錯誤,那就是擴展 `Object.prototype` 或者是其他內建類型的原型物件。 -這種技術叫做 [monkey patching][1] 並且會破壞 *封裝*。雖然被廣泛的應用到一些 Javascript 的架構,像是 [Prototype](http://prototypejs.org) , 但仍然沒有好的理由新增一個 *非標準* 的功能去搞亂內建型別 +這種技術叫做 [monkey patching][1] 並且會破壞 *封裝*。雖然被廣泛的應用到一些 Javascript 的架構,像是 [Prototype](http://prototypejs.org) , 但仍然沒有好的理由新增一個 *非標準* 的功能去搞亂內建型別。 擴展內置類型的 **唯一** 理由是為了和新的 JavaScript 保持一致,比如說 [`Array.forEach`][3] ### 總結 在寫複雜的程式碼的時候,要 **充分理解** 所有程式繼承的屬性還有原型鏈。 -還要堤防原型鏈過長帶來的性能問題,並知道如何通過縮短原型鏈來提高性能。 +還要提防原型鏈過長帶來的性能問題,並知道如何通過縮短原型鏈來提高性能。 絕對 **不要使用** `native prototype` 除非是為了和新的 JavaScript 引擎作兼容。 [1]: http://en.wikipedia.org/wiki/Monkey_patch diff --git a/doc/zhtw/other/timeouts.md b/doc/zhtw/other/timeouts.md index 3fe9a6da..d717a81e 100644 --- a/doc/zhtw/other/timeouts.md +++ b/doc/zhtw/other/timeouts.md @@ -1,13 +1,13 @@ ### `setTimeout` 和 `setInterval` -由於 Javascript 是一個非同步傳輸的系統,因此可以執行一個函式用 `setTimeout` 和 `setInterval`。 +由於 Javascript 具有非同步的特性,因此可以用 `setTimeout` 和 `setInterval` 來執行一個函式。 > **注意:** Timeouts 不在 ECMAScript 的標準中。它們是 [DOM][1] 其中的一部分 function foo() {} var id = setTimeout(foo, 1000); // returns a Number > 0 -當 `setTimeout` 被呼叫,它會回傳一個 ID 標準並是計畫在將來 **大約** 1000 毫秒後在在去呼叫 `foo` 函式。 +當 `setTimeout` 被呼叫,它會回傳一個 ID 標準並且 **大約** 1000 毫秒後在在去呼叫 `foo` 函式。 `foo` 函式只會被執行 **一次**。 基於 JavaScript 引擎的計時策略,以及基本的單線程運行的方式,所以其他的程式碼可以被阻塞。 @@ -85,13 +85,15 @@ ### 隱藏使用 `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` and `setInterval` 也可以使用字串當作他們的第一個參數. +不過這個特性 **絕對** 不要使用, 因為在內部他將利用 `eval` 來實作。 + +> **注意:** 由於 timeout 函式 **並未** 被列入 ECMAScript +> 標準中,當你將字串當成參數傳入時,在不同的 Javscript +> 實作中很有可能會造成不一樣的行為。比如說:在 Microsoft 的 JScript 中,就使用 `Function` +> 建構子來取代 `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 @@ -105,12 +107,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 be executed in the *global scope*; thus, it will -not use the local variable `foo` from the scope of `bar`. +在這個範例中,由於 `eval` 沒有被[直接](#core.eval)呼叫,在 `setTimeout` 中被傳入的字串將會在 *全域* 範圍中被執行,因此,他將不會使用在 `bar` 區域的 `foo`。 + +我們進一步建議 **不要** 用字串當作參數傳到會被 timeout 呼叫的函式中。 -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) {} @@ -122,18 +122,14 @@ function that will get called by either of the timeout functions. foo(1, 2, 3); }, 1000) -> **Note:** While it is also possible to use the syntax -> `setTimeout(foo, 1000, 1, 2, 3)`, it is not recommended, as its use may lead -> to subtle errors when used with [methods](#function.this). +> **注意** 儘管使用 `setTimeout(foo, 1000, 1, 2, 3)` +> 這樣的文法是可能的,但我們卻不建議這樣做,因為這和 [方法](#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. +**絕對** 不要使用字串當作 `setTimeout` 或 `setInterval` 參數。當參數要被當成呼叫的函式時,這絕對是 **不好** 的程式碼,相反的,利用 *匿名函式* 來完成這樣的行為。 -Furthermore, the use of `setInterval` should be avoided because its scheduler is not -blocked by executing JavaScript. +此外,應該避免使用 `setInterval`,因為他將不會被 Javascript 給中斷。 [1]: http://en.wikipedia.org/wiki/Document_Object_Model "Document Object Model" diff --git a/doc/zhtw/types/instanceof.md b/doc/zhtw/types/instanceof.md index 5bdb00d2..fa5e8c30 100644 --- a/doc/zhtw/types/instanceof.md +++ b/doc/zhtw/types/instanceof.md @@ -1,6 +1,6 @@ ## `instanceof` 操作符 -`instanceof` 操作符用來比較兩個建構函數的操作數。只有在比較字定義的物件時才有意義。這和 [typeof operator](#types.typeof)一樣用處不大。 +`instanceof` 操作符用來比較兩個建構函數的操作數。只有在比較自定義的物件時才有意義。這和 [typeof operator](#types.typeof)一樣用處不大。 ### 比較定意義物件 @@ -24,7 +24,7 @@ 'foo' instanceof String; // false 'foo' instanceof Object; // false -有一點需要注意的, `instanceof` 不能用來物件來自上下文不同的屬性(例如:瀏覽器中不同的文檔結構),因為它的建構函數不一樣。 +有一點需要注意的, `instanceof` 不會在來自不同的上下文的物件運作(例如:瀏覽器中不同的文檔結構),因為它的建構函數不一樣。 ### In Conclusion diff --git a/doc/zhtw/types/typeof.md b/doc/zhtw/types/typeof.md index 7058e55b..0a0908b0 100644 --- a/doc/zhtw/types/typeof.md +++ b/doc/zhtw/types/typeof.md @@ -3,7 +3,7 @@ `typeof` 操作符 (和 [`instanceof`](#types.instanceof)) 可能是最大的設計錯誤在 JavaScript,因為它幾乎不可能從它們那裡得到想要的結果。 -雖然 `instanceof` 還是有一些限制上的使用, `typeof` 只有一個實際上的運傭情形,但是 **不是** 用在檢查物件的類型。 +雖然 `instanceof` 還是有一些限制上的使用, `typeof` 只有一個實際上的運用情形,但是 **不是** 用在檢查物件的類型。 > **注意:** 由於 `typeof` 也可以像函式的語法被調用,例如 `typeof(obj)`,但這並是一個函數調用。 > 那兩個小括號只是用來計算一個表達式的值,這個返回值會作為 `typeof` 操作符的一個操作數。 @@ -67,8 +67,8 @@ JavaScript 標準文檔只給出了一種獲取 `[[Class]]` 值的方法,那 ### 結語 為了去檢查一個物件,強烈建議去使用 `Object.prototype.toString` 因為這是唯一可以依賴的方式。 -正如上面所看到的 `typeof` 的亦先返回值在標準文檔中未定義,因此不同的引擎可能不同。 +正如上面所看到的 `typeof` 的事先返回值在標準文檔中未定義,因此不同的引擎可能不同。 -除非為了檢測一個變數是否定義,我們應該避免是用 `typeof` 操作符。 +除非為了檢測一個變數是否定義,我們應該避免使用 `typeof` 操作符。 diff --git a/garden.jade b/garden.jade index bd191d39..bb67c1d1 100644 --- a/garden.jade +++ b/garden.jade @@ -79,10 +79,10 @@ html(lang=language) footer p Copyright ©. Built with | - a(href='http://nodejs.org/') Node.js - | using a - a(href='https://github.com/visionmedia/jade/') jade - | template. + a(href='http://nodejs.org/') Node.js + | using a + a(href='https://github.com/visionmedia/jade/') jade + | template. script(src='http://ajax.googleapis.com/ajax/libs/jquery/1.5.1/jquery.min.js') diff --git a/package.json b/package.json index ea637eb1..a9662f9f 100644 --- a/package.json +++ b/package.json @@ -2,6 +2,9 @@ "name": "javascript-garden", "description": "A collection of documentation about the most quirky parts of the JavaScript language.", "version": "0.0.0", + "scripts": { + "build": "node build.js" + }, "dependencies": { "fomatto": "0.5.0", "forever": "0.10.8", diff --git a/site/style/garden.css b/site/style/garden.css index 9c95ff95..b6d29302 100644 --- a/site/style/garden.css +++ b/site/style/garden.css @@ -72,13 +72,12 @@ body { nav { position: fixed; - margin-left: 750px; top: 0; + right: 0; padding-bottom: 20px; height: 100%; - text-shadow: none; - width: 240px; + width: 225px; } nav > div li { @@ -607,7 +606,6 @@ a abbr { #nav_main > ul > li { float: left; text-align: center; - width: 25%; border-bottom: 0; }