├── .gitignore ├── .lvimrc ├── CONTRIBUTING.md ├── JavaScript-Garden ├── LICENSE ├── README.md ├── build.js ├── deploy.sh ├── doc ├── by │ ├── array │ │ ├── constructor.md │ │ └── general.md │ ├── core │ │ ├── delete.md │ │ ├── eval.md │ │ ├── semicolon.md │ │ └── undefined.md │ ├── function │ │ ├── arguments.md │ │ ├── closures.md │ │ ├── constructors.md │ │ ├── general.md │ │ ├── scopes.md │ │ └── this.md │ ├── index.json │ ├── intro │ │ └── index.md │ ├── object │ │ ├── forinloop.md │ │ ├── general.md │ │ ├── hasownproperty.md │ │ └── prototype.md │ ├── other │ │ └── timeouts.md │ └── types │ │ ├── casting.md │ │ ├── equality.md │ │ ├── instanceof.md │ │ └── typeof.md ├── de │ ├── index.json │ └── intro │ │ ├── authors.md │ │ ├── contributors.md │ │ ├── index.md │ │ └── license.md ├── en │ ├── array │ │ ├── constructor.md │ │ └── general.md │ ├── core │ │ ├── delete.md │ │ ├── eval.md │ │ ├── semicolon.md │ │ └── undefined.md │ ├── function │ │ ├── arguments.md │ │ ├── closures.md │ │ ├── constructors.md │ │ ├── general.md │ │ ├── scopes.md │ │ └── this.md │ ├── index.json │ ├── intro │ │ └── index.md │ ├── object │ │ ├── forinloop.md │ │ ├── general.md │ │ ├── hasownproperty.md │ │ └── prototype.md │ ├── other │ │ └── timeouts.md │ └── types │ │ ├── casting.md │ │ ├── equality.md │ │ ├── instanceof.md │ │ └── typeof.md ├── es │ ├── array │ │ ├── constructor.md │ │ └── general.md │ ├── core │ │ ├── delete.md │ │ ├── eval.md │ │ ├── semicolon.md │ │ └── undefined.md │ ├── function │ │ ├── arguments.md │ │ ├── closures.md │ │ ├── constructors.md │ │ ├── general.md │ │ ├── scopes.md │ │ └── this.md │ ├── index.json │ ├── intro │ │ └── index.md │ ├── object │ │ ├── forinloop.md │ │ ├── general.md │ │ ├── hasownproperty.md │ │ └── prototype.md │ ├── other │ │ └── timeouts.md │ └── types │ │ ├── casting.md │ │ ├── equality.md │ │ ├── instanceof.md │ │ └── typeof.md ├── fi │ ├── array │ │ ├── constructor.md │ │ └── general.md │ ├── core │ │ ├── eval.md │ │ ├── semicolon.md │ │ └── undefined.md │ ├── function │ │ ├── arguments.md │ │ ├── closures.md │ │ ├── constructors.md │ │ ├── general.md │ │ ├── scopes.md │ │ └── this.md │ ├── index.json │ ├── intro │ │ ├── authors.md │ │ ├── contributors.md │ │ ├── index.md │ │ ├── license.md │ │ └── translators.md │ ├── object │ │ ├── forinloop.md │ │ ├── general.md │ │ ├── hasownproperty.md │ │ └── prototype.md │ ├── other │ │ └── timeouts.md │ └── types │ │ ├── casting.md │ │ ├── equality.md │ │ ├── instanceof.md │ │ └── typeof.md ├── fr │ ├── array │ │ ├── constructor.md │ │ └── general.md │ ├── core │ │ ├── delete.md │ │ ├── eval.md │ │ ├── semicolon.md │ │ └── undefined.md │ ├── function │ │ ├── arguments.md │ │ ├── closures.md │ │ ├── constructors.md │ │ ├── general.md │ │ ├── scopes.md │ │ └── this.md │ ├── index.json │ ├── intro │ │ └── index.md │ ├── object │ │ ├── forinloop.md │ │ ├── general.md │ │ ├── hasownproperty.md │ │ └── prototype.md │ ├── other │ │ └── timeouts.md │ └── types │ │ ├── casting.md │ │ ├── equality.md │ │ ├── instanceof.md │ │ └── typeof.md ├── hu │ ├── array │ │ ├── constructor.md │ │ └── general.md │ ├── core │ │ ├── delete.md │ │ ├── eval.md │ │ ├── semicolon.md │ │ └── undefined.md │ ├── function │ │ ├── arguments.md │ │ ├── closures.md │ │ ├── constructors.md │ │ ├── general.md │ │ ├── scopes.md │ │ └── this.md │ ├── index.json │ ├── intro │ │ └── index.md │ ├── object │ │ ├── forinloop.md │ │ ├── general.md │ │ ├── hasownproperty.md │ │ └── prototype.md │ ├── other │ │ └── timeouts.md │ └── types │ │ ├── casting.md │ │ ├── equality.md │ │ ├── instanceof.md │ │ └── typeof.md ├── it │ ├── array │ │ ├── constructor.md │ │ └── general.md │ ├── core │ │ ├── delete.md │ │ ├── eval.md │ │ ├── semicolon.md │ │ └── undefined.md │ ├── function │ │ ├── arguments.md │ │ ├── closures.md │ │ ├── constructors.md │ │ ├── general.md │ │ ├── scopes.md │ │ └── this.md │ ├── index.json │ ├── intro │ │ └── index.md │ ├── object │ │ ├── forinloop.md │ │ ├── general.md │ │ ├── hasownproperty.md │ │ └── prototype.md │ ├── other │ │ └── timeouts.md │ └── types │ │ ├── casting.md │ │ ├── equality.md │ │ ├── instanceof.md │ │ └── typeof.md ├── ja │ ├── array │ │ ├── constructor.md │ │ └── general.md │ ├── core │ │ ├── delete.md │ │ ├── eval.md │ │ ├── semicolon.md │ │ └── undefined.md │ ├── function │ │ ├── arguments.md │ │ ├── closures.md │ │ ├── constructors.md │ │ ├── general.md │ │ ├── scopes.md │ │ └── this.md │ ├── index.json │ ├── intro │ │ └── index.md │ ├── object │ │ ├── forinloop.md │ │ ├── general.md │ │ ├── hasownproperty.md │ │ └── prototype.md │ ├── other │ │ └── timeouts.md │ └── types │ │ ├── casting.md │ │ ├── equality.md │ │ ├── instanceof.md │ │ └── typeof.md ├── ko │ ├── array │ │ ├── constructor.md │ │ └── general.md │ ├── core │ │ ├── delete.md │ │ ├── eval.md │ │ ├── semicolon.md │ │ └── undefined.md │ ├── function │ │ ├── arguments.md │ │ ├── closures.md │ │ ├── constructors.md │ │ ├── general.md │ │ ├── scopes.md │ │ └── this.md │ ├── index.json │ ├── intro │ │ └── index.md │ ├── object │ │ ├── forinloop.md │ │ ├── general.md │ │ ├── hasownproperty.md │ │ └── prototype.md │ ├── other │ │ └── timeouts.md │ └── types │ │ ├── casting.md │ │ ├── equality.md │ │ ├── instanceof.md │ │ └── typeof.md ├── language.json ├── pl │ ├── array │ │ ├── constructor.md │ │ └── general.md │ ├── core │ │ ├── eval.md │ │ ├── semicolon.md │ │ └── undefined.md │ ├── function │ │ ├── arguments.md │ │ ├── closures.md │ │ ├── constructors.md │ │ ├── general.md │ │ ├── scopes.md │ │ └── this.md │ ├── index.json │ ├── intro │ │ ├── authors.md │ │ ├── contributors.md │ │ ├── hosting.md │ │ ├── index.md │ │ ├── license.md │ │ └── translators.md │ ├── object │ │ ├── forinloop.md │ │ ├── general.md │ │ ├── hasownproperty.md │ │ └── prototype.md │ ├── other │ │ └── timeouts.md │ └── types │ │ ├── casting.md │ │ ├── equality.md │ │ ├── instanceof.md │ │ └── typeof.md ├── ptbr │ ├── array │ │ ├── constructor.md │ │ └── general.md │ ├── core │ │ ├── delete.md │ │ ├── eval.md │ │ ├── semicolon.md │ │ └── undefined.md │ ├── function │ │ ├── arguments.md │ │ ├── closures.md │ │ ├── constructors.md │ │ ├── general.md │ │ ├── scopes.md │ │ └── this.md │ ├── index.json │ ├── intro │ │ └── index.md │ ├── object │ │ ├── forinloop.md │ │ ├── general.md │ │ ├── hasownproperty.md │ │ └── prototype.md │ ├── other │ │ └── timeouts.md │ └── types │ │ ├── casting.md │ │ ├── equality.md │ │ ├── instanceof.md │ │ └── typeof.md ├── ru │ ├── appendix │ │ └── fromtranslators.md │ ├── array │ │ ├── constructor.md │ │ └── general.md │ ├── core │ │ ├── delete.md │ │ ├── eval.md │ │ ├── semicolon.md │ │ └── undefined.md │ ├── function │ │ ├── arguments.md │ │ ├── closures.md │ │ ├── constructors.md │ │ ├── general.md │ │ ├── scopes.md │ │ └── this.md │ ├── index.json │ ├── intro │ │ ├── authors.md │ │ ├── contributors.md │ │ ├── index.md │ │ ├── license.md │ │ └── translators.md │ ├── object │ │ ├── forinloop.md │ │ ├── general.md │ │ ├── hasownproperty.md │ │ └── prototype.md │ ├── other │ │ └── timeouts.md │ └── types │ │ ├── casting.md │ │ ├── equality.md │ │ ├── instanceof.md │ │ └── typeof.md ├── tr │ ├── array │ │ ├── constructor.md │ │ └── general.md │ ├── core │ │ ├── delete.md │ │ ├── eval.md │ │ ├── semicolon.md │ │ └── undefined.md │ ├── function │ │ ├── arguments.md │ │ ├── closures.md │ │ ├── constructors.md │ │ ├── general.md │ │ ├── scopes.md │ │ └── this.md │ ├── index.json │ ├── intro │ │ └── index.md │ ├── object │ │ ├── forinloop.md │ │ ├── general.md │ │ ├── hasownproperty.md │ │ └── prototype.md │ ├── other │ │ └── timeouts.md │ └── types │ │ ├── casting.md │ │ ├── equality.md │ │ ├── instanceof.md │ │ └── typeof.md ├── zh │ ├── array │ │ ├── constructor.md │ │ └── general.md │ ├── core │ │ ├── eval.md │ │ ├── semicolon.md │ │ └── undefined.md │ ├── function │ │ ├── arguments.md │ │ ├── closures.md │ │ ├── constructors.md │ │ ├── general.md │ │ ├── scopes.md │ │ └── this.md │ ├── index.json │ ├── intro │ │ ├── authors.md │ │ ├── contributors.md │ │ ├── index.md │ │ └── license.md │ ├── object │ │ ├── forinloop.md │ │ ├── general.md │ │ ├── hasownproperty.md │ │ └── prototype.md │ ├── other │ │ └── timeouts.md │ └── types │ │ ├── casting.md │ │ ├── equality.md │ │ ├── instanceof.md │ │ └── typeof.md └── zhtw │ ├── array │ ├── constructor.md │ └── general.md │ ├── core │ ├── delete.md │ ├── eval.md │ ├── semicolon.md │ └── undefined.md │ ├── function │ ├── arguments.md │ ├── closures.md │ ├── constructors.md │ ├── general.md │ ├── scopes.md │ └── this.md │ ├── index.json │ ├── intro │ └── index.md │ ├── object │ ├── forinloop.md │ ├── general.md │ ├── hasownproperty.md │ └── prototype.md │ ├── other │ └── timeouts.md │ └── types │ ├── casting.md │ ├── equality.md │ ├── instanceof.md │ └── typeof.md ├── garden.jade ├── package.json └── site ├── favicon.ico ├── image └── sidebar-icon.png ├── javascript ├── garden.js ├── html5.js └── prettify.js └── style ├── garden.css └── print.css /.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | /html 3 | /log 4 | /node_modules 5 | /.idea/* 6 | 7 | /site 8 | !/site/favicon.ico 9 | !/site/image 10 | !/site/javascript 11 | !/site/style 12 | !/site/style 13 | 14 | *.md~ 15 | *.src.md 16 | *.DS_store 17 | -------------------------------------------------------------------------------- /.lvimrc: -------------------------------------------------------------------------------- 1 | set wildignore=node_modules 2 | set tabstop=2 3 | set shiftwidth=2 4 | set softtabstop=2 5 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to Javascript Garden 2 | 3 | 1. We're about Javascript AKA [ECMA script](http://www.ecma-international.org/ecma-262/5.1/) not a specific implementation. So we don't cover issues specific to one environment or interpreter, like browsers or V8 for node. 4 | 1. Micro-performance is out of scope: anything that's not a result of essential algorithmic complexity (e.g O(log n) vs O(n^2)) is down to a specific version of a specific interpreter (see 1). 5 | 1. Please test code examples to ensure they work, there's nothing more confusing than incorrect examples! 6 | 1. Contributing to JS Garden makes you a fantastic person, and Brendan Eich will find you immensely attractive. 7 | 8 | Thank you for being kind enough to help out! 9 | 10 | ## Testing locally 11 | 12 | 1. Run `npm run build` to build 13 | 1. Run a webserver from the root of the repo to view 14 | 15 | ## Getting changes merged 16 | 17 | 1. Squash your changes into one commit 18 | 1. Make sure the site still works :) 19 | 1. Make a PR 20 | -------------------------------------------------------------------------------- /JavaScript-Garden: -------------------------------------------------------------------------------- 1 | ./site -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2010 Ivo Wetzel. 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | 21 | -------------------------------------------------------------------------------- /deploy.sh: -------------------------------------------------------------------------------- 1 | set -e 2 | remote=mine 3 | if [[ $PRODUCTION ]]; then 4 | echo "Deploy to production? (y/n)" 5 | read ans 6 | if [[ $ans == "y" ]]; then 7 | remote="origin" 8 | fi 9 | fi 10 | diffs=`git diff --name-status HEAD` 11 | if [[ "" != $diffs ]]; then 12 | echo "Can't deploy, unsaved changes:" 13 | echo $diffs 14 | exit 15 | fi 16 | git checkout gh-pages 17 | git reset --hard master 18 | echo "Starting build" 19 | node build.js 20 | echo "Build complete" 21 | rm -rf `ls -d * | grep -vP 'site|node_modules' | xargs` 22 | echo "Cleaned out directory" 23 | mv site/* . 24 | if [[ $BUILD_ONLY ]]; then 25 | exit 26 | fi 27 | rm -rf site 28 | git add . -A 29 | git commit -m 'latest' 30 | echo "Commit created" 31 | git push --force $remote gh-pages 32 | echo "Deployed to $remote" 33 | git checkout master 34 | -------------------------------------------------------------------------------- /doc/by/array/constructor.md: -------------------------------------------------------------------------------- 1 | ## Канструктар `Array` 2 | 3 | Праз тое, што канструктар `Array` неадназначна апрацоўвае свае параметры, 4 | крайне рэкамендуецца выкарыстоўваць літэрал - `[]` - для стварэння масіваў. 5 | 6 | [1, 2, 3]; // Вынік: [1, 2, 3] 7 | new Array(1, 2, 3); // Вынік: [1, 2, 3] 8 | 9 | [3]; // Вынік: [3] 10 | new Array(3); // Вынік: [] 11 | new Array('3') // Вынік: ['3'] 12 | 13 | У выпадку, калі канструктару `Array` перадаецца толькі адзін параметр, і калі гэты 14 | аргумент тыпу `Number`, канструктар верне *разрэджаны* масіў, які мае уласціваць 15 | `length` са значэннем аргумента. Варта адзначыць, што такім чынам будзе зменена 16 | **толькі** значэнне ўласцівасці `length` масіва; індэксы масіва не будуць 17 | праініцыялізаваныя. 18 | 19 | var arr = new Array(3); 20 | arr[1]; // undefined 21 | 1 in arr; // false, індэкс не праініцыялізаваны 22 | 23 | Магчымасць загадзя вызначыць даўжыню масіва карысна толькі ў рэдкіх выпадках, 24 | напрыклад, паўтор радка без выкарыстання цыкла. 25 | 26 | new Array(count + 1).join(stringToRepeat); 27 | 28 | ### У заключэнне 29 | 30 | Літэралы маюць перавагі над канструктарам Array. Яны карацейшыя, маюць больш чысты 31 | сінтаксіс і робяць код больш чытэльным. 32 | -------------------------------------------------------------------------------- /doc/by/core/eval.md: -------------------------------------------------------------------------------- 1 | ## Чаму не варта выкарыстоўваць `eval` 2 | 3 | Функцыя `eval` выконвае радок JavaScript коду ў лакальнай зоне бачнасці. 4 | 5 | var number = 1; 6 | function test() { 7 | var number = 2; 8 | eval('number = 3'); 9 | return number; 10 | } 11 | test(); // 3 12 | number; // 1 13 | 14 | Тым не менш, `eval` выконваецца ў лакальнай прасторы імён толькі ў тым выпадку, калі 15 | яна была выклікана наўпрост *і* імя выкліканай функцыі — `eval`. 16 | 17 | var number = 1; 18 | function test() { 19 | var number = 2; 20 | var copyOfEval = eval; 21 | copyOfEval('number = 3'); 22 | return number; 23 | } 24 | test(); // 2 25 | number; // 3 26 | 27 | Лепш пазбягаць выкарыстоўвання `eval`. 99,9% яе «выкарыстанняў» можа быць дасягнута 28 | **без** яе. 29 | 30 | ### Схаваны `eval` 31 | 32 | Абедзве [функцыі тайм-аўты](#other.timeouts) `setTimeout` і `setInterval` могуць 33 | прымаць радок у якасці першага аргумента. Гэты радок будзе **заўсёды** выконвацца 34 | ў глабальнай прасторы імёнаў, бо `eval` не выклікаецца наўпрост у дадзеным выпадку. 35 | 36 | ### Праблемы з бяспекаю 37 | 38 | Таксама `eval` мае праблемы з бяспекаю, бо ён выконвае **любы** перададзены код. 39 | Таму яе **ніколі** не варта выкарыстоўваць з радкамі, што паходзяць з ненадзейных 40 | крыніцаў. 41 | 42 | ### Заключэнне 43 | 44 | Лепш ніколі не выкарыстоўваць `eval`. Любы код, што выкарыстоўвае яе, спрэчны ў 45 | плане якасці, карэктнасці, прадукцыйнасці і бяспекі. Калі для таго, каб нешта 46 | працавала, патрэбны `eval`, **не** трэба прымаць гэта рашэнне ў першую чаргу. 47 | *Лепшым рашэннем* будзе тое, што не будзе выкарыстоўваць `eval`. 48 | -------------------------------------------------------------------------------- /doc/by/function/general.md: -------------------------------------------------------------------------------- 1 | ## Выразы і аб'яўленне функцый 2 | 3 | У JavaScript функцыі таксама з'яўляюцца аб'ектамі. Гэта значыць іх можна перадаваць 4 | і прысвойваць як і любыя іншыя аб'екты. Адзін, часта выкарыстоўваемы варыянт, 5 | гэтай магчымасці - перадача *ананімнага метада* як функцыі зваротнага выкліку 6 | іншай, магчыма асінхроннай функцыі. 7 | 8 | ### Аб'яўленне `function` 9 | 10 | function foo() {} 11 | 12 | У вышэй прыведзеным прыкладзе функцыя [уздымаецца](#function.scopes) перад тым 13 | як пачынаецца выконванне праграмы; Такім чынам, яна даступная *паўсюль* у зоне 14 | бачнасці, у якой яна была *аб'яўлена*, нават калі выклік адбываецца да фактычнага 15 | аб'яўлення ў кодзе. 16 | 17 | foo(); // Працуе, бо функцыя будзе створана да выконвання кода 18 | function foo() {} 19 | 20 | ### `function` як выраз 21 | 22 | var foo = function() {}; 23 | 24 | У гэтым прыкладзе пераменнай `foo` прысвойваецца *ананімная* функцыя. 25 | 26 | foo; // 'undefined' 27 | foo(); // уздыме TypeError 28 | var foo = function() {}; 29 | 30 | Праз тое, што `var` - гэта аб'яўленне якое уздымае імя пераменнай `foo` перад тым 31 | як код будзе выкананы, `foo` будзе ўжо аб'яўленым калі ён пачне выконвацца. 32 | 33 | Але так як прысвойванні адбываюцца толькі пад час выконвання, значэнне `foo` 34 | будзе змоўчанным ([undefined](#core.undefined)) да выконвання адпаведнага кода. 35 | 36 | ### Выразы з іменаванымі функцыямі 37 | 38 | Яшчэ адзін выбітны выпадак - прысвойванне іменавай функцыі. 39 | 40 | var foo = function bar() { 41 | bar(); // працуе 42 | } 43 | bar(); // ReferenceError 44 | 45 | Тут, `bar` не даступны ў знешнім скоўпе, бо функцыя толькі прысвойваецца пераменнай 46 | `foo`; аднак, унутры `bar`, імя даступнае. Так адбываецца праз асаблівасці працы 47 | з [прастранствамі імён](#function.scopes) у JavaScript - імя функцыі *заўсёды* 48 | даступнае ў лакальным скоўпе функцыі. 49 | -------------------------------------------------------------------------------- /doc/by/index.json: -------------------------------------------------------------------------------- 1 | { 2 | "title": "JavaScript Garden", 3 | "langTitle": "JavaScript Garden па Беларуску", 4 | "description": "Мануал па недахопаў і дзівосах JavaScript", 5 | "sections": [ 6 | { 7 | "title": "Уводзіны", 8 | "dir": "intro", 9 | "articles": ["index"] 10 | }, 11 | { 12 | "title": "Аб'екты", 13 | "dir": "object", 14 | "articles": [ 15 | "general", 16 | "prototype", 17 | "hasownproperty", 18 | "forinloop" 19 | ] 20 | }, 21 | { 22 | "title": "Функцыі", 23 | "dir": "function", 24 | "articles": [ 25 | "general", 26 | "this", 27 | "closures", 28 | "arguments", 29 | "constructors", 30 | "scopes" 31 | ] 32 | }, 33 | { 34 | "title": "Масівы", 35 | "dir": "array", 36 | "articles": [ 37 | "general", 38 | "constructor" 39 | ] 40 | }, 41 | { 42 | "title": "Тыпы", 43 | "dir": "types", 44 | "articles": [ 45 | "equality", 46 | "typeof", 47 | "instanceof", 48 | "casting" 49 | ] 50 | }, 51 | { 52 | "title": "Ядро", 53 | "dir": "core", 54 | "articles": [ 55 | "eval", 56 | "undefined", 57 | "semicolon", 58 | "delete" 59 | ] 60 | }, 61 | { 62 | "title": "Рэшта", 63 | "dir": "other", 64 | "articles": [ 65 | "timeouts" 66 | ] 67 | } 68 | ] 69 | } 70 | -------------------------------------------------------------------------------- /doc/by/object/hasownproperty.md: -------------------------------------------------------------------------------- 1 | ## Метад `hasOwnProperty` 2 | 3 | Каб праверыць, ці ёсць у аб'екта ўласцівасць, вызначаная ў *ім самім*, а не дзе-небудзь 4 | у яго [ланцужку прататыпаў](#object.prototype), неабходна выкарыстаць метад 5 | `hasOwnProperty`, які ўсе аб'екты ўспадкоўваюць ад `Object.prototype`. 6 | 7 | > **Заўвага:** **недастаткова** праверыць, ці значэнне уласцівасці — `undefined`. 8 | > Уласцівасць можа існаваць, але яе значэнне было пазначана як `undefined`. 9 | 10 | `hasOwnProperty` — адзіная функцыя ў JavaScript, якая дазваляе атрымаць уласцівасці 11 | аб'екта **без** зварота да ланцужка прататыпаў. 12 | 13 | // Сапсуем Object.prototype 14 | Object.prototype.bar = 1; 15 | var foo = {goo: undefined}; 16 | 17 | foo.bar; // 1 18 | 'bar' in foo; // true 19 | 20 | foo.hasOwnProperty('bar'); // false 21 | foo.hasOwnProperty('goo'); // true 22 | 23 | Толькі `hasOwnProperty` дасць правільны чаканы вынік. Паглядзіце секцыю аб 24 | [цыкле `for in`](#object.forinloop) для падрабязнейшых звестак аб тым, як 25 | выкарыстоўваць `hasOwnProperty` падчас ітэрацыі па ўласцівасцях аб'екта. 26 | 27 | ### `hasOwnProperty` як уласцівасць 28 | 29 | JavaScript не абараняе ўласцівасць `hasOwnProperty`; такім чынам, ёсць верагоднасць 30 | што ў аб'екта можа быць уласцівасць з такім імем, неабходна выкарыстаць 31 | *знешні* `hasOwnProperty` для карэктнага выніку. 32 | 33 | var foo = { 34 | hasOwnProperty: function() { 35 | return false; 36 | }, 37 | bar: 'Тут жывуць драконы' 38 | }; 39 | 40 | foo.hasOwnProperty('bar'); // заўсёды верне false 41 | 42 | // выкарыстайце hasOwnProperty іншага аб'екта 43 | // і перадайце foo у якасці this 44 | ({}).hasOwnProperty.call(foo, 'bar'); // true 45 | 46 | // Такасама магчыма выкарыстаць hasOwnProperty з Object.prototype 47 | Object.prototype.hasOwnProperty.call(foo, 'bar'); // true 48 | 49 | 50 | ### Заключэнне 51 | 52 | Выкарыстоўванне `hasOwnProperty` ёсць **адзіным** надзейным спосабам, каб 53 | праверыць існаванне ўласцівасці ў аб'екце. Рэкамендуецца выкарыстоўваць 54 | `hasOwnProperty` пры ітэрацыі па ўласцівасцях аб'екта, як апісана ў секцыі 55 | [цыкла `for in` ](#object.forinloop). 56 | -------------------------------------------------------------------------------- /doc/by/types/instanceof.md: -------------------------------------------------------------------------------- 1 | ## Аператар `instanceof` 2 | 3 | Аператар `instanceof` параўноўвае канструктары двух аперандаў. Гэта карысна толькі 4 | для параўнання аб'ектаў не ўбудаваных тыпаў. Выкарыстоўванне на ўбудаваных тыпах не 5 | мае сэнсу, як і [аператар typeof](#types.typeof). 6 | 7 | ### Параўнанне адвольных аб'ектаў 8 | 9 | function Foo() {} 10 | function Bar() {} 11 | Bar.prototype = new Foo(); 12 | 13 | new Bar() instanceof Bar; // true 14 | new Bar() instanceof Foo; // true 15 | 16 | // Калі толькі прысвоім Bar.prototype аб'ект функцыі Foo, 17 | // але не самаго экзэмпляра Foo 18 | Bar.prototype = Foo; 19 | new Bar() instanceof Foo; // false 20 | 21 | ### Выкарыстоўванне `instanceof` з убудаванымі тыпамі 22 | 23 | new String('foo') instanceof String; // true 24 | new String('foo') instanceof Object; // true 25 | 26 | 'foo' instanceof String; // false 27 | 'foo' instanceof Object; // false 28 | 29 | Варта адзначыць, што `instanceof` не працуе на аб'ектах, якія паходзяць з розных 30 | кантэкстаў JavaScript (напрыклад, розных дакументаў у web-браузеры), бо іх канструктары 31 | насамрэч не будуць канструктарамі тых самых аб'ектаў. 32 | 33 | ### У заключэнне 34 | 35 | Аператар `instanceof` мае быць выкарыстаны **толькі** для працы з аб'ектамі не 36 | ўбудаваных тыпаў якія паходзяць з аднаго кантэкста JavaScript. Як і ў выпадку з 37 | [аператарам `typeof`](#types.typeof), трэба **пазбягаць** любога іншага яго выкарыстання. 38 | -------------------------------------------------------------------------------- /doc/de/index.json: -------------------------------------------------------------------------------- 1 | { 2 | "title": "JavaScript Garden", 3 | "langTitle": "JavaScript Garden in Deutsch", 4 | "description": "Ein Guide über JavaScript's Ecken und Kanten.", 5 | "sections": [ 6 | { 7 | "title": "Einführung", 8 | "dir": "intro", 9 | "articles": [ 10 | "authors", 11 | "contributors", 12 | "license" 13 | ] 14 | } 15 | ] 16 | } 17 | -------------------------------------------------------------------------------- /doc/de/intro/authors.md: -------------------------------------------------------------------------------- 1 | ## The Authors 2 | 3 | This guide is the work of two lovely Stack Overflow users, [Ivo Wetzel][1] 4 | (Writing) and [Zhang Yi Jiang][2] (Design). 5 | 6 | [1]: http://stackoverflow.com/users/170224/ivo-wetzel 7 | [2]: http://stackoverflow.com/users/313758/yi-jiang 8 | 9 | -------------------------------------------------------------------------------- /doc/de/intro/contributors.md: -------------------------------------------------------------------------------- 1 | ## Contributors 2 | 3 | - [Caio Romão][1] (Spelling corrections) 4 | - [Andreas Blixt][2] (Language corrections) 5 | 6 | [1]: https://github.com/caio 7 | [2]: https://github.com/blixt 8 | 9 | -------------------------------------------------------------------------------- /doc/de/intro/index.md: -------------------------------------------------------------------------------- 1 | ## Einführung 2 | 3 | **JavaScript Garden** ist eine wachsende Sammlung von Erklärungen der verzwicktesten Teile von JavaScript. Es gibt 4 | Hinweise um häufige Fehler, Performance Probleme und schlechten Stil zu vermeiden. 5 | 6 | JavaScript Garden ist **keine** Anleitung um JavaScript zu lernen. Ein grundlegendes Verständnis der Sprache wird 7 | wärmstens empfohlen. Eine gute [Einführung][1] findet sich zum Beispiel im Mozilla Developer Network. 8 | 9 | ## Die Autoren 10 | 11 | Dieses Dokument wurde von zwei liebenswerten [Stack Overflow][2] Benutzern geschrieben: [Ivo Wetzel][3] 12 | (Text) and [Zhang Yi Jiang][4] (Design). 13 | 14 | ## Beitragende 15 | 16 | - [Beitragende](https://github.com/BonsaiDen/JavaScript-Garden/graphs/contributors) 17 | 18 | ## Hosting 19 | 20 | JavaScript Garden wird von GitHub bereitgestellt, aber es wird auch von [Cramer Development][7] unterstützt durch 21 | einen Mirror auf [JavaScriptGarden.info][8]. 22 | 23 | ## Lizenz 24 | 25 | JavaScript Garden wurde unter der [MIT Lizenz][9] veröffentlich und wird von [GitHub][10] veröffentlicht. Wenn du 26 | Fehler findest mach bitte ein [Ticket][11] auf oder einen pull request ins repository. Du kannst uns auch im 27 | [JavaScript Raum][12] des Stack Overflow Chats finden. 28 | 29 | Mehr demnächst. 30 | 31 | [1]: https://developer.mozilla.org/en/JavaScript/Guide 32 | [2]: http://stackoverflow.com/ 33 | [3]: http://stackoverflow.com/users/170224/ivo-wetzel 34 | [4]: http://stackoverflow.com/users/313758/yi-jiang 35 | [5]: https://github.com/caio 36 | [6]: https://github.com/blixt 37 | [7]: http://cramerdev.com/ 38 | [8]: http://javascriptgarden.info/ 39 | [9]: https://github.com/BonsaiDen/JavaScript-Garden/blob/next/LICENSE 40 | [10]: https://github.com/BonsaiDen/JavaScript-Garden 41 | [11]: https://github.com/BonsaiDen/JavaScript-Garden/issues 42 | [12]: http://chat.[stackoverflow.com/rooms/17/javascript 43 | -------------------------------------------------------------------------------- /doc/de/intro/license.md: -------------------------------------------------------------------------------- 1 | ## License 2 | 3 | JavaScript Garden is published under the [MIT license][1] and hosted on 4 | [GitHub][2]. If you find errors or typos please [file an issue][3] or a pull 5 | request on the repository. You can also find us in the [JavaScript room][4] on 6 | Stack Overflow chat. 7 | 8 | [1]: https://github.com/BonsaiDen/JavaScript-Garden/blob/next/LICENSE 9 | [2]: https://github.com/BonsaiDen/JavaScript-Garden 10 | [3]: https://github.com/BonsaiDen/JavaScript-Garden/issues 11 | [4]: http://chat.stackoverflow.com/rooms/17/javascript 12 | 13 | -------------------------------------------------------------------------------- /doc/en/array/constructor.md: -------------------------------------------------------------------------------- 1 | ## The `Array` Constructor 2 | 3 | Since the `Array` constructor is ambiguous in how it deals with its parameters, 4 | it is highly recommended to use the array literal - `[]` notation - 5 | when creating new arrays. 6 | 7 | [1, 2, 3]; // Result: [1, 2, 3] 8 | new Array(1, 2, 3); // Result: [1, 2, 3] 9 | 10 | [3]; // Result: [3] 11 | new Array(3); // Result: [] 12 | new Array('3') // Result: ['3'] 13 | 14 | In cases when there is only one argument passed to the `Array` constructor 15 | and when that argument is a `Number`, the constructor will return a new *sparse* 16 | array with the `length` property set to the value of the argument. It should be 17 | noted that **only** the `length` property of the new array will be set this way; 18 | the actual indexes of the array will not be initialized. 19 | 20 | var arr = new Array(3); 21 | arr[1]; // undefined 22 | 1 in arr; // false, the index was not set 23 | 24 | Being able to set the length of the array in advance is only useful in a few 25 | cases, like repeating a string, in which it avoids the use of a loop. 26 | 27 | new Array(count + 1).join(stringToRepeat); 28 | 29 | ### In Conclusion 30 | 31 | Literals are preferred to the Array constructor. They are shorter, have a clearer syntax, and increase code 32 | readability. 33 | 34 | -------------------------------------------------------------------------------- /doc/en/core/eval.md: -------------------------------------------------------------------------------- 1 | ## Why Not to Use `eval` 2 | 3 | The `eval` function will execute a string of JavaScript code in the local scope. 4 | 5 | var number = 1; 6 | function test() { 7 | var number = 2; 8 | eval('number = 3'); 9 | return number; 10 | } 11 | test(); // 3 12 | number; // 1 13 | 14 | However, `eval` only executes in the local scope when it is being called 15 | directly *and* when the name of the called function is actually `eval`. 16 | 17 | var number = 1; 18 | function test() { 19 | var number = 2; 20 | var copyOfEval = eval; 21 | copyOfEval('number = 3'); 22 | return number; 23 | } 24 | test(); // 2 25 | number; // 3 26 | 27 | The use of `eval` should be avoided. 99.9% of its "uses" can be achieved 28 | **without** it. 29 | 30 | ### `eval` in Disguise 31 | 32 | The [timeout functions](#other.timeouts) `setTimeout` and `setInterval` can both 33 | take a string as their first argument. This string will **always** get executed 34 | in the global scope since `eval` is not being called directly in that case. 35 | 36 | ### Security Issues 37 | 38 | `eval` also is a security problem, because it executes **any** code given to it. 39 | It should **never** be used with strings of unknown or untrusted origins. 40 | 41 | ### In Conclusion 42 | 43 | `eval` should never be used. Any code that makes use of it should be questioned 44 | in its workings, performance and security. If something requires `eval` in 45 | order to work, it should **not** be used in the first place. A *better design* 46 | should be used, that does not require the use of `eval`. 47 | 48 | -------------------------------------------------------------------------------- /doc/en/function/general.md: -------------------------------------------------------------------------------- 1 | ## Function Declarations and Expressions 2 | 3 | Functions in JavaScript are first class objects. That means they can be 4 | passed around like any other value. One common use of this feature is to pass 5 | an *anonymous function* as a callback to another, possibly an asynchronous function. 6 | 7 | ### The `function` Declaration 8 | 9 | function foo() {} 10 | 11 | The above function gets [hoisted](#function.scopes) before the execution of the 12 | program starts; thus, it is available *everywhere* in the scope it was 13 | *defined*, even if called before the actual definition in the source. 14 | 15 | foo(); // Works because foo was created before this code runs 16 | function foo() {} 17 | 18 | ### The `function` Expression 19 | 20 | var foo = function() {}; 21 | 22 | This example assigns the unnamed and *anonymous* function to the variable `foo`. 23 | 24 | foo; // 'undefined' 25 | foo(); // this raises a TypeError 26 | var foo = function() {}; 27 | 28 | Due to the fact that `var` is a declaration that hoists the variable name `foo` 29 | before the actual execution of the code starts, `foo` is already declared when 30 | the script gets executed. 31 | 32 | But since assignments only happen at runtime, the value of `foo` will default 33 | to [undefined](#core.undefined) before the corresponding code is executed. 34 | 35 | ### Named Function Expression 36 | 37 | Another special case is the assignment of named functions. 38 | 39 | var foo = function bar() { 40 | bar(); // Works 41 | } 42 | bar(); // ReferenceError 43 | 44 | Here, `bar` is not available in the outer scope, since the function only gets 45 | assigned to `foo`; however, inside of `bar`, it is available. This is due to 46 | how [name resolution](#function.scopes) in JavaScript works, the name of the 47 | function is *always* made available in the local scope of the function itself. 48 | 49 | -------------------------------------------------------------------------------- /doc/en/index.json: -------------------------------------------------------------------------------- 1 | { 2 | "title": "JavaScript Garden", 3 | "langTitle": "JavaScript Garden in English", 4 | "description": "A Guide to JavaScript's Quirks and Flaws.", 5 | "sections": [ 6 | { 7 | "title": "Intro", 8 | "dir": "intro", 9 | "articles": ["index"] 10 | }, 11 | { 12 | "title": "Objects", 13 | "dir": "object", 14 | "articles": [ 15 | "general", 16 | "prototype", 17 | "hasownproperty", 18 | "forinloop" 19 | ] 20 | }, 21 | { 22 | "title": "Functions", 23 | "dir": "function", 24 | "articles": [ 25 | "general", 26 | "this", 27 | "closures", 28 | "arguments", 29 | "constructors", 30 | "scopes" 31 | ] 32 | }, 33 | { 34 | "title": "Arrays", 35 | "dir": "array", 36 | "articles": [ 37 | "general", 38 | "constructor" 39 | ] 40 | }, 41 | { 42 | "title": "Types", 43 | "dir": "types", 44 | "articles": [ 45 | "equality", 46 | "typeof", 47 | "instanceof", 48 | "casting" 49 | ] 50 | }, 51 | { 52 | "title": "Core", 53 | "dir": "core", 54 | "articles": [ 55 | "eval", 56 | "undefined", 57 | "semicolon", 58 | "delete" 59 | ] 60 | }, 61 | { 62 | "title": "Other", 63 | "dir": "other", 64 | "articles": [ 65 | "timeouts" 66 | ] 67 | } 68 | ] 69 | } 70 | -------------------------------------------------------------------------------- /doc/en/intro/index.md: -------------------------------------------------------------------------------- 1 | ## Intro 2 | 3 | **JavaScript Garden** is a growing collection of documentation about the most 4 | quirky parts of the JavaScript programming language. It gives advice to 5 | avoid common mistakes and subtle bugs, as well as performance issues and bad 6 | practices, that non-expert JavaScript programmers may encounter on their 7 | endeavours into the depths of the language. 8 | 9 | JavaScript Garden does **not** aim to teach you JavaScript. Former knowledge 10 | of the language is strongly recommended in order to understand the topics covered 11 | in this guide. In order to learn the basics of the language, please head over to 12 | the excellent [guide][1] on the Mozilla Developer Network. 13 | 14 | ## The Authors 15 | 16 | This guide is the work of two lovely [Stack Overflow][2] users, [Ivo Wetzel][3] 17 | (Writing) and [Zhang Yi Jiang][4] (Design). 18 | 19 | It's currently maintained by [Tim Ruffles](http://truffles.me.uk). 20 | 21 | ## Contributors 22 | 23 | - Too many to list here, [see all contributors](https://github.com/BonsaiDen/JavaScript-Garden/graphs/contributors). 24 | 25 | 26 | ## Hosting 27 | 28 | JavaScript Garden is hosted on GitHub, but [Cramer Development][7] supports us 29 | with a mirror at [JavaScriptGarden.info][8]. 30 | 31 | ## License 32 | 33 | JavaScript Garden is published under the [MIT license][9] and hosted on 34 | [GitHub][10]. If you find errors or typos please [file an issue][11] or a pull 35 | request on the repository. You can also find us in the [JavaScript room][12] on 36 | Stack Overflow chat. 37 | 38 | [1]: https://developer.mozilla.org/en/JavaScript/Guide 39 | [2]: http://stackoverflow.com/ 40 | [3]: http://stackoverflow.com/users/170224/ivo-wetzel 41 | [4]: http://stackoverflow.com/users/313758/yi-jiang 42 | [5]: https://github.com/caio 43 | [6]: https://github.com/blixt 44 | [7]: http://cramerdev.com/ 45 | [8]: http://javascriptgarden.info/ 46 | [9]: https://github.com/BonsaiDen/JavaScript-Garden/blob/next/LICENSE 47 | [10]: https://github.com/BonsaiDen/JavaScript-Garden 48 | [11]: https://github.com/BonsaiDen/JavaScript-Garden/issues 49 | [12]: http://chat.stackoverflow.com/rooms/17/javascript 50 | -------------------------------------------------------------------------------- /doc/en/types/instanceof.md: -------------------------------------------------------------------------------- 1 | ## The `instanceof` Operator 2 | 3 | The `instanceof` operator compares the constructors of its two operands. It is 4 | only useful when comparing custom made objects. Used on built-in types, it is 5 | nearly as useless as the [typeof operator](#types.typeof). 6 | 7 | ### Comparing Custom Objects 8 | 9 | function Foo() {} 10 | function Bar() {} 11 | Bar.prototype = new Foo(); 12 | 13 | new Bar() instanceof Bar; // true 14 | new Bar() instanceof Foo; // true 15 | 16 | // This just sets Bar.prototype to the function object Foo, 17 | // but not to an actual instance of Foo 18 | Bar.prototype = Foo; 19 | new Bar() instanceof Foo; // false 20 | 21 | ### Using `instanceof` with Native Types 22 | 23 | new String('foo') instanceof String; // true 24 | new String('foo') instanceof Object; // true 25 | 26 | 'foo' instanceof String; // false 27 | 'foo' instanceof Object; // false 28 | 29 | One important thing to note here is that `instanceof` does not work on objects 30 | that originate from different JavaScript contexts (e.g. different documents 31 | in a web browser), since their constructors will not be the exact same object. 32 | 33 | ### In Conclusion 34 | 35 | The `instanceof` operator should **only** be used when dealing with custom made 36 | objects that originate from the same JavaScript context. Just like the 37 | [`typeof`](#types.typeof) operator, every other use of it should be **avoided**. 38 | 39 | -------------------------------------------------------------------------------- /doc/es/array/constructor.md: -------------------------------------------------------------------------------- 1 | ## El constructor `Array` 2 | 3 | Desde el constructor `Array` es ambiguo en la forma en que ocupa sus párametros, 4 | es recomendable siempre el uso de arrays literales - la notación `[]` - 5 | cuando se crean nuevos arrays. 6 | 7 | [1, 2, 3]; // Resultado: [1, 2, 3] 8 | new Array(1, 2, 3); // Resultado: [1, 2, 3] 9 | 10 | [3]; // Resultado: [3] 11 | new Array(3); // Resultado: [] 12 | new Array('3') // Resultado: ['3'] 13 | 14 | En casos cuando sólo hay un argumento pasado al constructor del `Array`, 15 | y que el argumento es un `Número`, el contructor devolverá un array *disperso* 16 | con la propiedad `length` establecida al valor del argumento. Esto debe señalarse 17 | que la propiedad `length` **sólo** del nuevo array se establecerá de esa manera, 18 | los índices reales de la matriz no se iniciará. 19 | 20 | var arr = new Array(3); 21 | arr[1]; // undefined 22 | 1 in arr; // falso, el índice no se ha establecido 23 | 24 | El comportamiento de poder establecer la longitud de un array inicial sólo es útil 25 | en algunos casos array, como la repetición de una cadena, en la que se evita el uso 26 | del código de `bucle for`. 27 | 28 | new Array(count + 1).join(stringToRepeat); 29 | 30 | ### En conclusión 31 | 32 | El uso de un constructor `Array` debe ser devuelto como sea posible. 33 | Los literales son definitivamente preferidos. Estos son más cortos y tienen una 34 | sintaxis más limpia; por lo tanto, también se incrementa la legibilidad del código. 35 | 36 | -------------------------------------------------------------------------------- /doc/es/core/eval.md: -------------------------------------------------------------------------------- 1 | ## ¿Por qué no usar `eval`? 2 | 3 | La función `eval` ejecuta un string como código JavaScript en el ámbito local. 4 | 5 | var foo = 1; 6 | function test() { 7 | var foo = 2; 8 | eval('foo = 3'); 9 | return foo; 10 | } 11 | test(); // 3 12 | foo; // 1 13 | 14 | Pero `eval` sólo ejecutará en ámbito local cuando es llamado **directamente** *y* 15 | el nombre de la función llamada es `eval`. 16 | 17 | var foo = 1; 18 | function test() { 19 | var foo = 2; 20 | var bar = eval; 21 | bar('foo = 3'); 22 | return foo; 23 | } 24 | test(); // 2 25 | foo; // 3 26 | 27 | El uso de `eval` debe evitarse **a toda costa**. El 99.9% de su "uso" puede 28 | lograrse **sin** su uso.. 29 | 30 | ### `eval` disfrazado 31 | 32 | Las funciones de [tiempo de espera](#other.timeouts) `setTimeout` y `setInterval` pueden 33 | tomar un string como primer argumento. En este caso, el string **siempre** se ejecutará en 34 | el ámbito global ya que `eval` no ha sido llamado directamente. 35 | 36 | ### Problemas de seguridad 37 | 38 | `eval` es también un problema de seguridad ya que ejecuta **cualquier** código enviado, 39 | y **nunca** debe usarse con strings que no se conozcan o tengan un origen no confiable. 40 | 41 | ### En conclusión 42 | 43 | `eval` nunca debe ser usado, cualquier código que haga uso del mismo debe ser cuestionado 44 | en su funcionamiento, rendimiento y seguridad. En caso de que se necesite trabajar con 45 | `eval`, el diseño ha de ser cuestionado y **no** debe utilizarse en primer lugar, se 46 | debe usar un *mejor diseño*, que no requiera el uso de `eval`. 47 | 48 | -------------------------------------------------------------------------------- /doc/es/function/general.md: -------------------------------------------------------------------------------- 1 | ## La declaración de funciones y expresiones 2 | 3 | Las funciones en JavaScript son funciones de primera clase `(first class functions)`. 4 | Esto significa que se pueden tratar como objetos. Un uso común de esta característica es pasar de 5 | una *función anónima* a otra, posiblemente una función asíncrona. Esto se conoce como `callback`. 6 | 7 | ### La declaración `function` 8 | 9 | function foo() {} 10 | 11 | La función anterior se [carga](#function.scopes) así mismo antes de iniciar la ejecución del 12 | programa; por lo tanto, está disponible en *todo* el scope (ámbito) de la aplicación 13 | donde se ha *definido*, aunque hubiera sido llamado antes de definirse en el código. 14 | 15 | foo(); // Funciona porque foo ha sido creado antes que este código se ejecute 16 | function foo() {} 17 | 18 | ### La expresión `function` 19 | 20 | var foo = function() {}; 21 | 22 | Este ejemplo asigna una función sin nombre y anónima a la variable `foo`. 23 | 24 | foo; // 'undefined' 25 | foo(); // Lanza TypeError 26 | var foo = function() {}; 27 | 28 | Debido a la declaración de `var`, que carga el nombre de la variable `foo` antes 29 | de la ejecución real del inicio del código, `foo` ya estará definidido cuando se 30 | ejecute el script. 31 | 32 | Pero se asigna sólo si ocurre en tiempo de ejecución, el valor de `foo` de forma 33 | predetermina es [undefined](#core.undefined) antes de que el código se ejecute. 34 | 35 | ### Expresión nombre de función 36 | 37 | Otro caso especial de asignación de nombre de funciones. 38 | 39 | var foo = function bar() { 40 | bar(); // Funciona 41 | } 42 | bar(); // ReferenceError 43 | 44 | Aquí `bar` no está disponible en el ámbito externo (scope), ya que la función sólo es 45 | asignada a `foo`; Sin embargo, dentro de `bar` si está disponible. Esto se debe a la forma 46 | en como trabaja la [resolución de nombres](#function.scopes) en JavaScript, el nombre de 47 | la función esta *siempre* disponible en el ámbito local de la propia función. 48 | 49 | -------------------------------------------------------------------------------- /doc/es/index.json: -------------------------------------------------------------------------------- 1 | { 2 | "title": "Jardín de JavaScript", 3 | "langTitle": "JavaScript Garden es Español", 4 | "description": "Una guía sobre lo peculiar y defectos de JavaScript.", 5 | "sections": [ 6 | { 7 | "title": "Introducción", 8 | "dir": "intro", 9 | "articles": ["index"] 10 | }, 11 | { 12 | "title": "Objetos", 13 | "dir": "object", 14 | "articles": [ 15 | "general", 16 | "prototype", 17 | "hasownproperty", 18 | "forinloop" 19 | ] 20 | }, 21 | { 22 | "title": "Funciones", 23 | "dir": "function", 24 | "articles": [ 25 | "general", 26 | "this", 27 | "closures", 28 | "arguments", 29 | "constructors", 30 | "scopes" 31 | ] 32 | }, 33 | { 34 | "title": "Arrays", 35 | "dir": "array", 36 | "articles": [ 37 | "general", 38 | "constructor" 39 | ] 40 | }, 41 | { 42 | "title": "Tipos", 43 | "dir": "types", 44 | "articles": [ 45 | "equality", 46 | "typeof", 47 | "instanceof", 48 | "casting" 49 | ] 50 | }, 51 | { 52 | "title": "Núcleo", 53 | "dir": "core", 54 | "articles": [ 55 | "eval", 56 | "undefined", 57 | "semicolon" 58 | ] 59 | }, 60 | { 61 | "title": "Otros", 62 | "dir": "other", 63 | "articles": [ 64 | "timeouts" 65 | ] 66 | } 67 | ] 68 | } 69 | -------------------------------------------------------------------------------- /doc/es/intro/index.md: -------------------------------------------------------------------------------- 1 | ## Introducción 2 | 3 | **El Jardín de JavaScript** es una guía de documentación acerca de las 4 | partes más peculiares de este lenguaje de programación. Brinda consejos para evitar 5 | los errores más comunes y sutiles, así como problemas de rendimiento y de malas 6 | prácticas que los programadores menos experimentados en JavaScript pueden resolver 7 | en sus esfuerzos por profundizar en el lenguaje. 8 | 9 | El Jardín de JavaScript **no** prentende enseñar JavaScript. 10 | Se recomienda un conocimiento sobre el lenguaje para entender los temas tratados en 11 | esta guía. Con el fin de aprender los conceptos básicos del lenguaje, por favor 12 | diríjase a la excelente [guía][1] de los desarrolladores de Mozilla. 13 | 14 | ## Los autores 15 | 16 | Esta guía es el trabajo de dos encantadores usuarios del foro Stack Overflow, 17 | [Ivo Wetzel][3] (Escrito) y [Zhang Yi Jiang][4] (Diseño). 18 | 19 | ## Colaboradores 20 | 21 | - [Colaboradores](https://github.com/BonsaiDen/JavaScript-Garden/graphs/contributors) 22 | 23 | ## Hosting 24 | 25 | JavaScript Garden es hospedado en GitHub, además [Cramer Development][7] nos apoya 26 | con un sitio espejo en [JavaScriptGarden.info][8]. 27 | 28 | ## Licencia 29 | 30 | El Jardín de JavaScript es publicado bajo la [licencia MIT][9] y es hospedado en 31 | [GitHub][10]. Si encuentra algún error o errata por favor publique [una incidencia][11] o 32 | envie un pull request a nuestro repositorio. También nos puede encontrar en la 33 | [sala de chat de JavaScript][12] en Stack Overflow. 34 | 35 | [1]: https://developer.mozilla.org/en/JavaScript/Guide 36 | [2]: http://stackoverflow.com/ 37 | [3]: http://stackoverflow.com/users/170224/ivo-wetzel 38 | [4]: http://stackoverflow.com/users/313758/yi-jiang 39 | [5]: https://github.com/caio 40 | [6]: https://github.com/blixt 41 | [7]: http://cramerdev.com/ 42 | [8]: http://javascriptgarden.info/ 43 | [9]: https://github.com/BonsaiDen/JavaScript-Garden/blob/next/LICENSE 44 | [10]: https://github.com/BonsaiDen/JavaScript-Garden 45 | [11]: https://github.com/BonsaiDen/JavaScript-Garden/issues 46 | [12]: http://chat.stackoverflow.com/rooms/17/javascript 47 | -------------------------------------------------------------------------------- /doc/es/object/forinloop.md: -------------------------------------------------------------------------------- 1 | ## El bucle `for in` 2 | 3 | Al igual que el operador `in`, el bucle `for in` también recorre sobre la 4 | cadena de prototipo cuando este se repite en una iteración en las propiedades de un objeto. 5 | 6 | > **Nota:** El bucle `for in` **no** se repetirá en cualquier propiedad que 7 | > tenga atributos `enumerables` asignados a `false`; por ejemplo, la propiedad 8 | > `length` de un array. 9 | 10 | // Envenenamiento en Object.prototype 11 | Object.prototype.bar = 1; 12 | 13 | var foo = {moo: 2}; 14 | for(var i in foo) { 15 | console.log(i); // Imprime ambos bar y moo 16 | } 17 | 18 | Dado que no es posible cambiar el comportamiento del bucle `for in` en sí mismo, es 19 | necesario filtrar las propiedades internas no deseadas dentro del bucle, 20 | esto se hace mediante el uso del método [`hasOwnProperty`](#object.hasownproperty) del 21 | `Object.prototype`. 22 | 23 | > **Nota:** Dado que `for in` siempre recorre por completo la cadena de prototipo, 24 | > este se pondrá más lento con cada capa adicional que un objeto herede. 25 | 26 | ### Usando `hasOwnProperty` para filtrado 27 | 28 | // Aún es el foo del código de arriba 29 | for(var i in foo) { 30 | if (foo.hasOwnProperty(i)) { 31 | console.log(i); 32 | } 33 | } 34 | 35 | Está versión es la única forma correcta de uso. Esto se debe **sólo** al uso de 36 | `hasOwnProperty` que imprimirá `moo`. Cuando `hasOwnProperty` se omita, el código es 37 | propenso a errores en los casos de prototipos nativos - ej. `Object.prototype` - 38 | se ha extendedido. 39 | 40 | Uno de los frameworks más usado que implementa estas funcionalidades es [Prototype][1]. Cuando el 41 | framework es incluido, el bucle `for in` que no utilicen `hasOwnProperty` no podrá garantizar que 42 | se interrumpa. 43 | 44 | ### En conclusión 45 | 46 | Se recomienda utilizar **siempre** el uso de `hasOwnProperty`. Nunca debe suponer 47 | ningún entorno donde el código se ejecute, o si los prototipos 48 | nativos han sido extendidos o no. 49 | 50 | [1]: http://www.prototypejs.org/ 51 | 52 | -------------------------------------------------------------------------------- /doc/es/types/instanceof.md: -------------------------------------------------------------------------------- 1 | ## The `instanceof` Operator 2 | 3 | The `instanceof` operator compares the constructors of its two operands. It is 4 | only useful when comparing custom made objects. Used on built-in types, it is 5 | nearly as useless as the [typeof operator](#types.typeof). 6 | 7 | ### Comparing Custom Objects 8 | 9 | function Foo() {} 10 | function Bar() {} 11 | Bar.prototype = new Foo(); 12 | 13 | new Bar() instanceof Bar; // true 14 | new Bar() instanceof Foo; // true 15 | 16 | // This just sets Bar.prototype to the function object Foo 17 | // But not to an actual instance of Foo 18 | Bar.prototype = Foo; 19 | new Bar() instanceof Foo; // false 20 | 21 | ### Using `instanceof` with Native Types 22 | 23 | new String('foo') instanceof String; // true 24 | new String('foo') instanceof Object; // true 25 | 26 | 'foo' instanceof String; // false 27 | 'foo' instanceof Object; // false 28 | 29 | One important thing to note here is that `instanceof` does not work on objects 30 | that originate from different JavaScript contexts (e.g. different documents 31 | in a web browser), since their constructors will not be the exact same object. 32 | 33 | ### In Conclusion 34 | 35 | The `instanceof` operator should **only** be used when dealing with custom made 36 | objects that originate from the same JavaScript context. Just like the 37 | [`typeof`](#types.typeof) operator, every other use of it should be **avoided**. 38 | 39 | -------------------------------------------------------------------------------- /doc/fi/array/constructor.md: -------------------------------------------------------------------------------- 1 | ## `Array`-konstruktori 2 | 3 | `Array`-oletuskonstruktorin käytös ei ole lainkaan yksiselitteistä. Tämän vuoksi suositellaankin, että konstruktorin sijasta käytetään literaalinotaatiota `[]`. 4 | 5 | [1, 2, 3]; // Tulos: [1, 2, 3] 6 | new Array(1, 2, 3); // Tulos: [1, 2, 3] 7 | 8 | [3]; // Tulos: [3] 9 | new Array(3); // Tulos: [] 10 | new Array('3') // Tulos: ['3'] 11 | 12 | Mikäli `Array`-konstruktorille annetaan vain yksi argumentti ja se on tyypiltään `Number`, konstruktori palauttaa uuden *harvan* taulukon, jonka `length`-attribuutti on asetettu annetun numeron mukaisesti. On tärkeää huomata, että **ainoastaan** `length` asetetaan tällä tavoin, todellisia taulukon indeksejä ei alusteta. 13 | 14 | var arr = new Array(3); 15 | arr[1]; // undefined 16 | 1 in arr; // false, indeksiä ei ole alustettu 17 | 18 | Tämä on käytännöllistä vain harvoin, kuten merkkijonon toiston tapauksessa. Tällöin voidaan välttää `for-luupin` käyttämistä. 19 | 20 | new Array(count + 1).join(stringToRepeat); 21 | 22 | ### Yhteenveto 23 | 24 | `Array`-konstruktorin käyttöä tulee käyttää niin paljon kuin suinkin mahdollista. Sen sijaan on suositeltavaa käyttää literaalinotaatiota. Literaalit ovat lyhyempiä ja niiden syntaksi on selkeämpi. Tämän lisäksi ne tekevät koodista luettavampaa. 25 | 26 | -------------------------------------------------------------------------------- /doc/fi/core/eval.md: -------------------------------------------------------------------------------- 1 | ## Miksi `eval`-funktiota tulee välttää 2 | 3 | `eval` suorittaa JavaScript-koodia sisältävän merkkijonon paikallisessa näkyvyysalueessa. 4 | 5 | var foo = 1; 6 | function test() { 7 | var foo = 2; 8 | eval('foo = 3'); 9 | return foo; 10 | } 11 | test(); // 3 12 | foo; // 1 13 | 14 | `eval` suoritetaan paikallisessa näkyvyysalueessa ainoastaan kun sitä kutsutaan **suorasti** *ja* kutsutun funktion nimi on todellisuudessa `eval`. 15 | 16 | var foo = 1; 17 | function test() { 18 | var foo = 2; 19 | var bar = eval; 20 | bar('foo = 3'); 21 | return foo; 22 | } 23 | test(); // 2 24 | foo; // 3 25 | 26 | `eval`-funktion käyttöä tulee välttää **ehdottomasti**. 99.9% sen "käyttötapauksista" voidaan toteuttaa **ilman** sitä. 27 | 28 | ### Piilotettu `eval` 29 | 30 | [Aikakatkaisufunktiot](#other.timeouts) `setTimeout` and `setInterval` voivat kumpikin ottaa merkkijonon ensimmäisenä argumenttinaan. Kyseinen merkkijono suoritetaan **aina** globaalissa näkyvyysalueessa, koska tuolloin `eval`-funktiota kutsutaan epäsuorasti. 31 | 32 | ### Turvallisuusongelmat 33 | 34 | `eval` on myös turvallisuusongelma. Se suorittaa **minkä tahansa** sille annetun koodin. Tämän vuoksi sitä ei tule **ikinä** käyttää tuntemattomasta tai epäluotttavasta lähteestä tulevien merkkijonojen kanssa. 35 | 36 | ### Yhteenveto 37 | 38 | `eval`-funktiota ei pitäisi käyttää koskaan. Mikä tahansa sitä käyttävä koodi on kyseenalaista sekä suorituskyvyn että turvallisuuden suhteen. Mikäli jokin tarvitsee `eval`-funktiota toimiakseen, tulee sen suunnittelutapa kyseenalaistaa. Tässä tapauksessa on parempi suunnitella toisin ja välttää `eval`-funktion käyttöä. 39 | 40 | -------------------------------------------------------------------------------- /doc/fi/function/general.md: -------------------------------------------------------------------------------- 1 | ## Funktiomääreet ja lausekkeet 2 | 3 | JavaScriptissä funktiot ovat ensimmäisen luokan olioita. Tämä tarkoittaa sitä, että niitä voidaan välittää kuten muitakin arvoja. Usein tätä käytetään takaisinkutsuissa käyttämällä *nimettömiä, mahdollisesti asynkronisia funktioita*. 4 | 5 | ### `function`-määre 6 | 7 | function foo() {} 8 | 9 | Yllä oleva funktio [hilataan](#function.scopes) ennen ohjelman suorituksen alkua. Se näkyy *kaikkialle* näkyvyysalueessaan, jossa se on *määritelty*. Tämä on totta jopa silloin, jos sitä kutsutaan ennen määrittelyään. 10 | 11 | foo(); // Toimii, koska foo on luotu ennen kuin koodi suoritetaan 12 | function foo() {} 13 | 14 | ### `function`-lauseke 15 | 16 | var foo = function() {}; 17 | 18 | Tämä esimerkki asettaa nimeämättömän ja *nimettömän* funktion muuttujan `foo` arvoksi. 19 | 20 | foo; // 'undefined' 21 | foo(); // tämä palauttaa TypeError-virheen 22 | var foo = function() {}; 23 | 24 | `var` on määre. Tästä johtuen se hilaa muuttujanimen `foo` ennen kuin itse koodia ryhdytään suorittamaan. 25 | 26 | Sijoituslauseet suoritetaan *vasta* kun niihin saavutaan. Tästä johtuen `foo` saa arvokseen [undefined](#core.undefined) ennen kuin varsinaista sijoitusta päästään suorittamaan. 27 | 28 | ### Nimetty funktiolauseke 29 | 30 | Nimettyjen funktioiden sijoitus tarjoaa toisen erikoistapauksen. 31 | 32 | var foo = function bar() { 33 | bar(); // Toimii 34 | } 35 | bar(); // ReferenceError 36 | 37 | Tässä tapauksessa `bar` ei ole saatavilla ulommalla näkyvyysalueessa. Tämä johtuu siitä, että se on sidottu `foo`:n sisälle. Tämä johtuu siitä, kuinka näkyvyysalueet ja niihin kuuluvat jäsenet [tulkitaan](#function.scopes). Funktion nimi on *aina* saatavilla sen paikallisessa näkyvyysalueessa itsessään. 38 | 39 | -------------------------------------------------------------------------------- /doc/fi/index.json: -------------------------------------------------------------------------------- 1 | { 2 | "title": "JavaScript-puutarha", 3 | "langTitle": "JavaScript-puutarha suomeksi", 4 | "description": "Opas JavaScriptin outouksiin ja vikoihin ", 5 | "sections": [ 6 | { 7 | "title": "Johdanto", 8 | "dir": "intro", 9 | "articles": [ 10 | "authors", 11 | "contributors", 12 | "translators", 13 | "license" 14 | ] 15 | }, 16 | { 17 | "title": "Oliot", 18 | "dir": "object", 19 | "articles": [ 20 | "general", 21 | "prototype", 22 | "hasownproperty", 23 | "forinloop" 24 | ] 25 | }, 26 | { 27 | "title": "Funktiot", 28 | "dir": "function", 29 | "articles": [ 30 | "general", 31 | "this", 32 | "closures", 33 | "arguments", 34 | "constructors", 35 | "scopes" 36 | ] 37 | }, 38 | { 39 | "title": "Taulukot", 40 | "dir": "array", 41 | "articles": [ 42 | "general", 43 | "constructor" 44 | ] 45 | }, 46 | { 47 | "title": "Tyypit", 48 | "dir": "types", 49 | "articles": [ 50 | "equality", 51 | "typeof", 52 | "instanceof", 53 | "casting" 54 | ] 55 | }, 56 | { 57 | "title": "Ydin", 58 | "dir": "core", 59 | "articles": [ 60 | "eval", 61 | "undefined", 62 | "semicolon" 63 | ] 64 | }, 65 | { 66 | "title": "Muuta", 67 | "dir": "other", 68 | "articles": [ 69 | "timeouts" 70 | ] 71 | } 72 | ] 73 | } 74 | -------------------------------------------------------------------------------- /doc/fi/intro/authors.md: -------------------------------------------------------------------------------- 1 | ## Tekijät 2 | 3 | Tämä opas pohjautuu kahden mukavan [Stack Overflow][3] käyttäjän työhön. He ovat [Ivo Wetzel][1] (kirjoittaminen) sekä [Zhang Yi Jiang][2] (ulkoasu). 4 | 5 | [1]: http://stackoverflow.com/users/170224/ivo-wetzel 6 | [2]: http://stackoverflow.com/users/313758/yi-jiang 7 | [3]: http://stackoverflow.com/ 8 | 9 | -------------------------------------------------------------------------------- /doc/fi/intro/contributors.md: -------------------------------------------------------------------------------- 1 | ## Osallistujat 2 | 3 | - [Osallistujat](https://github.com/BonsaiDen/JavaScript-Garden/graphs/contributors) 4 | -------------------------------------------------------------------------------- /doc/fi/intro/index.md: -------------------------------------------------------------------------------- 1 | ## Johdanto 2 | 3 | **JavaScript-puutarha** sisältää kasvavan kokoelman JavaScriptin ongelmallisiin osiin liittyvää dokumentaatiota. Se tarjoaa vinkkejä, joiden avulla välttää yleisiä virheitä, bugeja sekä suorituskykyongelmia ja huonoja tapoja, joita aloittelevat JavaScript-ohjelmoijat saattavat kohdata kieleen tutustuessaan. 4 | 5 | JavaScript-puutarha **ei** tähtää itse kielen opettamiseen. On suositeltavaa, että lukija ymmärtää jo kielen perusteet ennen itse tekstin lukemista. Nämä perusteet voit oppia esimerkiksi perehtymällä Mozilla Developer Networkin erinomaiseen [oppaaseen][1]. 6 | 7 | [1]: https://developer.mozilla.org/en/JavaScript/Guide 8 | 9 | -------------------------------------------------------------------------------- /doc/fi/intro/license.md: -------------------------------------------------------------------------------- 1 | ## Lisenssi 2 | 3 | JavaScript-puutarha on julkaistu [MIT-lisenssin][1]-alaisena ja se on saatavilla [GitHubissa][2]. Mikäli löydät virheitä, lisää se [seurantajärjestelmään][3] tai tee `pull`-pyyntö. Löydät meidät myös [JavaScript huoneesta][4] Stack Overflown chatista. 4 | 5 | [1]: https://github.com/BonsaiDen/JavaScript-Garden/blob/next/LICENSE 6 | [2]: https://github.com/BonsaiDen/JavaScript-Garden 7 | [3]: https://github.com/BonsaiDen/JavaScript-Garden/issues 8 | [4]: http://chat.stackoverflow.com/rooms/17/javascript 9 | 10 | -------------------------------------------------------------------------------- /doc/fi/intro/translators.md: -------------------------------------------------------------------------------- 1 | ## Kääntäjät 2 | 3 | - [Juho Vepsäläinen][1] 4 | 5 | [1]: https://github.com/bebraw 6 | -------------------------------------------------------------------------------- /doc/fi/object/forinloop.md: -------------------------------------------------------------------------------- 1 | ## `for in`-luuppi 2 | 3 | Aivan kuten `in`-operaattori, myös `for in`-luuppi käy olion prototyyppiketjun läpi iteroidessaan sen ominaisuuksia. 4 | 5 | > **Huomio:** `for in`-luuppi **ei** iteroi ominaisuuksia, joiden `enumerable`-attribuutti on asetettu arvoon `false`. Eräs esimerkki tästä on taulukon `length`-ominaisuus. 6 | 7 | // Object.prototypen myrkyttäminen 8 | Object.prototype.bar = 1; 9 | 10 | var foo = {moo: 2}; 11 | for(var i in foo) { 12 | console.log(i); // tulostaa sekä bar että moo 13 | } 14 | 15 | Koska `for in`-luupin käytöstapaa ei voida muokata suoraan, tulee ei-halutut ominaisuudet karsia itse luupin sisällä. Tämä on mahdollista käyttäen `Object.prototype`-olion [`hasOwnProperty`](#object.hasownproperty)-metodia. 16 | 17 | > **Huomio:** `for in`-luupin suorittaminen hidastuu sitä enemmän, mitä pidempi olion prototyyppiketju on. Tämä johtuu siitä, että se joutuu käymään koko ketjun sisällön läpi. 18 | 19 | ### `hasOwnProperty`-metodin käyttäminen karsimiseen 20 | 21 | // foo kuten yllä 22 | for(var i in foo) { 23 | if (foo.hasOwnProperty(i)) { 24 | console.log(i); 25 | } 26 | } 27 | 28 | Tämä versio on ainut oikea. Se tulostaa **ainoastaan** `moo`, koska se käyttää `hasOwnProperty`-metodia oikein. Kun se jätetään pois, on koodi altis virheille tapauksissa, joissa prototyyppejä, kuten `Object.prototype`, on laajennettu. 29 | 30 | [Prototype][1] on eräs yleisesti käytetty ohjelmointialusta, joka tekee näin. Kun kyseistä alustaa käytetään, `for in`-luupit, jotka eivät käytä `hasOwnProperty`-metodia, menevät varmasti rikki. 31 | 32 | ### Yhteenveto 33 | 34 | On suositeltavaa käyttää **aina** `hasOwnProperty`-metodia. Ei ole kannattavaa tehdä ajoympäristöön tai prototyyppeihin liittyviä oletuksia. 35 | 36 | [1]: http://www.prototypejs.org/ 37 | 38 | -------------------------------------------------------------------------------- /doc/fi/object/hasownproperty.md: -------------------------------------------------------------------------------- 1 | ## `hasOwnProperty` 2 | 3 | Jotta voimme tarkistaa onko olion ominaisuus määritelty siinä *itsessään*, tulee käyttää erityistä `Object.prototype`-oliosta periytyvää `hasOwnProperty`-metodia. Tällä tavoin vältämme [prototyyppiketjun](#object.prototype) sisältämät ominaisuudet. 4 | 5 | > **Huomio:** **Ei** riitä tarkistaa vain että ominaisuuden arvo on `undefined`. Ominaisuus voi hyvinkin olla olemassa. Sen arvoksi on vain satuttu asettamaan `undefined`. 6 | 7 | `hasOwnProperty` on ainut JavaScriptin sisältämä metodi, joka käsittelee ominaisuuksia **eikä** käy prototyyppiketjun sisältöä läpi. 8 | 9 | // Object.prototypen myrkyttäminen 10 | Object.prototype.bar = 1; 11 | var foo = {goo: undefined}; 12 | 13 | foo.bar; // 1 14 | 'bar' in foo; // tosi 15 | 16 | foo.hasOwnProperty('bar'); // epätosi 17 | foo.hasOwnProperty('goo'); // tosi 18 | 19 | Ainoastaan `hasOwnProperty` palauttaa oikean ja odotetun tuloksen. Sen tietäminen on olennaista minkä tahansa olion ominaisuuksia iteroidessa. Tämä on **ainut** tapa löytää olion itsensä ominaisuudet prototyyppiketjusta riippumatta. 20 | 21 | ### `hasOwnProperty` ominaisuutena 22 | 23 | JavaScript **ei** suojele `hasOwnProperty`-metodin nimeä. Täten on mahdollista, että olio voi sisältää samannimisen ominaisuuden. Jotta voimme saada oikeita tuloksia, tulee sen sijaan käyttää *ulkoista* `hasOwnProperty`-metodia. 24 | 25 | var foo = { 26 | hasOwnProperty: function() { 27 | return false; 28 | }, 29 | bar: 'Olkoon vaikka lohikäärmeitä' 30 | }; 31 | 32 | foo.hasOwnProperty('bar'); // palauttaa aina epätoden 33 | 34 | // Käytä toisen olion hasOwnProperty-metodia ja kutsu sitä asettamalla 35 | // 'this' foohon 36 | ({}).hasOwnProperty.call(foo, 'bar'); // tosi 37 | 38 | ### Yhteenveto 39 | 40 | Mikäli pitää selvittää kuuluuko ominaisuus olioon vai ei, **ainoastaan** `hasOwnProperty` voi kertoa sen. Tämän lisäksi on suositeltavaa käyttää `hasOwnProperty`-metodia osana **jokaista** [`for in`-luuppia](#object.forinloop). Tällä tavoin voidaan välttää natiivien [prototyyppien](#object.prototype) laajentamiseen liittyviä ongelmia. 41 | 42 | -------------------------------------------------------------------------------- /doc/fi/types/instanceof.md: -------------------------------------------------------------------------------- 1 | ## `instanceof`-operaattori 2 | 3 | `instanceof`-operaattori vertaa kahden operandinsa konstruktoreita keskenään. Se on hyödyllinen ainoastaan, kun vertaillaan itsetehtyjä olioita. Natiivien tyyppien tapauksessa se on lähes yhtä hyödytön kuin [typeof-operaattori](#types.typeof). 4 | 5 | ### Itsetehtyjen olioiden vertailu 6 | 7 | function Foo() {} 8 | function Bar() {} 9 | Bar.prototype = new Foo(); 10 | 11 | new Bar() instanceof Bar; // tosi 12 | new Bar() instanceof Foo; // tosi 13 | 14 | // Tämä asettaa vain Bar.prototype-ominaisuudeksi 15 | // funktio-olion Foo 16 | // Se ei kuitenkaan ole Foon todellinen instanssi 17 | Bar.prototype = Foo; 18 | new Bar() instanceof Foo; // epätosi 19 | 20 | ### `instanceof` ja natiivit tyypit 21 | 22 | new String('foo') instanceof String; // tosi 23 | new String('foo') instanceof Object; // tosi 24 | 25 | 'foo' instanceof String; // epätosi 26 | 'foo' instanceof Object; // epätosi 27 | 28 | On tärkeää huomata, että `instanceof` ei toimi olioilla, jotka tulevat muista JavaScript-konteksteista (esim. selaimen eri dokumenteista). Tässä tapauksessa niiden konstruktorit viittaavat eri olioon. 29 | 30 | ### Yhteenveto 31 | 32 | `instanceof`-operaattoria tulee käyttää **ainoastaan**, mikäli käsitellään itsetehtyjä olioita saman JavaScript-kontekstin sisällä. Kuten [`typeof`](#types.typeof)-operaattorikin, myös muita sen käyttöjä tulee **välttää**. 33 | 34 | -------------------------------------------------------------------------------- /doc/fr/array/constructor.md: -------------------------------------------------------------------------------- 1 | ## Le constructeur `Array` 2 | 3 | Le constructeur `Array` traite ses paramètres de façon ambigu. 4 | Il est fortement recommandé d'utiliser le littéral de tableau - notation `[]` - pour créer de nouveaux tableaux. 5 | 6 | [1, 2, 3]; // Résultat: [1, 2, 3] 7 | new Array(1, 2, 3); // Résultat: [1, 2, 3] 8 | 9 | [3]; // Résultat: [3] 10 | new Array(3); // Résultat: [] 11 | new Array('3') // Résultat: ['3'] 12 | 13 | Dans les cas où il n'y a qu'un seul argument passé au constructeur `Array`, et quand cet argument est un nombre `Number`, le constructeur va retourner un nouveau tableau *clairsemé* avec la propriété `length` (longueur) fixée à la valeur de l'argument. 14 | Il faut noter que de cette façon, **seulement** la propriété `length` du nouveau tableau sera mise en place, les indices réels du tableau ne seront pas initialisés. 15 | 16 | var arr = new Array(3); 17 | arr[1]; // undefined 18 | 1 in arr; // faux, l'indice n'existe pas 19 | 20 | Être en mesure de régler la longueur du tableau à l'avance n'est utile que dans quelques cas, comme la répétition d'une chaîne de caractères, dans lequel on évite l'utilisation d'une boucle. 21 | 22 | new Array(count + 1).join(chaineARepeter); 23 | 24 | ### En conclusion 25 | 26 | Les littéraux sont préférés au constructeur `Array`. Ils sont plus courts, ont une syntaxe plus claire, et augmente la lisibilité du code. 27 | 28 | -------------------------------------------------------------------------------- /doc/fr/core/eval.md: -------------------------------------------------------------------------------- 1 | ## Il ne faut pas utiliser `eval` 2 | 3 | La fonction `eval` exécute une chaîne de caractères représentant du code JavaScript dans la portée locale. 4 | 5 | var number = 1; 6 | function test() { 7 | var number = 2; 8 | eval('number = 3'); 9 | return number; 10 | } 11 | test(); // 3 12 | number; // 1 13 | 14 | Cependant, `eval` n'exécute dans la portée locale que quand il est appelé directement *et* quand le nom de la fonction appelée est en fait `eval`. 15 | 16 | var number = 1; 17 | function test() { 18 | var number = 2; 19 | var copyOfEval = eval; 20 | copyOfEval('number = 3'); 21 | return number; 22 | } 23 | test(); // 2 24 | number; // 3 25 | 26 | L'utilisation de la fonction `eval` doit être évitée. 99,9% de ses "cas d'utilisation" peuvent être obtenues **sans** elle. 27 | 28 | ### `eval` déguisé 29 | 30 | Les [fonctions timeout](#other.timeouts) `setTimeout` et `setInterval` acceptent une chaîne comme premier argument. 31 | Cette chaîne sera **toujours** exécutée dans la portée globale car dans ce cas, `eval` n'est pas appelé directement. 32 | 33 | ### Problèmes de sécurité 34 | 35 | `eval` est aussi un problème de sécurité, car il exécute **n'importe quel** code qu'on lui donne. 36 | Il devrait **jamais** être utilisé avec des chaînes d'origines inconnues ou douteuses. 37 | 38 | ### En conclusion 39 | 40 | `eval` ne devrait jamais être utilisé. Sa presence met en doute le fonctionnement, la performance, et la sécurité du code qui l'utilise. 41 | Si quelque chose a besoin d'`eval` pour pouvoir fonctionner, il ne doit **pas** être utilisé en premier lieu. Un *meilleur design* qui n'utilise pas `eval` doit être trouvé et implementé. 42 | 43 | -------------------------------------------------------------------------------- /doc/fr/function/general.md: -------------------------------------------------------------------------------- 1 | ## Déclaration des fonctions et expressions 2 | 3 | Les fonctions en JavaScript sont des objets de première classe. Cela signifie qu'elles peuvent être passées comme toute autre valeur. Une utilisation courante de cette caractéristique est de passer une *fonction anonyme* comme une fonction de rappel "callback" qui peut être asynchrone. 4 | 5 | ### La déclaration `function` 6 | 7 | function foo() {} 8 | 9 | La fonction ci-dessus est [hissée](#function.scopes) "hoisted" avant le démarrage du programme; ainsi, elle est donc disponible partout dans la portée "scope" d'application où la fonction a été définie, même si appelé avant sa définition dans le code source. 10 | 11 | foo(); // Fonctionne car foo a été crée avant l'exécution de ce code 12 | function foo() {} 13 | 14 | ### L'expresssion `function` 15 | 16 | var foo = function() {}; 17 | 18 | Cet exemple attribue une fonction *anonyme* et sans nom à la variable `foo`. 19 | 20 | foo; // 'undefined' 21 | foo(); // provoque un erreur de type TypeError 22 | var foo = function() {}; 23 | 24 | En raison du fait que `var` est une déclaration qui hisse le nom de la variable `foo` avant que l'exécution réelle du code ne commence, `foo` est déjà déclarée lorsque le script est exécuté. 25 | 26 | Mais comme les assignements ne se produisent qu'au moment de l'exécution, la valeur de `foo` sera par défaut mise à [undefined](#core.undefined) avant l'exécution du code. 27 | 28 | ### L'expression de fonction nommée 29 | 30 | Un autre cas est l'attribution de fonctions nommées. 31 | 32 | var foo = function bar() { 33 | bar(); // Works 34 | } 35 | bar(); // erreur de reference ReferenceError 36 | 37 | Ici, `bar` n'est pas disponible dans la portée externe "outer scope", puisque la fonction est seulement assignée à `foo`, mais elle est disponible à l'intérieur de `bar`. Cela est dû à la méthode de [résolution de noms](#function.scopes) de JavaScript: le nom de la fonction est *toujours* disponible dans la portée locale "local scope" de la fonction elle-même. 38 | 39 | -------------------------------------------------------------------------------- /doc/fr/index.json: -------------------------------------------------------------------------------- 1 | { 2 | "title": "Le Jardin de JavaScript", 3 | "langTitle": "JavaScript Garden en Français", 4 | "description": "Un guide des defauts et excentricités de JavaScript", 5 | "sections": [ 6 | { 7 | "title": "Introduction", 8 | "dir": "intro", 9 | "articles": ["index"] 10 | }, 11 | { 12 | "title": "Objets", 13 | "dir": "object", 14 | "articles": [ 15 | "general", 16 | "prototype", 17 | "hasownproperty", 18 | "forinloop" 19 | ] 20 | }, 21 | { 22 | "title": "Fonctions", 23 | "dir": "function", 24 | "articles": [ 25 | "general", 26 | "this", 27 | "closures", 28 | "arguments", 29 | "constructors", 30 | "scopes" 31 | ] 32 | }, 33 | { 34 | "title": "Tableaux", 35 | "dir": "array", 36 | "articles": [ 37 | "general", 38 | "constructor" 39 | ] 40 | }, 41 | { 42 | "title": "Types", 43 | "dir": "types", 44 | "articles": [ 45 | "equality", 46 | "typeof", 47 | "instanceof", 48 | "casting" 49 | ] 50 | }, 51 | { 52 | "title": "Cœur", 53 | "dir": "core", 54 | "articles": [ 55 | "eval", 56 | "undefined", 57 | "semicolon", 58 | "delete" 59 | ] 60 | }, 61 | { 62 | "title": "Autres", 63 | "dir": "other", 64 | "articles": [ 65 | "timeouts" 66 | ] 67 | } 68 | ] 69 | } 70 | -------------------------------------------------------------------------------- /doc/fr/types/instanceof.md: -------------------------------------------------------------------------------- 1 | ## L'opérateur `instanceof` 2 | 3 | L'opérateur `instanceof` (instance de) compare les constructeurs de ses deux opérandes. Il est seulement utile pour comparer des objets faits sur mesure. Utilisé sur les types intégrés, il est 4 | aussi inutile que l'[opérateur typeof](# types.typeof). 5 | 6 | ### Comparer des objets personnalisés 7 | 8 | function Foo() {} 9 | function Bar() {} 10 | Bar.prototype = new Foo(); 11 | 12 | new Bar() instanceof Bar; // vrai 13 | new Bar() instanceof Foo; // vrai 14 | 15 | // Ceci définit simplement Bar.prototype à l'objet de fonction Foo, 16 | // mais pas à une instance réelle de Foo 17 | Bar.prototype = Foo; 18 | new Bar() instanceof Foo; // faux 19 | 20 | ### Utiliser `instanceof` avec des types natifs 21 | 22 | new String('foo') instanceof String; // vrai 23 | new String('foo') instanceof Object; // vrai 24 | 25 | 'foo' instanceof String; // faux 26 | 'foo' instanceof Object; // faux 27 | 28 | Une chose importante à noter ici est que `instanceof` ne fonctionne pas sur les objets qui proviennent de différents contextes JavaScript (par exemple, différents documents 29 | dans un navigateur web), car leurs constructeurs ne seront pas exactement le même objet. 30 | 31 | ### En conclusion 32 | 33 | L'opérateur `instanceof` devrait **seulement** être utilisé sur des objets crées sur mesure provenant du même contexte JavaScript. 34 | Tout comme l'opérateur [`typeof`](#types.typeof), chaque autre utilisation de celui-ci devrait être **évitée**. 35 | 36 | -------------------------------------------------------------------------------- /doc/hu/array/constructor.md: -------------------------------------------------------------------------------- 1 | ## Az `Array` konstruktor 2 | 3 | Mivel az `Array` konstruktora kétértelműen bánik a paraméterekkel, melegen 4 | ajánlott mindig a tömb literált - `[]` jelölés - használni új tömbök létrehozásakor. 5 | 6 | [1, 2, 3]; // Eredmény: [1, 2, 3] 7 | new Array(1, 2, 3); // Eredmény: [1, 2, 3] 8 | 9 | [3]; // Eredmény: [3] 10 | new Array(3); // Eredmény: [] 11 | new Array('3') // Eredmény: ['3'] 12 | 13 | Abban az esetben, ha ez a konstruktor csak egy `szám` paramétert kap, akkor 14 | visszatérési értékül egy olyan tömböt fog létrehozni amelynek a `length` mezője 15 | akkorára van beállítva, ahogy azt megadtuk az argumentumban. Megjegyzendő hogy 16 | **csak** a `length` tulajdonság lesz ekkor beállítva; az egyes indexek külön-külön 17 | nem lesznek inicializálva. 18 | 19 | var arr = new Array(3); 20 | arr[1]; // undefined 21 | 1 in arr; // hamis, nincs ilyen index 22 | 23 | A tömb hosszának közvetlen állítása amúgy is csak elég kevés esetben 24 | használható értelmesen, mint például alább, hogyha el akarjuk kerülni a 25 | `for ciklus` használatát egy string ismétlésekor. 26 | 27 | new Array(count + 1).join(ismetlendoString); 28 | 29 | ### Összegzésül 30 | 31 | Az `Array` konstruktor közvetlen használata erősen kerülendő. A literálok használata 32 | elfogadott inkább, mivel rövidebbek, tisztább a szintaxisuk és olvashatóbb kódot 33 | eredményeznek. 34 | 35 | -------------------------------------------------------------------------------- /doc/hu/core/eval.md: -------------------------------------------------------------------------------- 1 | ## Miért Ne Használjuk az `eval`-t 2 | 3 | Az `eval` (evil) funkció egy stringbe ágyazott JavaScript kódot futtat a 4 | lokális scopeon belül. 5 | 6 | var foo = 1; 7 | function test() { 8 | var foo = 2; 9 | eval('foo = 3'); 10 | return foo; 11 | } 12 | test(); // 3 13 | foo; // 1 14 | 15 | Viszont az `eval` csak akkor viselkedik így, hogyha expliciten hívjuk meg 16 | *és* a meghívott funkció neve valóban `eval`. 17 | 18 | var foo = 1; 19 | function test() { 20 | var foo = 2; 21 | var bar = eval; 22 | bar('foo = 3'); 23 | return foo; 24 | } 25 | test(); // 2 26 | foo; // 3 27 | 28 | Az `eval` használata kerülendő. A "felhasználása" az esetek 99.9%-ban 29 | **mellőzhető**. 30 | 31 | ### Az `eval` ezer arca 32 | 33 | A `setTimeout` és `setInterval` nevű [timeout függvények](#other.timeouts) is 34 | tudnak úgy működni, hogy első paraméterükként egy stringbe ágyazott kódot várnak. 35 | Ez a string **mindig** a globális hatókörben lesz végrehajtva, mivel az `eval`t 36 | így nem direktben hívjuk meg. 37 | 38 | ### Biztonsági problémák 39 | 40 | Az `eval` azért is veszélyes, mert **bármilyen** JS kódot végrehajt, amit odaadunk 41 | neki. Éppen ezért **sose** használjuk olyan kódok végrehajtására amiknek az eredete 42 | nem megbízható/ismeretlen. 43 | 44 | ### Összegzésül 45 | 46 | Soha ne használjunk `eval`t. Bármilyen kód működése, teljesítménye, ill. biztonsága 47 | megkérdőjelezhető, amely használja ezt a nyelvi elemet. Semmilyen megoldás 48 | használata **nem ajánlott** amely első sorban `eval`ra épül. Ekkor egy *jobb 49 | megoldás* szükségeltetik, amely nem függ az `eval`tól. -------------------------------------------------------------------------------- /doc/hu/function/general.md: -------------------------------------------------------------------------------- 1 | ## Függvény deklarációk és kifejezések 2 | 3 | A függvények JavaScriptben egyben objektumok is. Ez azt jelenti, hogy 4 | ugyanúgy lehet őket passzolgatni, mint bármelyik más értékeket. Ezt a featuret 5 | gyakran használják arra, hogy egy *névtelen (callback) függvényt* átadjunk 6 | egy másik -aszinkron- függvény paramétereként. 7 | 8 | ### A `függvény` deklaráció 9 | 10 | function foo() {} 11 | 12 | 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ő, 13 | 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 14 | definiáltuk volna (látszólag). 15 | 16 | foo(); // Így is működik 17 | function foo() {} 18 | 19 | ### A `függvény` kifejezés (expression) 20 | 21 | var foo = function() {}; 22 | 23 | A fentebbi példában egy *névtelen* függvényt adunk értékül a foo változónak. 24 | 25 | foo; // 'undefined' 26 | foo(); // TypeError hiba 27 | var foo = function() {}; 28 | 29 | Habár ebben a példában a `var` deklaráció futás előtt a kód tetejére kúszik, 30 | ettől függetlenül a foo mint függvény meghívásakor hibát fogunk kapni. 31 | 32 | Ugyanis a deklaráció felkúszott, azonban az értékadás csak futásidőben fog megtörténni, 33 | 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. 34 | 35 | ### Névvel ellátott függvény kifejezés 36 | 37 | Egy másik érdekes eset, amikor névvel ellátott függvényeket adunk értékül változóknak. 38 | 39 | var foo = function bar() { 40 | bar(); // Működik 41 | } 42 | bar(); // ReferenceError 43 | 44 | Ebben a példában a `bar`t önmagában nem lehet elérni egy külső scope-ból (utolsó sor), 45 | mivel egyből értékül adtuk a `foo` változónak. Ennek ellenére a `bar`on belül elérhető 46 | 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ő. 47 | 48 | 49 | -------------------------------------------------------------------------------- /doc/hu/index.json: -------------------------------------------------------------------------------- 1 | { 2 | "title": "JavaScript Garden", 3 | "description": "Bevezet\u00E9s a JavaScript bugyraiba, hib\u00E1iba.", 4 | "langTitle": "A JavaScript Garden magyarul", 5 | "sections": [ 6 | { 7 | "title": "Bevezet\u0151", 8 | "dir": "intro", 9 | "articles": [ "index" ] 10 | }, 11 | { 12 | "title": "Objektumok", 13 | "dir": "object", 14 | "articles": [ 15 | "general", 16 | "prototype", 17 | "hasownproperty", 18 | "forinloop" 19 | ] 20 | }, 21 | { 22 | "title": "F\u00FCggv\u00E9nyek", 23 | "dir": "function", 24 | "articles": [ 25 | "general", 26 | "this", 27 | "closures", 28 | "arguments", 29 | "constructors", 30 | "scopes" 31 | ] 32 | }, 33 | { 34 | "title": "T\u00F6mb\u00F6k", 35 | "dir": "array", 36 | "articles": [ 37 | "general", 38 | "constructor" 39 | ] 40 | }, 41 | { 42 | "title": "T\u00EDpusok", 43 | "dir": "types", 44 | "articles": [ 45 | "equality", 46 | "typeof", 47 | "instanceof", 48 | "casting" 49 | ] 50 | }, 51 | { 52 | "title": "L\u00E9nyeg", 53 | "dir": "core", 54 | "articles": [ 55 | "eval", 56 | "undefined", 57 | "semicolon", 58 | "delete" 59 | ] 60 | }, 61 | { 62 | "title": "Egy\u00E9b", 63 | "dir": "other", 64 | "articles": [ 65 | "timeouts" 66 | ] 67 | } 68 | ] 69 | } 70 | -------------------------------------------------------------------------------- /doc/hu/types/instanceof.md: -------------------------------------------------------------------------------- 1 | ## Az `instanceof` operátor 2 | 3 | Az `instanceof` operátor a két operandusának konstruktorait hasonlítja össze. 4 | Csak akkor bizonyul hasznosnak, amikor saját készítésű objektumokon alkalmazzuk. 5 | Beépített típusokon ugyanolyan hasztalan alkalmazni, mint a [typeof operátort](#types.typeof). 6 | 7 | ### Saját objektumok összehasonlítása 8 | 9 | function Foo() {} 10 | function Bar() {} 11 | Bar.prototype = new Foo(); 12 | 13 | new Bar() instanceof Bar; // igaz 14 | new Bar() instanceof Foo; // igaz 15 | 16 | // Ez csak a Bar.prototypeot beállítja a Foo fv. objektumra, 17 | // de nem egy kimondott Foo példányra 18 | Bar.prototype = Foo; 19 | new Bar() instanceof Foo; // hamis 20 | 21 | ### Az `instanceof` reakciója natív típusokra 22 | 23 | new String('foo') instanceof String; // igaz 24 | new String('foo') instanceof Object; // igaz 25 | 26 | 'foo' instanceof String; // hamis 27 | 'foo' instanceof Object; // hamis 28 | 29 | Érdemes itt megjegyezni hogy az `instanceof` nem működik olyan objektumokon, 30 | amelyek különböző JavaScript kontextusokból származnak (pl. különböző dokumentumok 31 | a böngészőn belül), mivel a konstruktoruk nem pontosan ugyanaz az objektum lesz. 32 | 33 | ### Összegzésül 34 | 35 | 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. -------------------------------------------------------------------------------- /doc/hu/types/typeof.md: -------------------------------------------------------------------------------- 1 | ## A `typeof` vizsgálat 2 | 3 | A `typeof` operátor (az [`instanceof`](#types.instanceof)-al karöltve) 4 | lehetőség szerint a JavaScript nyelv egyik legnagyobb buktatója, mivel majdnem 5 | teljesen **rosszul működik**. 6 | 7 | Habár az `instanceof`-nak korlátozottan még lehet értelme, a `typeof` operátor 8 | tényleg csak egyetlen praktikus use case-el rendelkezik és ez **nem** az, hogy egy 9 | objektum típusvizsgálatát elvégezzük. 10 | 11 | > **Megjegyzés:** Mivel a `typeof` vizsgálatot ravaszul úgy is le lehet írni, 12 | > mintha egy függvény lenne; `typeof(obj)`, itt jegyezzük meg hogy ez nem 13 | > egy függvényhívás. A zárójelek ebben a kifejezésben úgy működnek mint általában, 14 | > kiértékelik az obj változót és visszaadják az értékét. Ez pedig bekerül a 15 | > `typeof` operandusaként. **Nincsen** `typeof` függvény. -------------------------------------------------------------------------------- /doc/it/array/constructor.md: -------------------------------------------------------------------------------- 1 | ## Il costruttore `Array` 2 | 3 | Dato che il costruttore `Array` è ambiguo riguardo a come esso gestisca i suoi 4 | parametri, si consiglia calorosamente di usare l'array letterale (notazione `[]`) 5 | quando si creano array. 6 | 7 | [1, 2, 3]; // Risultato: [1, 2, 3] 8 | new Array(1, 2, 3); // Risultato: [1, 2, 3] 9 | 10 | [3]; // Risultato: [3] 11 | new Array(3); // Risultato: [] 12 | new Array('3') // Risultato: ['3'] 13 | 14 | Nei casi in cui c'è solo un argomento passato al costruttore `Array` e quando 15 | l'argomento è un `Number`, il costruttore ritornerà un nuovo array *frammentato* 16 | con la proprietà `length` impostata al valore dell'argomento. Si noti 17 | che in questo modo **solo** la proprietà `length` del nuovo array verrà impostata, 18 | mentre gli indici dell'array non verranno inizializzati. 19 | 20 | var arr = new Array(3); 21 | arr[1]; // undefined 22 | 1 in arr; // false, l'indice non è stato impostato 23 | 24 | Essere in grado di impostare la lunghezza dell'array in anticipo è utile soltanto 25 | in poche situazioni, come ad esempio la ripetizione di una stringa, nel cui caso 26 | si eviterebbe l'uso di un ciclo. 27 | 28 | new Array(count + 1).join(stringToRepeat); 29 | 30 | ### In conclusione 31 | 32 | I letterali sono da preferirsi al costruttore Array. Sono più concisi, hanno una 33 | sintassi più chiara ed incrementano la leggibilità del codice. 34 | 35 | -------------------------------------------------------------------------------- /doc/it/core/eval.md: -------------------------------------------------------------------------------- 1 | ## Perché non usare `eval` 2 | 3 | La funzione `eval` eseguirà una stringa di codice JavaScript nello scope locale. 4 | 5 | var number = 1; 6 | function test() { 7 | var number = 2; 8 | eval('number = 3'); 9 | return number; 10 | } 11 | test(); // 3 12 | number; // 1 13 | 14 | Comunque, `eval` esegue solo nello scope locale quando viene chiamata 15 | direttamente *e* quando il nome della funzione chiamata è `eval`. 16 | 17 | var number = 1; 18 | function test() { 19 | var number = 2; 20 | var copyOfEval = eval; 21 | copyOfEval('number = 3'); 22 | return number; 23 | } 24 | test(); // 2 25 | number; // 3 26 | 27 | L'uso di `eval` dovrebbe essere evitato. Il 99.9% dei suoi "utilizzi" può 28 | essere ottenuto **senza** di essa. 29 | 30 | ### `eval` sotto mentite spoglie 31 | 32 | Le [funzioni di timeout](#other.timeouts) `setTimeout` e `setInterval` possono 33 | entrambe accettare una stringa come loro primo argomento. Questa stringa verrà 34 | **sempre** eseguita nello scope globale dato che `eval` non viene chiamato 35 | direttamente in questo caso. 36 | 37 | ### Problemi di sicurezza 38 | 39 | `eval` è anche un problema di sicurezza, perché essa esegue **qualsiasi** 40 | codice le viene passato. Non si dovrebbe **mai** usare con stringhe di origine 41 | sconosciuta o inaffidabile. 42 | 43 | ### In conclusione 44 | 45 | `eval` non dovrebbe mai essere usata. Qualsiasi codice che ne faccia uso dovrebbe 46 | essere messo in discussione sotto l'aspetto della funzionalità, della performance 47 | e della sicurezza. Se qualcosa richiede `eval` per poter funzionare, allora **non** 48 | dovrebbe essere usato in primo luogo, ma si dovrebbe prevedere una 49 | *miglior progettazione* che non richieda l'uso di `eval`. 50 | -------------------------------------------------------------------------------- /doc/it/function/general.md: -------------------------------------------------------------------------------- 1 | ## Dichiarazioni ed espressioni di funzione 2 | 3 | Le funzioni in JavaScript sono oggetti di prima classe. Ciò significa che 4 | possono essere usate come ogni altro valore. Un uso comune di questa 5 | caratteristica è quello di passare una *funzione anonima* come funzione di 6 | callback ad un'altra funzione, possibilmente asincrona. 7 | 8 | ### La dichiarazione di `function` 9 | 10 | function foo() {} 11 | 12 | La funzione qui sopra viene [elevata](#function.scopes) (hoisted) prima 13 | che inizi l'esecuzione del programma. Questo vuol dire che essa è disponibile 14 | da un *qualsasi* punto dello scope in cui è stata *definita*, anche se 15 | richiamata prima dell'effettiva definizione nel sorgente. 16 | 17 | foo(); // funziona perché foo è stata creata prima di eseguire il codice 18 | function foo() {} 19 | 20 | ### L'espressione `function` 21 | 22 | var foo = function() {}; 23 | 24 | Questo esempio assegna la funzione *anonima* alla variabile `foo`. 25 | 26 | foo; // 'undefined' 27 | foo(); // questo solleva un TypeError 28 | var foo = function() {}; 29 | 30 | Dato che `var` è una dichiarazione che eleva il nome di variabile `foo` 31 | prima che l'esecuzione del codice inizi, `foo` è già dichiarata quando lo 32 | script viene eseguito. 33 | 34 | Ma, dal momento che le assegnazioni avvengono solo a runtime, il valore di 35 | `foo` sarà [undefined](#core.undefined) per default, prima che il relativo 36 | codice sia eseguito. 37 | 38 | ### Espressione di funzione con nome 39 | 40 | Un altro caso speciale è l'assegnazione di funzioni con nome. 41 | 42 | var foo = function bar() { 43 | bar(); // funziona 44 | } 45 | bar(); // ReferenceError 46 | 47 | Qui, `bar` non è disponibile nello scope più esterno, dal momento che la 48 | funzione viene assegnata solo a `foo`, mentre è disponibile all'interno di 49 | `bar`. Ciò è dato dal modo in cui funziona la [risoluzione dei nomi](#function.scopes) 50 | in JavaScript: il nome della funzione è *sempre* reso disponibile nello scope 51 | locale della funzione stessa. 52 | 53 | -------------------------------------------------------------------------------- /doc/it/index.json: -------------------------------------------------------------------------------- 1 | { 2 | "title": "JavaScript Garden", 3 | "langTitle": "JavaScript Garden in italiano", 4 | "description": "Guida alle peculiarità e i difetti del JavaScript.", 5 | "sections": [ 6 | { 7 | "title": "Introduzione", 8 | "dir": "intro", 9 | "articles": ["index"] 10 | }, 11 | { 12 | "title": "Oggetti", 13 | "dir": "object", 14 | "articles": [ 15 | "general", 16 | "prototype", 17 | "hasownproperty", 18 | "forinloop" 19 | ] 20 | }, 21 | { 22 | "title": "Funzioni", 23 | "dir": "function", 24 | "articles": [ 25 | "general", 26 | "this", 27 | "closures", 28 | "arguments", 29 | "constructors", 30 | "scopes" 31 | ] 32 | }, 33 | { 34 | "title": "Array", 35 | "dir": "array", 36 | "articles": [ 37 | "general", 38 | "constructor" 39 | ] 40 | }, 41 | { 42 | "title": "Tipi di dati", 43 | "dir": "types", 44 | "articles": [ 45 | "equality", 46 | "typeof", 47 | "instanceof", 48 | "casting" 49 | ] 50 | }, 51 | { 52 | "title": "Base", 53 | "dir": "core", 54 | "articles": [ 55 | "eval", 56 | "undefined", 57 | "semicolon", 58 | "delete" 59 | ] 60 | }, 61 | { 62 | "title": "Varie", 63 | "dir": "other", 64 | "articles": [ 65 | "timeouts" 66 | ] 67 | } 68 | ] 69 | } 70 | -------------------------------------------------------------------------------- /doc/it/types/instanceof.md: -------------------------------------------------------------------------------- 1 | ## L'operatore `instanceof` 2 | 3 | L'operatore `instanceof` confronta i costruttori dei suoi due operandi. 4 | È utile soltanto per la comparazione di oggetti realizzati dal 5 | programmatore. Se usato sui tipi interni del linguaggio, esso è 6 | praticamente inutile alla stregua dell'[operatore typeof](#types.typeof). 7 | 8 | ### Confronto di oggetti personalizzati 9 | 10 | function Foo() {} 11 | function Bar() {} 12 | Bar.prototype = new Foo(); 13 | 14 | new Bar() instanceof Bar; // true 15 | new Bar() instanceof Foo; // true 16 | 17 | // Questo imposta Bar.prototype all'oggetto funzione Foo, 18 | // ma non ad un'istanza di Foo 19 | Bar.prototype = Foo; 20 | new Bar() instanceof Foo; // false 21 | 22 | ### Uso di `instanceof` con i tipi nativi 23 | 24 | new String('foo') instanceof String; // true 25 | new String('foo') instanceof Object; // true 26 | 27 | 'foo' instanceof String; // false 28 | 'foo' instanceof Object; // false 29 | 30 | Un'importante cosa da notare qui è che `instanceof` non funziona con oggetti 31 | originati da differenti contesti JavaScript (ad esempio, differenti 32 | documenti in un browser web), dato che i loro costruttori non saranno 33 | esattamente lo stesso oggetto. 34 | 35 | ### In conclusione 36 | 37 | L'operatore `instanceof` dovrebbe essere usato **solo** quando si ha a che fare 38 | con oggetti personalizzati creati dal programmatore, che provengono dallo 39 | stesso contesto JavaScript. Proprio come per l'operatore [`typeof`](#types.typeof), 40 | ogni altro tipo di utilizzo dovrebbe essere **evitato**. 41 | 42 | -------------------------------------------------------------------------------- /doc/ja/array/constructor.md: -------------------------------------------------------------------------------- 1 | ## `Array`コンストラクター 2 | 3 | `Array`コンストラクターはそのパラメーターの扱い方が曖昧なので、新しい配列を作る時には、常に配列リテラル - `[]`記法 - を使用する事を強くお勧めします。 4 | 5 | [1, 2, 3]; // 結果: [1, 2, 3] 6 | new Array(1, 2, 3); // 結果: [1, 2, 3] 7 | 8 | [3]; // Result: [3] 9 | new Array(3); // 結果: [] 10 | new Array('3') // 結果: ['3'] 11 | 12 | このケースの場合、`Array`コンストラクターに渡される引数は一つだけですが、その引数は`Number`になります。コンストラクターは、引数に値がセットされた`length`プロパティを伴った新しい*疎*配列を返します。特筆すべきなのは、新しい配列の`length`プロパティ**のみ**が、このようにセットされるという事です。実際の配列のインデックスは初期化されません。 13 | 14 | var arr = new Array(3); 15 | arr[1]; // undefined 16 | 1 in arr; // false, インデックスがセットされていない 17 | 18 | 配列の長さが先行してセットされるという振舞いは、いくつかの場合に便利です。例えば、文字の繰り返しや、`for loop`を使用したコードの回避などの場合です。 19 | 20 | new Array(count + 1).join(stringToRepeat); 21 | 22 | ### 終わりに 23 | 24 | `Array`コンストラクターの使用は出来る限り避けてください。リテラルが当然望ましい形です。それらは、短かく明快な文法をもっている為に、コードの可読性を高めてくれます。 25 | 26 | -------------------------------------------------------------------------------- /doc/ja/array/general.md: -------------------------------------------------------------------------------- 1 | ## 配列の繰り返しとプロパティ 2 | 3 | JavaScriptの配列もまたオブジェクトですが、[`for in ループ`](#object.forinloop)を配列の繰り返し処理で使用することの良い理由は1つもありません。実際、配列に`for in`を使用**しない**為の正当な理由はたくさんあります。 4 | 5 | > **注意:** JavaScriptの配列は*連想配列*では**ありません**。JavaScriptは[objects](#object.general)だけがキーバリューをマッピングするものです。 6 | > また、連想配列は順序を**保持**しますが、オブジェクトは**保持しません**。 7 | 8 | `for in`ループはプロトタイプチェーン上の全てのプロパティを列挙するため、[`hasOwnProperty`](#object.hasownproperty)をそれらのプロパティの存在判定に使います。この為、通常の`for`ループよりも**20倍**遅くなります。 9 | 10 | ### 繰り返し 11 | 12 | 配列の要素を繰り返すとのに、最高のパフォーマンスを出したければ昔ながらの`for`ループを使うのが一番です。 13 | 14 | var list = [1, 2, 3, 4, 5, ...... 100000000]; 15 | for(var i = 0, l = list.length; i < l; i++) { 16 | console.log(list[i]); 17 | } 18 | 19 | 上記の例では1つ追加の仕掛けがありますが、それは`l = list.length`によって配列の長さをキャッシュする部分です。 20 | 21 | `length`プロパティは配列自身に定義されてはいますが、ループ中の繰り返しで毎回これを参照してしまうと、やはりオーバーヘッドが存在してしまいます。最近のJavaScriptエンジンはこのような場合に最適化する**はず**ですが、コードが新しいエンジンで実行されるかどうか、知る方法はありません。 22 | 23 | 実際には、キャッシュを抜きにするとループの結果はキャッシュされたものに比べてたった**半分の速度**にしかなりません。 24 | 25 | ### `length`プロパティ 26 | 27 | `length`プロパティの*ゲッター*は単に配列に含まれる要素の数を返すだけにも関わらず、*セッター*は配列を**トランケート**する為にも使用できます。 28 | 29 | var foo = [1, 2, 3, 4, 5, 6]; 30 | foo.length = 3; 31 | foo; // [1, 2, 3] 32 | 33 | foo.length = 6; 34 | foo; // [1, 2, 3] 35 | 36 | より小さいlengthを割り当てると配列をトランケートしますが、lengthが大きくなっても配列には何も影響しません。 37 | 38 | ### 終わりに 39 | 40 | 最高のパフォーマンスの為には、常に`for`ループを使用し、`length`プロパティをキャッシュする事をお勧めします。`for in`ループを配列で使用するのは、バグや最低のパフォーマンスの傾向があるコードを書く前兆になります。 41 | 42 | -------------------------------------------------------------------------------- /doc/ja/core/delete.md: -------------------------------------------------------------------------------- 1 | ## `delete`演算子 2 | 3 | 端的に言って、JavaScriptの関数やその他の要素は`DontDelete`属性が設定されているので、グローバル変数を消去する事は*不可能*です。 4 | 5 | ### グローバルコードと関数コード 6 | 7 | 変数や、関数がグローバルまたは[関数スコープ](#function.scopes)で定義された時は、そのプロパティは有効なオブジェクトかグローバルオブジェクトになります。このようなプロパティは属性のセットを持っていますが、それらの内の1つが`DontDelete`になります。変数や関数がグローバルや関数コードで宣言されると、常に`DontDelete`属性を作るために、消去できません。 8 | 9 | // グローバル変数: 10 | var a = 1; // DontDelete属性が設定される 11 | delete a; // false 12 | a; // 1 13 | 14 | // 通常関数: 15 | function f() {} // DontDelete属性が設定される 16 | delete f; // false 17 | typeof f; // "function" 18 | 19 | // 再代入も役に立たない: 20 | f = 1; 21 | delete f; // false 22 | f; // 1 23 | 24 | ### 明示的なプロパティ 25 | 26 | 明示的にプロパティを設定することが、通常通りの消去を可能にします。 27 | 28 | // プロパティを明示的に設定する 29 | var obj = {x: 1}; 30 | obj.y = 2; 31 | delete obj.x; // true 32 | delete obj.y; // true 33 | obj.x; // undefined 34 | obj.y; // undefined 35 | 36 | 上記の例の中で、`obj.x`と`obj.y`はそれぞれ`DontDelete`属性が無い為に消去できます。これが下記の例でも動作する理由です。 37 | 38 | // IE以外では、これも動作する 39 | var GLOBAL_OBJECT = this; 40 | GLOBAL_OBJECT.a = 1; 41 | a === GLOBAL_OBJECT.a; // true - ただのグローバルのvar 42 | delete GLOBAL_OBJECT.a; // true 43 | GLOBAL_OBJECT.a; // undefined 44 | 45 | ここでは`a`. [`this`](#function.this)を消す為にグローバルオブジェクトと明示的に宣言した`a`をそのプロパティとして参照させて、消去する事を許可するトリックを使います。 46 | 47 | IE(最低でも6-8で)は多少のバグがある為に、上記のコードは動作しません。 48 | 49 | 50 | ### 関数の引数と組み込み引数 51 | 52 | 関数の通常の引数である、[`arguments` objects](#function.arguments)と組み込みのプロパティもまた、`DontDelete`が設定されています。 53 | 54 | // 関数の引数とプロパティ: 55 | (function (x) { 56 | 57 | delete arguments; // false 58 | typeof arguments; // "object" 59 | 60 | delete x; // false 61 | x; // 1 62 | 63 | function f(){} 64 | delete f.length; // false 65 | typeof f.length; // "number" 66 | 67 | })(1); 68 | 69 | ### ホストオブジェクト 70 | 71 | `delete`演算子の挙動はホストオブジェクトにとって予測不可能になりかねません。仕様によりホストオブジェクトは、あらゆる挙動の実行が許可されている為です。 72 | 73 | ### 終わりに 74 | 75 | `delete`演算子は、しばしば予期せぬ挙動をします。唯一安全な使用方法は通常のオブジェクトに明示的に設定されたプロパティを扱う場合だけです。 76 | -------------------------------------------------------------------------------- /doc/ja/core/eval.md: -------------------------------------------------------------------------------- 1 | ## なぜ、`eval`を使ってはいけないのか 2 | 3 | `eval`関数はローカルスコープ中のJavaScriptコードの文字列を実行します。 4 | 5 | var foo = 1; 6 | function test() { 7 | var foo = 2; 8 | eval('foo = 3'); 9 | return foo; 10 | } 11 | test(); // 3 12 | foo; // 1 13 | 14 | しかし、`eval`は**直接**ローカルスコープから呼ばれて、*かつ*呼んだ関数の名前が実際の`eval`でないと実行しません。 15 | 16 | var foo = 1; 17 | function test() { 18 | var foo = 2; 19 | var bar = eval; 20 | bar('foo = 3'); 21 | return foo; 22 | } 23 | test(); // 2 24 | foo; // 3 25 | 26 | `eval`の使用は**全てのコスト**を払ってでも回避するべきです。その「使用法」の99.9%で、これ**無し**でも実装できます。 27 | 28 | ### 偽装された`eval` 29 | 30 | [timeout functions](#other.timeouts)である`setTimeout`と`setInterval`はどちらも最初の引数として文字列を取る事ができます。この文字列は`eval`がこの場合直接呼ばれていないので、**常に**グローバルスコープで実行されてしまいます。 31 | 32 | ### セキュリティの問題 33 | 34 | `eval`はまたセキュリティの問題もあります。なぜなら、**どんな**コードを与えられても実行してしまうからで、**絶対**に不明または信頼できない発行元の文字列は使ってはいけません。 35 | 36 | ### 終わりに 37 | 38 | `eval`は絶対に使用しないでください。これを使用しているどんなコードも、その働き、パフォーマンスやセキュリティについて問われてしまいます。`eval`が必要な場合でも、最初の段階で使用**しない**でください。*より良いデザイン*を使用するべきで、それには`eval`を使う必要性はありません。 39 | 40 | -------------------------------------------------------------------------------- /doc/ja/core/undefined.md: -------------------------------------------------------------------------------- 1 | ## `undefined`と`null` 2 | 3 | JavaScriptは`nothing`を表す2つの別個の値を持っています。これら2つの内で`undefined`はより便利な存在です。 4 | 5 | ### `undefined`の値 6 | 7 | `undefined`はただ1つの値`undefined`を持つ型です。 8 | 9 | この言語はまた、`undefined`の値を持つグローバル変数を定義しています。この値もまた`undefined`と呼ばれています。しかし、この変数は **どちらも** 言語のキーワードではなく、定数です。この事はこの*値*は簡単に上書きされてしまうという事になります。 10 | 11 | > **ES5での注意点:** ECMAScript 5での`undefined`は **もはや** strict modeでは *書き変えられない* 12 | > ようになっています。しかし、この名前は`undefined`という名前の関数の例に痕跡が見られるだけです。 13 | 14 | `undefined`が返される時の例をいくつか挙げます。 15 | 16 | - (未定義の)グローバル変数`undefined`にアクセスした時 17 | - `return`文が無い為に、暗黙のうちに関数が返された時 18 | - 何も返されない`return`がある時 19 | - 存在しないプロパティを探索する時 20 | - 関数のパラメーターで明示的な値が何も無い時 21 | - `undefined`が設定された全ての値 22 | 23 | ### `undefined`の値に変更する処理 24 | 25 | グローバル変数`undefined`のみが実際の`undefined`の*値*のコピーを保持するので、これに新しい値を代入しても`undefined`の*型* の値が変更される事は**ありません**。 26 | 27 | まだ、`undefined`の値に対して何かしらの比較をしないといけない場合は、最初に`undefined`の値を取得する必要があります。 28 | 29 | コードの`undefined`の変数の上書きを可能な限りしないよう保護する為には、一般的なテクニックとして[anonymous wrapper](#function.scopes)の引数にパラメーターを追加するというものがあります。 30 | 31 | var undefined = 123; 32 | (function(something, foo, undefined) { 33 | // ローカルスコープではundefined。 34 | // ここで値に対して参照がされる 35 | 36 | })('Hello World', 42); 37 | 38 | 同じ効果を得る事ができる別の方法として、ラッパーの内部での宣言を使うものがあります。 39 | 40 | var undefined = 123; 41 | (function(something, foo) { 42 | var undefined; 43 | ... 44 | 45 | })('Hello World', 42); 46 | 47 | これらの唯一の違いは、こちらのバージョンの方が4バイト余計に短縮できるという物です。また、他に`var`ステートメントは匿名ラッパーの中にはありません。 48 | 49 | ### `null`の使用 50 | 51 | JavaScriptというプログラム言語のコンテキストの中では、`undefined`は主に伝統的な意味での*null*の意味で使用される事が多いです。実際の`null`(リテラルも型も両方)は多かれ少なかれ、単なるデータ型です。 52 | 53 | それはJavaScriptの内部でいくつか使われています(プロトタイプチェーンの終わりに`Foo.prototype = null`という宣言をするようなもの)が、ほとんど全てのケースで、`undefined`に置き替える事が可能です。 54 | -------------------------------------------------------------------------------- /doc/ja/function/general.md: -------------------------------------------------------------------------------- 1 | ## 関数の宣言と式 2 | 3 | 関数はJavaScriptの第一級オブジェクトです。この事は、その他の値と同じように渡す事が出来るという事です。この機能で良く使われる一つとして**匿名関数**を他のオブジェクトにコールバックとして渡すというものがあり、これで非同期での実装が可能になります。 4 | 5 | ### `関数`宣言 6 | 7 | function foo() {} 8 | 9 | 上記の関数はプログラムの開始時の前に評価されるように[巻き上げ](#function.scopes)られます。従って*定義*されたスコープ内の*どこでも*使用する事が可能になります。ソース内での実際の定義が呼ばれる前でもです。 10 | 11 | foo(); // このコードが動作する前にfooが作られているので、ちゃんと動作する 12 | function foo() {} 13 | 14 | ### `関数`式 15 | 16 | var foo = function() {}; 17 | 18 | この例では、`foo`という変数に無名で*匿名*の関数が割り当てられています。 19 | 20 | foo; // 'undefined' 21 | foo(); // これはTypeErrorが起こる 22 | var foo = function() {}; 23 | 24 | `var`は宣言である為に、変数名`foo`がコードが開始される実際の評価時より前のタイミングにまで巻き上げられています。`foo`は既にスクリプトが評価される時には定義されているのです。 25 | 26 | しかし、コードの実行時にのみこの割り当てがされるため、`foo`という変数は対応するコードが実行される前にデフォルト値である[undefined](#core.undefined)が代入されるのです。 27 | 28 | ### 名前付き関数式 29 | 30 | 他に特殊なケースとして、名前付き関数があります。 31 | 32 | var foo = function bar() { 33 | bar(); // 動作する 34 | } 35 | bar(); // ReferenceError 36 | 37 | この場合の`bar`は`foo`に対して関数を割り当てるだけなので、外部スコープでは使用できません。しかし、`bar`は内部では使用できます。これはJavaScriptの[名前解決](#function.scopes)の方法によるもので、関数名は*いつも*関数自身のローカルスコープ内で有効になっています。 38 | -------------------------------------------------------------------------------- /doc/ja/index.json: -------------------------------------------------------------------------------- 1 | { 2 | "title": "JavaScript Garden", 3 | "langTitle": "JavaScript Garden in Japanese", 4 | "description": "JavaScriptの奇妙さと欠陥についてのガイドライン", 5 | "sections": [ 6 | { 7 | "title": "前書き", 8 | "dir": "intro", 9 | "articles": ["index"] 10 | }, 11 | { 12 | "title": "オブジェクト", 13 | "dir": "object", 14 | "articles": [ 15 | "general", 16 | "prototype", 17 | "hasownproperty", 18 | "forinloop" 19 | ] 20 | }, 21 | { 22 | "title": "関数", 23 | "dir": "function", 24 | "articles": [ 25 | "general", 26 | "this", 27 | "closures", 28 | "arguments", 29 | "constructors", 30 | "scopes" 31 | ] 32 | }, 33 | { 34 | "title": "配列", 35 | "dir": "array", 36 | "articles": [ 37 | "general", 38 | "constructor" 39 | ] 40 | }, 41 | { 42 | "title": "型", 43 | "dir": "types", 44 | "articles": [ 45 | "equality", 46 | "typeof", 47 | "instanceof", 48 | "casting" 49 | ] 50 | }, 51 | { 52 | "title": "コア", 53 | "dir": "core", 54 | "articles": [ 55 | "eval", 56 | "undefined", 57 | "semicolon", 58 | "delete" 59 | ] 60 | }, 61 | { 62 | "title": "その他", 63 | "dir": "other", 64 | "articles": [ 65 | "timeouts" 66 | ] 67 | } 68 | ] 69 | } 70 | -------------------------------------------------------------------------------- /doc/ja/intro/index.md: -------------------------------------------------------------------------------- 1 | ## 前書き 2 | 3 | **JavaScript Garden** はJavaScriptというプログラム言語の一番奇妙な部分についてのドキュメント集です。 4 | このドキュメントはJavaScriptという言語に慣れていないプログラマーがこの言語について深く知ろうとする際に遭遇する、良くある間違い・小さなバグ・パフォーマンスの問題・悪い習慣などを避ける為のアドバイスを与えます。 5 | 6 | JavaScript GardenはJavaScriptを教える事を**目的にしていません**。このガイドの項目を理解する為には、この言語に対する前提知識がある事を推奨します。この言語の基礎部分についてはMozilla Developer Networkの[ガイド][1] がオススメです。 7 | 8 | ## 著者 9 | 10 | このガイドは愛すべき[Stack Overflow][2]の2人のユーザー[Ivo Wetzel][3] 11 | (執筆)と[Zhang Yi Jiang][4] (デザイン)によって作られました。 12 | 13 | ## 貢献者 14 | 15 | - [貢献者](https://github.com/BonsaiDen/JavaScript-Garden/graphs/contributors) 16 | 17 | ## ホスティング 18 | 19 | JavaScript GardenはGitHubでホスティングされていますが、[Cramer Development][7]が[JavaScriptGarden.info][8]というミラーサイトを作ってくれています。 20 | 21 | ## ライセンス 22 | 23 | JavaScript Gardenは[MIT license][9]の下で公開されており、[GitHub][10]でホスティングされています。もしもエラーやtypoを見つけたら[file an issue][11]に登録するかリポジトリにプルリクエストを送ってください。 24 | またStack Overflowチャットの[JavaScript room][12]に私達はいます。 25 | 26 | 27 | [1]: https://developer.mozilla.org/en/JavaScript/Guide 28 | [2]: http://stackoverflow.com/ 29 | [3]: http://stackoverflow.com/users/170224/ivo-wetzel 30 | [4]: http://stackoverflow.com/users/313758/yi-jiang 31 | [5]: https://github.com/caio 32 | [6]: https://github.com/blixt 33 | [7]: http://cramerdev.com/ 34 | [8]: http://javascriptgarden.info/ 35 | [9]: https://github.com/BonsaiDen/JavaScript-Garden/blob/next/LICENSE 36 | [10]: https://github.com/BonsaiDen/JavaScript-Garden 37 | [11]: https://github.com/BonsaiDen/JavaScript-Garden/issues 38 | [12]: http://chat.stackoverflow.com/rooms/17/javascript 39 | -------------------------------------------------------------------------------- /doc/ja/object/forinloop.md: -------------------------------------------------------------------------------- 1 | ## `for in`ループ 2 | 3 | `in`オペレーターは単に、`for in`ループの中でオブジェクトのプロパティをプロトタイプチェーンの中で繰り返し遡る為にあるものです。 4 | 5 | > **注意:** `for in`ループは`enumerable`属性が`false`にセットされているプロパティを反復処理**しません**。; 6 | > 例えば、配列の`length`プロパティなどがそれに当たります。 7 | 8 | // Object.prototype汚染 9 | Object.prototype.bar = 1; 10 | 11 | var foo = {moo: 2}; 12 | for(var i in foo) { 13 | console.log(i); // barとmooが両方とも表示される 14 | } 15 | 16 | `for in`ループそれ自体の動作を変更する事は不可能ですが、ループ内にある要らないプロパティをフィルタリングする必要があります。そんな時は`Object.prototype`の[`hasOwnProperty`](#object.hasownproperty)メソッドを使うと解決します。 17 | 18 | > **注意:** `for in`は常にプロトタイプチェーンを完全に遡ります。これにより 19 | > オブジェクトに追加されている継承が多ければ多い程、速度は遅くなります。 20 | 21 | ### `hasOwnProperty`をフィルタリングに使用する 22 | 23 | // 継承されているfoo 24 | for(var i in foo) { 25 | if (foo.hasOwnProperty(i)) { 26 | console.log(i); 27 | } 28 | } 29 | 30 | このループの唯一正しい使い方がこの方法です。`hasOwnProperty`を使用しているので、 31 | `moo`**のみ**が表示されるようになります。`hasOwnProperty`が省略されている場合は、このコードは 32 | 組み込みのプロトタイプが存在する場合に(特に`Object.prototype`が拡張されている場合)エラーを発生しやすくなります。 33 | 34 | 一般に広く使用されているJavaScriptフレームワークとして[Prototype][1]が挙げられます。このフレームワークには、 35 | `for in` 内で`hasOwnProperty`が使用されプロトタプチェーン内を頭まで遡るのを中断する事が保証されています。 36 | 37 | ### 終わりに 38 | 39 | **常に**`hasOwnProperty`を使用する事を推奨します。コードの実行環境や、組み込みのプロトタイプが拡張されているかどうかを仮定して書くようなコードを絶対書いてはいけません。 40 | 41 | [1]: http://www.prototypejs.org/ 42 | 43 | -------------------------------------------------------------------------------- /doc/ja/object/hasownproperty.md: -------------------------------------------------------------------------------- 1 | ## `hasOwnProperty` 2 | 3 | オブジェクトは*自分自身*と**自分以外**のどちらで定義されたプロパティかを[prototype chain](#object.prototype)のどこかでチェックしなくてはなりません。これは`Object.prototype`から継承される全てのオブジェクトの`hasOwnProperty`メソッドを使う必要があります。 4 | 5 | > **注意:** この方法はプロパティが`undefined`かどうかを調べるには十分では**無い**方法です。 6 | > プロパティは、ほとんどのオブジェクトで存在しているはずの物ではありますが、`undefined`が 7 | > 値に設定される事態は起こり得ます。 8 | 9 | `hasOwnProperty`はJavaScriptで唯一プロトタイプチェーン内を**遡らず**にプロパティを扱う事が出来ます。 10 | 11 | // Object.prototype汚染 12 | Object.prototype.bar = 1; 13 | var foo = {goo: undefined}; 14 | 15 | foo.bar; // 1 16 | 'bar' in foo; // true 17 | 18 | foo.hasOwnProperty('bar'); // false 19 | foo.hasOwnProperty('goo'); // true 20 | 21 | `hasOwnProperty`だけが、正しく期待した結果を出すでしょう。これはあらゆるオブジェクトのプロパティの繰り返し処理をする時必須の事です。オブジェクト*自身*に定義されておらず、プロトタイプチェーンのどこかには定義されているというプロパティを除外する手段が他に**ありません**。 22 | 23 | ### プロパティとしての`hasOwnProperty` 24 | 25 | JavaScriptはプロパティ名として`hasOwnProperty`を保護して**いません**。;従って、この名前のプロパティを持ったオブジェクトが存在する事がありえます。正しい結果を得る為には*外部*の`hasOwnProperty`を使う必要があります。 26 | 27 | var foo = { 28 | hasOwnProperty: function() { 29 | return false; 30 | }, 31 | bar: 'Here be dragons' 32 | }; 33 | 34 | foo.hasOwnProperty('bar'); // 常にfalseを返す 35 | 36 | // 他のオブジェクトのhasOwnPropertyを使い、fooの'this'にセットして呼び出す 37 | ({}).hasOwnProperty.call(foo, 'bar'); // true 38 | 39 | ### 終わりに 40 | 41 | オブジェクトのプロパティの存在判定をする時は、`hasOwnProperty`が**唯一**のメソッドになります。 42 | また、**全て**の[`for in` ループ](#object.forinloop)内で`hasOwnProperty`を使う事を推奨します。 43 | そうする事により組み込みの[prototypes](#object.prototype)の拡張が原因のエラーを避ける事が出来ます。 44 | 45 | -------------------------------------------------------------------------------- /doc/ja/types/casting.md: -------------------------------------------------------------------------------- 1 | ## 型変換 2 | 3 | JavaScriptは*弱い型付け*の言語なので、可能な**限り**に*型強制*が適用されます。 4 | 5 | // これらはtrueです。 6 | new Number(10) == 10; // Number.toString()が変換される 7 | // numberに戻る 8 | 9 | 10 == '10'; // StringsがNumberに変換される 10 | 10 == '+10 '; // バカみたいに文字列を追加 11 | 10 == '010'; // もっともっと 12 | isNaN(null) == false; // nullが0に変換される 13 | // もちろんNaNではないです 14 | 15 | // これらはfalseです 16 | 10 == 010; 17 | 10 == '-10'; 18 | 19 | > **ES5での注意点:** `0`から始まるNumberリテラルは8進数(基数が8)として解釈されます。 20 | > このような8進数のサポートはECMAScript5のstrict modeでは**削除されました**。 21 | 22 | 上記の自体を避ける為に、[厳密等価演算子](#types.equality)を使用する事を**強く**推奨します。また、これはたくさんある落し穴を避けますが、それでもまだJavaScriptの弱い型付けシステムから発生する色々な課題が残っています。 23 | 24 | ### 組み込み型のコンストラクタ 25 | 26 | `Number`や`String`のような組み込み型のコンストラクタは、`new`キーワードの有無で振る舞いが違ってきます。 27 | 28 | new Number(10) === 10; // False, ObjectとNumber 29 | Number(10) === 10; // True, NumberとNumber 30 | new Number(10) + 0 === 10; // True, 暗黙の型変換によります 31 | 32 | `Number`のような組み込み型をコンストラクタとして使うと、新しい`Number`オブジェクトが作られますが、`new`キーワードを除外すると`Number`関数がコンバーターのように振る舞います。 33 | 34 | 加えて、リテラルかオブジェトではない値を持っていると、さらに型強制が多くなります。 35 | 36 | 最良のオプションは以下の3つの方法の内、1つで型を**明示**してキャストする事になります。 37 | 38 | ### Stringでキャストする 39 | 40 | '' + 10 === '10'; // true 41 | 42 | 空の文字列の付加により値を簡単に文字列にキャストできます。 43 | 44 | ### Numberでキャストする 45 | 46 | +'10' === 10; // true 47 | 48 | **単項**プラスオペレーターを使うと数字にキャストする事が可能です。 49 | 50 | ### Booleanでキャストする 51 | 52 | **not**オペレーターを2回使うと、値はブーリアンに変換できます。 53 | 54 | !!'foo'; // true 55 | !!''; // false 56 | !!'0'; // true 57 | !!'1'; // true 58 | !!'-1' // true 59 | !!{}; // true 60 | !!true; // true 61 | -------------------------------------------------------------------------------- /doc/ja/types/equality.md: -------------------------------------------------------------------------------- 1 | ## 等価と比較 2 | 3 | JavaScriptはオブジェクトの値の等価の比較方法を2種類持っています。 4 | 5 | ### 等価演算子 6 | 7 | 等価演算子は2つのイコール記号: `==`から成っています。 8 | 9 | JavaScriptは*弱い型付け*を特徴としています。これは等価演算子が比較をする際に型付けを**強制**するという意味です。 10 | 11 | "" == "0" // false 12 | 0 == "" // true 13 | 0 == "0" // true 14 | false == "false" // false 15 | false == "0" // true 16 | false == undefined // false 17 | false == null // false 18 | null == undefined // true 19 | " \t\r\n" == 0 // true 20 | 21 | 上記の表では型強制の結果が表示されています。`==`の使用が一般に悪い習慣とみなされる大きな理由として、変換ルールが複雑な為、バグの追跡が困難になる事が挙げられます。 22 | 23 | 加えて、型強制が行なわれるとパフォーマンスにも影響してしまいます。例えば、文字列は他の数字と比較する前に数値に変換されなければなりません。 24 | 25 | ### 厳密等価演算子 26 | 27 | 厳密等価演算子は**3つ**のイコール記号:`===`で成っています。 28 | 29 | これはオペランドの間で強制的な型変換が**実行されない**事を除けば、通常の等価演算子と同じように正確に動作します。 30 | 31 | "" === "0" // false 32 | 0 === "" // false 33 | 0 === "0" // false 34 | false === "false" // false 35 | false === "0" // false 36 | false === undefined // false 37 | false === null // false 38 | null === undefined // false 39 | " \t\r\n" === 0 // false 40 | 41 | 上記の結果は、より明確でコードの早期破損を可能にします。これはある程度までコードを硬化させて、オペランドが別の型の場合にパフォーマンスが向上します。 42 | 43 | ### オブジェクトの比較 44 | 45 | `==`と`===`は両方とも**等価**演算子とされていますが、そのオペランドの少なくとも一つが`Object`の場合は、両者は異なる動きをします。 46 | 47 | {} === {}; // false 48 | new String('foo') === 'foo'; // false 49 | new Number(10) === 10; // false 50 | var foo = {}; 51 | foo === foo; // true 52 | 53 | これら2つの演算子は**同一性**を比較していているのであって、等価を比較しているわけでは**ありません**。これは、これらの演算子はPythonの`is`演算子やCのポインター比較と同じように、同じオブジェクトの**インスタンス**を比較するという事になります。 54 | 55 | ### 終わりに 56 | 57 | **厳密等価**演算子だけを使用することを特に推奨します。型を強制的に型変換する場合は[explicitly](#types.casting)であるべきで、言語自体の複雑な変換ルールが残っているべきではありません。 58 | 59 | -------------------------------------------------------------------------------- /doc/ja/types/instanceof.md: -------------------------------------------------------------------------------- 1 | ## `instanceof`オペレーター 2 | 3 | `instanceof`オペレーターは2つのオペランドのコンストラクタを比較します。これはカスタムで作ったオブジェクトを比較する時にのみ有用です。組み込みの型に使用するのは[typeof operator](#types.typeof)を使用するのと同じくらい意味がありません。 4 | 5 | ### カスタムオブジェクトの比較 6 | 7 | function Foo() {} 8 | function Bar() {} 9 | Bar.prototype = new Foo(); 10 | 11 | new Bar() instanceof Bar; // true 12 | new Bar() instanceof Foo; // true 13 | 14 | // これは単に関数オブジェクトFooにBar.prototypeをセットしただけです。 15 | // しかし、実際のFooのインスタンスではありません。 16 | Bar.prototype = Foo; 17 | new Bar() instanceof Foo; // false 18 | 19 | ### ネイティブ型で`instanceof`を使用する 20 | 21 | new String('foo') instanceof String; // true 22 | new String('foo') instanceof Object; // true 23 | 24 | 'foo' instanceof String; // false 25 | 'foo' instanceof Object; // false 26 | 27 | ここで1つ重要な事は、異なるJavaScriptのコンテキスト(例えば、ブラウザの異なるウィンドウ)を元としたオブジェクトでは、コンストラクタが厳密に同じものでは無い為に`instanceof`は上手く動作しません。 28 | 29 | ### 終わりに 30 | 31 | `instanceof`オペレーターは同じJavaScriptのコンテキストが起源になっているカスタムメイドのオブジェクトを扱う場合**のみ**使うべきです。ちょうど[`typeof`](#types.typeof)オペレーターのように、その他での使用は**避けるべき**です。 32 | -------------------------------------------------------------------------------- /doc/ko/array/constructor.md: -------------------------------------------------------------------------------- 1 | ## `배열` 생성자 2 | 3 | 배열을 만들때 `배열` 생성자에 파라미터를 넣어 만드는 방법은 헷갈릴수있다. 그래서 항상 각 괄호(`[]`) 노테이션을 이용해 배열을 만들 것을 권한다 4 | 5 | [1, 2, 3]; // Result: [1, 2, 3] 6 | new Array(1, 2, 3); // Result: [1, 2, 3] 7 | 8 | [3]; // Result: [3] 9 | new Array(3); // Result: [] 10 | new Array('3') // Result: ['3'] 11 | 12 | `배열` 생성자에 숫자를 인자로 넣으면 그 숫자 크기 만큼의 빈 `배열`을 반환한다. 즉 배열의 `length`는 그 숫자가 된다. 이때 생성자는 **단지** `length` 프로퍼티에 그 숫자를 할당하기만 하고 `배열`은 실제로 초기화 하지도 않는다. 13 | 14 | var arr = new Array(3); 15 | arr[1]; // undefined 16 | 1 in arr; // false, 이 인덱스는 초기화되지 않음. 17 | 18 | `for`문을 사용하지 않고 문자열을 더하는 경우에는 length 프로퍼티에 숫자를 할당해주는 기능이 유용할 때도 있다. 19 | 20 | new Array(count + 1).join(stringToRepeat); 21 | 22 | ### 결론 23 | 24 | `배열` 생성자는 가능하면 사용하지 말고, 각 괄호 (`[]`) 노테이션이을 사용하자. 후자가 더 간략하고 명확할 뿐만 아니라 보기도 좋다. 25 | -------------------------------------------------------------------------------- /doc/ko/array/general.md: -------------------------------------------------------------------------------- 1 | ## 배열 순회와 프로퍼티 2 | 3 | JavaScript에서는 배열(Array)도 객체(Object)지만 객체 순회(Iterate)를 할 때 [`for in`](#object.forinloop)을 사용해서 좋을 게 없다. 실제로 배열을 탐색할때 `for in`문 사용하지 말아야 할 이유가 매우 많다. 4 | 5 | > **Note:** JavaScript의 배열은 *연관 배열(Associative Array)*이 **아니다**. JavaScript는 오직 key/value를 맵핑한 [객체](#object.general)만 있을 뿐이다. 연관 배열은 순서를 보장해주지만 객체는 순서를 보장하지 않는다. 6 | 7 | `for in`은 프로토타입 체인에 있는 프로퍼티를 모두 훑는(enumerate) 데다가 객체 자신의 프로퍼티만 훑으려면 [`hasOwnProperty`](#object.hasownproperty)를 사용해야 하기 때문에 `for`보다 20배 느리다. 8 | 9 | ### 배열 순회 10 | 11 | 배열을 순회 할때는 일반적인 `for`문을 사용하는 것이 가장 빠르다. 12 | 13 | var list = [1, 2, 3, 4, 5, ...... 100000000]; 14 | for(var i = 0, l = list.length; i < l; i++) { 15 | console.log(list[i]); 16 | } 17 | 18 | 이 예제에서 `l = list.length`로 배열의 length 값을 캐시해야 한다는 것을 꼭 기억해야 한다. 19 | 20 | 매번 반복할때마다 배열에 있는 `length` 프로퍼티에 접근하는 것은 좀 부담스럽다. 최신 JavaScript 엔진은 이 일을 알아서 처리해주기도 하지만 코드가 늘 새 엔진에서 실행되도록 보장할 방법이 없다. 21 | 22 | 실제로 캐시 하지 않으면 성능이 반으로 줄어든다. 23 | 24 | ### `length` 프로퍼티 25 | 26 | `length` 프로퍼티의 *getter*는 단순히 Array 안에 있는 엘리먼트의 개수를 반환하고 *setter*는 배열을 할당한 수만큼 잘라 버린다. 27 | 28 | var arr = [1, 2, 3, 4, 5, 6]; 29 | arr.length = 3; 30 | arr; // [1, 2, 3] 31 | 32 | arr.length = 6; 33 | arr.push(4); 34 | arr; // [1, 2, 3, undefined, undefined, undefined, 4] 35 | 36 | 현재 크기보다 더 작은 값을 할당하면 배열을 자른다. 배열의 크기를 증가시키면 드문드문(sparse)한 배열을 생성한다. 37 | 38 | ### 결론 39 | 40 | 최적의 성능을 위해서는 `for`문을 사용하고 `length` 프로퍼티 값을 캐시해야 한다. 배열에 `for in`을 사용하면 성능도 떨어지고 버그 나기도 쉽다. 41 | -------------------------------------------------------------------------------- /doc/ko/core/delete.md: -------------------------------------------------------------------------------- 1 | ## `delete` 연산자 2 | 3 | 간단히 말해서 전역 변수와 전역 함수 그리고 `DontDelete` 속성을 가진 자바스크립트 객체는 삭제할 수 없다. 4 | 5 | ### Global 코드와 Function 코드 6 | 7 | 전역이나 함수 스코프에 정의한 함수나 변수는 모두 Activation 객체나 전역 객체의 프로퍼티다. 이 프로퍼티는 모두 `DontDelete` 속성을 가진다. 전역이나 함수 코드에 정의한 변수와 함수는 항상 `DontDelete` 프로퍼티로 만들어지기 때문에 삭제될 수 없다: 8 | 9 | // Global 변수: 10 | var a = 1; // DontDelete가 설정된다. 11 | delete a; // false 12 | a; // 1 13 | 14 | // Function: 15 | function f() {} // DontDelete가 설정된다. 16 | delete f; // false 17 | typeof f; // "function" 18 | 19 | // 다시 할당해도 삭제할 수 없다: 20 | f = 1; 21 | delete f; // false 22 | f; // 1 23 | 24 | ### 명시적인(Explicit) 프로퍼티 25 | 26 | 다음 예제에서 만드는 프로퍼티는 delete할 수 있다. 이런 걸 명시적인(Explicit) 프로퍼티라고 부른다: 27 | 28 | // Explicit 프로퍼티를 만든다: 29 | var obj = {x: 1}; 30 | obj.y = 2; 31 | delete obj.x; // true 32 | delete obj.y; // true 33 | obj.x; // undefined 34 | obj.y; // undefined 35 | 36 | `obj.x`와 `obj.y`는 `DontDelete` 속성이 아니라서 delete할 수 있다. 하지만 다음과 같은 코드도 잘 동작하기 때문에 헷갈린다: 37 | 38 | // IE를 빼고 잘 동작한다: 39 | var GLOBAL_OBJECT = this; 40 | GLOBAL_OBJECT.a = 1; 41 | a === GLOBAL_OBJECT.a; // true - 진짜 Global 변수인지 확인하는 것 42 | delete GLOBAL_OBJECT.a; // true 43 | GLOBAL_OBJECT.a; // undefined 44 | 45 | [`this`](#function.this)가 전역 객체를 가리키는 것을 이용해서 명시적으로 프로퍼티 `a`를 선언하면 삭제할 수 있다. 이것은 꼼수다. 46 | 47 | IE (적어도 6-8)는 버그가 있어서 안 된다. 48 | 49 | ### Argument들과 Function의 기본 프로퍼티 50 | 51 | Function의 [`arguments` 객체](#function.arguments)와 기본 프로퍼티도 `DontDelete` 속성이다. 52 | 53 | // Function의 arguments와 프로퍼티: 54 | (function (x) { 55 | 56 | delete arguments; // false 57 | typeof arguments; // "object" 58 | 59 | delete x; // false 60 | x; // 1 61 | 62 | function f(){} 63 | delete f.length; // false 64 | typeof f.length; // "number" 65 | 66 | })(1); 67 | 68 | ### Host 객체 69 | 70 | > **역주:** Host 객체는 document같은 DOM 객체를 말한다. 71 | 72 | Host 객체를 delete하면 어떻게 될지 알 수 없다. 표준에는 어떻게 Host 객체를 delete해야 하는지 정의하지 않았다. 73 | 74 | ### 결론 75 | 76 | `delete` 연산자는 엉뚱하게 동작할 때가 많다. 명시적으로 정의한 일반 객체의 프로퍼티만 delete하는 것이 안전하다. 77 | -------------------------------------------------------------------------------- /doc/ko/core/eval.md: -------------------------------------------------------------------------------- 1 | ## 왜 `eval`을 사용하면 안 될까? 2 | 3 | `eval` 함수는 JavaScript 문자열을 지역 스코프에서 실행한다. 4 | 5 | var number = 1; 6 | function test() { 7 | var number = 2; 8 | eval('number = 3'); 9 | return number; 10 | } 11 | test(); // 3 12 | number; // 1 13 | 14 | `eval`함수는 `eval`이라는 이름으로 **직접** 실행할 때에만 지역 스코프에서 실행된다. 그리고 `eval`이라는 이름에 걸맞게 악명또한 높다. 15 | 16 | var number = 1; 17 | function test() { 18 | var number = 2; 19 | var copyOfEval = eval; 20 | copyOfEval('number = 3'); 21 | return number; 22 | } 23 | test(); // 2 24 | number; // 3 25 | 26 | 어쨌든 `eval`은 사용하지 말아야 한다. eval을 사용하는 99.9%는 사실 eval 없이도 만들수있다. 27 | 28 | ### 가짜 `eval` 29 | 30 | [`setTimeout`과 `setInterval`](#other.timeouts)은 첫 번째 인자로 스트링을 입력받을 수 있다. 이 경우에는 `eval`을 직접 호출하는 것이 아니라서 항상 Global Scope에서 실행된다. 31 | 32 | ### 보안 이슈 33 | 34 | `eval`은 어떤 코드라도 **무조건** 실행하기 때문에 보안 문제도 있다. 따라서 신뢰하지 못하거나 모르는 코드가 포함되어 있을 경우 **절대로** 사용해서는 안된다. 35 | 36 | ### 결론 37 | 38 | `eval`은 사용하지 않는 게 좋다. `eval`을 사용하는 모든 코드는 성능, 보안, 버그 문제를 일으킬 수 있다. 만약 `eval`이 필요해지면 *설계를 변경*하여 `eval`이 필요 없게 만들어야 한다. 39 | -------------------------------------------------------------------------------- /doc/ko/core/undefined.md: -------------------------------------------------------------------------------- 1 | ## `undefined`와 `null` 2 | 3 | JavaScript는 `nothing`을 표현할때 `null`과 `undefined` 두 가지로 표현할 수 있고 그중 `undefined`가 더 유용하다. 4 | 5 | ### `undefined`도 변수 6 | 7 | `undefined`는 `undefined`라는 값을 가지는 데이터 형식이다. 8 | 9 | `undefined`는 상수도 아니고 JavaScript의 키워드도 아니다. 그냥 `undefined`라는 이름의 Global 변수이고 이 변수에는 `undefined`라고 할당돼 있다. 그래서 이 Global 변수의 값을 쉽게 바꿀 수 있다. 10 | 11 | > **ES5 Note:** ECMAScript 5의 strict 모드에서는 `undefined`를 더는 바꿀 수 없도록 했다. 하지만 `undefined`라는 함수를 만들면 여전히 할당할 수 있다. 12 | 13 | `undefined` 값이 반환될 때: 14 | 15 | - global 변수 `undefined`에 접근할 때. 16 | - 선언은 했지만 아직 초기화하지 않은 변수에 접근할 때. 17 | - `return` 구문이 없는 함수는 암묵적으로 `undefined`를 반환함. 18 | - `return` 구문으로 아무것도 반환하지 않을 때. 19 | - 없는 프로퍼티를 찾을 때. 20 | - 함수 인자가 생략될 때. 21 | - `undefined`가 할당된 모든 것. 22 | - `void(expression)` 형식으로 된 표현 23 | 24 | > **역주:** 예를 들어 CoffeeScript Compliler는 CoffeeScript의 `undefined`를 JavaScript의 `void 0`로 컴파일한다. 25 | 26 | ### `undefined`가 바뀔 때를 대비하기 27 | 28 | global 변수 `undefined`는 `undefined`라는 객체를 가리키는 것뿐이기 때문에 새로운 값을 할당한다고 해도 `undefined`의 값 자체가 바뀌는 것이 아니다. 29 | 30 | 그래서 `undefined`와 비교하려면 먼저 `undefined`의 값을 찾아와야 한다. 31 | 32 | `undefined` 변수가 바뀔 때를 대비해서 `undefined`라는 변수를 인자로 받는 [anonymous wrapper](#function.scopes)로 감싸고 인자를 넘기지 않는 꼼수를 사용한다. 33 | 34 | var undefined = 123; 35 | (function(something, foo, undefined) { 36 | // Local Scope에 undefined를 만들어서 37 | // 원래 값을 가리키도록 했다. 38 | 39 | })('Hello World', 42); 40 | 41 | wrapper 안에 변수를 새로 정의하는 방법으로도 같은 효과를 볼 수 있다. 42 | 43 | var undefined = 123; 44 | (function(something, foo) { 45 | var undefined; 46 | ... 47 | 48 | })('Hello World', 42); 49 | 50 | 이 두 방법의 차이는 minified했을 때 4바이트만큼 차이 난다는 것과 한쪽은 wrapper 안에 var 구문이 없다는 것밖에 없다. 51 | 52 | ### `Null` 객체의 용도 53 | 54 | JavaScript 언어에서는 `undefined`를 다른 언어의 *null* 처럼 쓴다. 진짜 `null`은 그냥 데이터 타입 중 하나일 뿐이지 더도덜도 아니다. 55 | 56 | JavaScript를 깊숙히 건드리는 것이 아니면 null 대신 `undefined`를 사용해도 된다(`Foo.prototype = null`같이 프로토타입 체인을 끊을 때는 null을 사용한다). 57 | -------------------------------------------------------------------------------- /doc/ko/function/general.md: -------------------------------------------------------------------------------- 1 | ## 함수 선언과 함수 표현식 2 | 3 | JavaScript에서 함수는 First Class Object다. 즉, 함수 자체가 또 다른 함수의 인자될 수 있다는 말이다. 그래서 익명 함수를 비동기 함수의 콜백으로 넘기는 것도 이런 특징을 이용한 일반적인 사용법이다. 4 | 5 | ### `함수` 선언 6 | 7 | function foo() {} 8 | 9 | 위와 같이 선언한 함수는 프로그램이 실행하기 전에 먼저 [호이스트(Hoist)](#function.scopes) (스코프가 생성)되기 때문에 정의된 스코프(Scope) 안에서는 어디서든 이 함수를 사용할 수 있다. 심지어 함수를 정의하기 전에 호출해도 된다. 10 | 11 | foo(); // 이 코드가 실행되기 전에 foo가 만들어지므로 잘 동작한다. 12 | function foo() {} 13 | 14 | ### `함수` 표현식 15 | 16 | var foo = function() {}; 17 | 18 | 위 예제는 `foo` 변수에 *익명* 함수를 할당한다. 19 | 20 | foo; // 'undefined' 21 | foo(); // TypeError가 난다. 22 | var foo = function() {}; 23 | 24 | 'var'문을 이용해 선언하는 경우, 코드가 실행되기 전에 'foo' 라는 이름의 변수를 스코프의 맨 위로 올리게 된다.(호이스트 된다) 이때 foo 값은 undefiend로 정의된다. 25 | 26 | 하지만 변수에 값을 할당하는 일은 런타임 상황에서 이루어지게 되므로 실제 코드가 실행되는 순간의 `foo`변수는 기본 값인 [undefined](#core.undefined)이 된다. 27 | 28 | ### 이름있는 함수 표현식 29 | 30 | 이름있는 함수를 할당할때도 특이한 경우가 있다. 31 | 32 | var foo = function bar() { 33 | bar(); // 이 경우는 동작 하지만, 34 | } 35 | bar(); // 이 경우는 참조에러를 발생시킨다. 36 | 37 | foo 함수 스코프 밖에서는 foo 변수 외에는 다른 값이 없기 때문에 `bar`는 함수 밖에서 사용할 수 없지만 함수 안에서는 사용할 수 있다. [이와 같은 방법](#function.scopes)으로 자바스크립트에서 어떤 함수의 이름은 항상 그 함수의 지역 스코프 안에서 사용할수있다. -------------------------------------------------------------------------------- /doc/ko/index.json: -------------------------------------------------------------------------------- 1 | { 2 | "title": "JavaScript Garden", 3 | "langTitle": "JavaScript Garden", 4 | "description": "A Guide to JavaScript's Quirks and Flaws.", 5 | "sections": [ 6 | { 7 | "title": "소개", 8 | "dir": "intro", 9 | "articles": ["index"] 10 | }, 11 | { 12 | "title": "객체", 13 | "dir": "object", 14 | "articles": [ 15 | "general", 16 | "prototype", 17 | "hasownproperty", 18 | "forinloop" 19 | ] 20 | }, 21 | { 22 | "title": "함수", 23 | "dir": "function", 24 | "articles": [ 25 | "general", 26 | "this", 27 | "closures", 28 | "arguments", 29 | "constructors", 30 | "scopes" 31 | ] 32 | }, 33 | { 34 | "title": "Array", 35 | "dir": "array", 36 | "articles": [ 37 | "general", 38 | "constructor" 39 | ] 40 | }, 41 | { 42 | "title": "타입", 43 | "dir": "types", 44 | "articles": [ 45 | "equality", 46 | "typeof", 47 | "instanceof", 48 | "casting" 49 | ] 50 | }, 51 | { 52 | "title": "핵심", 53 | "dir": "core", 54 | "articles": [ 55 | "eval", 56 | "undefined", 57 | "semicolon", 58 | "delete" 59 | ] 60 | }, 61 | { 62 | "title": "기타", 63 | "dir": "other", 64 | "articles": [ 65 | "timeouts" 66 | ] 67 | } 68 | ] 69 | } 70 | -------------------------------------------------------------------------------- /doc/ko/intro/index.md: -------------------------------------------------------------------------------- 1 | ## Intro 2 | 3 | JavaScript 언어의 핵심에 대한 내용을 모아 **JavaScript Garden**을 만들어 었다. 이 글이 초보자가 JavaScript 익히면서 자주 겪는 실수, 미묘한 버그, 성능 이슈, 나쁜 습관들 줄일 수 있도록 도와줄 것이다. 4 | 5 | JavaScript Garden은 단순히 JavaScript 언어 자체를 설명하려 만들지 않았다. 그래서 이 글에서 설명하는 주제들을 이해하려면 반드시 언어에 대한 기본 지식이 필요하다. 먼저 Mozilla Developer Network에 있는 [문서][1]로 JavaScript 언어를 공부하기 바란다. 6 | 7 | ## 저자들 8 | 9 | 이 글은 [Stack Overflow][2]에서 사랑받는 두 사람 [Ivo Wetzel][3]과 [Zhang Yi Jiang][4]의 작품이다. Ivo Wetzel이 글을 썼고 Zhang Yi jiang이 디자인을 맡았다. 10 | 11 | ## 기여자들 12 | 13 | - [기여자들](https://github.com/BonsaiDen/JavaScript-Garden/graphs/contributors) 14 | 15 | ## 번역 16 | - [박창우][] 17 | - [손병대][] 18 | 19 | [박창우]: https://github.com/pismute 20 | [손병대]: https://github.com/miconblog 21 | 22 | ## 호스팅 23 | 24 | JavaScript Garden은 Github에서 호스팅하고 있고 [Cramer Development][7]가 [JavaScriptGarden.info][8]에서 미러링해주고 있다. 25 | 26 | ## 저작권 27 | 28 | JavaScript Garden은 [MIT license][9]를 따르고 [GitHub][10]에서 호스팅하고 있다. 문제를 발견하면 [이슈를 보고][11]하거나 수정해서 Pull Request를 하라. 아니면 Stack Overflow 채팅 사이트의 [Javascript room][12]에서 우리를 찾으라. 29 | 30 | [1]: https://developer.mozilla.org/en/JavaScript/Guide 31 | [2]: http://stackoverflow.com/ 32 | [3]: http://stackoverflow.com/users/170224/ivo-wetzel 33 | [4]: http://stackoverflow.com/users/313758/yi-jiang 34 | [5]: https://github.com/caio 35 | [6]: https://github.com/blixt 36 | [7]: http://cramerdev.com/ 37 | [8]: http://javascriptgarden.info/ 38 | [9]: https://github.com/BonsaiDen/JavaScript-Garden/blob/next/LICENSE 39 | [10]: https://github.com/BonsaiDen/JavaScript-Garden 40 | [11]: https://github.com/BonsaiDen/JavaScript-Garden/issues 41 | [12]: http://chat.stackoverflow.com/rooms/17/javascript 42 | -------------------------------------------------------------------------------- /doc/ko/object/forinloop.md: -------------------------------------------------------------------------------- 1 | ## `for in` Loop 2 | 3 | 객체의 프로퍼티를 탐색할때 `in` 연산자와 마찬가지로 `for in` 문도 프로토타입 체인까지 탐색한다. 4 | 5 | > **Note:** `for in`문은 배열의 `length`프로퍼티처럼 `enumerable` 속성이 `false`인 프로퍼티는 탐색하지 않는다. 6 | 7 | // Object.prototype을 오염시킨다. 8 | Object.prototype.bar = 1; 9 | 10 | var foo = {moo: 2}; 11 | for(var i in foo) { 12 | console.log(i); // bar와 moo 둘 다 출력한다. 13 | } 14 | 15 | `for in`문에 정의된 기본 동작을 바꿀순 없기 때문에 루프 안에서 불필요한 프로퍼티를 필터링 해야한다. 그래서 `Object.prototype`의 [`hasOwnProperty`](#object.hasownproperty)메소드를 이용해 본래 객체의 프로퍼티만 골라낸다. 16 | 17 | > **Note:** `for in`은 프로토타입 체인을 모두 탐색하기 때문에 상속할 때마다 더 느려진다. 18 | 19 | ### `hasOwnProperty`로 필터링 하기 20 | 21 | // 위의 예제에 이어서 22 | for(var i in foo) { 23 | if (foo.hasOwnProperty(i)) { 24 | console.log(i); 25 | } 26 | } 27 | 28 | 위와 같이 사용해야 올바른 사용법이다. `hasOwnProperty` 때문에 **오직** `moo`만 출력된다. `hasOwnProperty`가 없으면 이 코드는 `Object.prototype`으로 네이티브 객체가 확장될 때 에러가 발생할 수 있다. 29 | 30 | 따라서 [Proptotype 라이브러리][1]처럼 네이티브 객체를 프로토타입으로 확장한 프레임워크를 사용할 경우 `for in` 문에 `hasOwnProperty`를 사용하지 않을 경우 문제가 발생할 수 있다. 31 | 32 | ### 결론 33 | 34 | `hasOwnProperty`를 항상 사용하길 권한다. 실제 코드가 동작하는 환경에서는 절대로 네이티브 객체가 프로토타입으로 확장됐다 혹은 확장되지 않았다를 가정하면 안된다. 35 | 36 | [1]: http://www.prototypejs.org/ 37 | -------------------------------------------------------------------------------- /doc/ko/object/hasownproperty.md: -------------------------------------------------------------------------------- 1 | ## `hasOwnProperty` 2 | 3 | 어떤 객체의 프로퍼티가 자기 자신의 프로퍼티인지 아니면 [프로토타입 체인](#object.prototype)에 있는 것인지 확인하려면 `hasOwnProperty` 메소드를 사용한다. 그리고 이 메소드는 `Object.prototype`으로 부터 상속받아 모든 객체가 가지고 있다. 4 | 5 | > **Note:** hasOwnProperty 메소드로는 어떤 프로퍼티가 존재하는지 확인하는 용도로는 사용할수 있지만, 그 값이 `undefined`일 수 있기 때문에 어떤 프로퍼티의 값이 `undefined`인지 확인하는 용도로 사용하긴 어렵다. 6 | 7 | `hasOwnProperty`메소드는 프로토타입 체인을 탐색하지 않고, 프로퍼티를 다룰수있는 유일한 방법이다. 8 | 9 | // Object.prototype을 오염시킨다. 10 | Object.prototype.bar = 1; 11 | var foo = {goo: undefined}; 12 | 13 | foo.bar; // 1 14 | 'bar' in foo; // true 15 | 16 | foo.hasOwnProperty('bar'); // false 17 | foo.hasOwnProperty('goo'); // true 18 | 19 | `hasOwnProperty` 메소드는 어떤 프로퍼티가 자기 자신의 프로퍼티인지 아닌지 정확하게 알려주기 때문에 객체의 프로퍼티를 순회할때 꼭 필요하다. 그리고 프로토타입 체인 어딘가에 정의된 프로퍼티만을 제외하는 방법은 없다. 20 | 21 | ### `hasOwnProperty` 메소드도 프로퍼티다 22 | 23 | JavaScript는 `hasOwnProperty`라는 이름으로 프로퍼티를 덮어 쓸수도 있다. 그래서 객체 안에 같은 이름으로 정의된 `hasOwnProperty`가 있을 경우, 본래 `hasOwnProperty`의 값을 정확하게 얻고 싶다면 다른 객체의 `hasOwnProperty` 메소드를 빌려써야 한다. 24 | 25 | var foo = { 26 | hasOwnProperty: function() { 27 | return false; 28 | }, 29 | bar: 'Here be dragons' 30 | }; 31 | 32 | foo.hasOwnProperty('bar'); // 항상 false를 반환한다. 33 | 34 | // 다른 객체의 hasOwnProperty를 사용하여 foo 객체의 프로퍼티 유무를 확인한다. 35 | ({}).hasOwnProperty.call(foo, 'bar'); // true 36 | 37 | // Object에 있는 hasOwnProperty를 사용해도 된다. 38 | Object.prototype.hasOwnProperty.call(obj, 'bar'); // true 39 | 40 | 41 | ### 결론 42 | 43 | 어떤 객체에 원하는 프로퍼티가 있는지 확인하는 가장 확실한 방법은 `hasOwnProperty`를 사용하는 것이다. [`for in` loop](#object.forinloop)에서 네이티브 객체에서 확장된 프로퍼티를 제외하고 순회하려면 `hasOwnProperty`와 함께 사용하길 권한다. 44 | -------------------------------------------------------------------------------- /doc/ko/types/casting.md: -------------------------------------------------------------------------------- 1 | ## 타입 캐스팅 2 | 3 | JavaScript는 Weak Typing 언어이기 때문에 필요할 때마다 알아서 타입을 변환한다. 4 | 5 | // 다음은 모두 true 6 | new Number(10) == 10; // Number.toString()이 호출되고 7 | // 다시 Number로 변환된다. 8 | 9 | 10 == '10'; // 스트링은 Number로 변환된다. 10 | 10 == '+10 '; // 이상한 스트링 11 | 10 == '010'; // 엉뚱한 스트링 12 | isNaN(null) == false; // null은 NaN이 아녀서 0으로 변환된다. 13 | 14 | // 다음은 모두 false 15 | 10 == 010; 16 | 10 == '-10'; 17 | 18 | > **ES5 Note:** `0`으로 시작하는 숫자 리터럴은 8진수다. 하지만, ECMAScript 5의 strict 모드에서는 8진수로 더이상 해석하지 않는다. 19 | 20 | 위와 같은 문제들은 ***반드시** [삼중 등호 연산자](#types.equality)를 이용해 해결하길 권한다. 물론 삼중 등호로 많은 결점을 보완할 수 있지만, 여전히 weak typing 시스템 때문에 생기는 많은 문제가 남아있다. 21 | 22 | ### 기본 타입 생성자 23 | 24 | `Number`나 `String` 같은 기본 타입들의 생성자는 `new` 키워드가 있을 때와 없을 때 다르게 동작한다. 25 | 26 | new Number(10) === 10; // False, Object와 Number 27 | Number(10) === 10; // True, Number와 Number 28 | new Number(10) + 0 === 10; // True, 타입을 자동으로 변환해주기 때문에 29 | 30 | `new` 키워드와 함께 `Number` 같은 기본 타입의 생성자를 호출하면 객체를 생성하지만 `new` 없이 호출하면 형 변환만 시킨다. 31 | 32 | 그리고 객체가 아니라 단순히 값이나 리터럴을 사용하면 타입 변환이 더 많이 일어난다. 33 | 34 | 가능한 정확하게 타입을 변환해주는 것이 최선이다. 35 | 36 | ### 스트링으로 변환하기 37 | 38 | '' + 10 === '10'; // true 39 | 40 | 숫자를 빈 스트링과 더하면 쉽게 스트링으로 변환할 수 있다. 41 | 42 | ### 숫자로 변환하기 43 | 44 | +'10' === 10; // true 45 | 46 | `+` 연산자만 앞에 붙여주면 스트링을 쉽게 숫자로 변환할 수 있다. 47 | 48 | ### Boolean으로 변환하기 49 | 50 | '!' 연산자를 두 번 사용하면 쉽게 Boolean으로 변환할 수 있다. 51 | 52 | !!'foo'; // true 53 | !!''; // false 54 | !!'0'; // true 55 | !!'1'; // true 56 | !!'-1' // true 57 | !!{}; // true 58 | !!true; // true 59 | -------------------------------------------------------------------------------- /doc/ko/types/equality.md: -------------------------------------------------------------------------------- 1 | ## 객체 비교하기 2 | 3 | JavaScript에서 객체를 비교하는 방법은 두 가지가 있다. 4 | 5 | ### 이중 등호 연산자 6 | 7 | 이중 등호 연산자는 `==`을 말한다. 8 | 9 | JavaScript는 Weak Typing을 따르기 때문에 이중 등호를 이용해 비교할 때 두 객체의 자료형을 **강제로** 변환한다. 10 | 11 | "" == "0" // false 12 | 0 == "" // true 13 | 0 == "0" // true 14 | false == "false" // false 15 | false == "0" // true 16 | false == undefined // false 17 | false == null // false 18 | null == undefined // true 19 | " \t\r\n" == 0 // true 20 | 21 | 이 표는 이중 등호를 사용하면 왜 안되는지를 보여준다. 이 복잡한 변환 규칙은 실제로 골치 아픈 버그를 만들어 낸다. 22 | 23 | 게다가 강제로 타입을 변환하게 되면 성능에도 영향을 준다. 예를 들어 문자와 숫자를 비교하려면 반드시 먼저 문자를 숫자로 변환해야 한다. 24 | 25 | ### 삼중 등호 연산자 26 | 27 | 삼중 등호 연산자는 `===`을 말한다. 28 | 29 | 삼중 등호는 강제로 타입을 변환하지 않는다는 사실을 제외하면 이중 등호와 동일하다. 30 | 31 | "" === "0" // false 32 | 0 === "" // false 33 | 0 === "0" // false 34 | false === "false" // false 35 | false === "0" // false 36 | false === undefined // false 37 | false === null // false 38 | null === undefined // false 39 | " \t\r\n" === 0 // false 40 | 41 | 위 결과가 훨씬 더 명확하고 문제가 쉽게 드러난다. 삼중 등호를 사용하면 코드를 좀 더 튼튼하게 만들수 있고, 비교하는 두 객체의 타입이 다르면 더 좋은 성능을 얻을 수도 있다. 42 | 43 | ### 객체 비교하기 44 | 45 | 이중 등호와(`==`)와 삼중 등호(`===`)는 둘 다 **값을 비교하는** 연산이지만 피연산자중에 Object 타입이 하나라도 있으면 다르게 동작한다. 46 | 47 | {} === {}; // false 48 | new String('foo') === 'foo'; // false 49 | new Number(10) === 10; // false 50 | var foo = {}; 51 | foo === foo; // true 52 | 53 | 두 연산자 모두 두 객체의 값이 같은지를 비교하지 않고, 두 객체가 **같은 객체(identity)**인지를 비교한다. C에서 포인터를 비교하거나 Python의 is처럼 같은 인스턴스인지 비교하는 것이다. 54 | 55 | ### 결론 56 | 57 | **삼중 등호 연산자**를 사용할 것을 강력하게 권한다. 비교하기 위해서 타입 변환이 필요하면 언어의 복잡한 변환 규칙에 맡기지 말고 꼭 명시적으로 변환한 후에 비교해야 한다. 58 | -------------------------------------------------------------------------------- /doc/ko/types/instanceof.md: -------------------------------------------------------------------------------- 1 | ## `instanceof` 연산자 2 | 3 | `instanceof`연산자는 두 피연산자의 생성자를 비교할때 사용하고 직접 만든 객체를 비교할 때 매우 유용하다. 내장 타입에 쓰는 경우에는 [typeof](#types.typeof)처럼 거의 쓸모가 없다. 4 | 5 | ### 커스텀 객체를 `intanceof`로 비교하기 6 | 7 | function Foo() {} 8 | function Bar() {} 9 | Bar.prototype = new Foo(); 10 | 11 | new Bar() instanceof Bar; // true 12 | new Bar() instanceof Foo; // true 13 | 14 | // Bar.prototype에 함수 객체인 Foo를 할당하면 15 | // Bar의 인스턴스는 Foo의 인스턴스가 아니다. 16 | Bar.prototype = Foo; 17 | new Bar() instanceof Foo; // false 18 | 19 | ### 기본 내장 객체 타입을 `intanceof`로 비교하기 20 | 21 | new String('foo') instanceof String; // true 22 | new String('foo') instanceof Object; // true 23 | 24 | 'foo' instanceof String; // false 25 | 'foo' instanceof Object; // false 26 | 27 | JavaScript 컨텍스트마다(웹 브라우저의 도큐먼트 같은) 객체의 생성자는 다를 수밖에 없어서 `instanceof`는 다른 JavaScript 컨텍스트에 있는(웹 브라우저의 다른 도큐먼트에 있는) 객체와는 비교할 수 없다. 28 | 29 | ### 결론 30 | 31 | `instanceof`는 한 JavaScript 컨텍스트 내에서 사용자가 만든 타입의 객체를 비교할 때에만 유용하다. [`typeof`](#types.typeof)처럼 다른 목적으로는 사용하지 않는 것이 좋다. 32 | -------------------------------------------------------------------------------- /doc/language.json: -------------------------------------------------------------------------------- 1 | { 2 | "default": "en", 3 | "listed": ["by","en","es","fi","fr","hu","it","ja","ko","pl","ptbr","ru","tr","zh","zhtw"] 4 | } 5 | -------------------------------------------------------------------------------- /doc/pl/array/constructor.md: -------------------------------------------------------------------------------- 1 | ## Konstruktor `Array` 2 | 3 | Zaleca się zawsze korzystać z literału tablicy - notacja `[]` - podczas tworzenia 4 | nowych tablic, ponieważ konstruktor `Array` niejednoznacznie interpretuje 5 | przekazane do niego parametry. 6 | 7 | [1, 2, 3]; // Rezultat: [1, 2, 3] 8 | new Array(1, 2, 3); // Rezultat: [1, 2, 3] 9 | 10 | [3]; // Rezultat: [3] 11 | new Array(3); // Rezultat: [] 12 | new Array('3') // Rezultat: ['3'] 13 | 14 | W przypadku, gdy tylko jeden argument zostanie przekazany do kostruktora `Array` i 15 | ten argument jest typu `Number`, konstruktor zwróci nową *dziwną* tablicę 16 | z właściwością `length` ustawioną na wartość przekazaną jako argument. Należy 17 | zauważyć, że **tylko** właściwość `length` zostanie ustawiona w ten sposób. 18 | Rzeczywiste indeksy w tej tablicy nie zostaną zainicjalizowane. 19 | 20 | var arr = new Array(3); 21 | arr[1]; // undefined 22 | 1 in arr; // zwraca false, indeks nie został ustawiony 23 | 24 | Możliwość ustalenia z góry długości tablicy jest użyteczna tylko w kilku 25 | przypadkach, jak np. powtarzanie ciągu znaków, w którym unika się stosowania 26 | pętli `for`. 27 | 28 | // count - ilosc powtorzen 29 | // stringToRepeat - ciąg znaków do powtórzenia 30 | new Array(count + 1).join(stringToRepeat); 31 | 32 | ### Wnioski 33 | 34 | W miarę możliwości należy unikać używania konstruktora `Array`. Literały są 35 | zdecydowanie lepszym rozwiązaniem. Są krótsze i mają bardziej precyzyjną składnię. 36 | Zwiększają również czytelność kodu. 37 | 38 | -------------------------------------------------------------------------------- /doc/pl/core/eval.md: -------------------------------------------------------------------------------- 1 | ## Dlaczego nie należy używać `eval`? 2 | 3 | Funkcja `eval` uruchomi podany string jako kod JavaScript w lokalnym zasięgu (scopie). 4 | 5 | var foo = 1; 6 | function test() { 7 | var foo = 2; 8 | eval('foo = 3'); 9 | return foo; 10 | } 11 | test(); // 3 12 | foo; // 1 13 | 14 | Niestaty, `eval` zostanie wykonana w lokalnym zasięgu tylko wtedy, gdy zostanie wywołana 15 | **bezpośrednio** *i* nazwa wywoływanej funkcji równa się `eval`. 16 | 17 | var foo = 1; 18 | function test() { 19 | var foo = 2; 20 | var bar = eval; 21 | bar('foo = 3'); 22 | return foo; 23 | } 24 | test(); // 2 25 | foo; // 3 26 | 27 | Należy unikać stosowania `eval` **o ile to tylko możliwe**. W 99.9% przypadków można 28 | osiągnąć ten sam efekt **nie** używając `eval`. 29 | 30 | ### `eval` w przebraniu 31 | 32 | [Funkcje wykonywane po upływie czasu](#other.timeouts) `setTimeout` i `setInterval` 33 | mogą przyjąć string jako pierwszy argument. String ten **zawsze** będzie wykonywany 34 | w globalnym zasięgu, ponieważ funkcja `eval` jest w tym wypadku wywoływana pośrednio. 35 | 36 | ### Problemy z bezpieczeństwem 37 | 38 | Funkcja `eval` jest również problematyczna od strony bezpieczeństwa, ponieważ 39 | wykonuje **każdy** kod, który zostanie do niej przekazany i **nigdy** nie należy 40 | jej używać na stringach nieznanego lub niezaufanego pochodzenia. 41 | 42 | ### Wnioski 43 | 44 | Funkcja `eval` nie powinna być w ogóle używana. Każdy kod, który jej używa 45 | powinien zostać sprawdzony pod względem działania, wydajności i bezpieczeństwa. 46 | W przypadku gdy użycie `eval` jest niezbędne do działania, wówczas taki kod 47 | należy ponownie przemyśleć i *ulepszyć* aby nie wymagał użycia `eval`. 48 | 49 | -------------------------------------------------------------------------------- /doc/pl/function/general.md: -------------------------------------------------------------------------------- 1 | ## Deklaracje funkcji i wyrażenia funkcyjne 2 | 3 | Funkcje w języku JavaScript są [typami pierwszoklasowymi][1], co oznacza, że mogą 4 | być przekazywane jak każda inna wartość. Jednym z typowych zastosowań tej cechy 5 | jest przekazywanie *anonimowej funkcji* jako callback do innej, prawdopodobnie 6 | asynchronicznej funkcji. 7 | 8 | ### Deklaracja funkcji 9 | 10 | function foo() {} 11 | 12 | Powyższa funkcja zostaje [wyniesiona](#function.scopes) zanim program wystartuje. Dzięki temu 13 | jest dostępna *wszędzie* w ramach zasięgu, w którym została *zadeklarowana*, 14 | nawet, jeżeli ta funkcja została wywołana przed faktyczną definicją w kodzie źródłowym. 15 | 16 | foo(); // Działa ponieważ definicja funkcji została wyniesiona 17 | // na początek zasięgu przed uruchomieniem kodu 18 | function foo() {} 19 | 20 | ### Wyrażenie funkcyjne 21 | 22 | var foo = function() {}; 23 | 24 | Ten przykład przypisuje nienazwaną i *anonimową* funkcję do zmiennej `foo`. 25 | 26 | foo; // 'undefined' 27 | foo(); // wyrzuca błąd TypeError 28 | var foo = function() {}; 29 | 30 | Ze względu na fakt, że deklaracja `var` wynosi zmienną `foo` na początek zasięgu 31 | zanim kod faktycznie zostanie uruchomiony, `foo` będzie zdefiniowane kiedy skrypt 32 | będzie wykonywany. 33 | 34 | Ale ponieważ przypisania robione są dopiero podczas wykonania, wartość `foo` będzie 35 | ustawiona na domyślną wartość [undefined](#core.undefined) zanim powyższy kod 36 | zostanie uruchomiony. 37 | 38 | ### Nazwane wyrażenia funkcyjne 39 | 40 | Kolejnym specjalnym przypadkiem jest przypisanie nazwanej funkcji. 41 | 42 | var foo = function bar() { 43 | bar(); // Działa 44 | } 45 | bar(); // wyrzuca ReferenceError 46 | 47 | W zewnętrznym zakresie `bar` nie będzie dostępna, ponieważ funkcja zostaje 48 | przypisana do `foo`, jednakże w wewnętrznym zakresie `bar` będzie dostępna. 49 | Jest to spowodowane tym, jak działa [rozwiązywanie nazw](#function.scopes) 50 | w języku JavaScript. Nazwa funkcji jest *zawsze* dostępna w lokalnym 51 | zakresie tej funkcji. 52 | 53 | [1]: http://pl.wikipedia.org/wiki/Typ_pierwszoklasowy 54 | -------------------------------------------------------------------------------- /doc/pl/index.json: -------------------------------------------------------------------------------- 1 | { 2 | "title": "JavaScript Garden", 3 | "langTitle": "JavaScript Garden - ogród JavaScript po polsku", 4 | "description": "Przewodnik po dziwactwach i wadach języka JavaScript.", 5 | "sections": [ 6 | { 7 | "title": "Wstęp", 8 | "dir": "intro", 9 | "articles": [ 10 | "authors", 11 | "contributors", 12 | "translators", 13 | "hosting", 14 | "license" 15 | ] 16 | }, 17 | { 18 | "title": "Obiekty", 19 | "dir": "object", 20 | "articles": [ 21 | "general", 22 | "prototype", 23 | "hasownproperty", 24 | "forinloop" 25 | ] 26 | }, 27 | { 28 | "title": "Funkcje", 29 | "dir": "function", 30 | "articles": [ 31 | "general", 32 | "this", 33 | "closures", 34 | "arguments", 35 | "constructors", 36 | "scopes" 37 | ] 38 | }, 39 | { 40 | "title": "Tablice", 41 | "dir": "array", 42 | "articles": [ 43 | "general", 44 | "constructor" 45 | ] 46 | }, 47 | { 48 | "title": "Typy", 49 | "dir": "types", 50 | "articles": [ 51 | "equality", 52 | "typeof", 53 | "instanceof", 54 | "casting" 55 | ] 56 | }, 57 | { 58 | "title": "Jądro", 59 | "dir": "core", 60 | "articles": [ 61 | "eval", 62 | "undefined", 63 | "semicolon" 64 | ] 65 | }, 66 | { 67 | "title": "Inne", 68 | "dir": "other", 69 | "articles": [ 70 | "timeouts" 71 | ] 72 | } 73 | ] 74 | } 75 | -------------------------------------------------------------------------------- /doc/pl/intro/authors.md: -------------------------------------------------------------------------------- 1 | ## Autorzy 2 | 3 | Ten przewodnik jest dziełem dwóch uroczych użytkowników [Stack Overflow][1], 4 | [Ivo Wetzel][2] (Treść) oraz [Zhang Yi Jiang][3] (Projekt). 5 | 6 | [1]: http://stackoverflow.com/ 7 | [2]: http://stackoverflow.com/users/170224/ivo-wetzel 8 | [3]: http://stackoverflow.com/users/313758/yi-jiang -------------------------------------------------------------------------------- /doc/pl/intro/contributors.md: -------------------------------------------------------------------------------- 1 | ## Współtwórcy 2 | 3 | - [Współtwórcy](https://github.com/BonsaiDen/JavaScript-Garden/graphs/contributors) 4 | 5 | -------------------------------------------------------------------------------- /doc/pl/intro/hosting.md: -------------------------------------------------------------------------------- 1 | ## Hosting 2 | JavaScript Garden znajduje się na serwerach GitHub, ale dzięki wsparciu 3 | [Cramer Development] [1] posiadamy również mirror na serwerze [JavaScriptGarden.info] [2]. 4 | 5 | [1]: http://cramerdev.com/ 6 | [2]: http://javascriptgarden.info/ 7 | -------------------------------------------------------------------------------- /doc/pl/intro/index.md: -------------------------------------------------------------------------------- 1 | ## Wstęp 2 | **JavaScript Garden** jest rosnącą kolekcją dokumentów o najdziwniejszych 3 | częściach języka JavaScript. Dokumentacja pomaga uniknąć najczęściej popełnianych 4 | błędów, sybtelnych bugów, problemów wydajnościowych oraz złych praktyk, na które 5 | niedoświadczeni programiści JavaScript mogą natrafić próbując poznać tajniki tego 6 | języka. 7 | 8 | JavaScript Garden **nie** ma na celu nauczyć Cię języka JavaScript. Podstawowa 9 | wiedza na temat języka jest wymagana do zrozumienia zagadnień poruszanych w tym 10 | przewodniku. Aby nauczyć się podstaw jezyka JavaScript, odwiedź znakomity 11 | [przewodnik][1] na stronach Mozilla Developer Network. 12 | 13 | [1]: https://developer.mozilla.org/en/JavaScript/Guide 14 | -------------------------------------------------------------------------------- /doc/pl/intro/license.md: -------------------------------------------------------------------------------- 1 | ## Licencja 2 | 3 | JavaScript Garden jest publikowany w ramach [licencji MIT] [1] i kod źródłowy znajduje 4 | się na serwerze [GitHub] [2]. Jeśli znajdziesz jakieś błędy lub literówki, zgłoś proszę 5 | [problem] [3] lub rozwiąż go i zgloś pull request ze swojego repozytorium. 6 | Możesz nas także znaleźć w pokoju [JavaScript] [4] na chacie Stack Overflow. 7 | 8 | [1]: https://github.com/BonsaiDen/JavaScript-Garden/blob/next/LICENSE 9 | [2]: https://github.com/BonsaiDen/JavaScript-Garden 10 | [3]: https://github.com/BonsaiDen/JavaScript-Garden/issues 11 | [4]: http://chat.stackoverflow.com/rooms/17/javascript 12 | -------------------------------------------------------------------------------- /doc/pl/intro/translators.md: -------------------------------------------------------------------------------- 1 | ## Tłumaczenie 2 | 3 | - [Łukasz Kufel][1] 4 | - [Maciej Ciemborowicz][2] 5 | 6 | [1]: http://qfel13.pl 7 | [2]: http://blog.ciemborowicz.pl 8 | -------------------------------------------------------------------------------- /doc/pl/object/forinloop.md: -------------------------------------------------------------------------------- 1 | ## Pętla `for in` 2 | 3 | Podobnie jak operator `in`, pętla `for in` przeszukuje łańcuch prototypów 4 | podczas iteracji po właściwościach obiektu. 5 | 6 | > **Uwaga:** pętla `for in` **nie** będzie iterować po właściwościach, które 7 | > mają ustawiony atrybut `enumerable` na `false` (na przykład właściwość 8 | > `length` tablicy). 9 | 10 | // Zatrucie Object.prototype 11 | Object.prototype.bar = 1; 12 | 13 | var foo = {moo: 2}; 14 | for(var i in foo) { 15 | console.log(i); // wyświetla obie właściwości: bar i moo 16 | } 17 | 18 | Ponieważ zmiana zachowania pętli `for in` nie jest możliwa, niezbędne 19 | jest odfiltrowanie niechcianych właściwości wewnątrz ciała pętli, korzystając 20 | z metody [`hasOwnProperty`](#object.hasownproperty) z `Object.prototype`. 21 | 22 | > **Uwaga:** Ponieważ pętla `for in` zawsze przeszukuje cały łańcuch prototypów, 23 | > będzie się ona stawała coraz wolniejsza przy dodaniu każdej kolejnej warstwy 24 | > dziedziczenia do obiektu. 25 | 26 | ### Filtrowania przy użyciu `hasOwnProperty` 27 | 28 | // foo z przykładu powyżej 29 | for(var i in foo) { 30 | if (foo.hasOwnProperty(i)) { 31 | console.log(i); 32 | } 33 | } 34 | 35 | To jest jedyna poprawna wersja, której należy używać. Ze względu na użycie 36 | `hasOwnProperty` zostanie wypisane **jedynie** `moo`. Gdy opuścimy `hasOwnProperty`, 37 | kod będzie podatny na błędy, gdy natywne prototypy (np. `Object.prototype`) 38 | zostaną rozszerzone. 39 | 40 | [Prototype][1] jest jednym z popularniejszych frameworków, które dokonują 41 | takiego rozszerzenia. Używanie tego frameworku oraz nie stosowanie w pętli `for in` 42 | metody `hasOwnProperty` gwarantuje błędy w wykonaniu. 43 | 44 | ### Wnioski 45 | 46 | Zaleca się, aby zawsze używać metody `hasOwnProperty`. Nigdy nie powinno się dokonywać 47 | żadnych założeń na temat środowiska, w którym kod będzie wykonywany ani tego, czy 48 | natywne prototypy zostały rozszerzone, czy nie. 49 | 50 | [1]: http://www.prototypejs.org/ 51 | -------------------------------------------------------------------------------- /doc/pl/object/hasownproperty.md: -------------------------------------------------------------------------------- 1 | ## `hasOwnProperty` 2 | 3 | W celu sprawdzenia, czy dana właściwość została zdefiniowana *w tym* obiekcie, a **nie** 4 | w [łańcuchu prototypów](#object.prototype), niezbędne jest skorzystanie z metody 5 | `hasOwnProperty`, której wszystkie obiekty dziedziczą z `Object.prototype`. 6 | 7 | > **Uwaga:** **Nie** wystarczy sprawdzić, czy właściwość jest `undefined`, 8 | > ponieważ właściwość może istnieć, ale jej wartość być ustawiona na `undefined`. 9 | 10 | `hasOwnProperty` jest jedyną metodą w języku JavaScript, która operuje na właściwościach 11 | i **nie** przegląda całego łańcucha prototypów. 12 | 13 | // Zatrucie Object.prototype 14 | Object.prototype.bar = 1; 15 | var foo = {goo: undefined}; 16 | 17 | foo.bar; // 1 18 | 'bar' in foo; // true 19 | 20 | foo.hasOwnProperty('bar'); // false 21 | foo.hasOwnProperty('goo'); // true 22 | 23 | Tylko `hasOwnProperty` da prawidłowy i oczekiwany rezultat. Jest to istotne podczas 24 | iteracji po właściwościach obiektu. **Nie** ma innego sposobu na ominięcie 25 | właściwości, która nie została zdefiniowana przez ten **konkretny** obiekt, 26 | ale gdzieś indziej w łańcuchu prototypów. 27 | 28 | ### `hasOwnProperty` jako właściwość 29 | 30 | JavaScript **nie** chroni właściwości o nazwie `hasOwnProperty`, zatem istnieje 31 | możliwość, że obiekt będzie posiadać tak nazwaną właściwość. Konieczne jest użycie 32 | *zewnętrznego* `hasOwnProperty`, aby otrzymać poprawne rezultaty. 33 | 34 | var foo = { 35 | hasOwnProperty: function() { 36 | return false; 37 | }, 38 | bar: 'Here be dragons' 39 | }; 40 | 41 | foo.hasOwnProperty('bar'); // zawsze zwraca false 42 | 43 | // Została użyta metoda innego obiektu i wywołana z kontekstem 44 | // `this` ustawionym na foo 45 | ({}).hasOwnProperty.call(foo, 'bar'); // true 46 | 47 | ### Wnioski 48 | 49 | **Jedyną** metodą służącą do sprawdzenia istnienia jakiejś właściwości w konkretnym 50 | obiekcie jest metoda `hasOwnProperty`. Zaleca się korzystać z `hasOwnProperty` w 51 | **każdej** [pętli `for in`](#object.forinloop). Pozwoli to uniknąć błędów pochodzących 52 | z rozszerzonych natywnych [prototypów](#object.prototype). 53 | 54 | -------------------------------------------------------------------------------- /doc/pl/types/instanceof.md: -------------------------------------------------------------------------------- 1 | ## Operator `instanceof` 2 | 3 | Operator `instanceof` porównuje konstruktory obiektów przekazanych jako operendy. 4 | Jest on użyteczny jedynie do porównywania obiektów utworzonych klas. Stosowanie 5 | go na wbudowanych typach jest praktycznie tak samo bezużyteczne, jak operatora 6 | [typeof](#types.typeof). 7 | 8 | ### Porównywanie obiektów utworzonych klas 9 | 10 | function Foo() {} 11 | function Bar() {} 12 | Bar.prototype = new Foo(); 13 | 14 | new Bar() instanceof Bar; // true 15 | new Bar() instanceof Foo; // true 16 | 17 | // poniżej kod który przypisuje do Bar.prototype obiekt funkcji Foo 18 | // a nie faktyczną instancję Foo 19 | Bar.prototype = Foo; 20 | new Bar() instanceof Foo; // false 21 | 22 | ### Stosowanie `instanceof` na natywnych typach 23 | 24 | new String('foo') instanceof String; // true 25 | new String('foo') instanceof Object; // true 26 | 27 | 'foo' instanceof String; // false 28 | 'foo' instanceof Object; // false 29 | 30 | Jedną ważną rzeczą, którą należy zauważyć jest to, że `instanceof` nie zadziała 31 | na obiektach, które pochodzą z różnych kontekstów JavaScript (np. z różnych 32 | dokumentów wewnątrz przeglądarki), ponieważ ich konstruktory nie będą tymi 33 | samymi obiektami. 34 | 35 | ### Wnioski 36 | 37 | Operator `instanceof` powinien być używany **wyłącznie** podczas korzystania z obiektów 38 | klas utworzonych, które były zdefiniowane w tym samym kontekscie JavaScriptowym. 39 | Podobnie jak operator [`typeof`](#types.typeof), należy **unikać** korzystania 40 | z tego operatora w innych sytuacjach. 41 | 42 | -------------------------------------------------------------------------------- /doc/ptbr/array/constructor.md: -------------------------------------------------------------------------------- 1 | ## O construtor `Array` 2 | 3 | Uma vez que o construtor `Array` é ambíguo na forma como ele lida com seus parâmetros, 4 | o uso da notação `[]` é fortemente recomendado ao criar novo arrays. 5 | 6 | [1, 2, 3]; // Resultado: [1, 2, 3] 7 | new Array(1, 2, 3); // Resultado: [1, 2, 3] 8 | 9 | [3]; // Resultado: [3] 10 | new Array(3); // Resultado: [] 11 | new Array('3') // Resultado: ['3'] 12 | 13 | Nos casos onde somente um argumento é passado para o construtor `Array` e quando o argumento é 14 | um `Number`, o construtor retornará um novo array *sem elementos* com a propriedade `length` configurada de acordo com o valor do argumento. 15 | É importante perceber que **somente** a propriedade `length` do novo array será configurada desta maneira; os índices do array não serão inicializados. 16 | 17 | var arr = new Array(3); 18 | arr[1]; // undefined 19 | 1 in arr; // false, o índice não foi definida 20 | 21 | Ser capaz de definir o comprimento de um array antecipadamente é útil em poucos casos, 22 | como ao replicar uma string, em que se evita o uso de um loop. 23 | 24 | new Array(count + 1).join(stringToRepeat); 25 | 26 | ### Conclusão 27 | 28 | O uso de literais é preferencial na inicialição de Arrays. São curtos, possuem uma sintaxe limpa, e contribuem para a legibilidade do código. 29 | 30 | -------------------------------------------------------------------------------- /doc/ptbr/core/eval.md: -------------------------------------------------------------------------------- 1 | ## Por que não utilizar `eval` 2 | 3 | A função `eval` executará uma string de código JavaScript no escopo local. 4 | 5 | var foo = 1; 6 | function test() { 7 | var foo = 2; 8 | eval('foo = 3'); 9 | return foo; 10 | } 11 | test(); // 3 12 | foo; // 1 13 | 14 | Entretanto, `eval` somente é executado no escopo local quando é chamado diretamente 15 | *e* quando o nome da função chamada é `eval`. 16 | 17 | var foo = 1; 18 | function test() { 19 | var foo = 2; 20 | var bar = eval; 21 | bar('foo = 3'); 22 | return foo; 23 | } 24 | test(); // 2 25 | foo; // 3 26 | 27 | O uso de `eval` deve ser evitado. 99.9% de seu "uso" pode ser alcançado **sem** ele. 28 | 29 | ### `eval` dissimulado 30 | 31 | As [funções timeout](#other.timeouts) `setTimeout` e `setInterval` podem ambas receberem uma string 32 | como primeiro argumento. Tais strings **sempre** serão executadas no escopo global uma vez que 33 | `eval` não é chamado diretamente, naquele caso. 34 | 35 | ### Problemas de segurança 36 | 37 | `eval` também é considerado um problema de segurança, por que executa **qualquer** código dado. 38 | Ele **nunca** deve ser utilizado com strings de origens duvidosas ou desconhecidas. 39 | 40 | ### Conclusão 41 | 42 | `eval` nunca deve ser utilizado. Qualquer código que faça uso de `eval` seve ser questionado 43 | em sua utilidade, performance e segurança. Se algo necessita de `eval` para funcionar, então **não** deve ser utilizado. 44 | Um *design melhor* deve ser utilizado, um que não faça uso de `eval`. 45 | 46 | -------------------------------------------------------------------------------- /doc/ptbr/function/general.md: -------------------------------------------------------------------------------- 1 | ## Declaração de funções e expressões 2 | 3 | Funções em JavaScript são objetos de primeira classe. Isto significa que elas 4 | podem ser tratadas como qualquer outro tipo. Um uso muito comum desta característica é 5 | o de passar uma *função anônima* como uma callback para outra, talvez uma função assíncrona. 6 | 7 | ### A declaração `function` 8 | 9 | function foo() {} 10 | 11 | A função acima sofrerá [hoisting](#function.scopes) antes que a execução do programa se inicie; assim, 12 | ela estará disponível em *todo* o escopo em que foi *definida*, até mesmo se for chamada antes de ter 13 | sido definida no código. 14 | 15 | foo(); // Funciona pois foo foi elevada para o topo do escopo 16 | function foo() {} 17 | 18 | ### A expressão `function` 19 | 20 | var foo = function() {}; 21 | 22 | Este exemplo atribui uma função sem nome e *anônima* à variável `foo`. 23 | 24 | foo; // 'undefined' 25 | foo(); // dispara TypeError 26 | var foo = function() {}; 27 | 28 | Devido ao fato de que `var` é uma declaração que eleva a definição da variável `foo` ao topo do escopo, esta sofrerá hoist e `foo` estará declarado logo que o script for executado. 29 | 30 | Como atribuições só ocorrem em tempo de execução, o valor default de `foo` 31 | será [undefined](#core.undefined) antes que o código seja executado. 32 | 33 | ### Expressão de uma função nomeada 34 | 35 | Outro caso especial é a atribuição de funções nomeadas. 36 | 37 | var foo = function bar() { 38 | bar(); // Funciona 39 | } 40 | bar(); // ReferenceError 41 | 42 | Aqui, `bar` não está disponível fora do escopo, uma vez que a função se encontra atribuída 43 | em `foo`; no entanto, dentro de `bar`, ela esta disponível. Isto ocorre devido ao fato de 44 | como o [name resolution](#function.scopes) funciona em JavaScript, o nome da função está *sempre* 45 | disponível no escopo local da própria função. 46 | 47 | -------------------------------------------------------------------------------- /doc/ptbr/index.json: -------------------------------------------------------------------------------- 1 | { 2 | "title": "JavaScript Garden", 3 | "langTitle": "JavaScript Garden em Português", 4 | "description": "Um guia pelas vantagens e desvantagens do JavaScript.", 5 | "sections": [ 6 | { 7 | "title": "Introdução", 8 | "dir": "intro", 9 | "articles": ["index"] 10 | }, 11 | { 12 | "title": "Objetos", 13 | "dir": "object", 14 | "articles": [ 15 | "general", 16 | "prototype", 17 | "hasownproperty", 18 | "forinloop" 19 | ] 20 | }, 21 | { 22 | "title": "Funções", 23 | "dir": "function", 24 | "articles": [ 25 | "general", 26 | "this", 27 | "closures", 28 | "arguments", 29 | "constructors", 30 | "scopes" 31 | ] 32 | }, 33 | { 34 | "title": "Arrays", 35 | "dir": "array", 36 | "articles": [ 37 | "general", 38 | "constructor" 39 | ] 40 | }, 41 | { 42 | "title": "Tipos", 43 | "dir": "types", 44 | "articles": [ 45 | "equality", 46 | "typeof", 47 | "instanceof", 48 | "casting" 49 | ] 50 | }, 51 | { 52 | "title": "Core", 53 | "dir": "core", 54 | "articles": [ 55 | "eval", 56 | "undefined", 57 | "semicolon", 58 | "delete" 59 | ] 60 | }, 61 | { 62 | "title": "Outros assuntos", 63 | "dir": "other", 64 | "articles": [ 65 | "timeouts" 66 | ] 67 | } 68 | ] 69 | } 70 | -------------------------------------------------------------------------------- /doc/ptbr/object/forinloop.md: -------------------------------------------------------------------------------- 1 | ## O laço `for in` 2 | 3 | Assim como o operador `in`, o laço `for in` percorre a cadeia prototype quando interage sobre as propriedades de um objeto. 4 | 5 | > **Nota:** O laço `for in` **não** interage sobre propriedades que 6 | > que tenham o atributo `enumerable` configurado como `false`; por exemplo, a propriedade `length` de um array. 7 | 8 | // Poluindo o Object.prototype 9 | Object.prototype.bar = 1; 10 | 11 | var foo = {moo: 2}; 12 | for(var i in foo) { 13 | console.log(i); // retorna ambos bar e moo 14 | } 15 | 16 | Uma vez que não é possível alterar o comportamento do laço `for in` por si só, faz-se necessário filtrar as propriedades do objeto durante o ciclo de repetição do laço; isso é feito usando o método [`hasOwnProperty`](#object.hasownproperty) do `Object.prototype`. 17 | 18 | > **Nota:** Uma vez que o `for in` percorre toda a cadeia prototype, 19 | > cada camada a mais na herança do objeto deixa a execução do laço mais lenta. 20 | 21 | ### Utilizando `hasOwnProperty` como filtro 22 | 23 | // o mesmo foo utilizado anteriormente 24 | for(var i in foo) { 25 | if (foo.hasOwnProperty(i)) { 26 | console.log(i); 27 | } 28 | } 29 | 30 | Esta é única forma correta de usar. Devido ao uso de `hasOwnProperty`, o exemplo **só** irá retornar `moo`. Quando `hasOwnProperty` é deixado de lado, o código fica propenso a erros nos casos em que o prototype - por exemplo `Object.prototype`- tenha sido estendido. 31 | 32 | Um framework largamente utilizado que estende o `Object.prototype` é [Prototype][1]. 33 | Quando este framework é utilizado, laços `for in` que não utilizam 34 | `hasOwnProperty` ficam desprotegidos contra erros. 35 | 36 | ### Conclusão 37 | 38 | Recomenda-se utilizar `hasOwnProperty` **sempre**. Nunca faça pressuposições sobre o ambiente em que o código está sendo executado, ou se os prototypes nativos foram estendidos ou não. 39 | 40 | [1]: http://www.prototypejs.org/ 41 | 42 | -------------------------------------------------------------------------------- /doc/ptbr/types/instanceof.md: -------------------------------------------------------------------------------- 1 | ## O operador `instanceof` 2 | 3 | O operador `instanceof` compara os construtores de seus dois operandos. 4 | Ele é útil somente quando estamos comparando objetos personalizados. Quando utilizado em tipos nativos, 5 | ele é tão inútil quanto [o operador typeof](#types.typeof). 6 | 7 | ### Comparando objetos personalizados 8 | 9 | function Foo() {} 10 | function Bar() {} 11 | Bar.prototype = new Foo(); 12 | 13 | new Bar() instanceof Bar; // true 14 | new Bar() instanceof Foo; // true 15 | 16 | // Isto somente define Bar.prototype ao objeto de função Foo, 17 | // mas não à instância atual de Foo 18 | Bar.prototype = Foo; 19 | new Bar() instanceof Foo; // false 20 | 21 | ### Utilizando `instanceof` com tipos nativos 22 | 23 | new String('foo') instanceof String; // true 24 | new String('foo') instanceof Object; // true 25 | 26 | 'foo' instanceof String; // false 27 | 'foo' instanceof Object; // false 28 | 29 | Uma coisa importante para perceber aqui é que `instanceof` não funciona em objetos 30 | originados de diferentes contextos de JavaScript (isto é, de diferentes documentos em um 31 | navegador web), uma vez que seus construtores não irão representar exatamente o mesmo objeto. 32 | 33 | ### Conclusão 34 | 35 | O operador `instanceof` deve **somente** ser utilizado quando estive lidando 36 | com objetos customizados originados de um mesmo contexto JavaScript. Bem como o operador 37 | [`typeof`](#types.typeof), qualquer outro uso de `instanceof` deve ser **evitado**. 38 | 39 | -------------------------------------------------------------------------------- /doc/ru/array/constructor.md: -------------------------------------------------------------------------------- 1 | ## Конструктор `Array` 2 | 3 | Так как в конструкторе `Array` есть некоторая двусмысленность, касающаяся его параметров, настоятельно рекомендуется при создании массивов всегда использовать синтаксис литеральной нотации — `[]`. 4 | 5 | [1, 2, 3]; // Результат: [1, 2, 3] 6 | new Array(1, 2, 3); // Результат: [1, 2, 3] 7 | 8 | [3]; // Результат: [3] 9 | new Array(3); // Результат: [] 10 | new Array('3') // Результат: ['3'] 11 | 12 | В случае, когда в конструктор `Array` передаётся один аргумент и этот аргумент имеет тип `Number`, конструктор возвращает новый, *заполненный случайными значениями*, массив, имеющий длину равную значению переданного аргумента. Стоит заметить, что в этом случае будет установлено только свойство `length` нового массива, индексы массива фактически не будут проинициализированы. 13 | 14 | var arr = new Array(3); 15 | arr[1]; // не определён, undefined 16 | 1 in arr; // false, индекс не был установлен 17 | 18 | Поведение, которое позволяет изначально установить только размер массива, может пригодиться лишь в нескольких случаях, таких как повторение строк, за счёт чего избегается использование цикла `for`. 19 | 20 | new Array(count + 1).join(stringToRepeat); 21 | 22 | ### Заключение 23 | 24 | Использование конструктора `Array` нужно избегать, насколько это возможно. Литералы определённо предпочтительнее — это краткая запись и она имеет более понятный синтаксис, так что при этом даже улучшается читабельность кода. 25 | 26 | -------------------------------------------------------------------------------- /doc/ru/core/eval.md: -------------------------------------------------------------------------------- 1 | ## Почему нельзя использовать `eval` 2 | 3 | Функция `eval` выполняет строку кода JavaScript в локальной области видимости. 4 | 5 | var foo = 1; 6 | function test() { 7 | var foo = 2; 8 | eval('foo = 3'); 9 | return foo; 10 | } 11 | test(); // 3 12 | foo; // 1 13 | 14 | Но `eval` исполняется в локальной области видимости только тогда, когда он вызывается **напрямую** *и при этом* имя вызываемой функции именно `eval`. 15 | 16 | var foo = 1; 17 | function test() { 18 | var foo = 2; 19 | var bar = eval; 20 | bar('foo = 3'); 21 | return foo; 22 | } 23 | test(); // 2 24 | foo; // 3 25 | 26 | **Любой ценой** избегайте использования функции `eval`. 99.9% случаев её "использования" могут достигаться **без её участия**. 27 | 28 | ### `eval` под прикрытием 29 | 30 | Обе [функции работы с интервалами времени](#other.timeouts) `setTimeout` и `setInterval` могут принимать строку в качестве первого аргумента. Эта строка **всегда** будет выполняться в глобальной области видимости, поскольку `eval` в этом случае вызывается *не напрямую*. 31 | 32 | ### Проблемы с безопасностью 33 | 34 | Кроме всего прочего, функция `eval` — это проблема в безопасности, поскольку исполняется **любой** переданный в неё код; **никогда** не следует использовать её со строками из неизвестных или недоверенных источников. 35 | 36 | ### Заключение 37 | 38 | Никогда не стоит использовать `eval`: любое применение такого кода поднимает вопросы о качестве его работы, производительности и безопасности. Если вдруг для работы вам необходима `eval`, эта часть должна тут же ставиться под сомнение и **не** должна использоваться в первую очередь — необходимо найти *лучший способ*, которому не требуются вызовы `eval`. 39 | 40 | -------------------------------------------------------------------------------- /doc/ru/index.json: -------------------------------------------------------------------------------- 1 | { 2 | "title": "JavaScript Гарден", 3 | "langTitle": "JavaScript Гарден по-русски", 4 | "description": "Руководство по хитростям и трюкам JavaScript.", 5 | "sections": [ 6 | { 7 | "title": "Вступление", 8 | "dir": "intro", 9 | "articles": [ 10 | "authors", 11 | "contributors", 12 | "translators", 13 | "license" 14 | ] 15 | }, 16 | { 17 | "title": "Объекты", 18 | "dir": "object", 19 | "articles": [ 20 | "general", 21 | "prototype", 22 | "hasownproperty", 23 | "forinloop" 24 | ] 25 | }, 26 | { 27 | "title": "Функции", 28 | "dir": "function", 29 | "articles": [ 30 | "general", 31 | "this", 32 | "closures", 33 | "arguments", 34 | "constructors", 35 | "scopes" 36 | ] 37 | }, 38 | { 39 | "title": "Массивы", 40 | "dir": "array", 41 | "articles": [ 42 | "general", 43 | "constructor" 44 | ] 45 | }, 46 | { 47 | "title": "Типы", 48 | "dir": "types", 49 | "articles": [ 50 | "equality", 51 | "typeof", 52 | "instanceof", 53 | "casting" 54 | ] 55 | }, 56 | { 57 | "title": "Нативности", 58 | "dir": "core", 59 | "articles": [ 60 | "eval", 61 | "undefined", 62 | "semicolon" 63 | ] 64 | }, 65 | { 66 | "title": "Другое", 67 | "dir": "other", 68 | "articles": [ 69 | "timeouts" 70 | ] 71 | }, 72 | { 73 | "title": "Пояснения", 74 | "dir": "appendix", 75 | "articles": [ 76 | "fromtranslators" 77 | ] 78 | } 79 | 80 | ] 81 | } 82 | 83 | -------------------------------------------------------------------------------- /doc/ru/intro/authors.md: -------------------------------------------------------------------------------- 1 | ## Авторы 2 | 3 | Это руководство является результатом работы двух заядлых пользователей Stack Overflow: [Иво Ветцель /Ivo Wetzel/][1] (автора текста) и [Чжан И Цзян /Zhang Yi Jiang/][2] (дизайнера). 4 | 5 | [1]: http://stackoverflow.com/users/170224/ivo-wetzel 6 | [2]: http://stackoverflow.com/users/313758/yi-jiang 7 | 8 | -------------------------------------------------------------------------------- /doc/ru/intro/contributors.md: -------------------------------------------------------------------------------- 1 | ## Участники 2 | 3 | - [Участники](https://github.com/BonsaiDen/JavaScript-Garden/graphs/contributors) 4 | 5 | -------------------------------------------------------------------------------- /doc/ru/intro/index.md: -------------------------------------------------------------------------------- 1 | ## Вступление 2 | 3 | **JavaScript Гарден** — это постоянно обновляющаяся и растущая документация по самым заковыристым темам языка JavaScript. В ней вы найдёте советы о том, как избежать распространённых ошибок и предсказать появление тех или иных багов. В документации подробно освещены проблемы оптимизации и нерекомендуемые практики с которыми, продираясь к глубинам языка, могут столкнуться даже просвещённые JavaScript-программисты. 4 | 5 | JavaScript Гарден **не** имеет цели научить вас языку JavaScript. Вам понадобится реальный опыт работы с языком чтобы понимать темы, рассматриваемые в этом руководстве. Если вам требуется изучить основы языка, пожалуйста внимательно ознакомьтесь с замечательным [руководством][1] на сайте Mozilla Developer Network. 6 | 7 | [1]: https://developer.mozilla.org/en/JavaScript/Guide 8 | 9 | -------------------------------------------------------------------------------- /doc/ru/intro/license.md: -------------------------------------------------------------------------------- 1 | ## Лицензия 2 | 3 | JavaScript Гарден распространяется под [лицензией MIT][1] и располагается на [GitHub][2]. Если вы найдёте ошибку или опечатку, пожалуйста [сообщите нам о ней][3] или запросите права на загрузку в репозиторий. Кроме того, вы можете найти нас в [комнате JavaScript][4] среди чатов Stack Overflow. 4 | 5 | [1]: https://github.com/BonsaiDen/JavaScript-Garden/blob/next/LICENSE 6 | [2]: https://github.com/BonsaiDen/JavaScript-Garden 7 | [3]: https://github.com/BonsaiDen/JavaScript-Garden/issues 8 | [4]: http://chat.stackoverflow.com/rooms/17/javascript 9 | 10 | -------------------------------------------------------------------------------- /doc/ru/intro/translators.md: -------------------------------------------------------------------------------- 1 | ## Переводчики 2 | 3 | - ['shaman.sir'][1] 4 | - [Антон Шевчук][2] 5 | - [Максим Лозовой][3] 6 | - [Елена Пашкова][4] 7 | 8 | [1]: http://shamansir.madfire.net/ 9 | [2]: http://anton.shevchuk.name/ 10 | [3]: http://nixsolutions.com/ 11 | [4]: http://nixsolutions.com/ 12 | 13 | -------------------------------------------------------------------------------- /doc/ru/object/forinloop.md: -------------------------------------------------------------------------------- 1 | ## Цикл `for in` 2 | 3 | Как и оператор `in`, цикл `for in` проходит по всей цепочке прототипов, обходя свойства объекта. 4 | 5 | > **Примечание:** Цикл `for in` **не** обходит те свойства объекта, у которых атрибут `enumerable` установлен в `false`; как пример - свойство `length` у массивов 6 | 7 | // Испортим Object.prototype 8 | Object.prototype.bar = 1; 9 | 10 | var foo = {moo: 2}; 11 | for(var i in foo) { 12 | console.log(i); // печатает и bar и moo 13 | } 14 | 15 | Так как изменить поведение цикла `for in` как такового не представляется возможным, то для фильтрации нежелательных свойств объекта внутри этого цикла используют метод [`hasOwnProperty`](#object.hasownproperty) из `Object.prototype`. 16 | 17 | > **Примечание:** Цикл `for in` всегда обходит всю цепочку прототипов полностью: таким образом, чем больше прототипов (слоёв наследования) в цепочке, тем медленнее работает цикл. 18 | 19 | ### Использование `hasOwnProperty` в качестве фильтра 20 | 21 | // возьмём foo из примера выше 22 | for(var i in foo) { 23 | if (foo.hasOwnProperty(i)) { 24 | console.log(i); 25 | } 26 | } 27 | 28 | Это единственная версия правильного использования цикла. Благодаря использованию `hasOwnProperty` будет выведено **только** свойство `moo`. Если же убрать `hasOwnProperty`, код становится нестабилен и могут возникнуть ошибки, особенно если кто-то изменил встроенные прототипы, такие как `Object.prototype`. 29 | 30 | Один из самых популярных фреймворков [Prototype][1] как раз этим и славится, и если вы его подключаете, то не забудьте использовать `hasOwnProperty` внутри цикла `for in`, иначе у вас гарантированно возникнут проблемы. 31 | 32 | ### Рекомендации 33 | 34 | Рекомендация одна — **всегда** используйте `hasOwnProperty`. Пишите код, который будет в наименьшей мере зависеть от окружения, в котором он будет запущен — не стоит гадать, расширял кто-то прототипы или нет и используется ли в ней та или иная библиотека. 35 | 36 | [1]: http://www.prototypejs.org/ 37 | 38 | -------------------------------------------------------------------------------- /doc/ru/types/instanceof.md: -------------------------------------------------------------------------------- 1 | ## Оператор `instanceof` 2 | 3 | Оператор `instanceof` сравнивает конструкторы двух операндов. Это полезно только когда сравниваются пользовательские объекты. Использование на встроенных типах почти так же бесполезно, как и [оператор typeof](#types.typeof). 4 | 5 | ### Сравнение пользовательских объектов 6 | 7 | function Foo() {} 8 | function Bar() {} 9 | Bar.prototype = new Foo(); 10 | 11 | new Bar() instanceof Bar; // true 12 | new Bar() instanceof Foo; // true 13 | 14 | // Всего лишь присваиваем Bar.prototype объект функции Foo, 15 | // но не экземпляра Foo 16 | Bar.prototype = Foo; 17 | new Bar() instanceof Foo; // false 18 | 19 | ### Использование `instanceof` со встроенными типами 20 | 21 | new String('foo') instanceof String; // true 22 | new String('foo') instanceof Object; // true 23 | 24 | 'foo' instanceof String; // false 25 | 'foo' instanceof Object; // false 26 | 27 | Здесь надо отметить одну важную вещь: `instanceof` не работает на объектах, которые происходят из разных контекстов JavaScript (например, из различных документов в web-браузере), так как их конструкторы и правда не будут конструкторами *тех самых* объектов. 28 | 29 | ### Заключение 30 | 31 | Оператор `instanceof` должен использоваться **только** при обращении к пользовательским объектам, происходящим из одного контекста JavaScript. Так же, как и в случае оператора `typeof`, любого другого использования необходимо **избегать**. 32 | 33 | -------------------------------------------------------------------------------- /doc/tr/array/constructor.md: -------------------------------------------------------------------------------- 1 | ## `Array` Oluşturucusu 2 | 3 | `Array` oluşturucusunun parametrelerini nasıl değerlendirdiği belirsiz olduğu 4 | için, yeni diziler oluşturulurken her zaman dizi sabitlerinin (`[]` 5 | notasyonu) kullanılması tavsiye olunur. 6 | 7 | [1, 2, 3]; // Sonuç: [1, 2, 3] 8 | new Array(1, 2, 3); // Sonuç: [1, 2, 3] 9 | 10 | [3]; // Sonuç: [3] 11 | new Array(3); // Sonuç: [] 12 | new Array('3') // Sonuç: ['3'] 13 | 14 | `Array` oluşturucusuna tek bir argüman verildiğinde, ve bu argümanın türü 15 | `Number` ise, oluşacak *boş* dizinin `length` özelliği argümanın 16 | değerine eşit olacaktır. Bu şekilde oluşturulan bir dizinin **sadece** 17 | `length` özelliği belirlenmiş olup dizi indisleri tanımsız olacaktır. 18 | 19 | var arr = new Array(3); 20 | arr[1]; // undefined 21 | 1 in arr; // false, indisler atanmadı 22 | 23 | Dizinin uzunluğunu bu şekilde önceden belirlemek sadece bir iki durumda 24 | kullanışlıdır. Bunlardan birisi bir döngüye gerek olmadan bir karakter 25 | katarını tekrarlamaktır. 26 | 27 | new Array(count + 1).join(stringToRepeat); 28 | 29 | ### Sonuç 30 | 31 | `Array` oluşturucusunun kullanılmasından mümkün olduğu kadar kaçınılmalıdır. 32 | Bunun yerine her zaman dizi sabitleri tercih edilmelidir. Hem daha kısadırlar 33 | hem de daha anlaşılır bir sentaksa sahiptirler; bu nedenle programın 34 | okunabilirliğini de artırırlar. 35 | 36 | -------------------------------------------------------------------------------- /doc/tr/core/eval.md: -------------------------------------------------------------------------------- 1 | ## Neden `eval` Kullanılmamalı 2 | 3 | `eval` fonksiyonu bir JavaScript kodunu lokal kapsamda yürütür. 4 | 5 | var foo = 1; 6 | function test() { 7 | var foo = 2; 8 | eval('foo = 3'); 9 | return foo; 10 | } 11 | test(); // 3 12 | foo; // 1 13 | 14 | Fakat `eval` sadece **direkt olarak** çağrıldığında *ve* çağrılan fonksiyonun 15 | adı `eval` ise lokal kapsamda çalışır. 16 | 17 | var foo = 1; 18 | function test() { 19 | var foo = 2; 20 | var bar = eval; 21 | bar('foo = 3'); 22 | return foo; 23 | } 24 | test(); // 2 25 | foo; // 3 26 | 27 | `eval` fonksiyonu **asla** kullanılmamalıdır. Kullanıldığı durumların %99.9'unda 28 | `eval` **kullanılmadan** da istenen sonuç elde edilebilir. 29 | 30 | ### Gizli `eval` 31 | 32 | [Zamanlama fonksiyonları](#other.timeouts) `setTimeout` ve `setInterval`'ın her 33 | ikisinin de ilk argümanları bir karakter katarıdır. Bu durumda `eval` dolaylı 34 | olarak çağrıldığı için bu argüman **her zaman** genel kapsamda yürütülecektir. 35 | 36 | ### Güvenlik sorunları 37 | 38 | `eval` kendisine verilen **her** kodu işlettiği için aynı zamanda bir güvenlik 39 | sorunudur ve **asla** kaynağı bilinmeyen yada güvenilir olmayan karakter 40 | katarları ile kullanılmamalıdır. 41 | 42 | ### Sonuç 43 | 44 | `eval` asla kullanılmamalıdır, kullanan programlar ise doğruluk, performans ve 45 | güvenlik açılarından sorgulanmalıdır. `eval` kullanımı gerekli görülmüşse, 46 | programın tasarımı sorgulanmalı ve **kullanılmamalı**, bunun yerine `eval` 47 | gerektirmeyen *daha iyi bir tasarım* kullanılmalıdır. 48 | 49 | -------------------------------------------------------------------------------- /doc/tr/function/general.md: -------------------------------------------------------------------------------- 1 | ## Fonksiyon Tanımlaması ve Fonksiyon İfadesi 2 | 3 | Fonksiyonlar JavaScript'te birinci sınıf nesnelerdir, yani sıradan bir değer 4 | gibi kullanılabilirler. Bu özellik sıklıkla bir *isimsiz fonksiyonu* başka bir 5 | fonksiyona - ki bu muhtemelen asenkron bir fonksiyondur - `callback` olarak 6 | geçirmekte kullanılır. 7 | 8 | ### `function` tanımlaması 9 | 10 | function foo() {} 11 | 12 | Yukarıdaki fonksiyon tanımlaması program çalışmadan önce 13 | [yukarı taşınır](#function.scopes) ve böylece *tanımlandığı* kapsam içinde 14 | *her yerde* (hatta tanımlanmadan önce bile) kullanılabilir. 15 | 16 | foo(); // foo bu satır çalışmadan önce oluşturuldu 17 | function foo() {} 18 | 19 | ### `function` ifadesi 20 | 21 | var foo = function() {}; 22 | 23 | Bu örnekte *isimsiz fonksiyon* `foo` değişkenine atanır. 24 | 25 | foo; // 'undefined' 26 | foo(); // Bu satır bir TypeError hatasına neden olur 27 | var foo = function() {}; 28 | 29 | Yukarıdaki `var` anahtar kelimesi bir bildirim olduğu için `foo` değişkeni 30 | program çalışmadan önce yukarı alınır, program çalıştığında `foo` tanımlanmştır. 31 | 32 | Fakat değer atamaları sadece program çalışırken gerçekleşeceği için, ilgili 33 | satır çalıştığında, `foo` değişkeninin değeri varsayılan olarak 34 | [undefined](#core.undefined) olacaktır. 35 | 36 | ### İsimli fonksiyon ifadesi 37 | 38 | Bir başka özel durum isimli fonksiyon ifadesidir. 39 | 40 | var foo = function bar() { 41 | bar(); // Çalışır 42 | } 43 | bar(); // ReferenceError hatası verir 44 | 45 | Burada `bar` fonksiyonuna dış kapsamdan ulaşılamaz, çünkü sadece `foo` 46 | değişkenine atanmıştır; fakat iç kapsamda `bar` fonksiyonuna erişilebilir. 47 | Bunun nedeni JavaScript'te [isim çözümlemenin](#function.scopes) çalışma 48 | şeklidir, fonksiyonun adına fonksiyonun içinden *her zaman* erişilebilir. 49 | 50 | -------------------------------------------------------------------------------- /doc/tr/index.json: -------------------------------------------------------------------------------- 1 | { 2 | "title": "JavaScript Garden", 3 | "langTitle": "JavaScript Garden Türkçe", 4 | "description": "JavaScript'in Acayiplikleri ve Kusurları için bir Rehber.", 5 | "sections": [ 6 | { 7 | "title": "Giriş", 8 | "dir": "intro", 9 | "articles": ["index"] 10 | }, 11 | { 12 | "title": "Nesneler", 13 | "dir": "object", 14 | "articles": [ 15 | "general", 16 | "prototype", 17 | "hasownproperty", 18 | "forinloop" 19 | ] 20 | }, 21 | { 22 | "title": "Fonksiyonlar", 23 | "dir": "function", 24 | "articles": [ 25 | "general", 26 | "this", 27 | "closures", 28 | "arguments", 29 | "constructors", 30 | "scopes" 31 | ] 32 | }, 33 | { 34 | "title": "Diziler", 35 | "dir": "array", 36 | "articles": [ 37 | "general", 38 | "constructor" 39 | ] 40 | }, 41 | { 42 | "title": "Nesne Tipleri", 43 | "dir": "types", 44 | "articles": [ 45 | "equality", 46 | "typeof", 47 | "instanceof", 48 | "casting" 49 | ] 50 | }, 51 | { 52 | "title": "Temel", 53 | "dir": "core", 54 | "articles": [ 55 | "eval", 56 | "undefined", 57 | "semicolon", 58 | "delete" 59 | ] 60 | }, 61 | { 62 | "title": "Diğer", 63 | "dir": "other", 64 | "articles": [ 65 | "timeouts" 66 | ] 67 | } 68 | ] 69 | } 70 | -------------------------------------------------------------------------------- /doc/tr/intro/index.md: -------------------------------------------------------------------------------- 1 | ## Giriş 2 | 3 | **JavaScript Garden** JavaScript programlama dilinin acayiplikleri üzerine 4 | derlenmiş bir döküman koleksiyonudur. Henüz ustalaşmamış JavaScript 5 | programcılarının sıkça yaptığı yanlışlar, dile has incelikler ve performans 6 | sorunlarına karşı tavsiyeler içerir. 7 | 8 | JavaScript Garden'ın amacı size JavaScript öğretmek **değildir**. Bu rehberde 9 | anlatılan konuları anlamak için JavaScript dilini önceden biliyor olmanız 10 | gerekir. Eğer JavaScript dilinin temellerini öğrenmek istiyorsanız, lütfen 11 | Mozilla Programcı Ağı'nda bulunan mükemmel [rehbere][1] başvurun. 12 | 13 | ## Yazarlar 14 | 15 | Bu rehber, sevimli birer [Stack Overflow][2] kullanıcısı olan [Ivo Wetzel][3] (Yazım) 16 | ve [Zhang Yi Jiang][4] (Tasarım) tarafından hazırlanmıştır. 17 | 18 | ## Katkıda Bulunanlar 19 | 20 | - [Katkıda Bulunanlar](https://github.com/BonsaiDen/JavaScript-Garden/graphs/contributors) 21 | 22 | ## Sunum 23 | 24 | JavaScript Garden GitHub üzerinden, ve ayrıca [Cramer Development][7] 25 | tarafından desteklenen [JavaScriptGarden.info][8] adresinden sunulmaktadır. 26 | 27 | ## Lisans 28 | 29 | JavaScript Garden [MIT lisansı][9] altında yayınlanmıştır ve [GitHub][10] 30 | üzerinde bulunmaktadır. Eğer rehberde yanlışlıklar veya yazım hatalarına 31 | rastlarsanız lütfen [sorunu bize bildirin][11] veya bir `pull request` gönderin. 32 | Bizi ayrıca Stack Overflow'da [JavaScript sohbet odasında][12] da 33 | bulabilirsiniz. 34 | 35 | [1]: https://developer.mozilla.org/en/JavaScript/Guide 36 | [2]: http://stackoverflow.com/ 37 | [3]: http://stackoverflow.com/users/170224/ivo-wetzel 38 | [4]: http://stackoverflow.com/users/313758/yi-jiang 39 | [5]: https://github.com/caio 40 | [6]: https://github.com/blixt 41 | [7]: http://cramerdev.com/ 42 | [8]: http://javascriptgarden.info/ 43 | [9]: https://github.com/BonsaiDen/JavaScript-Garden/blob/next/LICENSE 44 | [10]: https://github.com/BonsaiDen/JavaScript-Garden 45 | [11]: https://github.com/BonsaiDen/JavaScript-Garden/issues 46 | [12]: http://chat.stackoverflow.com/rooms/17/javascript 47 | 48 | -------------------------------------------------------------------------------- /doc/tr/object/forinloop.md: -------------------------------------------------------------------------------- 1 | ## `for in` Döngüsü 2 | 3 | Tıpkı `in` operatörü gibi `for in` döngüsü de bir nesnenin özellikleri üzerinde 4 | iterasyon yaparken prototip zincirini dolaşır. 5 | 6 | > **Not:** `for in` döngüsü iterasyon yaparken `enumerable` niteliği `false` 7 | > olan özelliklere uğramaz; mesela, bir dizinin `length` özelliğini atlar. 8 | 9 | // Object.prototype'a bar özelliğini ekle 10 | Object.prototype.bar = 1; 11 | 12 | var foo = {moo: 2}; 13 | for(var i in foo) { 14 | console.log(i); // hem bar hem de moo yazar 15 | } 16 | 17 | `for in` döngüsünün davranışını değiştirmek mümkün olmadığı için, istenmeyen 18 | özelliklerin döngünün içinde filtrelenmesi gerekir, bu da `Object.prototype` 19 | nesnesinin [`hasOwnProperty`](#object.hasownproperty) metodu ile yapılır. 20 | 21 | > **Not:** `for in` döngüsü tüm prototip zincirini dolaştığı için bir nesneye 22 | > eklenen her yeni kalıtım katmanı döngüyü biraz daha yavaşlatacaktır. 23 | 24 | ### `hasOwnProperty` kullanarak filtrelemek 25 | 26 | // yukarıdaki örnekteki foo nesnesi 27 | for(var i in foo) { 28 | if (foo.hasOwnProperty(i)) { 29 | console.log(i); 30 | } 31 | } 32 | 33 | Doğru kullanım bu yeni versiyonda gösterildiği gibidir. `hasOwnProperty` kontrol 34 | edildiği için **sadece** `moo` yazacaktır. `hasOwnProperty` kullanılmaz ise ve 35 | `Object.prototype` 'ın baz özellikleri değiştirilmişse, program bazı hatalara 36 | yatkın olabilir. 37 | 38 | Bunu yapan ve yaygın olarak kullanılan bir JavaScript sistemi [Prototype][1] 39 | 'dır. Bu sistemde `hasOwnProperty` kullanmayan `for in` döngüleri kesinlikle 40 | hatalı sonuç verecektir. 41 | 42 | ### Sonuç 43 | 44 | `hasOwnProperty` **her zaman** kontrol edilmelidir. Programın içinde çalıştığı 45 | ortam için, nesnelerin baz özelliklerinin değiştirilip değiştirilmediğine dair 46 | hiçbir kabul yapılmamalıdır. 47 | 48 | [1]: http://www.prototypejs.org/ 49 | 50 | -------------------------------------------------------------------------------- /doc/tr/types/instanceof.md: -------------------------------------------------------------------------------- 1 | ## `instanceof` Operatörü 2 | 3 | `instanceof` operatörü verilen iki terimin nesne oluşturucularını karşılaştırır. 4 | Kullanışlı olduğu tek durum özel nesnelerin karşılaştırılmasıdır. Temel nesneler 5 | üzerinde kullanıldığında neredeyse [typeof operatörü](#types.typeof) kadar 6 | yararsızdır. 7 | 8 | ### Özel nesneleri karşılaştırmak 9 | 10 | function Foo() {} 11 | function Bar() {} 12 | Bar.prototype = new Foo(); 13 | 14 | new Bar() instanceof Bar; // true 15 | new Bar() instanceof Foo; // true 16 | 17 | // Bu satır sadece Bar.prototype'a Foo fonksiyon nesnesinin atar 18 | // Bir Foo sınıfı nesnesine değil 19 | Bar.prototype = Foo; 20 | new Bar() instanceof Foo; // false 21 | 22 | ### Temel nesnelerle `instanceof` kullanımı 23 | 24 | new String('foo') instanceof String; // true 25 | new String('foo') instanceof Object; // true 26 | 27 | 'foo' instanceof String; // false 28 | 'foo' instanceof Object; // false 29 | 30 | Dikkat edilmesi gereken ilginç bir nokta, `instanceof` operatörünün farklı 31 | JavaScript kaynaklarından gelen nesneler üzerinde çalışmamasıdır (mesela bir 32 | internet tarayıcısının farklı dökümanları), çünkü bu durumda nesne 33 | oluşturucuları aynı olmayacaktır. 34 | 35 | ### Sonuç 36 | 37 | `instanceof` operatörü **sadece** aynı JavaScript kaynağından gelen özel 38 | nesneler ile kullanılmalıdır. Tıpkı [`typeof`](#types.typeof) operatöründe 39 | olduğu gibi, bunun dışındaki tüm kullanımlarından **kaçınılmalıdır**. 40 | 41 | -------------------------------------------------------------------------------- /doc/zh/array/constructor.md: -------------------------------------------------------------------------------- 1 | ##`Array` 构造函数 2 | 3 | 由于 `Array` 的构造函数在如何处理参数时有点模棱两可,因此总是推荐使用数组的字面语法 - `[]` - 来创建数组。 4 | 5 | [1, 2, 3]; // 结果: [1, 2, 3] 6 | new Array(1, 2, 3); // 结果: [1, 2, 3] 7 | 8 | [3]; // 结果: [3] 9 | new Array(3); // 结果: [] 10 | new Array('3') // 结果: ['3'] 11 | 12 | // 译者注:因此下面的代码将会使人很迷惑 13 | new Array(3, 4, 5); // 结果: [3, 4, 5] 14 | new Array(3) // 结果: [],此数组长度为 3 15 | 16 | > **译者注:**这里的模棱两可指的是数组的[两种构造函数语法][1] 17 | 18 | 由于只有一个参数传递到构造函数中(译者注:指的是 `new Array(3);` 这种调用方式),并且这个参数是数字,构造函数会返回一个 `length` 属性被设置为此参数的空数组。 19 | 需要特别注意的是,此时只有 `length` 属性被设置,真正的数组并没有生成。 20 | 21 | > **译者注:**在 Firebug 中,你会看到 `[undefined, undefined, undefined]`,这其实是不对的。在上一节有详细的分析。 22 | 23 | var arr = new Array(3); 24 | arr[1]; // undefined 25 | 1 in arr; // false, 数组还没有生成 26 | 27 | 这种优先于设置数组长度属性的做法只在少数几种情况下有用,比如需要循环字符串,可以避免 `for` 循环的麻烦。 28 | 29 | new Array(count + 1).join(stringToRepeat); 30 | 31 | > **译者注:** `new Array(3).join('#')` 将会返回 `##` 32 | 33 | ###结论 34 | 35 | 应该尽量避免使用数组构造函数创建新数组。推荐使用数组的字面语法。它们更加短小和简洁,因此增加了代码的可读性。 36 | 37 | [1]: https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array 38 | 39 | -------------------------------------------------------------------------------- /doc/zh/array/general.md: -------------------------------------------------------------------------------- 1 | ##数组遍历与属性 2 | 3 | 虽然在 JavaScript 中数组是对象,但是没有好的理由去使用 [`for in` 循环](#object.forinloop) 遍历数组。 4 | 相反,有一些好的理由**不去**使用 `for in` 遍历数组。 5 | 6 | > **注意:** JavaScript 中数组**不是** *关联数组*。 7 | > JavaScript 中只有[对象](#object.general) 来管理键值的对应关系。但是关联数组是**保持**顺序的,而对象**不是**。 8 | 9 | 由于 `for in` 循环会枚举原型链上的所有属性,唯一过滤这些属性的方式是使用 [`hasOwnProperty`](#object.hasownproperty) 函数, 10 | 因此会比普通的 `for` 循环慢上好多倍。 11 | 12 | ###遍历 13 | 14 | 为了达到遍历数组的最佳性能,推荐使用经典的 `for` 循环。 15 | 16 | var list = [1, 2, 3, 4, 5, ...... 100000000]; 17 | for(var i = 0, l = list.length; i < l; i++) { 18 | console.log(list[i]); 19 | } 20 | 21 | 上面代码有一个处理,就是通过 `l = list.length` 来缓存数组的长度。 22 | 23 | 虽然 `length` 是数组的一个属性,但是在每次循环中访问它还是有性能开销。 24 | **可能**最新的 JavaScript 引擎在这点上做了优化,但是我们没法保证自己的代码是否运行在这些最近的引擎之上。 25 | 26 | 实际上,不使用缓存数组长度的方式比缓存版本要慢很多。 27 | 28 | ###`length` 属性 29 | 30 | `length` 属性的 *getter* 方式会简单的返回数组的长度,而 *setter* 方式会**截断**数组。 31 | 32 | var foo = [1, 2, 3, 4, 5, 6]; 33 | foo.length = 3; 34 | foo; // [1, 2, 3] 35 | 36 | foo.length = 6; 37 | foo; // [1, 2, 3] 38 | 39 | **译者注:** 40 | 在 Firebug 中查看此时 `foo` 的值是: `[1, 2, 3, undefined, undefined, undefined]` 41 | 但是这个结果并不准确,如果你在 Chrome 的控制台查看 `foo` 的结果,你会发现是这样的: `[1, 2, 3]` 42 | 因为在 JavaScript 中 `undefined` 是一个变量,注意是变量不是关键字,因此上面两个结果的意义是完全不相同的。 43 | 44 | // 译者注:为了验证,我们来执行下面代码,看序号 5 是否存在于 foo 中。 45 | 5 in foo; // 不管在 Firebug 或者 Chrome 都返回 false 46 | foo[5] = undefined; 47 | 5 in foo; // 不管在 Firebug 或者 Chrome 都返回 true 48 | 49 | 为 `length` 设置一个更小的值会截断数组,但是增大 `length` 属性值不会对数组产生影响。 50 | 51 | ###结论 52 | 53 | 为了更好的性能,推荐使用普通的 `for` 循环并缓存数组的 `length` 属性。 54 | 使用 `for in` 遍历数组被认为是不好的代码习惯并倾向于产生错误和导致性能问题。 55 | 56 | -------------------------------------------------------------------------------- /doc/zh/core/eval.md: -------------------------------------------------------------------------------- 1 | ##为什么不要使用 `eval` 2 | 3 | `eval` 函数会在当前作用域中执行一段 JavaScript 代码字符串。 4 | 5 | var foo = 1; 6 | function test() { 7 | var foo = 2; 8 | eval('foo = 3'); 9 | return foo; 10 | } 11 | test(); // 3 12 | foo; // 1 13 | 14 | 但是 `eval` 只在被**直接**调用并且调用函数就是 `eval` 本身时,才在当前作用域中执行。 15 | 16 | var foo = 1; 17 | function test() { 18 | var foo = 2; 19 | var bar = eval; 20 | bar('foo = 3'); 21 | return foo; 22 | } 23 | test(); // 2 24 | foo; // 3 25 | 26 | **[译者注][30]:**上面的代码等价于在全局作用域中调用 `eval`,和下面两种写法效果一样: 27 | 28 | // 写法一:直接调用全局作用域下的 foo 变量 29 | var foo = 1; 30 | function test() { 31 | var foo = 2; 32 | window.foo = 3; 33 | return foo; 34 | } 35 | test(); // 2 36 | foo; // 3 37 | 38 | // 写法二:使用 call 函数修改 eval 执行的上下文为全局作用域 39 | var foo = 1; 40 | function test() { 41 | var foo = 2; 42 | eval.call(window, 'foo = 3'); 43 | return foo; 44 | } 45 | test(); // 2 46 | foo; // 3 47 | 48 | 在**任何情况下**我们都应该避免使用 `eval` 函数。99.9% 使用 `eval` 的场景都有**不使用** `eval` 的解决方案。 49 | 50 | ###伪装的 `eval` 51 | 52 | [定时函数](#other.timeouts) `setTimeout` 和 `setInterval` 都可以接受字符串作为它们的第一个参数。 53 | 这个字符串**总是**在全局作用域中执行,因此 `eval` 在这种情况下没有被直接调用。 54 | 55 | 56 | ###安全问题 57 | 58 | `eval` 也存在安全问题,因为它会执行**任意**传给它的代码, 59 | 在代码字符串未知或者是来自一个不信任的源时,绝对不要使用 `eval` 函数。 60 | 61 | ###结论 62 | 63 | 绝对不要使用 `eval`,任何使用它的代码都会在它的工作方式,性能和安全性方面受到质疑。 64 | 如果一些情况必须使用到 `eval` 才能正常工作,首先它的设计会受到质疑,这**不应该**是首选的解决方案, 65 | 一个更好的不使用 `eval` 的解决方案应该得到充分考虑并优先采用。 66 | 67 | [30]: http://cnblogs.com/sanshi/ 68 | -------------------------------------------------------------------------------- /doc/zh/core/undefined.md: -------------------------------------------------------------------------------- 1 | ##`undefined` 和 `null` 2 | 3 | JavaScript 有两个表示‘空’的值,其中比较有用的是 `undefined`。 4 | 5 | ###`undefined` 的值 6 | 7 | `undefined` 是一个值为 `undefined` 的类型。 8 | 9 | 这个语言也定义了一个全局变量,它的值是 `undefined`,这个变量也被称为 `undefined`。 10 | 但是这个变量**不是**一个常量,也不是一个关键字。这意味着它的*值*可以轻易被覆盖。 11 | 12 | > **ES5 提示:** 在 ECMAScript 5 的严格模式下,`undefined` **不再是** *可写*的了。 13 | > 但是它的名称仍然可以被隐藏,比如定义一个函数名为 `undefined`。 14 | 15 | 下面的情况会返回 `undefined` 值: 16 | 17 | - 访问未修改的全局变量 `undefined`。 18 | - 由于没有定义 `return` 表达式的函数隐式返回。 19 | - `return` 表达式没有显式的返回任何内容。 20 | - 访问不存在的属性。 21 | - 函数参数没有被显式的传递值。 22 | - 任何被设置为 `undefined` 值的变量。 23 | 24 | ###处理 `undefined` 值的改变 25 | 26 | 由于全局变量 `undefined` 只是保存了 `undefined` 类型实际*值*的副本, 27 | 因此对它赋新值**不会**改变类型 `undefined` 的值。 28 | 29 | 然而,为了方便其它变量和 `undefined` 做比较,我们需要事先获取类型 `undefined` 的值。 30 | 31 | 为了避免可能对 `undefined` 值的改变,一个常用的技巧是使用一个传递到[匿名包装器](#function.scopes)的额外参数。 32 | 在调用时,这个参数不会获取任何值。 33 | 34 | var undefined = 123; 35 | (function(something, foo, undefined) { 36 | // 局部作用域里的 undefined 变量重新获得了 `undefined` 值 37 | 38 | })('Hello World', 42); 39 | 40 | 另外一种达到相同目的方法是在函数内使用变量声明。 41 | 42 | var undefined = 123; 43 | (function(something, foo) { 44 | var undefined; 45 | ... 46 | 47 | })('Hello World', 42); 48 | 49 | 这里唯一的区别是,在压缩后并且函数内没有其它需要使用 `var` 声明变量的情况下,这个版本的代码会多出 4 个字节的代码。 50 | 51 | > **[译者注][30]:**这里有点绕口,其实很简单。如果此函数内没有其它需要声明的变量,那么 `var` 总共 4 个字符(包含一个空白字符) 52 | 就是专门为 `undefined` 变量准备的,相比上个例子多出了 4 个字节。 53 | 54 | ###`null` 的用处 55 | 56 | JavaScript 中的 `undefined` 的使用场景类似于其它语言中的 *null*,实际上 JavaScript 中的 `null` 是另外一种数据类型。 57 | 58 | 它在 JavaScript 内部有一些使用场景(比如声明原型链的终结 `Foo.prototype = null`),但是大多数情况下都可以使用 `undefined` 来代替。 59 | 60 | [30]: http://cnblogs.com/sanshi/ 61 | -------------------------------------------------------------------------------- /doc/zh/function/closures.md: -------------------------------------------------------------------------------- 1 | ##闭包和引用 2 | 3 | 闭包是 JavaScript 一个非常重要的特性,这意味着当前作用域**总是**能够访问外部作用域中的变量。 4 | 因为 [函数](#function.scopes) 是 JavaScript 中唯一拥有自身作用域的结构,因此闭包的创建依赖于函数。 5 | 6 | > 译者注:ES2015 中增加了块级作用域。 7 | 8 | ###模拟私有变量 9 | 10 | function Counter(start) { 11 | var count = start; 12 | return { 13 | increment: function() { 14 | count++; 15 | }, 16 | 17 | get: function() { 18 | return count; 19 | } 20 | } 21 | } 22 | 23 | var foo = Counter(4); 24 | foo.increment(); 25 | foo.get(); // 5 26 | 27 | 这里,`Counter` 函数返回两个闭包,函数 `increment` 和函数 `get`。 这两个函数都维持着 28 | 对外部作用域 `Counter` 的引用,因此总可以访问此作用域内定义的变量 `count`。 29 | 30 | ###为什么不可以在外部访问私有变量 31 | 32 | 因为 JavaScript 中不可以对作用域进行引用或赋值,因此没有办法在外部访问 `count` 变量。 33 | 唯一的途径就是通过那两个闭包。 34 | 35 | var foo = new Counter(4); 36 | foo.hack = function() { 37 | count = 1337; 38 | }; 39 | 40 | 上面的代码**不会**改变定义在 `Counter` 作用域中的 `count` 变量的值,因为 `foo.hack` 没有 41 | 定义在那个**作用域**内。它将会创建或者覆盖*全局*变量 `count`。 42 | 43 | ###循环中的闭包 44 | 45 | 一个常见的错误出现在循环中使用闭包,假设我们需要在每次循环中调用循环序号 46 | 47 | for(var i = 0; i < 10; i++) { 48 | setTimeout(function() { 49 | console.log(i); 50 | }, 1000); 51 | } 52 | 53 | 上面的代码不会输出数字 `0` 到 `9`,而是会输出数字 `10` 十次。 54 | 55 | 当 `console.log` 被调用的时候,*匿名*函数保持对外部变量 `i` 的引用,此时 `for`循环已经结束, `i` 的值被修改成了 `10`。 56 | 57 | 为了得到想要的结果,需要在每次循环中创建变量 `i` 的**拷贝**。 58 | 59 | ###避免引用错误 60 | 61 | 为了正确的获得循环序号,最好使用 [匿名包装器](#function.scopes)(**[译者注][30]:**其实就是我们通常说的自执行匿名函数)。 62 | 63 | for(var i = 0; i < 10; i++) { 64 | (function(e) { 65 | setTimeout(function() { 66 | console.log(e); 67 | }, 1000); 68 | })(i); 69 | } 70 | 71 | 外部的匿名函数会立即执行,并把 `i` 作为它的参数,此时函数内 `e` 变量就拥有了 `i` 的一个拷贝。 72 | 73 | 当传递给 `setTimeout` 的匿名函数执行时,它就拥有了对 `e` 的引用,而这个值是**不会**被循环改变的。 74 | 75 | 有另一个方法完成同样的工作,那就是从匿名包装器中返回一个函数。这和上面的代码效果一样。 76 | 77 | for(var i = 0; i < 10; i++) { 78 | setTimeout((function(e) { 79 | return function() { 80 | console.log(e); 81 | }; 82 | })(i), 1000); 83 | } 84 | 85 | 86 | [30]: http://cnblogs.com/sanshi/ 87 | -------------------------------------------------------------------------------- /doc/zh/function/general.md: -------------------------------------------------------------------------------- 1 | ##函数声明与表达式 2 | 3 | 函数是 JavaScript 中的一等对象,这意味着可以把函数像其它值一样传递。 4 | 一个常见的用法是把*匿名函数*作为回调函数传递到异步函数中。 5 | 6 | ###函数声明 7 | 8 | function foo() {} 9 | 10 | 上面的方法会在执行前被 [解析(hoisted)](#function.scopes),因此它存在于当前上下文的*任意*一个地方, 11 | 即使在函数定义体的上面被调用也是对的。 12 | 13 | foo(); // 正常运行,因为 foo 在代码运行前已经被创建 14 | function foo() {} 15 | 16 | ### 函数赋值表达式 17 | 18 | var foo = function() {}; 19 | 20 | 这个例子把一个*匿名*的函数赋值给变量 `foo`。 21 | 22 | foo; // 'undefined' 23 | foo(); // 出错:TypeError 24 | var foo = function() {}; 25 | 26 | 由于 `var` 定义了一个声明语句,对变量 `foo` 的解析是在代码运行之前,因此 `foo` 变量在代码运行时已经被定义过了。 27 | 28 | 但是由于赋值语句只在运行时执行,因此在相应代码执行之前, `foo` 的值缺省为 [undefined](#core.undefined)。 29 | 30 | ###命名函数的赋值表达式 31 | 32 | 另外一个特殊的情况是将命名函数赋值给一个变量。 33 | 34 | var foo = function bar() { 35 | bar(); // 正常运行 36 | } 37 | bar(); // 出错:ReferenceError 38 | 39 | `bar` 函数声明外是不可见的,这是因为我们已经把函数赋值给了 `foo`; 40 | 然而在 `bar` 内部依然可见。这是由于 JavaScript 的 [命名处理](#function.scopes) 所致, 41 | 函数名在函数内*总是*可见的。 42 | > **注意: **在 IE8 及 IE8 以下版本浏览器 bar 在外部也是可见的,是因为浏览器对命名函数赋值表达式进行了错误的解析, 43 | > 解析成两个函数 `foo` 和 `bar` 44 | 45 | -------------------------------------------------------------------------------- /doc/zh/index.json: -------------------------------------------------------------------------------- 1 | { 2 | "title": "JavaScript 秘密花园", 3 | "langTitle": "JavaScript Garden 中文翻译", 4 | "description": "JavaScript 语言最古怪用法的文档集合", 5 | "sections": [ 6 | { 7 | "title": "简介", 8 | "dir": "intro", 9 | "articles": [ 10 | "authors", 11 | "contributors", 12 | "license" 13 | ] 14 | }, 15 | { 16 | "title": "对象", 17 | "dir": "object", 18 | "articles": [ 19 | "general", 20 | "prototype", 21 | "hasownproperty", 22 | "forinloop" 23 | ] 24 | }, 25 | { 26 | "title": "函数", 27 | "dir": "function", 28 | "articles": [ 29 | "general", 30 | "this", 31 | "closures", 32 | "arguments", 33 | "constructors", 34 | "scopes" 35 | ] 36 | }, 37 | { 38 | "title": "数组", 39 | "dir": "array", 40 | "articles": [ 41 | "general", 42 | "constructor" 43 | ] 44 | }, 45 | { 46 | "title": "类型", 47 | "dir": "types", 48 | "articles": [ 49 | "equality", 50 | "typeof", 51 | "instanceof", 52 | "casting" 53 | ] 54 | }, 55 | { 56 | "title": "核心", 57 | "dir": "core", 58 | "articles": [ 59 | "eval", 60 | "undefined", 61 | "semicolon" 62 | ] 63 | }, 64 | { 65 | "title": "其它", 66 | "dir": "other", 67 | "articles": [ 68 | "timeouts" 69 | ] 70 | } 71 | ] 72 | } 73 | -------------------------------------------------------------------------------- /doc/zh/intro/authors.md: -------------------------------------------------------------------------------- 1 | ##关于作者 2 | 3 | 这篇文章的作者是两位 [Stack Overflow][1] 用户, [伊沃·韦特泽尔 Ivo Wetzel][2](写作) 和 [张易江 Zhang Yi Jiang][3](设计)。 4 | 5 | [1]: http://stackoverflow.com/ 6 | [2]: http://stackoverflow.com/users/170224/ivo-wetzel 7 | [3]: http://stackoverflow.com/users/313758/yi-jiang 8 | -------------------------------------------------------------------------------- /doc/zh/intro/contributors.md: -------------------------------------------------------------------------------- 1 | ##贡献者 2 | 3 | - [贡献者](https://github.com/BonsaiDen/JavaScript-Garden/graphs/contributors) 4 | 5 | ##中文翻译 6 | - [三生石上][29] 7 | 8 | 此中文翻译由[三生石上][29]独立完成,[博客园][30]首发,转载请注明出处。 9 | 10 | [1]: https://github.com/caio 11 | [2]: https://github.com/blixt 12 | [29]: http://sanshi.me/ 13 | [30]: http://cnblogs.com/sanshi/ 14 | -------------------------------------------------------------------------------- /doc/zh/intro/index.md: -------------------------------------------------------------------------------- 1 | ##简介 2 | 3 | **JavaScript 秘密花园**是一个不断更新,主要关心 JavaScript 一些古怪用法的文档。 4 | 对于如何避免常见的错误,难以发现的问题,以及性能问题和不好的实践给出建议, 5 | 初学者可以籍此深入了解 JavaScript 的语言特性。 6 | 7 | JavaScript 秘密花园**不是**用来教你 JavaScript。为了更好的理解这篇文章的内容, 8 | 你需要事先学习 JavaScript 的基础知识。在 Mozilla 开发者网络中有一系列非常棒的 JavaScript 学习[向导][1]。 9 | 10 | > **译者注:** 文中提到的 ES5 是 ECMAScript 5 的简写,是 ECMAScript 标准语言的下一版本,正在开发中。 11 | JavaScript 是此标准语言的一个方言。 12 | 13 | [1]: https://developer.mozilla.org/en/JavaScript/Guide 14 | 15 | -------------------------------------------------------------------------------- /doc/zh/intro/license.md: -------------------------------------------------------------------------------- 1 | ##许可 2 | 3 | JavaScript 秘密花园在 [MIT license][1] 许可协议下发布,并存放在 [GitHub][2] 开源社区。 4 | 如果你发现错误,请[新建一个任务单][3]或者发一个抓取请求(Pull Request)。 5 | 你也可以在 Stack Overflow 的 [JavaScript 聊天室][4]找到我们。 6 | 7 | [1]: https://github.com/BonsaiDen/JavaScript-Garden/blob/next/LICENSE 8 | [2]: https://github.com/BonsaiDen/JavaScript-Garden 9 | [3]: https://github.com/BonsaiDen/JavaScript-Garden/issues 10 | [4]: http://chat.stackoverflow.com/rooms/17/javascript 11 | 12 | -------------------------------------------------------------------------------- /doc/zh/object/forinloop.md: -------------------------------------------------------------------------------- 1 | ##`for in` 循环 2 | 3 | 和 `in` 操作符一样,`for in` 循环同样在查找对象属性时遍历原型链上的所有属性。 4 | 5 | > **注意:** `for in` 循环**不会**遍历那些 `enumerable` 设置为 `false` 的属性;比如数组的 `length` 属性。 6 | 7 | // 修改 Object.prototype 8 | Object.prototype.bar = 1; 9 | 10 | var foo = {moo: 2}; 11 | for(var i in foo) { 12 | console.log(i); // 输出两个属性:bar 和 moo 13 | } 14 | 15 | 由于不可能改变 `for in` 自身的行为,因此有必要过滤出那些不希望出现在循环体中的属性, 16 | 这可以通过 `Object.prototype` 原型上的 [`hasOwnProperty`](#object.hasownproperty) 函数来完成。 17 | 18 | > **注意:** 由于 `for in` 总是要遍历整个原型链,因此如果一个对象的继承层次太深的话会影响性能。 19 | 20 | ###使用 `hasOwnProperty` 过滤 21 | 22 | // foo 变量是上例中的 23 | for(var i in foo) { 24 | if (foo.hasOwnProperty(i)) { 25 | console.log(i); 26 | } 27 | } 28 | 29 | 这个版本的代码是唯一正确的写法。由于我们使用了 `hasOwnProperty`,所以这次**只**输出 `moo`。 30 | 如果不使用 `hasOwnProperty`,则这段代码在原生对象原型(比如 `Object.prototype`)被扩展时可能会出错。 31 | 32 | 一个广泛使用的类库 [Prototype][1] 就扩展了原生的 JavaScript 对象。 33 | 因此,当这个类库被包含在页面中时,不使用 `hasOwnProperty` 过滤的 `for in` 循环难免会出问题。 34 | 35 | ###总结 36 | 37 | 推荐**总是**使用 `hasOwnProperty`。不要对代码运行的环境做任何假设,不要假设原生对象是否已经被扩展了。 38 | 39 | [1]: http://www.prototypejs.org/ 40 | 41 | -------------------------------------------------------------------------------- /doc/zh/object/hasownproperty.md: -------------------------------------------------------------------------------- 1 | ##`hasOwnProperty` 函数 2 | 3 | 为了判断一个对象是否包含*自定义*属性而*不是*[原型链](#object.prototype)上的属性, 4 | 我们需要使用继承自 `Object.prototype` 的 `hasOwnProperty` 方法。 5 | 6 | > **注意:** 通过判断一个属性是否 `undefined` 是**不够**的。 7 | > 因为一个属性可能确实存在,只不过它的值被设置为 `undefined`。 8 | 9 | `hasOwnProperty` 是 JavaScript 中唯一一个处理属性但是**不**查找原型链的函数。 10 | 11 | // 修改 Object.prototype 12 | Object.prototype.bar = 1; 13 | var foo = {goo: undefined}; 14 | 15 | foo.bar; // 1 16 | 'bar' in foo; // true 17 | 18 | foo.hasOwnProperty('bar'); // false 19 | foo.hasOwnProperty('goo'); // true 20 | 21 | 只有 `hasOwnProperty` 可以给出正确和期望的结果。可以查看 [`for in` 循环](#object.forinloop) 22 | 章节来获取关于在迭代遍历对象属性的时候,何时使用 `hasOwnProperty` 的更多信息。 23 | 24 | ###`hasOwnProperty` 作为属性 25 | 26 | JavaScript **不会**保护 `hasOwnProperty` 被非法占用,因此如果一个对象碰巧存在这个属性, 27 | 就需要使用*外部*的 `hasOwnProperty` 函数来获取正确的结果。 28 | 29 | var foo = { 30 | hasOwnProperty: function() { 31 | return false; 32 | }, 33 | bar: 'Here be dragons' 34 | }; 35 | 36 | foo.hasOwnProperty('bar'); // 总是返回 false 37 | 38 | // 使用其它对象的 hasOwnProperty,并将其上下文设置为 foo 39 | ({}).hasOwnProperty.call(foo, 'bar'); // true 40 | 41 | ###结论 42 | 43 | 当检查对象上某个属性是否存在时,`hasOwnProperty` 是**唯一**可用的方法。 44 | 同时在使用 [`for in` loop](#object.forinloop) 遍历对象时,推荐**总是**使用 `hasOwnProperty` 方法, 45 | 这将会避免[原型](#object.prototype)对象扩展带来的干扰。 46 | 47 | -------------------------------------------------------------------------------- /doc/zh/types/casting.md: -------------------------------------------------------------------------------- 1 | ##类型转换 2 | 3 | JavaScript 是*弱类型*语言,所以会在**任何**可能的情况下应用*强制类型转换*。 4 | 5 | // 下面的比较结果是:true 6 | new Number(10) == 10; // Number.toString() 返回的字符串被再次转换为数字 7 | 8 | 10 == '10'; // 字符串被转换为数字 9 | 10 == '+10 '; // 同上 10 | 10 == '010'; // 同上 11 | isNaN(null) == false; // null 被转换为数字 0 12 | // 0 当然不是一个 NaN(译者注:否定之否定) 13 | 14 | // 下面的比较结果是:false 15 | 10 == 010; 16 | 10 == '-10'; 17 | 18 | > **ES5 提示:** 以 `0` 开头的数字字面值会被作为八进制数字解析。 19 | > 而在 ECMAScript 5 严格模式下,这个特性被**移除**了。 20 | 21 | 为了避免上面复杂的强制类型转换,**强烈**推荐使用[严格的等于操作符](#types.equality)。 22 | 虽然这可以避免大部分的问题,但 JavaScript 的弱类型系统仍然会导致一些其它问题。 23 | 24 | ###内置类型的构造函数 25 | 26 | 内置类型(比如 `Number` 和 `String`)的构造函数在被调用时,使用或者不使用 `new` 的结果完全不同。 27 | 28 | new Number(10) === 10; // False, 对象与数字的比较 29 | Number(10) === 10; // True, 数字与数字的比较 30 | new Number(10) + 0 === 10; // True, 由于隐式的类型转换 31 | 32 | 使用内置类型 `Number` 作为构造函数将会创建一个新的 `Number` 对象, 33 | 而在不使用 `new` 关键字的 `Number` 函数更像是一个数字转换器。 34 | 35 | 另外,在比较中引入对象的字面值将会导致更加复杂的强制类型转换。 36 | 37 | 最好的选择是把要比较的值**显式**的转换为三种可能的类型之一。 38 | 39 | ###转换为字符串 40 | 41 | '' + 10 === '10'; // true 42 | 43 | 将一个值加上空字符串可以轻松转换为字符串类型。 44 | 45 | ###转换为数字 46 | 47 | +'10' === 10; // true 48 | 49 | 使用**一元**的加号操作符,可以把字符串转换为数字。 50 | 51 | **[译者注][30]:**字符串转换为数字的常用方法: 52 | 53 | +'010' === 10 54 | Number('010') === 10 55 | parseInt('010', 10) === 10 // 用来转换为整数 56 | 57 | +'010.2' === 10.2 58 | Number('010.2') === 10.2 59 | parseInt('010.2', 10) === 10 60 | 61 | 62 | ###转换为布尔型 63 | 64 | 通过使用 **否** 操作符两次,可以把一个值转换为布尔型。 65 | 66 | !!'foo'; // true 67 | !!''; // false 68 | !!'0'; // true 69 | !!'1'; // true 70 | !!'-1' // true 71 | !!{}; // true 72 | !!true; // true 73 | 74 | [30]: http://cnblogs.com/sanshi/ 75 | -------------------------------------------------------------------------------- /doc/zh/types/equality.md: -------------------------------------------------------------------------------- 1 | ##相等与比较 2 | 3 | JavaScript 有两种方式判断两个值是否相等。 4 | 5 | ###等于操作符 6 | 7 | 等于操作符由两个等号组成:`==` 8 | 9 | JavaScript 是*弱类型*语言,这就意味着,等于操作符会为了比较两个值而进行**强制类型转换**。 10 | 11 | "" == "0" // false 12 | 0 == "" // true 13 | 0 == "0" // true 14 | false == "false" // false 15 | false == "0" // true 16 | false == undefined // false 17 | false == null // false 18 | null == undefined // true 19 | " \t\r\n" == 0 // true 20 | 21 | 上面的表格展示了强制类型转换,这也是使用 `==` 被广泛认为是不好编程习惯的主要原因, 22 | 由于它的复杂转换规则,会导致难以跟踪的问题。 23 | 24 | 此外,强制类型转换也会带来性能消耗,比如一个字符串为了和一个数字进行比较,必须事先被强制转换为数字。 25 | 26 | ###严格等于操作符 27 | 28 | 严格等于操作符由**三**个等号组成:`===` 29 | 30 | 不像普通的等于操作符,严格等于操作符**不会**进行强制类型转换。 31 | 32 | "" === "0" // false 33 | 0 === "" // false 34 | 0 === "0" // false 35 | false === "false" // false 36 | false === "0" // false 37 | false === undefined // false 38 | false === null // false 39 | null === undefined // false 40 | " \t\r\n" === 0 // false 41 | 42 | 上面的结果更加清晰并有利于代码的分析。如果两个操作数类型不同就肯定不相等也有助于性能的提升。 43 | 44 | ###比较对象 45 | 46 | 虽然 `==` 和 `===` 操作符都是等于操作符,但是当其中有一个操作数为对象时,行为就不同了。 47 | 48 | {} === {}; // false 49 | new String('foo') === 'foo'; // false 50 | new Number(10) === 10; // false 51 | var foo = {}; 52 | foo === foo; // true 53 | 54 | 这里等于操作符比较的**不是**值是否相等,而是是否属于同一个**身份**;也就是说,只有对象的同一个实例才被认为是相等的。 55 | 这有点像 Python 中的 `is` 和 C 中的指针比较。 56 | > **注意:**为了更直观的看到`==`和`===`的区别,可以参见[JavaScript Equality Table](http://dorey.github.io/JavaScript-Equality-Table/) 57 | 58 | ###结论 59 | 60 | 强烈推荐使用**严格等于操作符**。如果类型需要转换,应该在比较之前[显式](#types.casting)的转换, 61 | 而不是使用语言本身复杂的强制转换规则。 62 | 63 | [30]: http://cnblogs.com/sanshi/ 64 | -------------------------------------------------------------------------------- /doc/zh/types/instanceof.md: -------------------------------------------------------------------------------- 1 | ##`instanceof` 操作符 2 | 3 | `instanceof` 操作符用来比较两个操作数的构造函数。只有在比较自定义的对象时才有意义。 4 | 如果用来比较内置类型,将会和 [`typeof` 操作符](#types.typeof) 一样用处不大。 5 | 6 | ###比较自定义对象 7 | 8 | function Foo() {} 9 | function Bar() {} 10 | Bar.prototype = new Foo(); 11 | 12 | new Bar() instanceof Bar; // true 13 | new Bar() instanceof Foo; // true 14 | 15 | // 如果仅仅设置 Bar.prototype 为函数 Foo 本身,而不是 Foo 构造函数的一个实例 16 | Bar.prototype = Foo; 17 | new Bar() instanceof Foo; // false 18 | 19 | ###`instanceof` 比较内置类型 20 | 21 | new String('foo') instanceof String; // true 22 | new String('foo') instanceof Object; // true 23 | 24 | 'foo' instanceof String; // false 25 | 'foo' instanceof Object; // false 26 | 27 | 有一点需要注意,`instanceof` 用来比较属于不同 JavaScript 上下文的对象(比如,浏览器中不同的文档结构)时将会出错, 28 | 因为它们的构造函数不会是同一个对象。 29 | 30 | ### 结论 31 | 32 | `instanceof` 操作符应该**仅仅**用来比较来自同一个 JavaScript 上下文的自定义对象。 33 | 正如 [`typeof`](#types.typeof) 操作符一样,任何其它的用法都应该是避免的。 34 | 35 | [30]: http://cnblogs.com/sanshi/ 36 | -------------------------------------------------------------------------------- /doc/zhtw/array/constructor.md: -------------------------------------------------------------------------------- 1 | ## `Array` 的建構函式 2 | 3 | `Array` 的建構函式在處理參數上一直有模糊的地帶,所以建議使用 `array`的字面語法來使用 - `[]` - 來新增一個的Array 4 | 5 | [1, 2, 3]; // 結果: [1, 2, 3] 6 | new Array(1, 2, 3); // 結果: [1, 2, 3] 7 | 8 | [3]; // 結果: [3] 9 | new Array(3); // 結果: [] 10 | new Array('3') // 結果: ['3'] 11 | 12 | 在上面的範例 `new Array(3)` 當只有一個參數傳入到 `Array` 的建構函數 13 | 且那個參數是一個數字,建構函數會回傳空值 14 | 但是 `Array` 長度的屬性會變成跟那個參數一樣(以此範例來看他回傳的長度為 3) 15 | **注意** 只有他長度的屬性會被設定,整個 Array裡面的數值都不會初始化 16 | 17 | var arr = new Array(3); 18 | arr[1]; // undefined 19 | 1 in arr; // false, 數值沒有被設定進去 20 | 21 | 被設定用來當做 `Array` 的長度只有少數情況使用 22 | 先設定 `Array` 的長度可以用一下的範例來避免使用 `for loop` 的麻煩 23 | 24 | new Array(count + 1).join(stringToRepeat); 25 | 26 | ### 結語 27 | 28 | `Array` 的建構函式需要避免,建議使用字面語法。因為他們比較簡短、也更增加閱讀性 29 | -------------------------------------------------------------------------------- /doc/zhtw/array/general.md: -------------------------------------------------------------------------------- 1 | ## Array 迴圈和屬性 2 | 3 | 雖然在 Javascript 中 Array 都是 Objects,但是沒有好的理由要使用他 4 | 在 [`for in`](#object.forinloop) 的迴圈中。事實上有很多原因要避免使用 `for in` 在 Array 之中 5 | 6 | > **注意:** Javascript Arrays **不是** *關連性 Arrays* 7 | > 只有 [objects](#object.general) 來管理建值的相對應關係 8 | > Arrays 是**保持** 順序的,Objects **則沒有** 9 | 10 | 因為 `for in` 迴圈會使用[`hasOwnProperty`](#object.hasownproperty),所以它會列舉所有在原型 Array 上的屬性,這會使得 Array 比原本的 `for` 迴圈慢上二十幾倍 11 | 12 | ### 迴圈 13 | 14 | 為了要達到最好的性能所以最好使用 `for` 迴圈來讀取一個 Array 裡面的數值。 15 | 16 | var list = [1, 2, 3, 4, 5, ...... 100000000]; 17 | for(var i = 0, l = list.length; i < l; i++) { 18 | console.log(list[i]); 19 | } 20 | 21 | 在上面的例子中利用 `l = list.length` 來處理 Array 的長度問題。 22 | 23 | 雖然 `length` 屬性是屬於 Array 中其中一個屬性,但是他在每次循環還是有一定的性能消耗。 24 | 近期 Javascript **可能**使用來解決在這上面的效率問題,但是在現在的引擎上還不一定有支援。 25 | 26 | 實際上,不使用暫存 Array 長度的方式比使用暫存的版本還要慢很多。 27 | 28 | ### `length` 的屬性 29 | 30 | `length` 屬性中的 *getter* 直接回傳在 Array 之中的程度,而 *setter* 可以用來 **刪除** Array。 31 | 32 | var foo = [1, 2, 3, 4, 5, 6]; 33 | foo.length = 3; 34 | foo; // [1, 2, 3] 35 | 36 | foo.length = 6; 37 | foo.push(4); 38 | foo; // [1, 2, 3, undefined, undefined, undefined, 4] 39 | 40 | 在上面的例子可以看到,如果給的長度比較小他就會去刪除 Array 中的數值。如果比較大的話,他就會自己增加一些 `undefined` 的數值進去 41 | 42 | ### 結語 43 | 44 | 為了達到更好的效率,建議使用 `for` 迴圈還有暫存 `length` 的屬性。 45 | 而 `for in` 迴圈則是會讓程式中有更多的錯誤和性能問題。 46 | 47 | -------------------------------------------------------------------------------- /doc/zhtw/core/delete.md: -------------------------------------------------------------------------------- 1 | ## `delete` 控制符 2 | 3 | 簡單來說,那是 *不可能* 去刪除一個全域變數,函式和其他東西在 JavaScript 中有一個 `DontDelete` 的屬性 4 | 5 | ### 全域和函式 6 | 7 | 當一個變數或是一個函式在一個全域範圍被定義或是在一個 [funciton scope](#function.scopes) ,這些屬性可能是動態的物件或是全域的物件。這些特性有一系列的屬性。其中一個就是 `DontDelete`。 8 | 在這些變數和函式的宣告都會有一個屬性叫 `DontDelete`,這會使得它無法被刪除。 9 | 10 | // 全域變數 11 | var a = 1; // DontDelete 屬性被建立 12 | delete a; // false 13 | a; // 1 14 | 15 | // normal function: 16 | function f() {} // DontDelete 屬性被建立 17 | delete f; // false 18 | typeof f; // "function" 19 | 20 | // reassigning doesn't help: 21 | f = 1; 22 | delete f; // false 23 | f; // 1 24 | 25 | ### 明確的屬性 26 | 27 | 明確的屬性可以被簡單的刪除。 28 | 29 | // explicitly set property: 30 | var obj = {x: 1}; 31 | obj.y = 2; 32 | delete obj.x; // true 33 | delete obj.y; // true 34 | obj.x; // undefined 35 | obj.y; // undefined 36 | 37 | 在上面的例子中, `obj.x` 和 `obj.y` 可以被刪除是因為他們沒有 `DontDelete` 的屬性。 38 | 所以下面的例子也可以這樣用。 39 | 40 | // 可以運作,除了 IE: 41 | var GLOBAL_OBJECT = this; 42 | GLOBAL_OBJECT.a = 1; 43 | a === GLOBAL_OBJECT.a; // true - just a global var 44 | delete GLOBAL_OBJECT.a; // true 45 | GLOBAL_OBJECT.a; // undefined 46 | 47 | 這裡我們想要去刪除 `a`。 [`this`](#funciton.this) 這裡指向一個全域的物件,和我們明確了地定義 `a` 是它的屬性,所以可以刪除它。 48 | 49 | IE 有些臭蟲,所以上面的程式碼無法使用(至少 6~8) 50 | 51 | ### 函式的參數和內建 52 | 53 | 函式的普通參數,[`arguments` object](#function.arguments) 還有一些內建的屬性都有 `DontDelete` 的建立 54 | 55 | // function 參數和屬性 56 | (function (x) { 57 | 58 | delete arguments; // false 59 | typeof arguments; // "object" 60 | 61 | delete x; // false 62 | x; // 1 63 | 64 | function f(){} 65 | delete f.length; // false 66 | typeof f.length; // "number" 67 | 68 | })(1); 69 | 70 | ### 接受物件 71 | 72 | 控制符可以接受無法預測的物件。由於一些特別的情況,會允許它能夠 `delete` 73 | 74 | ### 結語 75 | 76 | `delete` 控制符通常都有難以預料的行為,所以我們只可以安全的刪除顯著的屬性在普通的物件上。 77 | 78 | 79 | -------------------------------------------------------------------------------- /doc/zhtw/core/eval.md: -------------------------------------------------------------------------------- 1 | ## 為什麼不要使用 `eval` 2 | 3 | 因為 `eval` 函數會在 Javascript 的區域性的區間執行那段程式碼。 4 | 5 | var foo = 1; 6 | function test() { 7 | var foo = 2; 8 | eval('foo = 3'); 9 | return foo; 10 | } 11 | test(); // 3 12 | foo; // 1 13 | 14 | 但是, `eval` 只接受直接的呼叫而且那個函數只能叫做 `eval`,才能在一個區段中執行。 15 | 16 | var foo = 1; 17 | function test() { 18 | var foo = 2; 19 | var bar = eval; 20 | bar('foo = 3'); 21 | return foo; 22 | } 23 | test(); // 2 24 | foo; // 3 25 | 26 | 所有的 `eval` 都應該去比免試用。有 99.9% 的使用情況都可以 **不必** 使用到而達到同等效果。 27 | 28 | ### 偽裝的 `eval` 29 | 30 | [定時函數](#other.timeouts) `setTimeout` 和 `setInterval` 都可以接受一個字串當做他們第一個參數。這些字串 **永遠** 都會在全域範圍內執行,因此在這種情況下 `eval` 沒有被直接的使用。 31 | 32 | ### 安全上的顧慮 33 | 34 | `eval` 同樣有安全上的問題,因為所有的程式碼都可以被直接執行。 35 | 而他不應去執行一串未知的字串或是來自不信任的來源。 36 | 37 | ### 結語 38 | 39 | `eval` 應該永遠不要去只用它,任何的程式在被他執行後都有性能和安全上的考慮。如果有情況需要去使用他,他都不應該列為第一順位的解決方法。 40 | 41 | 應該有更好的方法能夠去使用,但是最好都不要去使用 `eval`。 42 | 43 | -------------------------------------------------------------------------------- /doc/zhtw/core/undefined.md: -------------------------------------------------------------------------------- 1 | ## `undefined` 和 `null` 2 | 3 | JavaScript 中有兩個表示空值的方式, `null` 和 `undefined` , `undefined`是比較常用的一種。 4 | 5 | ### `undefined` 的值 6 | 7 | `undefined` 是一個值為 `undefined` 的類型。 8 | 9 | 語言中也定義了一個全域變數,它的值為 `undefined`,這個變數的被稱作 `undefined` 。 10 | 這個變數 **不是** 一個常數,也不是一個關鍵字。這表示它的值可以被輕易的覆蓋。 11 | 12 | > **ES5 提示: ** `undefined` 在 ECMAScript 5 裡 **不再是** *可寫* 的 13 | > 但是它的名稱還是可以被隱藏,比如說定義一個函數為 `undefined`。 14 | 15 | 這裡有一些例子會回傳 `undefined` 的值: 16 | 17 | - 進入尚未修改的全域變數 `undefined`。 18 | - 進入一個宣告但 **尚未** 初始化的變數。 19 | - `return` 表示式中沒有返回任何內容。 20 | - 呼叫不存在的屬性。 21 | - 函式參數沒有被傳遞數值。 22 | - 任何被被設定為 `undefined` 的變數。 23 | - 任何表達式中形式為 `void(expression)` 24 | 25 | ### 處理 `undefined` 值的改變 26 | 27 | 由於全域變數 `undefined` 只有保存 `undefined` 類型實際值的一個副本,指定了一個新的值並 **不會** 改變 `undefined`類型裡面的值。 28 | 29 | 為了避免去改變 `undefined` 的值,常用的技巧就是加上一個新的變數到 [匿名包裝器](#function.scopes)。在使用的時候,這個參數不會接受任何的值。 30 | 31 | var undefined = 123; 32 | (function(something, foo, undefined) { 33 | // undefined 在區域區間內得到了 `undefined` 的值 34 | 35 | })('Hello World', 42); 36 | 37 | 另外一個可以得到同樣的效果就是在內部宣告一個變數 38 | 39 | var undefined = 123; 40 | (function(something, foo) { 41 | var undefined; 42 | ... 43 | 44 | })('Hello World', 42); 45 | 46 | 唯一的不同就是在下者會多 4 個多 bytes 用來壓縮檔案,而且函數內也沒有其他需要使用 `var` 47 | 48 | ### 使用 `null` 49 | 50 | JavaScript 中所使用的 `undefined` 類似別的語言中的 *null* , 但實際上在 JavaScript 中的 `null` 算是另外一個類型。 51 | 52 | 它在 JavaScript 有些可以使用的地方 (例如說宣告一個原型的終結,例如 `Foo.prototype = null` )。 53 | 但是在大部分的時候可以用 `undefined`,來取代。 54 | -------------------------------------------------------------------------------- /doc/zhtw/function/general.md: -------------------------------------------------------------------------------- 1 | ## 函式的宣告和表達方式 2 | 3 | 函式在 JavaScript 是第一等物件。這表示他們可以把函式當做值一樣傳遞。 4 | 一個常見的用法是用 *匿名函式* 當做一個回傳去呼叫另一個函式,這是一種非同步函式 5 | 6 | ### 函式的宣告 7 | 8 | function foo() {} 9 | 10 | 上面的函式在被執行之前會被 [解析(hoisted)](#function.scopes),因此它可以在 **任意** 的地方都是 *有宣告的* ,就算是在比這個函式還早呼叫。 11 | 12 | 13 | foo(); // 可以執行,因為 foo 已經在運行前就被建立 14 | function foo() {} 15 | 16 | ### `function` 的表達式 17 | 18 | var foo = function() {}; 19 | 20 | 這個例子把一個 *匿名* 函式賦值給變數 `foo`。 21 | 22 | foo; // 'undefined' 23 | foo(); // 錯誤: TypeError 24 | var foo = function() {}; 25 | 26 | 由於 `var` 已經宣告變數 `foo` 在所有的程式碼執行之前。 27 | 所以 `foo`已經在程式運行前就已經被定義過了。 28 | 但是因為賦值只會在運行時去執行,所以在程式碼執行前,`foo` 的值還沒被宣告所以為 [undefined](#core.undefined)。 29 | 30 | 31 | ### 命名函式的賦值表達式 32 | 33 | 另一個特殊狀況是將一個命名函式賦值給一個變數。 34 | 35 | var foo = function bar() { 36 | bar(); // 可以運行 37 | } 38 | bar(); // 錯誤:ReferenceError 39 | 40 | `bar` 不可以在外部的區域被執行,因為它只有在 `foo` 的函式內才可以執行。 41 | 然而在 `bar` 內部還是可以看見。這是由於 JavaScript的 [命名處理](#function.scopes)所致。 42 | 函式名在函式內 *都* 可以使用。 43 | 44 | -------------------------------------------------------------------------------- /doc/zhtw/index.json: -------------------------------------------------------------------------------- 1 | { 2 | "title": "JavaScript Garden", 3 | "langTitle": "JavaScript Garden 繁體中文翻譯", 4 | "description": "JavaScript 語言中古怪用法及缺點的文件總集", 5 | "sections": [ 6 | { 7 | "title": "簡介", 8 | "dir": "intro", 9 | "articles": ["index"] 10 | }, 11 | { 12 | "title": "物件", 13 | "dir": "object", 14 | "articles": [ 15 | "general", 16 | "prototype", 17 | "hasownproperty", 18 | "forinloop" 19 | ] 20 | }, 21 | { 22 | "title": "函式", 23 | "dir": "function", 24 | "articles": [ 25 | "general", 26 | "this", 27 | "closures", 28 | "arguments", 29 | "constructors", 30 | "scopes" 31 | ] 32 | }, 33 | { 34 | "title": "陣列", 35 | "dir": "array", 36 | "articles": [ 37 | "general", 38 | "constructor" 39 | ] 40 | }, 41 | { 42 | "title": "類型", 43 | "dir": "types", 44 | "articles": [ 45 | "equality", 46 | "typeof", 47 | "instanceof", 48 | "casting" 49 | ] 50 | }, 51 | { 52 | "title": "核心", 53 | "dir": "core", 54 | "articles": [ 55 | "eval", 56 | "undefined", 57 | "semicolon", 58 | "delete" 59 | ] 60 | }, 61 | { 62 | "title": "其他", 63 | "dir": "other", 64 | "articles": [ 65 | "timeouts" 66 | ] 67 | } 68 | ] 69 | } 70 | -------------------------------------------------------------------------------- /doc/zhtw/intro/index.md: -------------------------------------------------------------------------------- 1 | ## 簡介 2 | 3 | JavaScript Garden 是一個不斷更新的文件,最主要是要去了解一些 Javascript 比較古怪的部份。 4 | 給一些意見來防止遇到一些常見的錯誤和一些難以發現的問題,以及性能問題和不好的習慣。 5 | 初學者也可以藉此去了解 Javascript 這項語言的特性。 6 | 7 | JavaScript Garden 並 **不是** 要教導你 Javascript 的語言。 8 | 如果要能夠理解這篇文章的內容,你需要事先學習 JavaScript 的基礎知識。 9 | 在 Mozilla 開發者網路中有一系列非常棒的學習[guide][1]。 10 | 11 | 12 | ## 作者 13 | 14 | 這個使用手冊是來自於 [Stack Overflow][2] 的使用者, [Ivo Wetzel][3] 15 | (寫作) 和 [Zhang Yi Jiang][4] (設計)。 16 | 17 | 目前為 [Tim Ruffles](http://truffles.me.uk) 維護此專案。 18 | 19 | ## 貢獻者 20 | 21 | - [貢獻者](https://github.com/BonsaiDen/JavaScript-Garden/graphs/contributors) 22 | 23 | ## 繁體中文翻譯 24 | 25 | - [紀力榮][29] 26 | - [張仲威][30] 27 | - [Bo-Yi Wu][31] 28 | 29 | ## 存放空間 30 | 31 | JavaScript Garden 目前存放於 GitHub,但是 [Cramer Development][7] 讓我們有另一個存放位置在 [JavaScriptGarden.info][8]。 32 | 33 | ## 許可 34 | 35 | JavaScript Garden 是在 [MIT license][9] 許可協議下發佈,並存在於 36 | [GitHub][10],如果你有發現錯誤或是打字上的錯誤 [新增一個任務][11] 或者發一個請求。 37 | 你也可以在 StackOverflow 的 [JavaScript room][12] 上面找到我們。 38 | 39 | [1]: https://developer.mozilla.org/en/JavaScript/Guide 40 | [2]: http://stackoverflow.com/ 41 | [3]: http://stackoverflow.com/users/170224/ivo-wetzel 42 | [4]: http://stackoverflow.com/users/313758/yi-jiang 43 | [5]: https://github.com/caio 44 | [6]: https://github.com/blixt 45 | [7]: http://cramerdev.com/ 46 | [8]: http://javascriptgarden.info/ 47 | [9]: https://github.com/BonsaiDen/JavaScript-Garden/blob/next/LICENSE 48 | [10]: https://github.com/BonsaiDen/JavaScript-Garden 49 | [11]: https://github.com/BonsaiDen/JavaScript-Garden/issues 50 | [12]: http://chat.stackoverflow.com/rooms/17/javascript 51 | [29]: https://github.com/chilijung 52 | [30]: https://github.com/wwwy3y3 53 | [31]: https://github.com/appleboy 54 | -------------------------------------------------------------------------------- /doc/zhtw/object/forinloop.md: -------------------------------------------------------------------------------- 1 | ## `for in` 迴圈 2 | 3 | 就像其他的 `in` 操作符一樣, `for in` 循環也進入所有在物件中的屬性 4 | 5 | > **注意: ** `for in` 迴圈 **不會** 進入那些 `enumerable` 屬性是 `false`,舉例來說,陣列中 `length` 的屬性 6 | 7 | // 修改 Object.prototype 8 | Object.prototype.bar = 1; 9 | 10 | var foo = {moo: 2}; 11 | for(var i in foo) { 12 | console.log(i); // 輸出兩個屬性:bar 和 moo 13 | } 14 | 15 | 由於不可能改變 `for in` 本身的行為,因為有必要過濾出那些不希望在迴圈出現的屬性,這可以用 `Object.prototype` 原型上的 [`hasOwnProperty`](#object.hasownproperty) 的函數來完成。 16 | 17 | > **注意: ** 由於 `for in` 總是要到所有原型鏈裡,因此如果物件的繼承層次太深的話會影響性能。 18 | 19 | 20 | ### 用 `hasOwnProperty` 來過濾 21 | 22 | // foo 變數是上面範例中的 23 | for(var i in foo) { 24 | if (foo.hasOwnProperty(i)) { 25 | console.log(i); 26 | } 27 | } 28 | 29 | 這個版本的程式碼是唯一正確的寫法。由於我們使用了 `hasOwnProperty`,這次 **只** 輸出 `moo`。 30 | 如果不使用這個程式碼在原型物件中(比如 `Object.prototype`)被擴展可能會出錯。 31 | 32 | 一個廣泛使用的舊函式庫 [Prototype][1]就擴展了原型的 JavaScript 物件。 33 | 因此,當這個函式庫包含在頁面中時,不使用 `hasOwnProperty` 過濾的 `for in` 迴圈難免會出問題。 34 | 35 | ### 總結 36 | 37 | 推薦 **總是** 使用 `hasOwnProperty`。不要對程式碼的環境做任何假設,不要假設原生的對象是否被擴張。 38 | 39 | [1]: http://www.prototypejs.org/ 40 | 41 | -------------------------------------------------------------------------------- /doc/zhtw/object/hasownproperty.md: -------------------------------------------------------------------------------- 1 | ## `hasOwnProperty` 2 | 3 | 為了判斷一個物件是否包含 *自定義* 屬性而 *不是* [原型](#object.prototype)上的屬性,我們需要使用繼承 `Object.prototype` 的 `hasOwnProperty` 方法。 4 | 5 | > **注意:** 判斷一個屬性是否 `undefined` 是 **不夠的**。 6 | > 因為一個屬性可能存在,但是它的值被設成 `undefined`。 7 | 8 | `hasOwnProperty` 是 JavaScript 中唯一一個處理屬性但是 **不** 找原型鏈的函式。 9 | 10 | // 修改 Object.prototype 11 | Object.prototype.bar = 1; 12 | var foo = {goo: undefined}; 13 | 14 | foo.bar; // 1 15 | 'bar' in foo; // true 16 | 17 | foo.hasOwnProperty('bar'); // false 18 | foo.hasOwnProperty('goo'); // true 19 | 20 | 只有 `hasOwnProperty` 給予正確的結果,這對進入物件的屬性很有效果,**沒有** 其他方法可以用來排除原型上的屬性,而不是定義在物件 *自己* 上的屬性。 21 | 22 | ### `hasOwnProperty` 作為屬性 23 | 24 | JavaScript **不會** 保護 `hasOwnProperty`被占用,因此如果碰到存在這個屬性,就需要使用 *外部* 的 `hasOwnProperty` 來獲取正確的結果。 25 | 26 | var foo = { 27 | hasOwnProperty: function() { 28 | return false; 29 | }, 30 | bar: 'Here be dragons' 31 | }; 32 | 33 | foo.hasOwnProperty('bar'); // 永遠返回 false 34 | 35 | // 使用其他對象的 hasOwnProperty,並將其上下設置為 foo 36 | ({}).hasOwnProperty.call(foo, 'bar'); // true 37 | 38 | // 也可以透過原生 Object prototype 的 hasOwnProperty 函數來達成目的 39 | Object.prototype.hasOwnProperty.call(foo, 'bar'); // true 40 | 41 | ### 結論 42 | 43 | 當檢查一個物件是否存在的時候, `hasOwnProperty` 是 **唯一** 可用的方法。 44 | 同時在使用 [`for in loop`](#object.forinloop) 45 | 建議使用 `hasOwnProperty` 避免 [原型](#object.prototype)所帶來的干擾。 46 | -------------------------------------------------------------------------------- /doc/zhtw/types/casting.md: -------------------------------------------------------------------------------- 1 | ## 類型轉換 2 | 3 | JavaScript 是一個 *弱類型* 的程式語言,所以在 **任何** 情況下都可以 *強制類型轉換*。 4 | 5 | // 這些都是真 6 | new Number(10) == 10; // Number.toString() is converted 7 | // back to a number 8 | 9 | 10 == '10'; // Strings gets converted to Number 10 | 10 == '+10 '; // More string madness 11 | 10 == '010'; // And more 12 | isNaN(null) == false; // null converts to 0 13 | // which of course is not NaN 14 | 15 | // 下面都假 16 | 10 == 010; 17 | 10 == '-10'; 18 | 19 | > **ES5 注意:** 如果數字字面值的開頭是 `0` 它會強制轉為八進位數字解析。 20 | > 而在 ES5 嚴格模式下,它已經被刪除了。 21 | 22 | 為了去避免上驗的事件發生,我們會用 [嚴格等於操作符](#types.equality) 這是強烈建議。 23 | 因為它可以避免很多常見的問題,但 JavaScript 的弱類型系同仍然會導致一些其他問題。 24 | 25 | ### 內置類型的建構函式 26 | 27 | 內置類型(比如 `Number` 和 `String`)在被調用時,使用或不使用 `new` 的結果完全不同。 28 | 29 | new Number(10) === 10; // False, Object and Number 30 | Number(10) === 10; // True, Number and Number 31 | new Number(10) + 0 === 10; // True, due to implicit conversion 32 | 33 | 使用內置類型 `Number` 作為建構函式會建造一個新的 `Number` 物件,而在不使用 `new` 關鍵字的 `Number` 函式更像是一個數字轉換器。 34 | 35 | 另外,在比較中引入物件的字面值會導致更加複雜的強制類型轉換。 36 | 37 | 最好的方式是比較值的 **顯示** 的轉換成最有可能的三種形態 38 | 39 | ### 轉換成字符串 40 | 41 | '' + 10 === '10'; // true 42 | 43 | 將一個值加上空字符串可以輕鬆轉為字符串類型。 44 | 45 | ### 轉換成一個數字 46 | 47 | +'10' === 10; // true 48 | 49 | 使用 **一元** 的加號操作符,可以把字符串轉為數字。 50 | 51 | ### 轉換成一個 Bool 52 | 通過使用 **否** 操作符兩字,可以把一個值轉換為 Bool。 53 | 54 | !!'foo'; // true 55 | !!''; // false 56 | !!'0'; // true 57 | !!'1'; // true 58 | !!'-1' // true 59 | !!{}; // true 60 | !!true; // true 61 | 62 | 63 | -------------------------------------------------------------------------------- /doc/zhtw/types/equality.md: -------------------------------------------------------------------------------- 1 | ## 相等與比較 2 | 3 | JavaScript 有兩個不同的方式來比較兩個物件是否相等。 4 | 5 | ### 等於操作符 6 | 7 | 等於操作符是由兩個等號組成: `==` 8 | 9 | JavaScript 是一個 *弱類型* 語言。這代表它會為了比較兩個值而做 **強制類型轉換**。 10 | 11 | "" == "0" // false 12 | 0 == "" // true 13 | 0 == "0" // true 14 | false == "false" // false 15 | false == "0" // true 16 | false == undefined // false 17 | false == null // false 18 | null == undefined // true 19 | " \t\r\n" == 0 // true 20 | 21 | 上面的表格可以看出來這些結果強制轉換類型,這也代表說用 `==` 是一個不好的習慣,因為它會很難追蹤問題由於它複雜的規則。 22 | 23 | 此外,也有效率上面的問題在強制轉換類型。 24 | 例如說一個字串會被轉成數字來和別的數字做比較。 25 | 26 | ### 嚴格等於操作符 27 | 28 | 不像普通的等於操作符 `===` 不會做強制類型轉換。 29 | 30 | "" === "0" // false 31 | 0 === "" // false 32 | 0 === "0" // false 33 | false === "false" // false 34 | false === "0" // false 35 | false === undefined // false 36 | false === null // false 37 | null === undefined // false 38 | " \t\r\n" === 0 // false 39 | 40 | 上面的結果比較清楚,也有利於程式碼的分析。如果這兩個操作數的類型不一樣都就不會相等,有助於它性能的提昇。 41 | 42 | ### 比較物件 43 | 44 | 雖然 `==` 和 `===` 都是等於操作符,但其中有一個操作數為物件時,它的行為就會不同。 45 | 46 | {} === {}; // false 47 | new String('foo') === 'foo'; // false 48 | new Number(10) === 10; // false 49 | var foo = {}; 50 | foo === foo; // true 51 | 52 | 在這裡等於操作符比較 **不是** 值的相等,而是否是 **相同** 的身分。 53 | 有點像 Python 的 `is` 和 C 中的指標。 54 | 55 | ### 結論 56 | 57 | 強烈建議使用 **嚴格等於** 58 | 如果要轉換類型,應該要在 [explicitly](#types.casting)的時候轉換,而不是在語言本身用複雜的轉換規則。 59 | 60 | 61 | -------------------------------------------------------------------------------- /doc/zhtw/types/instanceof.md: -------------------------------------------------------------------------------- 1 | ## `instanceof` 操作符 2 | 3 | `instanceof` 操作符用來比較兩個建構函數的操作數。只有在比較自定義的物件時才有意義。這和 [typeof operator](#types.typeof)一樣用處不大。 4 | 5 | ### 比較定意義物件 6 | 7 | function Foo() {} 8 | function Bar() {} 9 | Bar.prototype = new Foo(); 10 | 11 | new Bar() instanceof Bar; // true 12 | new Bar() instanceof Foo; // true 13 | 14 | // This just sets Bar.prototype to the function object Foo, 15 | // but not to an actual instance of Foo 16 | Bar.prototype = Foo; 17 | new Bar() instanceof Foo; // false 18 | 19 | ### `instanceof` 比較內置類型 20 | 21 | new String('foo') instanceof String; // true 22 | new String('foo') instanceof Object; // true 23 | 24 | 'foo' instanceof String; // false 25 | 'foo' instanceof Object; // false 26 | 27 | 有一點需要注意的, `instanceof` 不會在來自不同的上下文的物件運作(例如:瀏覽器中不同的文檔結構),因為它的建構函數不一樣。 28 | 29 | ### In Conclusion 30 | 31 | `instanceof` 操作符應該 **只** 用來比較同一個 JavaScript 上下文定意義的物件。 32 | 正如 [`typeof`](#types.typeof)操作符一樣,任何其他用法都要避免。 33 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "javascript-garden", 3 | "description": "A collection of documentation about the most quirky parts of the JavaScript language.", 4 | "version": "0.0.0", 5 | "scripts": { 6 | "build": "node build.js" 7 | }, 8 | "dependencies": { 9 | "fomatto": "0.5.0", 10 | "forever": "0.10.8", 11 | "jade": "0.35.0", 12 | "neko": "1.1.2", 13 | "marked": "~0.2.9", 14 | "lodash": "~2.2.1" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /site/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BonsaiDen/JavaScript-Garden/064e78964d8e5d4a7b0dca664f633fc786ba18d5/site/favicon.ico -------------------------------------------------------------------------------- /site/image/sidebar-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BonsaiDen/JavaScript-Garden/064e78964d8e5d4a7b0dca664f633fc786ba18d5/site/image/sidebar-icon.png -------------------------------------------------------------------------------- /site/javascript/html5.js: -------------------------------------------------------------------------------- 1 | // html5shiv MIT @rem remysharp.com/html5-enabling-script 2 | // iepp v1.6.2 MIT @jon_neal iecss.com/print-protector 3 | /*@cc_on(function(m,c){var z="abbr|article|aside|audio|canvas|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video";function n(d){for(var a=-1;++ai";if(g.childNodes.length!==1){var i=z.split("|"),o=i.length,s=RegExp("(^|\\s)("+z+")", 4 | "gi"),t=RegExp("<(/*)("+z+")","gi"),u=RegExp("(^|[^\\n]*?\\s)("+z+")([^\\n]*)({[\\n\\w\\W]*?})","gi"),r=c.createDocumentFragment(),k=c.documentElement;g=k.firstChild;var h=c.createElement("body"),l=c.createElement("style"),f;n(c);n(r);g.insertBefore(l, 5 | g.firstChild);l.media="print";m.attachEvent("onbeforeprint",function(){var d=-1,a=p(c.styleSheets,"all"),e=[],b;for(f=f||c.body;(b=u.exec(a))!=null;)e.push((b[1]+b[2]+b[3]).replace(s,"$1.iepp_$2")+b[4]);for(l.styleSheet.cssText=e.join("\n");++d