Repository: rwaldron/idiomatic.js Branch: master Commit: d88432591ecf Files: 24 Total size: 601.4 KB Directory structure: gitextract_w5co02kf/ ├── .gitattributes ├── .gitignore ├── cc-license.md ├── contributors.md ├── readme.md └── translations/ ├── bg_BG/ │ └── readme.md ├── de_DE/ │ └── readme.md ├── es_ES/ │ └── readme.md ├── fr_FR/ │ └── readme.md ├── gr_GR/ │ └── readme.md ├── hi_HI/ │ └── readme.md ├── id_ID/ │ └── readme.md ├── it_IT/ │ └── readme.md ├── ja_JP/ │ └── readme.md ├── ko_KR/ │ └── readme.md ├── pl_PL/ │ └── readme.md ├── pt_BR/ │ └── readme.md ├── ro_RO/ │ └── readme.md ├── ru_RU/ │ └── readme.md ├── sr_SR/ │ └── readme.md ├── vi_VN/ │ └── readme.md ├── zh_CN/ │ └── readme.md ├── zh_TW/ │ └── readme.md └── ср_СР/ └── readme.md ================================================ FILE CONTENTS ================================================ ================================================ FILE: .gitattributes ================================================ eol=lf ================================================ FILE: .gitignore ================================================ .DS_Store *.swp dist kits/makefile-kit/dist kits/jakefile-kit/dist kits/jakefile-kit/node_modules ================================================ FILE: cc-license.md ================================================ Creative Commons License
Principles of Writing Consistent, Idiomatic JavaScript by Rick Waldron and Contributors is licensed under a Creative Commons Attribution 3.0 Unported License.
Based on a work at github.com/rwldrn/idiomatic.js. This applies to all documents and translations in this repository. ================================================ FILE: contributors.md ================================================ * Rick Waldron [@rwaldron](http://twitter.com/rwaldron), [github](https://github.com/rwldrn) * Mathias Bynens [@mathias](http://twitter.com/mathias), [github](https://github.com/mathiasbynens) * Schalk Neethling [@ossreleasefeed](http://twitter.com/ossreleasefeed), [github](https://github.com/ossreleasefeed/) * Kit Cambridge [@kitcambridge](http://twitter.com/kitcambridge), [github](https://github.com/kitcambridge) * Raynos [github](https://github.com/Raynos) * Matias Arriola [@MatiasArriola](https://twitter.com/MatiasArriola), [github](https://github.com/MatiasArriola/) * John Fischer [@jfroffice](https://twitter.com/jfroffice), [github](https://github.com/jfroffice/) * Idan Gazit [@idangazit](http://twitter.com/idangazit), [github](https://github.com/idan) * Leo Balter [@leobalter](http://twitter.com/leobalter), [github](https://github.com/leobalter) * Breno Oliveira [@garu_rj](http://twitter.com/garu_rj), [github](https://github.com/garu) * Leo Beto Souza [@leobetosouza](http://twitter.com/leobetosouza), [github](https://github.com/leobetosouza) * Ryuichi Okumura [@okuryu](http://twitter.com/okuryu), [github](https://github.com/okuryu) * Pascal Precht [@PascalPrecht](http://twitter.com/PascalPrecht), [github](https://github.com/pascalprecht) * EngForDev [engfordev](http://www.opentutorials.org/course/167/1363) - Hwan Min Hong / MinTaek Kwon [@leoinsight](http://twitter.com/leoinsight) / Tw Shim [@marocchino](http://twitter.com/marocchino), [github](https://github.com/marocchino) / Nassol Kim [@nassol99](http://twitter.com/nassol99), [github](https://github.com/nassol) / Juntai Park [@rkJun](http://twitter.com/rkJun), [github](https://github.com/rkJun) / Minkyu Shim / Gangmin Won / Justin Yoo [@justinchronicle](http://twitter.com/justinchronicle) / Daeyup Lee * Marco Trulla [@marcotrulla](http://twitter.com/marcotrulla), [github](https://github.com/Ragnarokkr) * Alex Navasardyan [@alexnavasardyan](http://twitter.com/alexnavasardyan), [github](https://github.com/2k00l) * Mihai Paun [@mihaipaun](http://twitter.com/mihaipaun), [github](https://github.com/mihaipaun) * Evgeny Mandrikov [@\_godin\_](http://twitter.com/_godin_), [github](https://github.com/Godin) * Sofish Lin [@sofish](http://twitter.com/sofish), [github](https://github.com/sofish) * Дејан Димић [@dejan_dimic](http://twitter.com/dejan_dimic), [github](https://github.com/rubystream) * Miloš Gavrilović [@gavrisimo](http://twitter.com/gavrisimo), [github](https://github.com/gavrisimo) * Firede [@firede](https://twitter.com/firede) [github](https://github.com/firede) * monkadd [github](https://github.com/monkadd) * Stephan Lindauer [@stephanlindauer](http://twitter.com/stephanlindauer), [github](https://github.com/stephanlindauer) * Thomas P [@dragon5689](https://twitter.com/dragon5689) [github](https://github.com/dragon5689) * Yotam Ofek [@yotamofek](https://twitter.com/yotamofek) [github](https://github.com/yotamofek) * Aleksandr Filatov [@greybax](http://twitter.com/greybax), [github](https://github.com/greybax) * Duc Nguyen [@ducntq](https://twitter.com/ducntq), [github](https://github.com/ducntq) * James Young [@jamsyoung](http://twitter.com/jamsyoung), [github](https://github.com/jamsyoung) * Calvin Jeng [@l0ckys](http://twitter.com/l0ckys), [github](https://github.com/lockys) * Richard Gibson [@gibson042](http://twitter.com/gibson042), [github](https://github.com/gibson042) * Fesuy [github](https://github.com/fesuydev) * Stephane Moreau [github](https://github.com/stmoreau) * Akshat Joshi [@akshat_joshi](http://twitter.com/akshat_joshi), [github](https://https://github.com/akshatjoshii) ================================================ FILE: readme.md ================================================ # Principles of Writing Consistent, Idiomatic JavaScript ## This is a living document and new ideas for improving the code around us are always welcome. Contribute: fork, clone, branch, commit, push, pull request. * Rick Waldron [@rwaldron](http://twitter.com/rwaldron), [github](https://github.com/rwaldron) * Mathias Bynens [@mathias](http://twitter.com/mathias), [github](https://github.com/mathiasbynens) * Schalk Neethling [@ossreleasefeed](http://twitter.com/ossreleasefeed), [github](https://github.com/ossreleasefeed/) * Kit Cambridge [@kitcambridge](http://twitter.com/kitcambridge), [github](https://github.com/kitcambridge) * Raynos [github](https://github.com/Raynos) * Matias Arriola [@MatiasArriola](https://twitter.com/MatiasArriola), [github](https://github.com/MatiasArriola/) * John Fischer [@jfroffice](https://twitter.com/jfroffice), [github](https://github.com/jfroffice/) * Idan Gazit [@idangazit](http://twitter.com/idangazit), [github](https://github.com/idan) * Leo Balter [@leobalter](http://twitter.com/leobalter), [github](https://github.com/leobalter) * Breno Oliveira [@garu_rj](http://twitter.com/garu_rj), [github](https://github.com/garu) * Leo Beto Souza [@leobetosouza](http://twitter.com/leobetosouza), [github](https://github.com/leobetosouza) * Ryuichi Okumura [@okuryu](http://twitter.com/okuryu), [github](https://github.com/okuryu) * Pascal Precht [@PascalPrecht](http://twitter.com/PascalPrecht), [github](https://github.com/pascalprecht) * EngForDev [engfordev](https://opentutorials.org/course/245/1788) - Hwan Min Hong / MinTaek Kwon [@leoinsight](http://twitter.com/leoinsight) / Tw Shim [@marocchino](http://twitter.com/marocchino), [github](https://github.com/marocchino) / Nassol Kim [@nassol99](http://twitter.com/nassol99), [github](https://github.com/nassol) / Juntai Park [@rkJun](http://twitter.com/rkJun), [github](https://github.com/rkJun) / Minkyu Shim / Gangmin Won / Justin Yoo [@justinchronicle](http://twitter.com/justinchronicle) / Daeyup Lee * Marco Trulla [@marcotrulla](http://twitter.com/marcotrulla), [github](https://github.com/Ragnarokkr) * Alex Navasardyan [@alexnavasardyan](http://twitter.com/alexnavasardyan), [github](https://github.com/2k00l) * Mihai Paun [@mihaipaun](http://twitter.com/mihaipaun), [github](https://github.com/mihaipaun) * Evgeny Mandrikov [@\_godin\_](http://twitter.com/_godin_), [github](https://github.com/Godin) * Sofish Lin [@sofish](http://twitter.com/sofish), [github](https://github.com/sofish) * Дејан Димић [@dejan_dimic](http://twitter.com/dejan_dimic), [github](https://github.com/rubystream) * Miloš Gavrilović [@gavrisimo](http://twitter.com/gavrisimo), [github](https://github.com/gavrisimo) * Firede [@firede](https://twitter.com/firede) [github](https://github.com/firede) * monkadd [github](https://github.com/monkadd) * Stephan Lindauer [@stephanlindauer](http://twitter.com/stephanlindauer), [github](https://github.com/stephanlindauer) * Thomas P [@dragon5689](https://twitter.com/dragon5689) [github](https://github.com/dragon5689) * Yotam Ofek [@yotamofek](https://twitter.com/yotamofek) [github](https://github.com/yotamofek) * Aleksandr Filatov [@greybax](http://twitter.com/greybax), [github](https://github.com/greybax) * Duc Nguyen [@ducntq](https://twitter.com/ducntq), [github](https://github.com/ducntq) * James Young [@jamsyoung](http://twitter.com/jamsyoung), [github](https://github.com/jamsyoung) * Hao-Wei Jeng [@l0ckys](http://twitter.com/l0ckys), [github](https://github.com/lockys) * Richard Gibson [@gibson042](http://twitter.com/gibson042), [github](https://github.com/gibson042) * Fesuy [github](https://github.com/fesuydev) * Stephane Moreau [github](https://github.com/stmoreau) * Boris Nekezov [github](https://github.com/boris-nekezov) * Akshat Joshi [@akshat_joshi](http://twitter.com/akshat_joshi), [github](https://https://github.com/akshatjoshii) ## All code in any code-base should look like a single person typed it, no matter how many people contributed. ### The following list outlines the practices that I use in all code that I am the original author of; contributions to projects that I have created should follow these guidelines. ### I do not intend to impose my style preferences on other people's code or projects; if an existing common style exists, it should be respected. > ### "Arguments over style are pointless. There should be a style guide, and you should follow it" >_Rebecca_ _Murphey_   > ### "Part of being a good steward to a successful project is realizing that writing code for yourself is a Bad Idea™. If thousands of people are using your code, then write your code for maximum clarity, not your personal preference of how to get clever within the spec." >_Idan_ _Gazit_ ## Translations * [Bulgarian](https://github.com/rwldrn/idiomatic.js/tree/master/translations/bg_BG) * [German](https://github.com/rwldrn/idiomatic.js/tree/master/translations/de_DE) * [French](https://github.com/rwldrn/idiomatic.js/tree/master/translations/fr_FR) * [Spanish](https://github.com/rwldrn/idiomatic.js/tree/master/translations/es_ES) * [Portuguese - Brazil](https://github.com/rwldrn/idiomatic.js/tree/master/translations/pt_BR) * [Korean](https://github.com/rwldrn/idiomatic.js/tree/master/translations/ko_KR) * [日本語](https://github.com/rwldrn/idiomatic.js/tree/master/translations/ja_JP) * [Italian](https://github.com/rwldrn/idiomatic.js/tree/master/translations/it_IT) * [Russian](https://github.com/rwldrn/idiomatic.js/tree/master/translations/ru_RU) * [Romanian](https://github.com/rwldrn/idiomatic.js/tree/master/translations/ro_RO) * [简体中文](https://github.com/rwldrn/idiomatic.js/tree/master/translations/zh_CN) * [Serbian - cyrilic alphabet](https://github.com/rwldrn/idiomatic.js/tree/master/translations/ср_СР) * [Serbian - latin alphabet](https://github.com/rwldrn/idiomatic.js/tree/master/translations/sr_SR) * [繁體中文](https://github.com/rwaldron/idiomatic.js/tree/master/translations/zh_TW) * [Indonesian](https://github.com/rwaldron/idiomatic.js/tree/master/translations/id_ID) * [Greek](https://github.com/rwaldron/idiomatic.js/tree/master/translations/gr_GR) * [Hindi](https://github.com/rwaldron/idiomatic.js/tree/master/translations/hi_HI) ## Important, Non-Idiomatic Stuff: ### Code Quality Tools, Resources & References * [SonarQube](https://www.sonarqube.org/) * [Plato](https://github.com/es-analysis/plato) * [jsPerf](http://jsperf.com/) * [jsFiddle](http://jsfiddle.net/) * [Codepen](http://codepen.io/) * [jsbin](http://jsbin.com/) * [JavaScript Lint (JSL)](http://javascriptlint.com/) * [jshint](http://jshint.com/) * [jslint](http://jslint.org/) * [eslint](http://eslint.org/) * [jscs](https://www.npmjs.org/package/jscs) * [jscodesniffer](https://www.npmjs.org/package/jscodesniffer) * [Editorconfig](http://editorconfig.org/) * [Hound](https://houndci.com/) ## Get Smart ### [Annotated ECMAScript 5.1](http://es5.github.com/) ### [EcmaScript Language Specification, 5.1 Edition](http://ecma-international.org/ecma-262/5.1/) The following should be considered 1) incomplete, and 2) *REQUIRED READING*. I don't always agree with the style written by the authors below, but one thing is certain: They are consistent. Furthermore, these are authorities on the language. * [Baseline For Front End Developers: 2015](https://rmurphey.com/posts/a-baseline-for-front-end-developers-2015/) * [Eloquent JavaScript](http://eloquentjavascript.net/) * [JavaScript, JavaScript](http://javascriptweblog.wordpress.com/) * [Adventures in JavaScript Development](http://rmurphey.com/) * [Perfection Kills](http://perfectionkills.com/) * [Douglas Crockford's Wrrrld Wide Web](http://www.crockford.com) * [JS Assessment](https://github.com/rmurphey/js-assessment) ### Build & Deployment Process Projects should always attempt to include some generic means by which source can be linted, tested and compressed in preparation for production use. For this task, [grunt](https://github.com/gruntjs/grunt) by Ben Alman is second to none and has officially replaced the "kits/" directory of this repo. ### Test Facility Projects _must_ include some form of unit, reference, implementation or functional testing. Use case demos DO NOT QUALIFY as "tests". The following is a list of test frameworks, none of which are endorsed more than the other. * [QUnit](http://github.com/jquery/qunit) * [Jasmine](https://github.com/pivotal/jasmine) * [Vows](https://github.com/cloudhead/vows) * [Mocha](https://github.com/visionmedia/mocha) * [Hiro](http://hirojs.com/) * [JsTestDriver](https://code.google.com/p/js-test-driver/) * [Buster.js](http://busterjs.org/) * [Sinon.js](http://sinonjs.org/) * [Tape](https://github.com/substack/tape) * [Jest](https://facebook.github.io/jest/) ## Table of Contents * [Whitespace](#whitespace) * [Beautiful Syntax](#spacing) * [Type Checking (Courtesy jQuery Core Style Guidelines)](#type) * [Conditional Evaluation](#cond) * [Practical Style](#practical) * [Naming](#naming) * [Misc](#misc) * [Native & Host Objects](#native) * [Comments](#comments) * [One Language Code](#language) ------------------------------------------------ ## Preface The following sections outline a _reasonable_ style guide for modern JavaScript development and are not meant to be prescriptive. The most important take-away is the **law of code style consistency**. Whatever you choose as the style for your project should be considered law. Link to this document as a statement of your project's commitment to code style consistency, readability and maintainability. ## Idiomatic Style Manifesto 1. Whitespace - Never mix spaces and tabs. - When beginning a project, before you write any code, choose between soft indents (spaces) or real tabs, consider this **law**. - For readability, I always recommend setting your editor's indent size to two characters — this means two spaces or two spaces representing a real tab. - If your editor supports it, always work with the "show invisibles" setting turned on. The benefits of this practice are: - Enforced consistency - Eliminating end of line whitespace - Eliminating blank line whitespace - Commits and diffs that are easier to read - Use [Editorconfig](http://editorconfig.org/) when possible. It supports most IDEs and handles most whitespace settings. 2. Beautiful Syntax A. Parens, Braces, Linebreaks ```javascript // if/else/for/while/try always have spaces, braces and span multiple lines // this encourages readability // 2.A.1.1 // Examples of really cramped syntax if(condition) doSomething(); while(condition) iterating++; for(var i=0;i<100;i++) someIterativeFn(); // 2.A.1.1 // Use whitespace to promote readability if ( condition ) { // statements } while ( condition ) { // statements } for ( var i = 0; i < 100; i++ ) { // statements } // Even better: var i, length = 100; for ( i = 0; i < length; i++ ) { // statements } // Or... var i = 0, length = 100; for ( ; i < length; i++ ) { // statements } var prop; for ( prop in object ) { // statements } if ( true ) { // statements } else { // statements } ``` B. Assignments, Declarations, Functions ( Named, Expression, Constructor ) ```javascript // 2.B.1.1 // Variables var foo = "bar", num = 1, undef; // Literal notations: var array = [], object = {}; // 2.B.1.2 // Using only one `var` per scope (function) or one `var` for each variable, // promotes readability and keeps your declaration list free of clutter. // Using one `var` per variable you can take more control of your versions // and makes it easier to reorder the lines. // One `var` per scope makes it easier to detect undeclared variables // that may become implied globals. // Choose better for your project and never mix them. // Bad var foo = "", bar = ""; var qux; // Good var foo = ""; var bar = ""; var qux; // or.. var foo = "", bar = "", qux; // or.. var // Comment on these foo = "", bar = "", quux; // 2.B.1.3 // var statements should always be in the beginning of their respective scope (function). // Bad function foo() { // some statements here var bar = "", qux; } // Good function foo() { var bar = "", qux; // all statements after the variables declarations. } // 2.B.1.4 // const and let, from ECMAScript 6, should likewise be at the top of their scope (block). // Bad function foo() { let foo, bar; if ( condition ) { bar = ""; // statements } } // Good function foo() { let foo; if ( condition ) { let bar = ""; // statements } } ``` ```javascript // 2.B.2.1 // Named Function Declaration function foo( arg1, argN ) { } // Usage foo( arg1, argN ); // 2.B.2.2 // Named Function Declaration function square( number ) { return number * number; } // Usage square( 10 ); // Really contrived continuation passing style function square( number, callback ) { callback( number * number ); } square( 10, function( square ) { // callback statements }); // 2.B.2.3 // Function Expression var square = function( number ) { // Return something valuable and relevant return number * number; }; // Function Expression with Identifier // This preferred form has the added value of being // able to call itself and have an identity in stack traces: var factorial = function factorial( number ) { if ( number < 2 ) { return 1; } return number * factorial( number - 1 ); }; // 2.B.2.4 // Constructor Declaration function FooBar( options ) { this.options = options; } // Usage var fooBar = new FooBar({ a: "alpha" }); fooBar.options; // { a: "alpha" } ``` C. Exceptions, Slight Deviations ```javascript // 2.C.1.1 // Functions with callbacks foo(function() { // Note there is no extra space between the first paren // of the executing function call and the word "function" }); // Function accepting an array, no space foo([ "alpha", "beta" ]); // 2.C.1.2 // Function accepting an object, no space foo({ a: "alpha", b: "beta" }); // Single argument string literal, no space foo("bar"); // Expression parens, no space if ( !("foo" in obj) ) { obj = (obj.bar || defaults).baz; } ``` D. Consistency Always Wins In sections 2.A-2.C, the whitespace rules are set forth as a recommendation with a simpler, higher purpose: consistency. It's important to note that formatting preferences, such as "inner whitespace" should be considered optional, but only one style should exist across the entire source of your project. ```javascript // 2.D.1.1 if (condition) { // statements } while (condition) { // statements } for (var i = 0; i < 100; i++) { // statements } if (true) { // statements } else { // statements } ``` E. Quotes Whether you prefer single or double shouldn't matter, there is no difference in how JavaScript parses them. What **ABSOLUTELY MUST** be enforced is consistency. **Never mix quotes in the same project. Pick one style and stick with it.** F. End of Lines and Empty Lines Whitespace can ruin diffs and make changesets impossible to read. Consider incorporating a pre-commit hook that removes end-of-line whitespace and blanks spaces on empty lines automatically. 3. Type Checking (Courtesy jQuery Core Style Guidelines) A. Actual Types String: typeof variable === "string" Number: typeof variable === "number" Boolean: typeof variable === "boolean" Object: typeof variable === "object" Array: Array.isArray( arrayLikeObject ) (wherever possible) Node: elem.nodeType === 1 null: variable === null null or undefined: variable == null undefined: Global Variables: typeof variable === "undefined" Local Variables: variable === undefined Properties: object.prop === undefined object.hasOwnProperty( prop ) "prop" in object B. Coerced Types Consider the implications of the following... Given this HTML: ```html ``` ```javascript // 3.B.1.1 // `foo` has been declared with the value `0` and its type is `number` var foo = 0; // typeof foo; // "number" ... // Somewhere later in your code, you need to update `foo` // with a new value derived from an input element foo = document.getElementById("foo-input").value; // If you were to test `typeof foo` now, the result would be `string` // This means that if you had logic that tested `foo` like: if ( foo === 1 ) { importantTask(); } // `importantTask()` would never be evaluated, even though `foo` has a value of "1" // 3.B.1.2 // You can preempt issues by using smart coercion with unary + or - operators: foo = +document.getElementById("foo-input").value; // ^ unary + operator will convert its right side operand to a number // typeof foo; // "number" if ( foo === 1 ) { importantTask(); } // `importantTask()` will be called ``` Here are some common cases along with coercions: ```javascript // 3.B.2.1 var number = 1, string = "1", bool = false; number; // 1 number + ""; // "1" string; // "1" +string; // 1 +string++; // 1 string; // 2 bool; // false +bool; // 0 bool + ""; // "false" ``` ```javascript // 3.B.2.2 var number = 1, string = "1", bool = true; string === number; // false string === number + ""; // true +string === number; // true bool === number; // false +bool === number; // true bool === string; // false bool === !!string; // true ``` ```javascript // 3.B.2.3 var array = [ "a", "b", "c" ]; !!~array.indexOf("a"); // true !!~array.indexOf("b"); // true !!~array.indexOf("c"); // true !!~array.indexOf("d"); // false // Note that the above should be considered "unnecessarily clever" // Prefer the obvious approach of comparing the returned value of // indexOf, like: if ( array.indexOf( "a" ) >= 0 ) { // ... } ``` ```javascript // 3.B.2.4 var num = 2.5; parseInt( num, 10 ); // is the same as... ~~num; num >> 0; num >>> 0; // All result in 2 // Keep in mind however, that negative numbers will be treated differently... var neg = -2.5; parseInt( neg, 10 ); // is the same as... ~~neg; neg >> 0; // All result in -2 // However... neg >>> 0; // Will result in 4294967294 ``` 4. Conditional Evaluation ```javascript // 4.1.1 // When only evaluating that an array has length, // instead of this: if ( array.length > 0 ) ... // ...evaluate truthiness, like this: if ( array.length ) ... // 4.1.2 // When only evaluating that an array is empty, // instead of this: if ( array.length === 0 ) ... // ...evaluate truthiness, like this: if ( !array.length ) ... // 4.1.3 // When only evaluating that a string is not empty, // instead of this: if ( string !== "" ) ... // ...evaluate truthiness, like this: if ( string ) ... // 4.1.4 // When only evaluating that a string _is_ empty, // instead of this: if ( string === "" ) ... // ...evaluate falsy-ness, like this: if ( !string ) ... // 4.1.5 // When only evaluating that a reference is true, // instead of this: if ( foo === true ) ... // ...evaluate like you mean it, take advantage of built in capabilities: if ( foo ) ... // 4.1.6 // When evaluating that a reference is false, // instead of this: if ( foo === false ) ... // ...use negation to coerce a true evaluation if ( !foo ) ... // ...Be careful, this will also match: 0, "", null, undefined, NaN // If you _MUST_ test for a boolean false, then use if ( foo === false ) ... // 4.1.7 // When only evaluating a ref that might be null or undefined, but NOT false, "" or 0, // instead of this: if ( foo === null || foo === undefined ) ... // ...take advantage of == type coercion, like this: if ( foo == null ) ... // Remember, using == will match a `null` to BOTH `null` and `undefined` // but not `false`, "" or 0 null == undefined ``` ALWAYS evaluate for the best, most accurate result - the above is a guideline, not a dogma. ```javascript // 4.2.1 // Type coercion and evaluation notes // Prefer `===` over `==` (unless the case requires loose type evaluation) // === does not coerce type, which means that: "1" === 1; // false // == does coerce type, which means that: "1" == 1; // true // 4.2.2 // Booleans, Truthies & Falsies // Booleans: true, false // Truthy: "foo", 1 // Falsy: "", 0, null, undefined, NaN, void 0 ``` 5. Practical Style ```javascript // 5.1.1 // A Practical Module (function( global ) { var Module = (function() { var data = "secret"; return { // This is some boolean property bool: true, // Some string value string: "a string", // An array property array: [ 1, 2, 3, 4 ], // An object property object: { lang: "en-Us" }, getData: function() { // get the current value of `data` return data; }, setData: function( value ) { // set the value of `data` and return it return ( data = value ); } }; })(); // Other things might happen here // expose our module to the global object global.Module = Module; })( this ); ``` ```javascript // 5.2.1 // A Practical Constructor (function( global ) { function Ctor( foo ) { this.foo = foo; return this; } Ctor.prototype.getFoo = function() { return this.foo; }; Ctor.prototype.setFoo = function( val ) { return ( this.foo = val ); }; // To call constructor's without `new`, you might do this: var ctor = function( foo ) { return new Ctor( foo ); }; // expose our constructor to the global object global.ctor = ctor; })( this ); ``` 6. Naming A. You are not a human code compiler/compressor, so don't try to be one. The following code is an example of egregious naming: ```javascript // 6.A.1.1 // Example of code with poor names function q(s) { return document.querySelectorAll(s); } var i,a=[],els=q("#foo"); for(i=0;iMisc This section will serve to illustrate ideas and concepts that should not be considered dogma, but instead exists to encourage questioning practices in an attempt to find better ways to do common JavaScript programming tasks. A. Using `switch` should be avoided, modern method tracing will blacklist functions with switch statements There seems to be drastic improvements to the execution of `switch` statements in latest releases of Firefox and Chrome. http://jsperf.com/switch-vs-object-literal-vs-module Notable improvements can be witnessed here as well: https://github.com/rwldrn/idiomatic.js/issues/13 ```javascript // 7.A.1.1 // An example switch statement switch( foo ) { case "alpha": alpha(); break; case "beta": beta(); break; default: // something to default to break; } // 7.A.1.2 // A alternate approach that supports composability and reusability is to // use an object to store "cases" and a function to delegate: var cases, delegator; // Example returns for illustration only. cases = { alpha: function() { // statements // a return return [ "Alpha", arguments.length ]; }, beta: function() { // statements // a return return [ "Beta", arguments.length ]; }, _default: function() { // statements // a return return [ "Default", arguments.length ]; } }; delegator = function() { var args, key, delegate; // Transform arguments list into an array args = [].slice.call( arguments ); // shift the case key from the arguments key = args.shift(); // Assign the default case handler delegate = cases._default; // Derive the method to delegate operation to if ( cases.hasOwnProperty( key ) ) { delegate = cases[ key ]; } // The scope arg could be set to something specific, // in this case, |null| will suffice return delegate.apply( null, args ); }; // 7.A.1.3 // Put the API in 7.A.1.2 to work: delegator( "alpha", 1, 2, 3, 4, 5 ); // [ "Alpha", 5 ] // Of course, the `case` key argument could easily be based // on some other arbitrary condition. var caseKey, someUserInput; // Possibly some kind of form input? someUserInput = 9; if ( someUserInput > 10 ) { caseKey = "alpha"; } else { caseKey = "beta"; } // or... caseKey = someUserInput > 10 ? "alpha" : "beta"; // And then... delegator( caseKey, someUserInput ); // [ "Beta", 1 ] // And of course... delegator(); // [ "Default", 0 ] ``` B. Early returns promote code readability with negligible performance difference ```javascript // 7.B.1.1 // Bad: function returnLate( foo ) { var ret; if ( foo ) { ret = "foo"; } else { ret = "quux"; } return ret; } // Good: function returnEarly( foo ) { if ( foo ) { return "foo"; } return "quux"; } ``` 8. Native & Host Objects The basic principle here is: ### Don't do stupid shit and everything will be ok. To reinforce this concept, please watch the following presentation: #### “Everything is Permitted: Extending Built-ins” by Andrew Dupont (JSConf2011, Portland, Oregon) https://www.youtube.com/watch?v=xL3xCO7CLNM 9. Comments #### Single line above the code that is subject #### Multiline is good #### End of line comments are prohibited! #### JSDoc style is good, but requires a significant time investment 10. One Language Code Programs should be written in one language, whatever that language may be, as dictated by the maintainer or maintainers. ## Appendix ### Comma First. Any project that cites this document as its base style guide will not accept comma first code formatting, unless explicitly specified otherwise by that project's author. ---------- Creative Commons License
Principles of Writing Consistent, Idiomatic JavaScript by Rick Waldron and Contributors is licensed under a Creative Commons Attribution 3.0 Unported License.
Based on a work at github.com/rwldrn/idiomatic.js. ================================================ FILE: translations/bg_BG/readme.md ================================================ # Принципи на консистентно и идиоматично писане на JavaScript ## Това е "жив" документ и нови идеи за подобряване на кода са винаги добре дошли. Допринесете: fork, clone, branch, commit, push, pull request. * Rick Waldron [@rwaldron](http://twitter.com/rwaldron), [github](https://github.com/rwaldron) * Mathias Bynens [@mathias](http://twitter.com/mathias), [github](https://github.com/mathiasbynens) * Schalk Neethling [@ossreleasefeed](http://twitter.com/ossreleasefeed), [github](https://github.com/ossreleasefeed/) * Kit Cambridge [@kitcambridge](http://twitter.com/kitcambridge), [github](https://github.com/kitcambridge) * Raynos [github](https://github.com/Raynos) * Matias Arriola [@MatiasArriola](https://twitter.com/MatiasArriola), [github](https://github.com/MatiasArriola/) * John Fischer [@jfroffice](https://twitter.com/jfroffice), [github](https://github.com/jfroffice/) * Idan Gazit [@idangazit](http://twitter.com/idangazit), [github](https://github.com/idan) * Leo Balter [@leobalter](http://twitter.com/leobalter), [github](https://github.com/leobalter) * Breno Oliveira [@garu_rj](http://twitter.com/garu_rj), [github](https://github.com/garu) * Leo Beto Souza [@leobetosouza](http://twitter.com/leobetosouza), [github](https://github.com/leobetosouza) * Ryuichi Okumura [@okuryu](http://twitter.com/okuryu), [github](https://github.com/okuryu) * Pascal Precht [@PascalPrecht](http://twitter.com/PascalPrecht), [github](https://github.com/pascalprecht) * EngForDev [engfordev](https://opentutorials.org/course/245/1788) - Hwan Min Hong / MinTaek Kwon [@leoinsight](http://twitter.com/leoinsight) / Tw Shim [@marocchino](http://twitter.com/marocchino), [github](https://github.com/marocchino) / Nassol Kim [@nassol99](http://twitter.com/nassol99), [github](https://github.com/nassol) / Juntai Park [@rkJun](http://twitter.com/rkJun), [github](https://github.com/rkJun) / Minkyu Shim / Gangmin Won / Justin Yoo [@justinchronicle](http://twitter.com/justinchronicle) / Daeyup Lee * Marco Trulla [@marcotrulla](http://twitter.com/marcotrulla), [github](https://github.com/Ragnarokkr) * Alex Navasardyan [@alexnavasardyan](http://twitter.com/alexnavasardyan), [github](https://github.com/2k00l) * Mihai Paun [@mihaipaun](http://twitter.com/mihaipaun), [github](https://github.com/mihaipaun) * Evgeny Mandrikov [@\_godin\_](http://twitter.com/_godin_), [github](https://github.com/Godin) * Sofish Lin [@sofish](http://twitter.com/sofish), [github](https://github.com/sofish) * Дејан Димић [@dejan_dimic](http://twitter.com/dejan_dimic), [github](https://github.com/rubystream) * Miloš Gavrilović [@gavrisimo](http://twitter.com/gavrisimo), [github](https://github.com/gavrisimo) * Firede [@firede](https://twitter.com/firede) [github](https://github.com/firede) * monkadd [github](https://github.com/monkadd) * Stephan Lindauer [@stephanlindauer](http://twitter.com/stephanlindauer), [github](https://github.com/stephanlindauer) * Thomas P [@dragon5689](https://twitter.com/dragon5689) [github](https://github.com/dragon5689) * Yotam Ofek [@yotamofek](https://twitter.com/yotamofek) [github](https://github.com/yotamofek) * Aleksandr Filatov [@greybax](http://twitter.com/greybax), [github](https://github.com/greybax) * Duc Nguyen [@ducntq](https://twitter.com/ducntq), [github](https://github.com/ducntq) * James Young [@jamsyoung](http://twitter.com/jamsyoung), [github](https://github.com/jamsyoung) * Hao-Wei Jeng [@l0ckys](http://twitter.com/l0ckys), [github](https://github.com/lockys) * Richard Gibson [@gibson042](http://twitter.com/gibson042), [github](https://github.com/gibson042) * Fesuy [github](https://github.com/fesuydev) * Stephane Moreau [github](https://github.com/stmoreau) * Boris Nekezov [github](https://github.com/boris-nekezov) * Akshat Joshi [@akshat_joshi](http://twitter.com/akshat_joshi), [github](https://https://github.com/akshatjoshii) ## Целият код във всяка кодова база трябва да изглежда като писано от един човек, няма значение колко души са допринесли. ### Последващия списък изтъква практиките, които използвам в всичкия ми код, на който съм оригинален автор; участия в проекти, които съм създал трябва да следват тези напътствия. ### Нямам намерение да налагам моите предпочитания за стил на кода или проекти на други хора; ако има наличие на съществуващ общ стил, той трябва да се спазва. > ### "Спорове за стилове са безсмислени. Трябва да има ръководство за стила и трябва да го спазвате" >_Rebecca_ _Murphey_   > ### "Част от това да си добър ръководител на един успешен проект е да осъзнаете, че писането на код за вас е лоша идея. Ако хиляди души използват вашия код, тогава пишете кода ви максилнално ясно, а не по вашето лично предпочитание." >_Idan_ _Gazit_ ## Translations * [ORIGINAL](https://github.com/rwldrn/idiomatic.js/) * [Bulgarian](https://github.com/rwldrn/idiomatic.js/tree/master/translations/bg_BG) * [German](https://github.com/rwldrn/idiomatic.js/tree/master/translations/de_DE) * [French](https://github.com/rwldrn/idiomatic.js/tree/master/translations/fr_FR) * [Spanish](https://github.com/rwldrn/idiomatic.js/tree/master/translations/es_ES) * [Portuguese - Brazil](https://github.com/rwldrn/idiomatic.js/tree/master/translations/pt_BR) * [Korean](https://github.com/rwldrn/idiomatic.js/tree/master/translations/ko_KR) * [日本語](https://github.com/rwldrn/idiomatic.js/tree/master/translations/ja_JP) * [Italian](https://github.com/rwldrn/idiomatic.js/tree/master/translations/it_IT) * [Russian](https://github.com/rwldrn/idiomatic.js/tree/master/translations/ru_RU) * [Romanian](https://github.com/rwldrn/idiomatic.js/tree/master/translations/ro_RO) * [简体中文](https://github.com/rwldrn/idiomatic.js/tree/master/translations/zh_CN) * [Serbian - cyrilic alphabet](https://github.com/rwldrn/idiomatic.js/tree/master/translations/ср_СР) * [Serbian - latin alphabet](https://github.com/rwldrn/idiomatic.js/tree/master/translations/sr_SR) * [繁體中文](https://github.com/rwaldron/idiomatic.js/tree/master/translations/zh_TW) * [Indonesian](https://github.com/rwaldron/idiomatic.js/tree/master/translations/id_ID) * [Greek](https://github.com/rwaldron/idiomatic.js/tree/master/translations/gr_GR) * [Hindi](https://github.com/rwaldron/idiomatic.js/tree/master/translations/hi_HI) ## Важни, Не-Идиоматични Неща: ### Инструменти за Качество на Кода, Ресурси & Референции * [JavaScript Plugin](http://docs.codehaus.org/display/SONAR/JavaScript+Plugin) for [Sonar](http://www.sonarsource.org/) * [Plato](https://github.com/es-analysis/plato) * [jsPerf](http://jsperf.com/) * [jsFiddle](http://jsfiddle.net/) * [Codepen](http://codepen.io/) * [jsbin](http://jsbin.com/) * [JavaScript Lint (JSL)](http://javascriptlint.com/) * [jshint](http://jshint.com/) * [jslint](http://jslint.org/) * [eslint](http://eslint.org/) * [jscs](https://www.npmjs.org/package/jscs) * [jscodesniffer](https://www.npmjs.org/package/jscodesniffer) * [Editorconfig](http://editorconfig.org/) * [Hound](https://houndci.com/) ## Станете Умни ### [Annotated ECMAScript 5.1](http://es5.github.com/) ### [Спецификация на Езика EcmaScript, Издание 5.1](http://ecma-international.org/ecma-262/5.1/) Последващото трябва да се вземе под внимание 1) недовършено, и 2) *ИЗИСКВА СЕ ЧЕТЕНЕ*. Не винаги съм съгласен със стила написан от авторите по-долу, но едно нещо е сигурно: Те са консистентни. Нещо повече, това са авторитети на езика. * [Baseline For Front End Developers: 2015](http://rmurphey.com/blog/2015/03/23/a-baseline-for-front-end-developers-2015/) * [Eloquent JavaScript](http://eloquentjavascript.net/) * [JavaScript, JavaScript](http://javascriptweblog.wordpress.com/) * [Adventures in JavaScript Development](http://rmurphey.com/) * [Perfection Kills](http://perfectionkills.com/) * [Douglas Crockford's Wrrrld Wide Web](http://www.crockford.com) * [JS Assessment](https://github.com/rmurphey/js-assessment) ### Процес на компилация и деплойване Проектите винаги трябва да включат някои общи средства, чрез които източникът да бъде свързан, тестван и компресиран при подготовка за производствена употреба. За тази задача, [grunt](https://github.com/gruntjs/grunt) на Бен Алман е най-добрата от всички официални заместители на папката "kits/" в това хранилище. ### Тестова база Проектите трябва да включват някаква форма на единица, референция, имплементация или функционално тестване. Демострационни случаи на употреба НЕ СЕ КВАЛИФИЦИРАТ като "тестове". По-долу има списък със тестови рамки, нито една от които не е одобрена повече от другата. * [QUnit](http://github.com/jquery/qunit) * [Jasmine](https://github.com/pivotal/jasmine) * [Vows](https://github.com/cloudhead/vows) * [Mocha](https://github.com/visionmedia/mocha) * [Hiro](http://hirojs.com/) * [JsTestDriver](https://code.google.com/p/js-test-driver/) * [Buster.js](http://busterjs.org/) * [Sinon.js](http://sinonjs.org/) * [Tape](https://github.com/substack/tape) * [Jest](https://facebook.github.io/jest/) ## Съдържание * [Whitespace](#whitespace) * [Beautiful Syntax](#spacing) * [Type Checking (Courtesy jQuery Core Style Guidelines)](#type) * [Conditional Evaluation](#cond) * [Practical Style](#practical) * [Naming](#naming) * [Misc](#misc) * [Native & Host Objects](#native) * [Comments](#comments) * [One Language Code](#language) ------------------------------------------------ ## Предговор Следващите раздели посочват едно разумно ръководство на стил за съвременна разработка на JavaScript и не е предназначен за норматив. Най-важната част е **закона за постоянност на стила на кода**. Каквото и да изберете като стил за вашия проект, трябва да се счита за закон. Използвайте този документ като напътствие на вашето отдаване към проекта ви за консистентност на стила на кода, четимост и поддържане. ## Манифест на идиоматичния стил 1. Празно пространство - Никога не смесвайте спейсове и табове. - Когато започнете един проект, преди да почнете да пишете какъвто и да е код, изберете между меки отсъпи (интервали) или реални табулации, считайте го за **закон** - За четимост, винаги препоръчвам да зададете размера на отстъпа на вашия редактор на два знака — което означава два интервала или два интервала, представляващи истинска табулация. - Винаги работете с включена настройка "покажи скрити", ако редактора ви я поддържа. Предимствата на тази практика са: - Усилена консистенция - Премахване на интервал в края на реда - Премахване на празни редове - Комитите и разликите в кода са по-лесни за четене - Използвайте [Editorconfig](http://editorconfig.org/) когато е възможно. Поддържа повечето IDEs и обработва повечето настройки за празно пространство. 2. Красив синтаксис A. Parens, Braces, Linebreaks А. Скоби, Фигурни Скоби, Пренасяне на редовете ```javascript // if/else/for/while/try винаги имат интервали между тях, къдравите скоби и разделението между секциите са на множество редове // това подобрява четимостта // 2.A.1.1 // Примери за наистина нечетлив синтаксис if(condition) doSomething(); while(condition) iterating++; for(var i=0;i<100;i++) someIterativeFn(); // 2.A.1.1 // Използвайте интервали за да повишите четимостта if ( condition ) { // изрази } while ( condition ) { // изрази } for ( var i = 0; i < 100; i++ ) { // изрази } // Още по-добре: var i, length = 100; for ( i = 0; i < length; i++ ) { // изрази } // Или... var i = 0, length = 100; for ( ; i < length; i++ ) { // изрази } var prop; for ( prop in object ) { // изрази } if ( true ) { // изрази } else { // изрази } ``` B. Прислояване, Декларации, Функции ( Именувани, Изрази, Конструктори) ```javascript // 2.B.1.1 // Променливи var foo = "bar", num = 1, undef; // Литерална нотация: var array = [], object = {}; // 2.B.1.2 // Използването на само един `var` на всеки обхват (функция) или по един `var` на всяка променлива, // повишава четимостта и пази вашия списък на декларации от безредие. // Използването по един `var` на всяка променлива можете да контролирате по-добре версиите // и освен това улеснява разместването на редовете. // Един `var` на всеки обхват улеснява намирането на недекларирани променливи, // които могат да станат подразбиращи се глобални. // Изберете по-добрия подход за вашия проект и никога не го смесвайте // Лош пример var foo = "", bar = ""; var qux; // Добър пример var foo = ""; var bar = ""; var qux; // или.. var foo = "", bar = "", qux; // или.. var // Коментар на тези foo = "", bar = "", quux; // 2.B.1.3 // Операторите 'var' винаги трябва да са в началото на техния съответен обxват (функция). // Лош пример function foo() { // някакви изрази var bar = "", qux; } // Добър пример function foo() { var bar = "", qux; // всички изрази след декларацията на променливите } // 2.B.1.4 // 'const' и `let`, от ECMAScript 6, също трябва да са в горната част на техния обхват (блоков). // Лош пример function foo() { let foo, bar; if ( condition ) { bar = ""; // изрази } } // Добър пример function foo() { let foo; if ( condition ) { let bar = ""; // изрази } } ``` ```javascript // 2.B.2.1 // Деклариране на именувана функция function foo( arg1, argN ) { } // Използване foo( arg1, argN ); // 2.B.2.2 // Деклариране на именувана функция function square( number ) { return number * number; } // Използване square( 10 ); // Много измислен стил на подаване на параметри function square( number, callback ) { callback( number * number ); } square( 10, function( square ) { // изрази с обратно извикване }); // 2.B.2.3 // Функция-Израз var square = function( number ) { // Върнете нещо важно и релевантно return number * number; }; // Функция-Израз с Идентификатор // Тази предпочитана форма има добавената стойност // и името му ще бъде видимо в стека на функционалните обаждания: var factorial = function factorial( number ) { if ( number < 2 ) { return 1; } return number * factorial( number - 1 ); }; // 2.B.2.4 // Деклариране на Конструктор function FooBar( options ) { this.options = options; } // Използване var fooBar = new FooBar({ a: "alpha" }); fooBar.options; // { a: "alpha" } ``` C. Изключения, леки отклонения ```javascript // 2.C.1.1 // Функции с обратно извикване foo(function() { // Забележете, че няма интервали между първата скоба // на изпълненото фунционално извикване и думата "function" }); // Функция приемаща масив като параметър, без интервал foo([ "alpha", "beta" ]); // 2.C.1.2 // Функция приемаща обект като параметър, без интервал foo({ a: "alpha", b: "beta" }); // Единичен низ като параметър, също без интервал foo("bar"); // Съдържание във вътрешни скоби, също без интервал if ( !("foo" in obj) ) { obj = (obj.bar || defaults).baz; } ``` D. Консистентността винаги побеждава В секции 2.A-2.C, правилата за интервали са изложени като препоръка с по-проста и по-извисена цел: консистентност. Важно е да се отбележи, че предпочитанията за форматиране, такива като "вътрешно пространство", трябва да се считат за незадължителни, но само един стил трябва да съществува из целия код на вашия проект. ```javascript // 2.D.1.1 if (condition) { // изрази } while (condition) { // изрази } for (var i = 0; i < 100; i++) { // изрази } if (true) { // изрази } else { // изрази } ``` E. Кавички Независимо от това дали предпочитате единични или двойни кавички, няма разлика в това как JavaScript ги парсва. Това което **АБСОЛЮТНО ТРЯБВА** да се наложи е консистентност. **Никога не смесвайте кавичките в един и същи проект. Изберете един стил и се придържайте към него.** F. Край на Редовете и Празни Редове Пространствата могат да развалят разликите и да направят промените невъзможни за четене. Помислете да включите "pre-commit" кука, която да премахне автоматично пространството на края на реда и празните пространства на редовете. 3. Type Checking (Courtesy jQuery Core Style Guidelines) A. Типове String: typeof variable === "string" Number: typeof variable === "number" Boolean: typeof variable === "boolean" Object: typeof variable === "object" Array: Array.isArray( arrayLikeObject ) (wherever possible) Node: elem.nodeType === 1 null: variable === null null or undefined: variable == null undefined: Глобални променливи: typeof variable === "undefined" Локални променливи: variable === undefined Свойства: object.prop === undefined object.hasOwnProperty( prop ) "prop" in object B. Прехвърляне на Типове Представете си следното... Даден ви е следния HTML: ```html ``` ```javascript // 3.B.1.1 // `foo` е деклариран със стойност `0` и неговия тип е `number` var foo = 0; // typeof foo; // "number" ... // Някъде по-късно във вашия код, трябва да обновите `foo` // с нова стойност взета от елемента 'input' foo = document.getElementById("foo-input").value; // Ако сега тествате 'typeof foo`, резултатът ще бъде 'string' // Това означава, че ако имате логика, която тества 'foo' като тази: if ( foo === 1 ) { importantTask(); } // `importantTask()` няма никога да бъде достигнат дори и `foo` да има стойност "1" // 3.B.1.2 // Можете да избегнете проблеми като използвате умно конвертиране в унарните оператори + и -: foo = +document.getElementById("foo-input").value; // ^ унарния оператор + ще преобразува десния си операнд в тип 'number' // typeof foo; // "number" if ( foo === 1 ) { importantTask(); } // `importantTask()` ще бъде извикана ``` Ето няколко често срещани примера за прехвърляне на типове: ```javascript // 3.B.2.1 var number = 1, string = "1", bool = false; number; // 1 number + ""; // "1" string; // "1" +string; // 1 +string++; // 1 string; // 2 bool; // false +bool; // 0 bool + ""; // "false" ``` ```javascript // 3.B.2.2 var number = 1, string = "1", bool = true; string === number; // false string === number + ""; // true +string === number; // true bool === number; // false +bool === number; // true bool === string; // false bool === !!string; // true ``` ```javascript // 3.B.2.3 var array = [ "a", "b", "c" ]; !!~array.indexOf("a"); // true !!~array.indexOf("b"); // true !!~array.indexOf("c"); // true !!~array.indexOf("d"); // false // Забележете, че горните примери може да се считат за "ненужно умни" // За предпочитане е очевидния подход да сравнявате върнатата стойност на // indexOf, по този начин: if ( array.indexOf( "a" ) >= 0 ) { // ... } ``` ```javascript // 3.B.2.4 var num = 2.5; parseInt( num, 10 ); // е съшото като ... ~~num; num >> 0; num >>> 0; // Във всички случаи резултатът е равен на 2 // Помнете, че отрицателните числа ще бъдат обработени различно ... var neg = -2.5; parseInt( neg, 10 ); // е същото като... ~~neg; neg >> 0; // Във всички случаи резултатът е равен на -2 // Въпреки че при... neg >>> 0; // Резултата ще е 4294967294 ``` 4. Условна Проверка ```javascript // 4.1.1 // Проверете дали масивът има дължина, // вместо: if ( array.length > 0 ) ... // ...проверявайте за истина, по този начин: if ( array.length ) ... // 4.1.2 // Проверете дали масива е празен, // вместо: if ( array.length === 0 ) ... // ...проверявайте за вярност, по този начин: if ( !array.length ) ... // 4.1.3 // Проверете дали низа не е празен, // вместо: if ( string !== "" ) ... // ...проверявайте за вярност, по този начин: if ( string ) ... // 4.1.4 // Проверете дали низа _е_ празен, // вместо: if ( string === "" ) ... // ...проверявайте дали израдът е неверен, по този начин: if ( !string ) ... // 4.1.5 // Проверете дали тази референция е вярна, // вместо: if ( foo === true ) ... // ...проверете, възползвайки се от вградените възможности: if ( foo ) ... // 4.1.6 // Проверете дали тази референция е невярна, // вместо: if ( foo === false ) ... // ...проверете, използвайки отрицание if ( !foo ) ... // ...Внимавайте, това важи и за: 0, "", null, undefined, NaN // Ако _трябва_ да тествате за булево невярно, тогава използвайте if ( foo === false ) ... // 4.1.7 // Когато проверявате дали е null или undefined, но НЕ Е false, "" или 0, // вместо това: if ( foo === null || foo === undefined ) ... // ...използвайте оператора ==: if ( foo == null ) ... // Помнете, че използвайки оператора == с `null` важи И ЗА ДВЕТЕ `null` и `undefined` // но не `false ', "" или 0 null == undefined ``` ВИНАГИ проверявайте за най-добрия и точен резултат - горното е ръководство, не догма. ```javascript // 4.2.1 // Преобразуване на типове и бележки за проверяване // За предпочитане е да използвате `===` вместо `==` (освен ако конкретния случай не изисква слабо типизирана оценка) // === проверява и типа, т.е.: "1" === 1; // false // == не проверява типа, т.е.: "1" == 1; // true // 4.2.2 // Логически изрази, Вярни & Невярни // Логически изрази: true, false // Вярни: "foo", 1 // Невярни: "", 0, null, undefined, NaN, void 0 ``` 5. Стил на Практика ```javascript // 5.1.1 // Практичен модул (function( global ) { var Module = (function() { var data = "secret"; return { // Логическо свойство bool: true, // Стойност от тип низ string: "a string", // Свойство - масив array: [ 1, 2, 3, 4 ], // Свойство - обект object: { lang: "bg-BG" }, getData: function() { // вземете текущата стойност на променливата `data` return data; }, setData: function( value ) { // присвоете стойността на `data` и я върнете return ( data = value ); } }; })(); // Други декларации // добавяме нашия модул към глобалния обект global.Module = Module; })( this ); ``` ```javascript // 5.2.1 // Практичен Конструктор (function( global ) { function Ctor( foo ) { this.foo = foo; return this; } Ctor.prototype.getFoo = function() { return this.foo; }; Ctor.prototype.setFoo = function( val ) { return ( this.foo = val ); }; // За да извикате конструктора без `new`, можете да направите това: var ctor = function( foo ) { return new Ctor( foo ); }; // добави нашия конструктор към глобалния обект global.ctor = ctor; })( this ); ``` 6. Наименуване A. Вие не сте човешки компилатор/компресор на код, затова не се опитвайте да бъдете такъв. Последващия код е пример за лошо именуване: ```javascript // 6.A.1.1 // Пример за код с лоши имена function q(s) { return document.querySelectorAll(s); } var i,a=[],els=q("#foo"); for(i=0;iРазни Този раздел ще служи за илюстриране на идеи и концепции, които не трябва да се считат за догма, вместо това съществува за да даде под съмнение практиките в опит да се намери по-добри начини за изпълнение, на често срещани JavaScript задачи. A. Използването на `switch` трябва да се избягва, тъй като съвременния метод за отстраняване на грешки ще скрие повикванията на функции, които го използват. Изглежда че последните версии на браузърите Firefox и Chrome имат значителни подобрения в работата на функциите, които използват `switch`. http://jsperf.com/switch-vs-object-literal-vs-module Забележими подобрения могат да се видят също и тук: https://github.com/rwldrn/idiomatic.js/issues/13 ```javascript // 7.A.1.1 // Пример на оператора switch switch( foo ) { case "alpha": alpha(); break; case "beta": beta(); break; default: // код по подразбиране break; } // 7.A.1.2 // Алтернативен подход, който подкрепя използваемостта и повторната употреба е да // се използва обект за съхранение на "случаи" и функция за делегация var cases, delegator; // Примерът връща само с илюстративни цели. cases = { alpha: function() { // изрази // връщане return [ "Alpha", arguments.length ]; }, beta: function() { // изрази // връщане return [ "Beta", arguments.length ]; }, _default: function() { // изрази // връщане return [ "Default", arguments.length ]; } }; delegator = function() { var args, key, delegate; // Трансформиране на списъка с аргументите в масив args = [].slice.call( arguments ); // Променяне на ключа на случая от аргументите key = args.shift(); // Определяне на ключа по подразбиране delegate = cases._default; // Извличане на метода за да делегиране на операция if ( cases.hasOwnProperty( key ) ) { delegate = cases[ key ]; } // Обхватния аргумент може да бъде зададен към нещо специфични, // в този случай, |null| ще бъде достатъчно return delegate.apply( null, args ); }; // 7.A.1.3 // Сложете Апито в 7.A.1.2 да работи: delegator( "alpha", 1, 2, 3, 4, 5 ); // [ "Alpha", 5 ] // Разбира се, ключовият аргумент на `случая` може да се основава лесно // при някакво друго произволно условие. var caseKey, someUserInput; // Вероятно някакво поле на форма? someUserInput = 9; if ( someUserInput > 10 ) { caseKey = "alpha"; } else { caseKey = "beta"; } // или... caseKey = someUserInput > 10 ? "alpha" : "beta"; // И тогава... delegator( caseKey, someUserInput ); // [ "Beta", 1 ] // И разбира се... delegator(); // [ "Default", 0 ] ``` B. Ранните връщания подобряват четимостта на кода с незначителна разлика в производителността ```javascript // 7.B.1.1 // Лош пример: function returnLate( foo ) { var ret; if ( foo ) { ret = "foo"; } else { ret = "quux"; } return ret; } // Добър пример: function returnEarly( foo ) { if ( foo ) { return "foo"; } return "quux"; } ``` 8. "Родни" и "Чужди" обекти Основния принципт тук е: ### Не правете глупости и всичко ще бъде наред. За да подсилите тази концепция, моля гледайте последващата презентация: #### “Everything is Permitted: Extending Built-ins” от Андрю Дюпонт (JSConf2011, Портланд, Орегон) https://www.youtube.com/watch?v=xL3xCO7CLNM 9. Коментари #### Едноредов коментар над кода, за който е предназначен #### Многоредови коментари също са добре дошли #### Коментарите в края на реда са забранени! #### Стила JSDoc е добър, но изисква да се инвестира значително време 10. Код на Един Език Програмите трябва да бъдат написани на един език, независимо какъв е той, както се изисква от хората, които поддържат кода. ## Приложение ### Първа Запетая. Всеки проект, който се отнася до този документ като основно ръководство за стил, няма да приеме форматирането на кода "първа запетая", освен ако авторът на проекта конкретно не посочи това. ---------- Creative Commons License
Principles of Writing Consistent, Idiomatic JavaScript by Rick Waldron and Contributors is licensed under a Creative Commons Attribution 3.0 Unported License.
Based on a work at github.com/rwldrn/idiomatic.js. ================================================ FILE: translations/de_DE/readme.md ================================================ # Grundsätze für das Schreiben von konsequentem und idiomatischem JavaScript ## Dies ist ein lebendiges Dokument und neue Ideen, die den Code in unserem Umfeld verbessern, sind immer willkommen. Tragt dazu bei: "fork", "clone", "branch", "commit", "push", "pull request". * Rick Waldron [@rwaldron](http://twitter.com/rwaldron), [github](https://github.com/rwaldron) * Mathias Bynens [@mathias](http://twitter.com/mathias), [github](https://github.com/mathiasbynens) * Schalk Neethling [@ossreleasefeed](http://twitter.com/ossreleasefeed), [github](https://github.com/ossreleasefeed/) * Kit Cambridge [@kitcambridge](http://twitter.com/kitcambridge), [github](https://github.com/kitcambridge) * Raynos [github](https://github.com/Raynos) * Matias Arriola [@MatiasArriola](https://twitter.com/MatiasArriola), [github](https://github.com/MatiasArriola/) * John Fischer [@jfroffice](https://twitter.com/jfroffice), [github](https://github.com/jfroffice/) * Idan Gazit [@idangazit](http://twitter.com/idangazit), [github](https://github.com/idangazit) * Leo Balter [@leobalter](http://twitter.com/leobalter), [github](https://github.com/leobalter) * Breno Oliveira [@garu_rj](http://twitter.com/garu_rj), [github](https://github.com/garu) * Leo Beto Souza [@leobetosouza](http://twitter.com/leobetosouza), [github](https://github.com/leobetosouza) * Ryuichi Okumura [@okuryu](http://twitter.com/okuryu), [github](https://github.com/okuryu) * Pascal Precht [@PascalPrecht](http://twitter.com/PascalPrecht), [github](https://github.com/pascalprecht) * EngForDev [engfordev](http://www.opentutorials.org/course/167/1363) - Hwan Min Hong / MinTaek Kwon [@leoinsight](http://twitter.com/leoinsight) / Tw Shim [@marocchino](http://twitter.com/marocchino), [github](https://github.com/marocchino) / Nassol Kim [@nassol99](http://twitter.com/nassol99), [github](https://github.com/nassol) / Juntai Park [@rkJun](http://twitter.com/rkJun), [github](https://github.com/rkJun) / Minkyu Shim / Gangmin Won / Justin Yoo [@justinchronicle](http://twitter.com/justinchronicle) / Daeyup Lee * Marco Trulla [@marcotrulla](http://twitter.com/marcotrulla), [github](https://github.com/Ragnarokkr) * Alex Navasardyan [@alexnavasardyan](http://twitter.com/alexnavasardyan), [github](https://github.com/2k00l) * Mihai Paun [@mihaipaun](http://twitter.com/mihaipaun), [github](https://github.com/mihaipaun) * Evgeny Mandrikov [@\_godin\_](http://twitter.com/_godin_), [github](https://github.com/Godin) * Sofish Lin [@sofish](http://twitter.com/sofish), [github](https://github.com/sofish) * Дејан Димић [@dejan_dimic](http://twitter.com/dejan_dimic), [github](https://github.com/rubystream) * Miloš Gavrilović [@gavrisimo](http://twitter.com/gavrisimo), [github](https://github.com/gavrisimo) * Duc Nguyen [@ducntq](https://twitter.com/ducntq), [github](https://github.com/ducntq) * James Young [@jamsyoung](http://twitter.com/jamsyoung), [github](https://github.com/jamsyoung) * Stephane Moreau [github](https://github.com/stmoreau) * Boris Nekezov [github](https://github.com/boris-nekezov) * Akshat Joshi [@akshat_joshi](http://twitter.com/akshat_joshi), [github](https://https://github.com/akshatjoshii) ## Code sollte grundsätzlich so aussehen, als wäre er von einer einzigen Person geschrieben worden, völlig egal, wie viele letztlich daran gearbeitet haben. ### Das folgende Dokument zeigt Praktiken, die sich in jedem Code, den ich ursprünglich geschrieben habe, wiederfinden. Sämtliche Beiträge für Projekte, die ich kreiert habe, sollten diesen Praktiken folgen. ### Ich möchte anderen Leuten nicht meine Vorlieben aufzwängen; wenn es bereits einen geläufigen Style gibt, sollte dieser respektiert werden. > "Dass es eine schlechte Idee ist, nur für sich selbst Code zu schreiben, ist etwas, was man als guter Betreuer eines erfolgreichen Projektes begreifen muss™. Wenn tausende Leute deinen Code benutzen, dann schreibe deinen Code möglichst klar und übersichtlich, nicht einfach nur nach deinen persönlichen Vorlieben." - Idan Gazit ## Übersetzungen * [ORIGINAL](https://github.com/rwldrn/idiomatic.js/) * [Bulgarian](https://github.com/rwldrn/idiomatic.js/tree/master/translations/bg_BG) * [German](https://github.com/rwldrn/idiomatic.js/tree/master/translations/de_DE) * [French](https://github.com/rwldrn/idiomatic.js/tree/master/translations/fr_FR) * [Spanish](https://github.com/rwldrn/idiomatic.js/tree/master/translations/es_ES) * [Portuguese - Brazil](https://github.com/rwldrn/idiomatic.js/tree/master/translations/pt_BR) * [Korean](https://github.com/rwldrn/idiomatic.js/tree/master/translations/ko_KR) * [Japanese](https://github.com/rwldrn/idiomatic.js/tree/master/translations/ja_JP) * [Italian](https://github.com/rwldrn/idiomatic.js/tree/master/translations/it_IT) * [Russian](https://github.com/rwldrn/idiomatic.js/tree/master/translations/ru_RU) * [Romanian](https://github.com/rwldrn/idiomatic.js/tree/master/translations/ro_RO) * [简体中文](https://github.com/rwldrn/idiomatic.js/tree/master/translations/zh_CN) * [Serbian - cyrilic alphabet](https://github.com/rwldrn/idiomatic.js/tree/master/translations/ср_СР) * [Serbian - latin aplphabet](https://github.com/rwldrn/idiomatic.js/tree/master/translations/sr_SR) * [Greek](https://github.com/rwaldron/idiomatic.js/tree/master/translations/gr_GR) * [Hindi](https://github.com/rwaldron/idiomatic.js/tree/master/translations/hi_HI) ## Wichtiger, nicht-idiomatischer Kram: ### Code-Qualität: Tolle Werkzeuge, Ressourcen und Referenzen * [JavaScript Plugin](http://docs.codehaus.org/display/SONAR/JavaScript+Plugin) für [Sonar](http://www.sonarsource.org/) * [Plato](https://github.com/jsoverson/plato) * [jsPerf](http://jsperf.com/) * [jsFiddle](http://jsfiddle.net/) * [jsbin](http://jsbin.com/) * [JavaScript Lint (JSL)](http://javascriptlint.com/) * [jshint](http://jshint.com/) * [jslint](http://jslint.org/) * [Editorconfig](http://editorconfig.org/) [Leveraging Code Quality Tools by Anton Kovalyov](http://anton.kovalyov.net/slides/gothamjs/) ### Schlau werden [http://es5.github.com/](http://es5.github.com/) Bei den folgenden Ressourcen sollte berücksichtigt werden, dass sie 1) unvollständig und 2) *PFLICHTLEKTÜREN* sind. Ich stimme dem beschriebenen Style der unten stehenden Autoren nicht immer zu, aber eins ist sicher: Sie sind konsequent. Außerdem sind dies echte Autoritäten in dieser Sprache. * [Baseline For Front End Developers](http://rmurphey.com/blog/2012/04/12/a-baseline-for-front-end-developers/) * [Eloquent JavaScript](http://eloquentjavascript.net/) * [JavaScript, JavaScript](http://javascriptweblog.wordpress.com/) * [Adventures in JavaScript Development](http://rmurphey.com/) * [Perfection Kills](http://perfectionkills.com/) * [Douglas Crockford's Wrrrld Wide Web](http://www.crockford.com) * [JS Assessment](https://github.com/rmurphey/js-assessment) ### Build- und Deployment-Prozess Jedes Projekt sollte Komponenten verwenden, um den Code zu linten, testen oder komprimieren, um so im Produktivbereich eingesetzt zu werden. Ben Alan hat für diese Aufgabe [grunt](https://github.com/cowboy/grunt) entworfen und damit offiziell das "kits/" Verzeichnis aus diesem Repository ersetzt. ### Hilfsmittel zum Testen Projekte _müssen_ irgendeine Art von Unit-, Reference, Implementation- oder Functional-Testing enthalten. Demonstrationen von Anwendungsfällen reichen als Test nicht aus. Die unten aufgeführte Liste beinhaltet eine Menge nützlicher Test-Frameworks. * [QUnit](http://github.com/jquery/qunit) * [Jasmine](https://github.com/pivotal/jasmine) * [Vows](https://github.com/cloudhead/vows) * [Mocha](https://github.com/visionmedia/mocha) * [Hiro](http://hirojs.com/) * [JsTestDriver](https://code.google.com/p/js-test-driver/) * [Buster.js](http://busterjs.org/) ## Inhaltsverzeichnis * [Whitespace](#whitespace) * [Schöne Syntax](#spacing) * [Typprüfung](#type) * [Bedingte Auswertungen](#cond) * [Praktischer Style](#practical) * [Bezeichnungen](#naming) * [Sonstiges](#misc) * [Native & Host Objekte](#native) * [Kommentare](#comments) * [Einsprachiger Code](#language) ------------------------------------------------ ## Vorwort Die folgenden Bereiche zeigen einen vertretbaren Style Guide für moderne JavaScript-Entwicklung. Es handelt sich dabei aber nicht etwa um eine Art Vorschrift. Das Wichtigste, was man aber mitnehmen sollte, ist das **Gesetz der Stilkonsistenz**. Egal, welchen Stil du für dein Projekt wählst, er sollte als Regel betrachtet werden. ## Idiomatisches Style Manifest 1. Whitespace - Mische niemals Spaces und Tabs - Bevor du mit einem Projekt beginnst und Code schreibst, entscheide dich zwischen Soft Intends (Spaces) oder echten Tabs. - Für die Lesbarkeit empfehle ich, die Einrückung immer auf die Größe von zwei Zeichen zu setzen. Das bedeutet zwei Spaces repräsentieren einen echten Tab. - Wenn dein Editor die Konfiguration "Steuerzeichen einblenden" unterstützt, solltest du sie einschalten. Das bringt folgende Vorteile mit sich: - Erzwungene Konsistenz - Löschen von Whitespaces am Ende der Zeile - Löschen von leeren "Whitespace Zeilen" - Commits und Diffs sind einfacher zu lesen 2. Schöne Syntax A. Leerzeichen, geschweifte Klammern und Zeilenumbrüche ```javascript // if/else/for/while/try enthalten immer Leerzeichen, geschweifte Klammern // und erstrecken sich über mehrere Zeilen // Das trägt zur Lesbarkeit bei // 2.A.1.1 // Beispiele von echt verkrampfter Syntax if(Bedingung) machWas(); while(Bedingung) iterieren++; for(var i=0;i<100;i++) irgendeineIterativeFunktion(); // 2.A.1.1 // Benutze Whitespaces um die Lesbarkeit zu verbessern if ( Bedingung ) { // statements } while ( Bedingung ) { // statements } for ( var i = 0; i < 100; i++ ) { // statements } // Noch besser: var i, length = 100; for ( i = 0; i < length; i++ ) { // statements } // Oder... var i = 0, length = 100; for ( ; i < length; i++ ) { // statements } var prop; for ( prop in object ) { // statements } if ( true ) { // statements } else { // statements } ``` B. Zuweisungen, Deklarationen, Funktionen (Benamte, Ausdrücke, Kontruktoren) ```javascript // 2.B.1.1 // Variablen var foo = "bar", num = 1, undef; // Literalnotationen: var array = [], object = {}; // 2.B.1.2 // Nur einmal `var` pro Scope (Funktion) zu verwenden, verbessert die Lesbarkeit // und hält deine Deklarationsliste frei von Verwirrungen // Schlecht var foo = ""; var bar = ""; var qux; // Gut var foo = "", bar = "", quux; // Oder.. var // Hier kommentieren foo = "", bar = "", quux; // 2.B.1.3 // var Statements sollten immer an den Anfang ihres respektiven Scopes (Funktion) // Das gleiche gilt für const und let aus ECMAScript 6 // Schlecht function foo() { // irgendwas var bar = "", qux; } // Gut function foo() { var bar = "", qux; // alle Statements nach der var-Deklaration } ``` ```javascript // 2.B.2.1 // Benannte Funktionsdeklaration function foo( arg1, argN ) { } // Benutzung foo( arg1, argN ); // 2.B.2.2 // Benannte Funktionsdeklaration function quadrat(zahl) { return zahl * zahl; } // Benutzung quadrat( 10 ); function quadrat( zahl, callback ) { callback( zahl * zahl); } quadrat( 10, function (square) { // callback Statements }); // 2.B.2.3 // Funktionsausdruck var quadrat = function ( zahl ) { // gibt irgendwas zurück return zahl * zahl; } // Funktionsausdruck mit Bezeichner // Diese Form hat den Vorteil, dass sie sich selbst aufrufen kann // und der Bezeichner im Stack Trace zufinden ist var factorial = function factorial( zahl ) { if ( zahl < 2 ) { return 1; } return zahl * factorial( zahl-1 ); }; // 2.B.2.4 // Konstrukturdeklaration function fooBar ( options) { this.options = options; } // Benutzung var fooBar = new FooBar({ a: "alpha" }); fooBar.options: // { a: "alpha" } ``` C. Ausnahmen, Leichte Abweichungen ```javascript // 2.C.1.1 // Funktionen mit Callbacks foo(function() { // Achte darauf, dass es hier keinen extra Whitespace nach der ersten Klammer gibt }); // Funktionen, die ein Array erwarten, haben keine Whitespaces auf erster Ebene foo([ "alpha", "beta" ]); // 2.C.1.2 // Funktionen, die ein Object erwarten, haben ebenfalls keine Spaces foo({ a: "alpha", b: "beta" }); // Einzelner Stringliteral, kein Space foo("bar"); // Inner gruppierte Klammern, kein Space if ( !("foo" in obj) ) { } ``` D. Konsistenz gewinnt immer In Sektion 2.A-2.C, sieht man den Vorteil durch die Verwendung von Whitespaces, Lesbarkeit und Konsistenz. Es ist immer wichtig darauf zu achten, Formatierung-Vorlieben, wie der Whitespace innerhalb der Klammern, als optional zu betrachten. Trotzdem sollte sich eine Formatierung durch den ganzen Quelltext einheitlich erstrecken. ```javascript // 2.D.1.1 if (Bedingung) { // statements } while (Bedingung) { // statements } for (var i = 0; i < 100; i++) { // statements } if (true) { // statements } else { // statements } ``` E. Anführungszeichen Ob du jetzt einfache oder doppelte Anführungszeichen bevorzugst ist völlig egal. JavaScript parst sie immer gleich. Das Einzige, worauf auf jeden Fall geachtet werden **MUSS**, ist Konsistenz. **Vermische niemals Anführungszeichen innerhalb eines Projekts.** Suche dir einen Stil aus und bleib dabei. F. Zeilenenden und leere Zeilen Whitespaces können diffs ruinieren. Pre-Commit-Hooks können verwendet werden, um End-Of-Line-Whitespaces zu leere Zeilen zu entfernen. 3. Typprüfung A. Primitive Typen String: typeof variable === "string" Number: typeof variable === "number" Boolean: typeof variable === "boolean" Object: typeof variable === "object" Array: Array.isArray( arrayArtigesObjekt ) (wenn möglich) Node: elem.nodeType === 1 null: variable === null null oder undefined: variable == null undefined: Globale Variablen: typeof variable === "undefined" Lokale Variablen: variable === undefined Properties: object.prop === undefined object.hasOwnProperty( prop ) "prop" in object B. Gezwungene Typen Betrachten wir folgende Auswirkungen... Dieses HTML ist gegeben: ```html ``` ```js // 3.B.1.1 // `foo` wurde mit dem Wert `0` deklariert und ist vom Typ `number` var foo = 0; // typeof foo; // "number" ... // Später im Code musst du `foo` mit einem neuen Wert aus dem input-Element überschreiben foo = document.getElementById("foo-input").value; // Wenn du jetzt mit `typeof foo` testen möchtest, wird das Ergebnis `string` sein // Das bedeutet, wenn du Logik hast, die `foo` so testet: if ( foo === 1 ) { wichtigeFunktion(); } // `wichtigeFunktion()` würde niemals ausgeführt werden, selbst wenn `foo` den wert "1" hätte // 3.B.1.2 // Du kannst diese Probleme umgehen, indem du die Typen mit unären - oder + - Operationen erzwingst: foo = +document.getElementById("foo-input").value; // ^ unärer + - Operator konvertiert den rechten Operanden in eine Zahl (Number) // typeof foo; // "number" if ( foo === 1 ) { wichtigeFunktion(); } // `wichtigeFunktion()` würde ausgeführt ``` Hier sind ein paar Fälle in denen Erzwingungen verwendet werden: ```javascript // 3.B.2.1 var number = 1, string = "1", bool = false; number; // 1 number + ""; // "1" string; // "1" +string; // 1 +string++; // 1 string; // 2 bool; // false +bool; // 0 bool + ""; // "false" ``` ```javascript // 3.B.2.2 var number = 1, string = "1", bool = true; string === number; // false string === number + ""; // true +string === number; // true bool === number; // false +bool === number; // true bool === string; // false bool == !!string; // true ``` ```javascript // 3.B.2.3 var array = [ "a", "b", "c" ]; !!~array.indexOf("a"); // true !!~array.indexOf("b"); // true !!~array.indexOf("c"); // true !!~array.indexOf("d"); // false ``` ```javascript // 3.B.2.3 var num = 2.5; parseInt( num, 10 ); // ist das Gleiche wie... ~~num; num >> 0; num >>> 0; // Gibt 2 zurück // Denke daran, dass negative Zahlen anders behandelt werden... var neg = -2.5; parseInt( neg, 10 ); // Ist das Gleiche wie... ~~neg; neg >> 0; // Gibt 2 zurück // Wie dem auch sei... neg >>> 0; // Gibt 4294967294 zurück ``` 4. Bedingte Auswertungen ```javascript //4.1.1 // Wenn du nur prüfen willst, ob ein Array eine Länge hat, ... if ( array.length > 0 ) ... // prüfe es so: if ( array.length ) ... // 4.1.2 // Wenn du nur prüfen willst, ob ein Array leer ist... if ( array.length === 0 ) ... // mach es so: if ( !array.length ) ... // 4.1.3 // Wenn du prüfen willst, ob ein String nich leer ist if ( string !== "" ) ... // ... mach es so: if ( string ) ... // 4.1.4 // Wenn du prüfen willst, ob ein String leer ist... if ( string === "" ) ... // ... mach es so: if ( !string ) ... // 4.1.5 // Wenn du prüfen willst, ob eine Referenz false ist... if ( foo === false ) ... // ... nutze die Negierung um eine eine true-Auswertung zu erzwingen if ( !foo ) ... // ... aber vorsicht, das würde auch bei 0, "", null, undefined und NaN funktionieren // Wenn du für einen boolsches false testen _musst_, mach's so: if ( foo === false ) ... // 4.1.7 // Wenn du eine Referenz prüfen möchtest, die möglicherweise null oder undefined, aber NICHT false ist... if ( foo === null || foo === undefined ) ... // ... nutze den Vorteil der Typerzwingung if ( foo == null ) ... // Denk daran, '==' wird 'null' auf 'null' UND 'undefined' matchen, aber nicht 'false', "" oder 0 null == undefined ``` 5. Praktischer Style ```javascript // 5.1.1 // Ein angewandtes Modul (function( global ) { var Module = (function() { var data = "secret"; return { // Eine boolesche Eigenschaft bool: true, // Ein Stringwert string: "a string", // Eine Array-Eigenschaft array: [ 1, 2, 3, 4 ], // Eine Objekteigenschaft object: { lang: "en-Us" }, getData: function() { // gibt den Wert von data return data; }, setData: function( value ) { // setzt den Wert von data return ( data = value ); } }; })(); // Hier könnten weitere Dinge passieren // Das Modul im globalen Namensraum verfügbar machen global.Module = Module; })( this ); ``` ```javascript // 5.2.1 // Ein angewandter Konstruktor (function( global ) { function Ctor( foo ) { this.foo = foo; return this; } Ctor.prototype.getFoo = function() { return this.foo; }; Ctor.prototype.setFoo = function( val ) { return ( this.foo = val ); }; // Um den Konstruktor ohne `new` aufzurufen, machst du möglicherweise sowas: var ctor = function( foo ) { return new Ctor( foo ); }; // Konstruktor im globalen Namensraum verfügbar machen global.ctor = ctor; })( this ); ``` 6. Bezeichnungen Du bist kein Compiler, also versuch nicht, einer zu sein. Der folgende Code ist ein Beispiel für entsetzlich schlechte Bezeichnungen: ```javascript // 6.1.1 // Beispielcode mit schlechten Bezeichnungen function q(s) { return document.querySelectorAll(s); } var i,a=[],els=q("#foo"); for(i=0;iSonstiges Diese Sektion stellt Ideen und Konzepte dar, die nicht dogmatisch betrachtet werden sollten. Sie sollen fragliche Praktiken fördern, die immer wieder in der JavaScript Programmierung auftauchen. A. `switch` Statements sollten vermieden werden. Es scheint starke Verbesserungen bei der Ausführung von `switch` Statements im neuesten Firefox und Chrome zu geben. http://jsperf.com/switch-vs-object-literal-vs-module https://github.com/rwldrn/idiomatic.js/issues/13 ```javascript // 7.A.1.1 // Ein Beispiel Switch Statement switch( foo ) { case "alpha": alpha(); break; case "beta": beta(); break; default: // Fallback break; } // 7.A.1.2 // Besser sollte man aber ein Objektliteral oder Modul verwenden: var switchObj = { alpha: function() { // statements // a return }, beta: function() { // statements // a return }, _default: function() { // statements // a return } }; var switchModule = (function () { return { alpha: function() { // statements // a return }, beta: function() { // statements // a return }, _default: function() { // statements // a return } }; })(); // 7.A.1.3 // Wenn `foo` eine Eigenschaft von `switchObj` oder `switchModule` ist, führe diesen Code hier aus.. ( Object.hasOwnProperty.call( switchObj, foo ) && switchObj[ foo ] || switchObj._default )( args ); ( Object.hasOwnProperty.call( switchObj, foo ) && switchModule[ foo ] || switchModule._default )( args ); // Wenn du auf die Werte von `foo` vertraust und weißt, was drin ist, // kannst du die ODER-Prüfung weglassen und den Code einfach nur ausführen: switchObj[ foo ]( args ); switchModule[ foo ]( args ); // Dieses Muster sorgt außerdem für Wiederverwendbarkeit von Code ``` B. Frühzeitige Rückgaben sorgen für lesbareren Code mit einem kleinen Performance-Unterschied ```javascript // 7.B.1.1 // Schlecht: function returnLate( foo ) { var ret; if ( foo ) { ret = "foo"; } else { ret = "quux"; } return ret; } // Gut: function returnEarly( foo ) { if ( foo ) { return "foo"; } return "quux"; } ``` 8. Native & Host Objekte Das grundsätzliche Prinzip ist hier: ### Mach keinen Unsinn und alles wird gut. Um das Ganze noch mehr zu stärken, schaue dir folgende Präsentationen an: #### “Everything is Permitted: Extending Built-ins” by Andrew Dupont (JSConf2011, Portland, Oregon) https://www.youtube.com/watch?v=xL3xCO7CLNM 9. Kommentare * Mehrzeilige Kommentare sind gut * Kommentare am Zeilenende sind untersagt! * JSDoc Style Kommentare sind gut, aber erfordern mehr Zeit. 10. Einsprachiger Code Programme sollten in der Sprache geschrieben sein, egal um welche Sprache es sich handelt, die der Projektbetreuer vorgibt. ## Anhang ### Comma First. Jedes Projekt, welches dieses Dokument als grundsätzlichen Style Guide verwendet, akzeptiert keine Comma-First-Formatierung, solange es nicht explizit vom Projektautor angegeben wurde. ---------- Creative Commons License
Grundsätze for das schreiben vonkonsequentem und idiomatischem JavaScript von Rick Waldron und Mitwirkenden ist lizensiert unter Creative Commons Attribution 3.0 Unported License.
Basierend auf einer Arbeit unter github.com/rwldrn/idiomatic.js. ================================================ FILE: translations/es_ES/readme.md ================================================ # Principios para escribir JavaScript consistente e idiomático ## Este es un documento vivo, y nuevas ideas para mejorar el código que nos rodea son siempre bienvenidas. Contribuye: forkea, clona, branchea, commitea, pushea y haz alguna pull request. * Rick Waldron [@rwaldron](http://twitter.com/rwaldron), [github](https://github.com/rwaldron) * Mathias Bynens [@mathias](http://twitter.com/mathias), [github](https://github.com/mathiasbynens) * Schalk Neethling [@ossreleasefeed](http://twitter.com/ossreleasefeed), [github](https://github.com/ossreleasefeed/) * Kit Cambridge [@kitcambridge](http://twitter.com/kitcambridge), [github](https://github.com/kitcambridge) * Raynos [github](https://github.com/Raynos) * Matias Arriola [@MatiasArriola](https://twitter.com/MatiasArriola), [github](https://github.com/MatiasArriola/) * John Fischer [@jfroffice](https://twitter.com/jfroffice), [github](https://github.com/jfroffice/) * Idan Gazit [@idangazit](http://twitter.com/idangazit), [github](https://github.com/idan) * Leo Balter [@leobalter](http://twitter.com/leobalter), [github](https://github.com/leobalter) * Breno Oliveira [@garu_rj](http://twitter.com/garu_rj), [github](https://github.com/garu) * Leo Beto Souza [@leobetosouza](http://twitter.com/leobetosouza), [github](https://github.com/leobetosouza) * Ryuichi Okumura [@okuryu](http://twitter.com/okuryu), [github](https://github.com/okuryu) * Pascal Precht [@PascalPrecht](http://twitter.com/PascalPrecht), [github](https://github.com/pascalprecht) * EngForDev [engfordev](http://www.opentutorials.org/course/167/1363) - Hwan Min Hong / MinTaek Kwon [@leoinsight](http://twitter.com/leoinsight) / Tw Shim [@marocchino](http://twitter.com/marocchino), [github](https://github.com/marocchino) / Nassol Kim [@nassol99](http://twitter.com/nassol99), [github](https://github.com/nassol) / Juntai Park [@rkJun](http://twitter.com/rkJun), [github](https://github.com/rkJun) / Minkyu Shim / Gangmin Won / Justin Yoo [@justinchronicle](http://twitter.com/justinchronicle) / Daeyup Lee * Marco Trulla [@marcotrulla](http://twitter.com/marcotrulla), [github](https://github.com/Ragnarokkr) * Alex Navasardyan [@alexnavasardyan](http://twitter.com/alexnavasardyan), [github](https://github.com/2k00l) * Mihai Paun [@mihaipaun](http://twitter.com/mihaipaun), [github](https://github.com/mihaipaun) * Evgeny Mandrikov [@\_godin\_](http://twitter.com/_godin_), [github](https://github.com/Godin) * Sofish Lin [@sofish](http://twitter.com/sofish), [github](https://github.com/sofish) * Дејан Димић [@dejan_dimic](http://twitter.com/dejan_dimic), [github](https://github.com/rubystream) * Miloš Gavrilović [@gavrisimo](http://twitter.com/gavrisimo), [github](https://github.com/gavrisimo) * Firede [@firede](https://twitter.com/firede) [github](https://github.com/firede) * monkadd [github](https://github.com/monkadd) * Stephan Lindauer [@stephanlindauer](http://twitter.com/stephanlindauer), [github](https://github.com/stephanlindauer) * Thomas P [@dragon5689](https://twitter.com/dragon5689) [github](https://github.com/dragon5689) * Yotam Ofek [@yotamofek](https://twitter.com/yotamofek) [github](https://github.com/yotamofek) * Duc Nguyen [@ducntq](https://twitter.com/ducntq), [github](https://github.com/ducntq) * James Young [@jamsyoung](http://twitter.com/jamsyoung), [github](https://github.com/jamsyoung) * Stephane Moreau [github](https://github.com/stmoreau) * Boris Nekezov [github](https://github.com/boris-nekezov) * Akshat Joshi [@akshat_joshi](http://twitter.com/akshat_joshi), [github](https://https://github.com/akshatjoshii) ## Todo el código en cualquier proyecto debería verse como si una sola persona lo hubiera escrito, sin importar cuánta gente haya contribuído. ### La lista que se presenta a continuación destaca las prácticas que uso en todo el código del que soy autor, y las contribuciones a todos los proyectos que he creado deben seguir estas prácticas. ### No intento imponer mis preferencias de estilo en el código de otras personas; si tienen un algún estilo común, homogéneo, esto debería ser respetado. > ### "Argumentación por sobre el estilo, no tiene sentido. Debería existir una guía de estilo, y tú deberías seguirla" >_Rebecca_ _Murphey_   > ### "Parte de ser un buen colaborador en un proyecto exitoso es darse cuenta que escribir código para uno mismo es una Mala Idea™. Si miles de personas están utilizando tu código, entonces escríbelo para máxima claridad, no tu preferencia personal de cómo ser inteligente aunque dentro de las especificaciones. " >_Idan_ _Gazit_ ## Traducciones * [ORIGINAL](https://github.com/rwldrn/idiomatic.js/) * [Bulgarian](https://github.com/rwldrn/idiomatic.js/tree/master/translations/bg_BG) * [German](https://github.com/rwldrn/idiomatic.js/tree/master/translations/de_DE) * [French](https://github.com/rwldrn/idiomatic.js/tree/master/translations/fr_FR) * [Spanish](https://github.com/rwldrn/idiomatic.js/tree/master/translations/es_ES) * [Portuguese - Brazil](https://github.com/rwldrn/idiomatic.js/tree/master/translations/pt_BR) * [Korean](https://github.com/rwldrn/idiomatic.js/tree/master/translations/ko_KR) * [Japanese](https://github.com/rwldrn/idiomatic.js/tree/master/translations/ja_JP) * [Italian](https://github.com/rwldrn/idiomatic.js/tree/master/translations/it_IT) * [Russian](https://github.com/rwldrn/idiomatic.js/tree/master/translations/ru_RU) * [Romanian](https://github.com/rwldrn/idiomatic.js/tree/master/translations/ro_RO) * [简体中文](https://github.com/rwldrn/idiomatic.js/tree/master/translations/zh_CN) * [Serbian - cyrilic alphabet](https://github.com/rwldrn/idiomatic.js/tree/master/translations/ср_СР) * [Serbian - latin aplphabet](https://github.com/rwldrn/idiomatic.js/tree/master/translations/sr_SR) * [Greek](https://github.com/rwaldron/idiomatic.js/tree/master/translations/gr_GR) * [Hindi](https://github.com/rwaldron/idiomatic.js/tree/master/translations/hi_HI) ## Cosas importantes, no relacionadas directamente con el JS idiomático: ### Calidad de código: herramientas, recursos y referencias * [Plug-in de JavaScript](http://docs.codehaus.org/display/SONAR/JavaScript+Plugin) para [Sonar](http://www.sonarsource.org/) * [Plato](https://github.com/jsoverson/plato) * [jsPerf](http://jsperf.com/) * [jsFiddle](http://jsfiddle.net/) * [jsbin](http://jsbin.com/) * [JavaScript Lint (JSL)](http://javascriptlint.com/) * [jshint](http://jshint.com/) * [jslint](http://jslint.org/) * [Editorconfig](http://editorconfig.org/) ### Conociendo mejor el lenguaje ### [Annotated ECMAScript 5.1](http://es5.github.com/) ### [EcmaScript Language Specification, 5.1 Edition](http://ecma-international.org/ecma-262/5.1/) Los siguientes artículos son 1) incompletos y 2) *OBLIGATORIOS*. No siempre estoy de acuerdo con el estilo escrito por sus autores, pero una cosa es cierta: son consistentes. Además, son autoridades en el lenguaje. * [Baseline For Front End Developers](http://rmurphey.com/blog/2012/04/12/a-baseline-for-front-end-developers/) * [Eloquent JavaScript](http://eloquentjavascript.net/) * [JavaScript, JavaScript](http://javascriptweblog.wordpress.com/) * [Adventures in JavaScript Development](http://rmurphey.com/) * [Perfection Kills](http://perfectionkills.com/) * [Douglas Crockford's Wrrrld Wide Web](http://www.crockford.com) * [JS Assessment](https://github.com/rmurphey/js-assessment) (Todos estos artículos están en inglés) ### Proceso de Build y Deployment Los proyectos deberían tratar de incluir siempre algún mecanismo para que el código pueda ser verificado, comprimido y optimizado para su uso en producción. Para esta tarea, [grunt](https://github.com/gruntjs/grunt) por Ben Alman es la primera en ganar una gran popularidad, y ha reemplazado oficialmente la carpeta "kits/" que había en este repo. ### Testing Los proyectos _deben_ incluir alguna forma de prueba (test unitario, test funcional, etc). Las demos NO CUENTAN como "tests". A continuación, una lista de frameworks para testing, ninguno de los cuales recomiendo más que otro. * [QUnit](https://github.com/jquery/qunit) * [Jasmine](https://github.com/pivotal/jasmine) * [Vows](https://github.com/cloudhead/vows) * [Mocha](https://github.com/visionmedia/mocha) * [Hiro](http://hirojs.com/) * [JsTestDriver](https://code.google.com/p/js-test-driver/) * [Buster.js](http://busterjs.org/) * [Sinon.js](http://sinonjs.org/) ## Tabla de contenidos * [Espacios en blanco](#whitespace) * [Beautiful Syntax](#spacing) * [Comprobación de tipos (Cortesía de la guía de estilo de jQuery)](#type) * [Evaluación condicional](#cond) * [Estilo práctico](#practical) * [Naming](#naming) * [Varios](#misc) * [Native & Host Objects](#native) * [Comentarios](#comments) * [Código en un lenguaje](#language) ------------------------------------------------ ## Prólogo Las siguientes secciones delinean una guía de estilos _razonable_ para un desarrollo moderno de JavaScript, y no intentan ser prescriptivas. Lo más importante es la **ley de consistencia de estilo de código**. Cualquiera sea el estilo que escojas para tu proyecto debería ser considerado ley. Piensa en este documento como una declaración del compromiso para con la consistencia de estilo, legibilidad y mantenibilidad. ## Manifiesto de estilo idiomático 1. Espacios en blanco - Nunca mezclar espacios y tabulaciones. - Al comenzar un proyecto, antes de escribir código, escoger entre indentación blanda (espacios), o tabulaciones — Esto es **LEY**. - Para mayor legibilidad, siempre recomiendo ajustar las preferencias de tu editor para que el tamaño de la indentación sea de dos caracteres — esto significa, usar dos espacios, o que dos espacios representen una tabulación. - Si tu editor lo soporta, trabajar siempre con la preferencia activada para que se muestren los caracteres invisibles. Los beneficios de esta práctica son: - Reforzar la consistencia. - Eliminar el espacio en blanco del fin de línea. - Eliminar los espacios en blanco de las líneas vacías. - Commits y diffs más fáciles de leer. 2. Sintaxis elegante A. Paréntesis, Llaves, Fines de línea ```javascript // if/else/for/while/try siempre tienen espacios y se extienden a múltiples líneas // Esto mejora la legibilidad // 2.A.1.1 // Ejemplos de sintaxis toda comprimida if(condition) doSomething(); while(condition) iterating++; for(var i=0;i<100;i++) someIterativeFn(); // 2.A.1.1 // Uso de espacios para mejorar la legibilidad if ( condition ) { // statements } while ( condition ) { // statements } for ( var i = 0; i < 100; i++ ) { // statements } // Aún mejor: var i, length = 100; for ( i = 0; i < length; i++ ) { // statements } // O... var i = 0, length = 100; for ( ; i < length; i++ ) { // statements } var prop; for ( prop in object ) { // statements } if ( true ) { // statements } else { // statements } ``` B. Asignaciones, Declaraciones, Funciones (Nombradas, Expresiones, Constructores) ```javascript // 2.B.1.1 // Variables var foo = "bar", num = 1, undef; // Notaciones literales: var array = [], object = {}; // 2.B.1.2 // Usando solo una instancia de `var` por scope (o sea, dentro de la función), mejora la legibilidad // y mantiene tu lista de declaraciones claras (también ahorra de tipear un poco más) // Mal var foo = ""; var bar = ""; var qux; // Bien var foo = "", bar = "", quux; // o.. var // comentar en éstos foo = "", bar = "", quux; // 2.B.1.3 // sentencias `var` deberían estar siempre al principio de su respectivo scope (alcance), que sería la función. // Mal function foo() { // algunas sentencias var bar = "", qux; } // Bien function foo() { var bar = "", qux; // todas las sentencias luego de la declaración de variables. } // 2.B.1.4 // const y let, de ECMAScript 6, de la misma manera deberían aparecer al principio de su scope (alcance), que sería el bloque. // Mal function foo() { let foo, bar; if (condition) { bar = ""; // sentencias } } // Bien function foo() { let foo; if (condition) { let bar = ""; // sentencias } } ``` ```javascript // 2.B.2.1 // Declaración De Función Nombrada function foo( arg1, argN ) { } // Uso foo( arg1, argN ); // 2.B.2.2 // Declaración De Función Nombrada function square( number ) { return number * number; } // Uso square( 10 ); // Really contrived continuation passing style function square( number, callback ) { callback( number * number ); } square( 10, function( square ) { // callback statements }); // 2.B.2.3 // Expresión de función var square = function( number ) { // Retornar algo relevante y con valor agregado return number * number; }; // Expresión de función con identificador // Esta forma es preferida porque tiene el valor agregado de // poder ser llamada a sí misma y ser identificable en el seguimiento de la pila (MUY útil para debugging): var factorial = function factorial( number ) { if ( number < 2 ) { return 1; } return number * factorial( number-1 ); }; // 2.B.2.4 // Declaración de Constructor function FooBar( options ) { this.options = options; } // Uso var fooBar = new FooBar({ a: "alpha" }); fooBar.options; // { a: "alpha" } ``` C. Algunas excepciones ```javascript // 2.C.1.1 // Funciones con callbacks foo(function() { // Como se ve, no hay espacio entre el primer paréntesis // y la palabra "function" }); // Función que acepta un Array como parámetro, sin espacio entre ([ foo([ "alpha", "beta" ]); // 2.C.1.2 // Función que acepta un objeto, sin espacio foo({ a: "alpha", b: "beta" }); // Argumento único de tipo string, sin espacio foo("bar"); // Grupo de paréntesis dentro de paréntesis, sin espacio if ( !("foo" in obj) ) { } ``` D. La consistencia siempre gana En las secciones 2.A-2.C, las reglas para los espacios son puestas con un objetivo más simple y con un propósito más general: consistencia. Es importante destacar que algunas preferencias de formato, deberían ser consideradas opcionales, pero solo un estilo debería existir a través de todo el código fuente de tu proyecto. ```javascript // 2.D.1.1 if (condition) { // sentencias } while (condition) { // sentencias } for (var i = 0; i < 100; i++) { // sentencias } if (true) { // sentencias } else { // sentencias } ``` E. Comillas Si prefieres comillas simples o dobles no debería importar, no hay diferencias ya que JavaScript las parsea. Lo que **ABSOLUTAMENTE DEBE** ser cumplido es la consistencia. **Nunca mezclar comillas en el mismo proyecto. Elegir un estilo y cumplirlo a rajatabla.** F. Fin de línea y líneas vacías Espacios en blanco pueden arruinar diffs y hacer los cambios imposibles de leer. Considera agregar algún mecanismo para remover automáticamente los espacios que se encuentran al final de la línea o en líneas vacías. 3. Verificación de tipos (Cortesía de la guía de estilo de jQuery) A. Tipos String: typeof variable === "string" Number: typeof variable === "number" Boolean: typeof variable === "boolean" Object: typeof variable === "object" Array: Array.isArray( arrayLikeObject ) (cuando sea posible / hay implementaciones que no tienen esta función) Node: elem.nodeType === 1 null: variable === null null o undefined: variable == null undefined: Variables globales: typeof variable === "undefined" Variables locales: variable === undefined Propiedades: object.prop === undefined object.hasOwnProperty( prop ) "prop" in object B. Conversiones implícitas de tipos Considera lo que causaría lo siguiente... Dado este HTML: ```html ``` ```javascript // 3.B.1.1 // `foo` ha sido declarado con el valor `0` y su tipo es `number` var foo = 0; // typeof foo; // "number" ... // En algún lugar, más tarde en tu código, necesitas modificar `foo` // con un nuevo valor derivado del elemento input del HTML foo = document.getElementById("foo-input").value; // Si vas a testear `typeof foo` ahora, el resultado sería `string` // Esto significa que si hubieras tenido lógica que comparar `foo` así: if ( foo === 1 ) { importantTask(); } // `importantTask()` nunca habría sido evaluada, incluso con `foo` teniendo un valor de "1" // 3.B.1.2 // Te puedes adelantar a los problemas, usando conversión de tipos con los operadores unarios + o - : foo = +document.getElementById("foo-input").value; // ^ el operador unario + va a convertir su operando derecho a number // typeof foo; // "number" if ( foo === 1 ) { importantTask(); } // `importantTask()` va a ser llamada ``` Aquí hay algunos casos comunes de conversiones implícitas: ```javascript // 3.B.2.1 var number = 1, string = "1", bool = false; number; // 1 number + ""; // "1" string; // "1" +string; // 1 +string++; // 1 string; // 2 bool; // false +bool; // 0 bool + ""; // "false" ``` ```javascript // 3.B.2.2 var number = 1, string = "1", bool = true; string === number; // false string === number + ""; // true +string === number; // true bool === number; // false +bool === number; // true bool === string; // false bool === !!string; // true ``` ```javascript // 3.B.2.3 var array = [ "a", "b", "c" ]; !!~array.indexOf( "a" ); // true !!~array.indexOf( "b" ); // true !!~array.indexOf( "c" ); // true !!~array.indexOf( "d" ); // false // Nótese que el ejemplo anterior debería ser considerado "innecesariamente inteligente" // Prefiérase el método obvio de comparar el valor retornado de // indexOf, como en: if ( array.indexOf( "a" ) >= 0 ) { // ... } ``` ```javascript // 3.B.2.4 var num = 2.5; parseInt( num, 10 ); // es lo mismo que... ~~num; num >> 0; num >>> 0; // Todos resultan en 2 // Tener en cuenta que los números negativos serán tratados de otra manera... var neg = -2.5; parseInt( neg, 10 ); // es lo mismo que... ~~neg; neg >> 0; // Todos resultan en -2 // Sin embargo... neg >>> 0; // Va a resultar en 4294967294 ``` 4. Evaluación condicional ```javascript // 4.1.1 // Cuando evaluamos para saber si un array tiene algún elemento, // en lugar de hacer esto: if ( array.length > 0 ) ... // ...evaluar por el valor de verdad de la expresión, como en este caso: if ( array.length ) ... // 4.1.2 // Cuando solo evaluamos que un array está vacío, // en lugar de esto: if ( array.length === 0 ) ... // ...evaluar el valor de verdad de la expresión: if ( !array.length ) ... // 4.1.3 // Cuando evaluamos que un string no es vacío, // en vez de hacer esto: if ( string !== "" ) ... // ...evaluar el valor de verdad de la expresión: if ( string ) ... // 4.1.4 // Cuando evaluamos si un string es vacío, // en lugar de: if ( string === "" ) ... // ...evaluar la expresión por falso, como aquí: if ( !string ) ... // 4.1.5 // Cuando evaluamos si una variable es true, // en lugar de esto: if ( foo === true ) ... // ...expresar directamente de la siguiente manera: if ( foo ) ... // 4.1.6 // Cuando evaluamos si una variable es false, // en vez de: if ( foo === false ) ... // ...usar negación y expresar de esta manera if ( !foo ) ... // ...Tener cuidado, porque la anterior expresión va a ser true también para: 0, "", null, undefined, NaN // si se _DEBE_ testear por el valor false únicamente, utilizar el === if ( foo === false ) ... // 4.1.7 // Cuando solamente se está evaluando una referencia que puede ser null o undefined, pero NO false, "" or 0, // en lugar de: if ( foo === null || foo === undefined ) ... // ...tomar ventaja del uso del operador ==: if ( foo == null ) ... // Recuerda, usar == va a comparar `null` con AMBOS `null` y `undefined` // pero no `false`, "" o 0 null == undefined ``` SIEMPRE evaluar por el mejor, por el resultado más preciso - lo de arriba es sólo una guía, no un dogma. ```javascript // 4.2.1 // Sobre los tipos y evaluación de expresiones Preferir `===` sobre `==` (a menos que el caso particular requiera una evaluación no fuertemente tipada) === no genera coerción de tipos, lo que significa que: "1" === 1; // false == genera coerción de tipos, lo que significa que: "1" == 1; // true // 4.2.2 // Booleanos, Verdaderos y Falsos //Booleanos: true, false //Verdaderos: "foo", 1 //Falsos: "", 0, null, undefined, NaN, void 0 ``` 5. Estilo práctico ```javascript // 5.1.1 // Un módulo práctico (function( global ) { var Module = (function() { var data = "secret"; return { // Esta es una propiedad booleana bool: true, // Algún valor string string: "a string", // Una propiedad Array array: [ 1, 2, 3, 4 ], // Una propiedad objeto object: { lang: "es-AR" }, getData: function() { // Obtener el valor de `data` return data; }, setData: function( value ) { // asigna el valor de `data` y lo retorna return ( data = value ); } }; })(); // Otras cosas podrían pasar aquí // Exponer nuestro módulo al módulo global global.Module = Module; })( this ); ``` ```javascript // 5.2.1 // Un constructor práctico (function( global ) { function Ctor( foo ) { this.foo = foo; return this; } Ctor.prototype.getFoo = function() { return this.foo; }; Ctor.prototype.setFoo = function( val ) { return ( this.foo = val ); }; // para llamar al constructor sin usar `new`, se podría hacer de la siguiente manera: var ctor = function( foo ) { return new Ctor( foo ); }; // Exponer nuestro constructor al objeto global global.ctor = ctor; })( this ); ``` 6. Naming Si no eres un compilador/compresor humano de código, no te esfuerces por serlo. A continuación ejemplos "tristes" de nombramiento de variables ```javascript // 6.1.1 // Ejemplo de código con nombres de variables pobres / poco descriptivos function q(s) { return document.querySelectorAll(s); } var i,a=[],els=q("#foo"); for(i=0;iVarios Esta sección servirá para describir ideas y conceptos que no deberían ser considerados dogmas, pero existen para alentar a cuestionarse prácticas, en un intento para encontrar mejores maneras de llevar a cabo tareas comunes de programación en JavaScript. A. El uso de `switch` debería ser evitado, ya que los métodos modernos de tracing marcarán como negativas las funciones que contengan sentencias `switch`. Parecen haber mejoras drásticas en la ejecución de sentencias `switch` en las últimas versiones de Firefox y Chrome. http://jsperf.com/switch-vs-object-literal-vs-module Mejoras destacables pueden ser vistas aquí también: https://github.com/rwldrn/idiomatic.js/issues/13 ```javascript // 7.A.1.1 // Ejemplo de una sentencia switch switch( foo ) { case "alpha": alpha(); break; case "beta": beta(); break; default: // hacer algo por defecto break; } // 7.A.1.2 // Una manera alternativa que soporta componibilidad y reusabilidad es // usar un objeto para guardar "cases" y una función para delegar: var cases, delegator; // returns de ejemplo sólo para demostración. cases = { alpha: function() { // sentencias // un return return [ "Alpha", arguments.length ]; }, beta: function() { // sentencias // un return return [ "Beta", arguments.length ]; }, _default: function() { // sentencias // un return return [ "Default", arguments.length ]; } }; delegator = function() { var args, key, delegate; // Transforma la lista de argumentos en un array args = [].slice.call( arguments ); // Obtiene la llave del "case" del array key = args.shift(); // Asigna el handler por defecto para el "case" delegate = cases._default; // Deriva el método a la operación delegada if ( cases.hasOwnProperty( key ) ) { delegate = cases[ key ]; } // El argumento de alcance podría ser asignado a algo específico, // en este caso, |null| va a ser suficiente return delegate.apply( null, args ); }; // 7.A.1.3 // Poner la API de 7.A.1.2 a trabajar: delegator( "alpha", 1, 2, 3, 4, 5 ); // [ "Alpha", 5 ] // Por supuesto, el argumento de la llave del `case` podría ser // basado en alguna otra condición arbitraria. var caseKey, someUserInput; // Possibly some kind of form input? someUserInput = 9; if ( someUserInput > 10 ) { caseKey = "alpha"; } else { caseKey = "beta"; } // o... caseKey = someUserInput > 10 ? "alpha" : "beta"; // Y luego... delegator( caseKey, someUserInput ); // [ "Beta", 1 ] // Y por supuesto... delegator(); // [ "Default", 0 ] ``` B. Hacer un return temprano mejora la legibilidad del código y no tiene un impacto significativo en el rendimiento ```javascript // 7.B.1.1 // Mal: function returnLate( foo ) { var ret; if ( foo ) { ret = "foo"; } else { ret = "quux"; } return ret; } // Bien: function returnEarly( foo ) { if ( foo ) { return "foo"; } return "quux"; } ``` 8. Native & Host Objects El principio fundamental aquí es: ### No hagas cosas estúpidas y todo irá bien. Para reforzar este concepto, mirar esta presentación: #### “Everything is Permitted: Extending Built-ins” by Andrew Dupont (JSConf2011, Portland, Oregon) - recomendada! [Andrew Dupont: Everything is Permitted: Extending Built-ins](https://www.youtube.com/watch?v=xL3xCO7CLNM) 9. Comentarios #### Comentar en la línea que está justo arriba del código del que se está hablando #### Comentarios en múltiples líneas son buenos #### Comentarios en el fin de línea están prohibidos! #### El estilo de JSDoc es bueno, pero requiere una inversión de tiempo significativa 10. Código en un lenguaje Los programas deberían ser escritos en un lenguaje, cualquiera sea, como sea impuesto por el mantenedor o mantenedores. ## Apéndice ### Coma Primero. Cualquier proyecto que cite este documento como una guía para estilo no va a aceptar formateo de código con "coma primero", a menos que sea explícitamente especificado por el autor de ese proyecto. ---------- Creative Commons License
Principles of Writing Consistent, Idiomatic JavaScript by Rick Waldron and Contributors is licensed under a Creative Commons Attribution 3.0 Unported License.
Based on a work at github.com/rwldrn/idiomatic.js. ================================================ FILE: translations/fr_FR/readme.md ================================================ # Principes d'écriture d'un code JavaScript cohérent et idiomatique ## Il s'agit d'un document vivant, les nouvelles idées pour améliorer le code autour de nous sont toujours les bienvenues. Pour contribuer : "fork", "clone", "branch", "commit", "push", "pull request". * Rick Waldron [@rwaldron](http://twitter.com/rwaldron), [github](https://github.com/rwaldron) * Mathias Bynens [@mathias](http://twitter.com/mathias), [github](https://github.com/mathiasbynens) * Schalk Neethling [@ossreleasefeed](http://twitter.com/ossreleasefeed), [github](https://github.com/ossreleasefeed/) * Kit Cambridge [@kitcambridge](http://twitter.com/kitcambridge), [github](https://github.com/kitcambridge) * Raynos [github](https://github.com/Raynos) * Matias Arriola [@MatiasArriola](https://twitter.com/MatiasArriola), [github](https://github.com/MatiasArriola/) * John Fischer [@jfroffice](https://twitter.com/jfroffice), [github](https://github.com/jfroffice/) * Idan Gazit [@idangazit](http://twitter.com/idangazit), [github](https://github.com/idangazit) * Leo Balter [@leobalter](http://twitter.com/leobalter), [github](https://github.com/leobalter) * Breno Oliveira [@garu_rj](http://twitter.com/garu_rj), [github](https://github.com/garu) * Leo Beto Souza [@leobetosouza](http://twitter.com/leobetosouza), [github](https://github.com/leobetosouza) * Ryuichi Okumura [@okuryu](http://twitter.com/okuryu), [github](https://github.com/okuryu) * Pascal Precht [@PascalPrecht](http://twitter.com/PascalPrecht), [github](https://github.com/pascalprecht) * EngForDev [engfordev](http://www.opentutorials.org/course/167/1363) - Hwan Min Hong / MinTaek Kwon [@leoinsight](http://twitter.com/leoinsight) / Tw Shim [@marocchino](http://twitter.com/marocchino), [github](https://github.com/marocchino) / Nassol Kim [@nassol99](http://twitter.com/nassol99), [github](https://github.com/nassol) / Juntai Park [@rkJun](http://twitter.com/rkJun), [github](https://github.com/rkJun) / Minkyu Shim / Gangmin Won / Justin Yoo [@justinchronicle](http://twitter.com/justinchronicle) / Daeyup Lee * Marco Trulla [@marcotrulla](http://twitter.com/marcotrulla), [github](https://github.com/Ragnarokkr) * Alex Navasardyan [@alexnavasardyan](http://twitter.com/alexnavasardyan), [github](https://github.com/2k00l) * Mihai Paun [@mihaipaun](http://twitter.com/mihaipaun), [github](https://github.com/mihaipaun) * Evgeny Mandrikov [@\_godin\_](http://twitter.com/_godin_), [github](https://github.com/Godin) * Sofish Lin [@sofish](http://twitter.com/sofish), [github](https://github.com/sofish) * Дејан Димић [@dejan_dimic](http://twitter.com/dejan_dimic), [github](https://github.com/rubystream) * Miloš Gavrilović [@gavrisimo](http://twitter.com/gavrisimo), [github](https://github.com/gavrisimo) * Duc Nguyen [@ducntq](https://twitter.com/ducntq), [github](https://github.com/ducntq) * James Young [@jamsyoung](http://twitter.com/jamsyoung), [github](https://github.com/jamsyoung) * Stephane Moreau [github](https://github.com/stmoreau) * Boris Nekezov [github](https://github.com/boris-nekezov) * Akshat Joshi [@akshat_joshi](http://twitter.com/akshat_joshi), [github](https://https://github.com/akshatjoshii) ## Tout code, peu importe les bases sur lesquelles il est établi, devrait ressembler au code tapé par une seule personne, peu importe le nombre de personnes ayant contribué. ### La liste suivante donne un aperçu des pratiques que j'utilise dans tout le code dont je suis l'auteur. Les contributions aux projets dont je suis l'auteur doivent suivre ces lignes directrices. ### Je n'ai pas l'intention d'imposer mes préférences de style sur le code d'autres personnes. Si elles ont un style commun, dans ce cas, il est important de respecter le style de chacun. > "Il est essentiel de réaliser que pour la réussite d'un projet, un bon intervenant ne doit pas coder pour soi-même mais pour les autres. Si un millier de personnes doivent utiliser votre code, écrivez-le avec un maximum de clarté, non pour des préférences personnelles, mais pour être au plus près du besoin." - Idan Gazit ## Traductions * [ORIGINAL](https://github.com/rwldrn/idiomatic.js/) * [Bulgarian](https://github.com/rwldrn/idiomatic.js/tree/master/translations/bg_BG) * [German](https://github.com/rwldrn/idiomatic.js/tree/master/translations/de_DE) * [French](https://github.com/rwldrn/idiomatic.js/tree/master/translations/fr_FR) * [Spanish](https://github.com/rwldrn/idiomatic.js/tree/master/translations/es_ES) * [Portuguese - Brazil](https://github.com/rwldrn/idiomatic.js/tree/master/translations/pt_BR) * [Korean](https://github.com/rwldrn/idiomatic.js/tree/master/translations/ko_KR) * [Japanese](https://github.com/rwldrn/idiomatic.js/tree/master/translations/ja_JP) * [Italian](https://github.com/rwldrn/idiomatic.js/tree/master/translations/it_IT) * [Russian](https://github.com/rwldrn/idiomatic.js/tree/master/translations/ru_RU) * [Romanian](https://github.com/rwldrn/idiomatic.js/tree/master/translations/ro_RO) * [简体中文](https://github.com/rwldrn/idiomatic.js/tree/master/translations/zh_CN) * [Serbian - cyrilic alphabet](https://github.com/rwldrn/idiomatic.js/tree/master/translations/ср_СР) * [Serbian - latin aplphabet](https://github.com/rwldrn/idiomatic.js/tree/master/translations/sr_SR) * [Greek](https://github.com/rwaldron/idiomatic.js/tree/master/translations/gr_GR) * [Hindi](https://github.com/rwaldron/idiomatic.js/tree/master/translations/hi_HI) ## Important, aspect non idiomatique : ### Qualité du Code : indispensables, ressources et références * [JavaScript Plugin](http://docs.codehaus.org/display/SONAR/JavaScript+Plugin) for [Sonar](http://www.sonarsource.org/) * [Plato](https://github.com/jsoverson/plato) * [jsPerf](http://jsperf.com/) * [jsFiddle](http://jsfiddle.net/) * [jsbin](http://jsbin.com/) * [JavaScript Lint (JSL)](http://javascriptlint.com/) * [jshint](http://jshint.com/) * [jslint](http://jslint.org/) * [Editorconfig](http://editorconfig.org/) [Optimisation des outils de qualité de code par Anton Kovalyov](http://anton.kovalyov.net/slides/gothamjs/) ### Soyez cohérent [http://es5.github.com/](http://es5.github.com/) Ce qui suit doit être considéré comme 1) __incomplet__, et comme une 2) __LECTURE OBLIGATOIRE__. Je ne suis pas toujours d'accord avec le style écrit par les auteurs ci-dessous, mais une chose est certaine : ils sont conformes. En outre, ce sont des autorités sur le langage. * [Eloquent JavaScript](http://eloquentjavascript.net/) * [JavaScript, JavaScript](http://javascriptweblog.wordpress.com/) * [Rebecca Murphey](http://www.rebeccamurphey.com/) or [Adventures in JavaScript Development](http://rmurphey.com/) * [Perfection Kills](http://perfectionkills.com/) * [Douglas Crockford's Wrrrld Wide Web](http://www.crockford.com) ### Processus de "build" et de déploiement Les projets doivent toujours tenter d'inclure des moyens de vérifier le code implémenté avec Lint, tester et minifier les fichiers afin d'avoir de meilleures performances en production. Pour cette tâche, [Grunt](https://github.com/cowboy/grunt) maintenu par Ben Alman rassemble les bonnes pratiques, que nous soutenons dans notre projet. ### Testabilité Les projets _doivent_ inclure certaines formes de test unitaire : tests d'implémentation et de périmètre fonctionnel. Utiliser des démos de cas d'utilisation NE SONT PAS des "tests". Ce qui suit est une liste de bibliothèques de test, aucune d'entre elles n'est approuvée plus que l'autre. * [QUnit](http://github.com/jquery/qunit) * [Jasmine](https://github.com/pivotal/jasmine) * [Vows](https://github.com/cloudhead/vows) * [Mocha](https://github.com/visionmedia/mocha) * [Hiro](http://hirojs.com/) * [JsTestDriver](https://code.google.com/p/js-test-driver/) ## Table des matières * [Les Espaces](#whitespace) * [Une Syntaxe Précise](#spacing) * [Vérification de Type (Courtesy jQuery Core Style Guidelines)](#type) * [Tests Conditionnels](#cond) * [Style Pratique](#practical) * [Règles de nommage](#naming) * [Divers](#misc) * [Native & Host Objects](#native) * [Commentaires](#comments) * [Un code, un langage](#language) ------------------------------------------------ ## Préface Les sections suivantes décrivent un guide de style _raisonable_ pour tout développement moderne en JavaScript et ne sont pas censées être normatives. Le plus important à appliquer est la **loi de cohérence dans le style de code**. Le style que vous avez choisi pour votre projet, quel qu'il soit, doit être considéré comme la loi. Référer à ce document pour afficher l'engagement de votre projet à utiliser un style de code cohérent, lisible et maintenable. ## Manifeste : style idiomatique 1. Les Espaces - Ne jamais mélanger les espaces et les tabulations. - Avant d'écrire le moindre code en début de projet, vous devez choisir entre l'indentation par espace ou par tabulation. C'est une règle. - Pour la lisibilité, paramétrez votre éditeur avec une indentation de deux caractères — ce qui veut dire deux espaces ou une tabulation représentant deux espaces. - Si votre éditeur le supporte, travaillez toujours avec le mode "afficher les caractères invisibles" actif. Les avantages de cette pratique sont : - Améliorer la cohérence du code - Éliminer les espaces de fin de ligne - Éliminer les espaces utilisées pour des lignes blanches - Améliorer la lisibilité de vos "commit" et des "diff" 2. Une Syntaxe Précise A. Parenthèses, Accolades, Sauts de ligne ```javascript // if/else/for/while/try ont toujours des espaces, des parenthèses et plusieurs sauts de ligne // cela améliore la lisibilité // 2.A.1.1 // Exemples de mauvaises pratiques if(condition) doSomething(); while(condition) iterating++; for(var i=0;i<100;i++) someIterativeFn(); // 2.A.1.1 // Utilisez les espaces afin d'améliorer la lisibilité if ( condition ) { // déclarations } while ( condition ) { // déclarations } for ( var i = 0; i < 100; i++ ) { // déclarations } // même mieux : var i, length = 100; for ( i = 0; i < length; i++ ) { // déclarations } // Ou... var i = 0, length = 100; for ( ; i < length; i++ ) { // déclarations } var prop; for ( prop in object ) { // déclarations } if ( true ) { // déclarations } else { // déclarations } ``` B. Déclaration, Affectation, Fonction ( Nommage, Expression, Constructeur ) ```javascript // 2.B.1.1 // Variables var foo = "bar", num = 1, undef; // Notations littérales : var array = [], object = {}; // 2.B.1.2 // Utiliser une unique déclaration `var` par portée de (fonction) améliore la // lisibilité et permet de garder une déclaration séparée du corps de la fonction // (en adéquation avec la portée des variables JS) // Mauvais var foo = ""; var bar = ""; var qux; // Correct var foo = "", bar = "", quux; // ou.. var // donnez votre avis foo = "", bar = "", quux; // 2.B.1.3 // La déclaration des variables 'var' doit toujours être au début de la portée de chaque fonction. // Le même principe s'applique au 'const' défini dans ECMAScript 6. // Mauvais function foo() { // déclarations var bar = "", qux; } // Correcte function foo() { var bar = "", qux; // toutes les autres déclarations sont après la déclaration des variables. } ``` ```javascript // 2.B.2.1 // Déclaration de fonction nommée function foo( arg1, argN ) { } // Utilisation foo( arg1, argN ); // 2.B.2.2 // Déclaration de fonction nommée function square( number ) { return number * number; } // Utilisation square( 10 ); // Passage d'une callback par variable nommée function square( number, callback ) { callback( number * number ); } square( 10, function( square ) { // déclaration de la callback }); // 2.B.2.3 // Expression de fonction var square = function( number ) { // Renvoie quelque chose de pertinent return number * number; }; // Expression de fonction avec un identifiant // Cette forme préférée a pour valeur ajoutée d'être en mesure de se faire appeler // et d'avoir une identité dans les traces de pile var factorial = function factorial( number ) { if ( number < 2 ) { return 1; } return number * factorial( number-1 ); }; // 2.B.2.4 // Déclaration de Constructeur function FooBar( options ) { this.options = options; } // Utilisation var fooBar = new FooBar({ a: "alpha" }); fooBar.options; // { a: "alpha" } ``` C. Exceptions et légères différences ```javascript // 2.C.1.1 // Fonctions avec 'callbacks' foo(function() { // remarque : il n'y a pas d'espace supplémentaire entre la première parenthèse // d'exécution de la fonction appelée et le mot réservé "function" }); // Fonction acceptant un tableau, sans espace foo([ "alpha", "beta" ]); // 2.C.1.2 // Fonction acceptant un objet, sans espace foo({ a: "alpha", b: "beta" }); // Regroupement de déclaration à l'intérieur de parenthèse, sans espace if ( !("foo" in obj) ) { } ``` D. La cohérence gagne toujours Dans les sections 2.A-2.C, les règles d'espacement sont énoncées sous forme de recommandation avec un objectif simple et plus abouti : la cohérence. Il est important de noter que les préférences de formatage, telles que les "espaces situées à l'intérieur de déclaration", doivent être considérées comme optionnelles. Un _unique style_ doit exister pour toutes les sources d'un projet. ```javascript // 2.D.1.1 if (condition) { // déclarations } while (condition) { // déclarations } for (var i = 0; i < 100; i++) { // déclarations } if (true) { // déclarations } else { // déclarations } ``` E. Fin de ligne et lignes vides Les espaces peuvent anéantir la lisibilité de vos "diffs". Considérez que la suppression des espaces et des espaces en fin de ligne doit être effectuée __automatiquement__ avant chaque "commit". 3. Vérification de Type (Courtesy jQuery Core Style Guidelines) 3.A Types réels * String : `typeof variable === "string"` * Number : `typeof variable === "number"` * Boolean : `typeof variable === "boolean"` * Object : `typeof variable === "object"` * Array : `Array.isArray(arrayObject)` (dans la mesure du possible) * null : `variable === null` * null ou undefined : `variable == null` * undefined : * Variable globale : * `typeof variable === "undefined"` * Variable locale : * `variable === undefined` * Propriétés : * `object.prop === undefined` * `object.hasOwnProperty( prop )` * `"prop" in object` JavaScript est un langage typé dynamiquement - ce qui peut être votre meilleur ami comme votre pire ennemi : respectez donc les 'types', en appliquant les règles ci-dessus. 3.B Conversion de type Considérons les implications de ce qui suit... Etant donné ce code HTML : ```html ``` ```js // 3.B.1.1 // `foo` a été déclaré avec la valeur `0` et son type est `number` var foo = 0; // typeof foo; // "number" ... // Quelque part plus loin dans votre code, vous devez mettre jour `foo` // avec une nouvelle valeur issue de l'élément 'input' foo = document.getElementById("foo-input").value; // Si vous deviez tester `typeof foo` maintenant, le résultat serait "string" // Cela signifie que si vous aviez la logique testant `foo` comme suit : if ( foo === 1 ) { important(); } // `important()` ne serait jamais évalué, même si `foo` a une valeur de "1" // 3.B.1.2 // Vous pouvez vous prémunir de ce problème en utilisant la conversion de type avec l'opérateur unaire + ou - : foo = +document.getElementById("foo-input").value; ^ opérateur unaire + convertissant à sa droite l'opérande en "number" // typeof foo; // "number" if ( foo === 1 ) { important(); } // `important()` sera évalué ``` Voici quelques cas courants de conversion : ```javascript // 3.B.2.1 var number = 1, string = "1", bool = false; number; // 1 number + ""; // "1" string; // "1" +string; // 1 +string++; // 1 string; // 2 bool; // false +bool; // 0 bool + ""; // "false" ``` ```javascript // 3.B.2.2 var number = 1, string = "1", bool = true; string === number; // false string === number + ""; // true +string === number; // true bool === number; // false +bool === number; // true bool === string; // false bool === !!string; // true ``` ```javascript // 3.B.2.3 var array = [ "a", "b", "c" ]; !!~array.indexOf( "a" ); // true !!~array.indexOf( "b" ); // true !!~array.indexOf( "c" ); // true !!~array.indexOf( "d" ); // false var num = 2.5; parseInt( num, 10 ); // identique à... ~~num; ``` 4. Tests Conditionnels ```javascript // 4.1.1 // Lorsque vous évaluez que la taille d'un tableau est non nulle, // Plutôt que d'utiliser l'expression suivante : if ( array.length > 0 ) ... // ...préférez : if ( array.length ) ... // 4.1.2 // A l'inverse, lorsque vous évaluez si un tableau est vide, // Plutôt que d'utiliser l'expression suivante : if ( array.length === 0 ) ... // ...préférez : if ( !array.length ) ... // 4.1.3 // Lorsque vous évaluez si une chaîne est non vide, // Plutôt que d'utiliser l'expression suivante : if ( string !== "" ) ... // ...préférez : if ( string ) ... // 4.1.4 // A l'inverse, lorsque vous évaluez si une chaîne est vide, // Plutôt que d'utiliser l'expression suivante : if ( string === "" ) ... // ...préférez : if ( !string ) ... // 4.1.5 // Lorsque vous évaluez si une référence est vraie, // Plutôt que d'utiliser l'expression suivante : if ( foo === true ) ... // ...évaluez ce que cela signifie et bénéficiez des tests primitifs : if ( foo ) ... // 4.1.6 // Lorsque vous évaluez si une référence est fausse, // Plutôt que d'utiliser l'expression suivante : if ( foo === false ) ... // ...utilisez la négation et la conversion de l'évaluation de la vérité : if ( !foo ) ... // ...Soyez prudent, cela correspondra aux valeurs suivantes : 0, "", null, undefined, NaN // Vous _DEVEZ_ dans ce cas tester la valeur `faux`, comme suit : if ( foo === false ) ... // 4.1.7 // Lorsque vous évaluez une référence et seulement une référence qui peut être null ou undefined, mais NOT fausse, "" ou 0, // Plutôt que d'utiliser l'expression suivante : if ( foo === null || foo === undefined ) ... // ...bénéficiez de la conversion de type ==, comme suit : if ( foo == null ) ... // Souvenez-vous, utiliser == vérifiera une égalité avec `null` et `null` & `undefined` // mais pas `false`, "" ou 0 null == undefined ``` _TOUJOURS_ tester avec le meilleur et le plus performant des résultats - les consignes ci-dessus sont une ligne de conduite et non un dogme. ```javascript // 4.2.1 // Conversion de type et remarques Preferez `===` à la place de `==` (à moins que le cas de test ne requiert la perte d'évaluation de type) === n'effectue pas de conversion de type, ce qui signifie que : "1" === 1; // faux == effectue la conversion de type, ce qui signifie que : "1" == 1; // vrai // 4.2.2 // Booléens, valeurs de vérité et de négation Booléens : true, false sont vrais : "foo", 1 sont faux : "", 0, null, undefined, NaN, void 0 ``` 5. Style usuel ```javascript // 5.1.1 // Module (function( global ) { var Module = (function() { var data = "secret"; return { //Ceci est une proprété booléenne (boolean) bool: true, // Une chaîne de caractère (string) string: "a string", // Une propriété tableau (array) array: [ 1, 2, 3, 4 ], // Une propriété objet (object) object: { lang: "en-Us" }, getData: function() { // obtenir la valeur courante de `data` return data; }, setData: function( value ) { // affecter une valeur `value` à `data` et la renvoyer return ( data = value ); } }; })(); // D'autres choses peuvent être implémentées ici // Exposition de notre module via l'objet global global.Module = Module; })( this ); ``` ```javascript // 5.2.1 // Constructeur (function( global ) { function Ctor( foo ) { this.foo = foo; return this; } Ctor.prototype.getFoo = function() { return this.foo; }; Ctor.prototype.setFoo = function( val ) { return ( this.foo = val ); }; // Appel du contructeur sans `new`, en utilisant cette syntaxe : var ctor = function( foo ) { return new Ctor( foo ); }; // Exposition de notre constructeur via l'objet global global.ctor = ctor; })( this ); ``` 6. Règles de nommage Vous n'êtes pas un compilateur ou un minificateur, il ne faut pas essayer d'en être un. Le code suivant est un exemple flagrant de ce qu'il ne faut pas faire : ```javascript // 6.1.1 // Example of code with poor names function q(s) { return document.querySelectorAll(s); } var i,a=[],els=q("#foo"); for(i=0;iDivers Cette section servira à illustrer des idées et des concepts qui ne devraient pas être considérés comme un dogme, mais il existe, au lieu d'encourager les pratiques en doute dans une tentative de trouver de meilleures façons de le faire les tâches courantes de programmation JavaScript. A. L'utilisation des `switch` doit être évitée, les méthodes modernes de tracking devraient 'blacklister' l'utilisation des fonctions avec `switch`. Il semble y avoir des améliorations radicales à l'exécution des déclarations de `switch` dans les dernières version de Firefox et Chrome. http://jsperf.com/switch-vs-object-literal-vs-module Des améliorations notables sont également visibles ici : https://github.com/rwldrn/idiomatic.js/issues/13 ```javascript // 7.A.1.1 // Exemple de déclaration de `switch` switch( foo ) { case "alpha": alpha(); break; case "beta": beta(); break; default: // comportement par défaut break; } // 7.A.1.2 // Une meilleure approche est d'utiliser un object littéral ou même un module : var switchObj = { alpha: function() { // déclarations // return }, beta: function() { // déclarations // return }, _default: function() { // déclarations // return } }; var switchModule = (function () { return { alpha: function() { // déclarations // return }, beta: function() { // déclarations // return }, _default: function() { // déclarations // return } }; })(); // 7.A.1.3 // If `foo` is a property of `switchObj` or `switchModule`, execute as a method... ( Object.hasOwnProperty.call( switchObj, foo ) && switchObj[ foo ] || switchObj._default )( args ); ( Object.hasOwnProperty.call( switchObj, foo ) && switchModule[ foo ] || switchModule._default )( args ); // If you know and trust the value of `foo`, you could even omit the OR check // leaving only the execution: switchObj[ foo ]( args ); switchModule[ foo ]( args ); // This pattern also promotes code reusability. ``` B. Les "return" prématurés permettent d'améliorer la lisibilité du code avec une différence de performance négligeable ```javascript // 7.B.1.1 // Bad: function returnLate( foo ) { var ret; if ( foo ) { ret = "foo"; } else { ret = "quux"; } return ret; } // Good: function returnEarly( foo ) { if ( foo ) { return "foo"; } return "quux"; } ``` 8. Native & Host Objects Le principe de base est ici : ### Ne faites pas de choses stupides et tout sera OK. Pour renforcer ce concept, regardez s'il vous plaît la présentation suivante : #### “Everything is Permitted: Extending Built-ins” by Andrew Dupont (JSConf2011, Portland, Oregon) https://www.youtube.com/watch?v=xL3xCO7CLNM 9. Commentaires * Le style de commentaire JSDoc est bon (Closure Compiler type hints++) * Une seule ligne de commentaire au-dessus du code auquel il s'applique * L'utilisation de plusieurs lignes est bonne * Les commentaires en fin de ligne sont interdits ! 10. Un code, un langage Les programmes doivent être rédigés dans un langage, quel que soit le langage, le mainteneur ou les mainteneurs doivent donner les bonnes pratiques. ## Appendice ### Première virgule. Tout projet qui cite ce document comme son guide de style de base ne pourra accepter le formatage du code première virgule, sauf mention contraire. ================================================ FILE: translations/gr_GR/readme.md ================================================ # Αρχές γραφής συνεπούς και ιδιοματικής Javascript ## Αυτό είναι απλά ένα αρχείο και νέες ιδέες που βελτιώνουν τον κώδικα γύρω μας είναι πάντα ευπρόσδεκτες. Συνεισφέρετε, κάντε fork, clone, branch, commit, push και pull request. * Rick Waldron [@rwaldron](http://twitter.com/rwaldron), [github](https://github.com/rwaldron) * Mathias Bynens [@mathias](http://twitter.com/mathias), [github](https://github.com/mathiasbynens) * Schalk Neethling [@ossreleasefeed](http://twitter.com/ossreleasefeed), [github](https://github.com/ossreleasefeed/) * Kit Cambridge [@kitcambridge](http://twitter.com/kitcambridge), [github](https://github.com/kitcambridge) * Raynos [github](https://github.com/Raynos) * Matias Arriola [@MatiasArriola](https://twitter.com/MatiasArriola), [github](https://github.com/MatiasArriola/) * John Fischer [@jfroffice](https://twitter.com/jfroffice), [github](https://github.com/jfroffice/) * Idan Gazit [@idangazit](http://twitter.com/idangazit), [github](https://github.com/idan) * Leo Balter [@leobalter](http://twitter.com/leobalter), [github](https://github.com/leobalter) * Breno Oliveira [@garu_rj](http://twitter.com/garu_rj), [github](https://github.com/garu) * Leo Beto Souza [@leobetosouza](http://twitter.com/leobetosouza), [github](https://github.com/leobetosouza) * Ryuichi Okumura [@okuryu](http://twitter.com/okuryu), [github](https://github.com/okuryu) * Pascal Precht [@PascalPrecht](http://twitter.com/PascalPrecht), [github](https://github.com/pascalprecht) * EngForDev [engfordev](http://www.opentutorials.org/course/167/1363) - Hwan Min Hong / MinTaek Kwon [@leoinsight](http://twitter.com/leoinsight) / Tw Shim [@marocchino](http://twitter.com/marocchino), [github](https://github.com/marocchino) / Nassol Kim [@nassol99](http://twitter.com/nassol99), [github](https://github.com/nassol) / Juntai Park [@rkJun](http://twitter.com/rkJun), [github](https://github.com/rkJun) / Minkyu Shim / Gangmin Won / Justin Yoo [@justinchronicle](http://twitter.com/justinchronicle) / Daeyup Lee * Marco Trulla [@marcotrulla](http://twitter.com/marcotrulla), [github](https://github.com/Ragnarokkr) * Alex Navasardyan [@alexnavasardyan](http://twitter.com/alexnavasardyan), [github](https://github.com/2k00l) * Mihai Paun [@mihaipaun](http://twitter.com/mihaipaun), [github](https://github.com/mihaipaun) * Evgeny Mandrikov [@\_godin\_](http://twitter.com/_godin_), [github](https://github.com/Godin) * Sofish Lin [@sofish](http://twitter.com/sofish), [github](https://github.com/sofish) * Дејан Димић [@dejan_dimic](http://twitter.com/dejan_dimic), [github](https://github.com/rubystream) * Miloš Gavrilović [@gavrisimo](http://twitter.com/gavrisimo), [github](https://github.com/gavrisimo) * Firede [@firede](https://twitter.com/firede) [github](https://github.com/firede) * monkadd [github](https://github.com/monkadd) * Stephan Lindauer [@stephanlindauer](http://twitter.com/stephanlindauer), [github](https://github.com/stephanlindauer) * Thomas P [@dragon5689](https://twitter.com/dragon5689) [github](https://github.com/dragon5689) * Yotam Ofek [@yotamofek](https://twitter.com/yotamofek) [github](https://github.com/yotamofek) * Aleksandr Filatov [@greybax](http://twitter.com/greybax), [github](https://github.com/greybax) * Duc Nguyen [@ducntq](https://twitter.com/ducntq), [github](https://github.com/ducntq) * James Young [@jamsyoung](http://twitter.com/jamsyoung), [github](https://github.com/jamsyoung) * Hao-Wei Jeng [@l0ckys](http://twitter.com/l0ckys), [github](https://github.com/lockys) * Richard Gibson [@gibson042](http://twitter.com/gibson042), [github](https://github.com/gibson042) * Fesuy [github](https://github.com/fesuydev) * Stephane Moreau [github](https://github.com/stmoreau) * Boris Nekezov [github](https://github.com/boris-nekezov) * Akshat Joshi [@akshat_joshi](http://twitter.com/akshat_joshi), [github](https://https://github.com/akshatjoshii) ## Όλος ο κώδικας σε ένα project πρέπει να φαίνεται σαν να τον έχει γράψει ένα άτομο, ασχέτως του πόσα άτομα έχουν συνεισφέρει. ### Η παρακάτω λίστα δείχνει τις πρακτικές που ακολουθώ σε όλον τον κώδικα για τον οποίο είμαι ο author. Contributions σε projects που έχω δημιουργήσει πρέπει να ακολουθούν αυτές τις οδηγίες. ### Δεν σκοπεύω να επιβάλω τα style preferences μου σε κώδικα άλλων ανθρώπων, αν ένα κοινό στυλ υπάρχει πρέπει να ακολουθείται αυτό. > ### "Επιχειρήματα αντί για στυλ δεν έχει νόημα. Θα πρέπει να υπάρχει ένα style guide και θα πρέπει να το ακολουθείτε" >_Rebecca_ _Murphey_   > ### "Μέρος του να είσαι καλός διαχειριστής ενός επιτυχημένου project είναι η συνειδητοποίηση ότι το να γράφεις κώδικα για τον εαυτό σου είναι κακή ιδέα. Εάν χιλιάδες άνθρωποι χρησιμοποιούν τον κωδικό σας, τότε γράψτε τον κωδικό σας για μέγιστη σαφήνεια, όχι με την προσωπική σας προτίμηση για το πώς να το παίξετε έξυπνοι με το spec." >_Idan_ _Gazit_ ## Translations * [ORIGINAL](https://github.com/rwldrn/idiomatic.js/) * [Bulgarian](https://github.com/rwldrn/idiomatic.js/tree/master/translations/bg_BG) * [German](https://github.com/rwldrn/idiomatic.js/tree/master/translations/de_DE) * [French](https://github.com/rwldrn/idiomatic.js/tree/master/translations/fr_FR) * [Spanish](https://github.com/rwldrn/idiomatic.js/tree/master/translations/es_ES) * [Portuguese - Brazil](https://github.com/rwldrn/idiomatic.js/tree/master/translations/pt_BR) * [Korean](https://github.com/rwldrn/idiomatic.js/tree/master/translations/ko_KR) * [日本語](https://github.com/rwldrn/idiomatic.js/tree/master/translations/ja_JP) * [Italian](https://github.com/rwldrn/idiomatic.js/tree/master/translations/it_IT) * [Russian](https://github.com/rwldrn/idiomatic.js/tree/master/translations/ru_RU) * [Romanian](https://github.com/rwldrn/idiomatic.js/tree/master/translations/ro_RO) * [简体中文](https://github.com/rwldrn/idiomatic.js/tree/master/translations/zh_CN) * [Serbian - cyrilic alphabet](https://github.com/rwldrn/idiomatic.js/tree/master/translations/ср_СР) * [Serbian - latin alphabet](https://github.com/rwldrn/idiomatic.js/tree/master/translations/sr_SR) * [繁體中文](https://github.com/rwaldron/idiomatic.js/tree/master/translations/zh_TW) * [Indonesian](https://github.com/rwaldron/idiomatic.js/tree/master/translations/id_ID) * [Greek](https://github.com/rwaldron/idiomatic.js/tree/master/translations/gr_GR) * [Hindi](https://github.com/rwaldron/idiomatic.js/tree/master/translations/hi_HI) ## Σημαντικά, Μη-Ιδιωματικά Πράγματα: ### Code Quality Εργαλεία, Πόροι & Αναφορές * [JavaScript Plugin](http://docs.codehaus.org/display/SONAR/JavaScript+Plugin) για το [Sonar](http://www.sonarsource.org/) * [Plato](https://github.com/es-analysis/plato) * [jsPerf](http://jsperf.com/) * [jsFiddle](http://jsfiddle.net/) * [Codepen](http://codepen.io/) * [jsbin](http://jsbin.com/) * [JavaScript Lint (JSL)](http://javascriptlint.com/) * [jshint](http://jshint.com/) * [jslint](http://jslint.org/) * [eslint](http://eslint.org/) * [jscs](https://www.npmjs.org/package/jscs) * [jscodesniffer](https://www.npmjs.org/package/jscodesniffer) * [Editorconfig](http://editorconfig.org/) * [Hound](https://houndci.com/) ## Γίνετε έξυπνοι ### [Annotated ECMAScript 5.1](http://es5.github.com/) ### [EcmaScript Language Specification, 5.1 Edition](http://ecma-international.org/ecma-262/5.1/) Τα επόμενα θα πρέπει να θεωρρηθούν 1) μη τελειωμένα και 2) *ΑΠΑΡΑΙΤΗΤΟ ΔΙΑΒΑΣΜΑ*. Δεν συμφωνώ πάντα με το στυλ που χρησιμοποιείται από τους παρακάτω συγγραφείς, αλλά ένα είναι σίγουρο: είναι συνεπής. Επιπλέον, πρόκειται για αρχές σχετικά με τη γλώσσα. * [Baseline For Front End Developers: 2015](http://rmurphey.com/blog/2015/03/23/a-baseline-for-front-end-developers-2015/) * [Eloquent JavaScript](http://eloquentjavascript.net/) * [JavaScript, JavaScript](http://javascriptweblog.wordpress.com/) * [Adventures in JavaScript Development](http://rmurphey.com/) * [Perfection Kills](http://perfectionkills.com/) * [Douglas Crockford's Wrrrld Wide Web](http://www.crockford.com) * [JS Assessment](https://github.com/rmurphey/js-assessment) ### Διαδικασία Δημιουργίας και Deployment Τα project θα πρέπει πάντα να προσπαθούν να περιέχουν κάποιους γενικούς τρόπους με τους οποίους να μπορούν να γίνουν linted, tested και συμπιεσμένα για την παραγωγή. Για αυτή τη διαδικασία το [grunt](https://github.com/gruntjs/grunt) από τον Ben Alman και το [webpack](https://github.com/webpack/webpack) είναι σπουδαία εργαλεία. ### Test Facility Τα projects _πρέπει_ να περιέχουν κάποιου είδους unit, reference, implementation ή functional testing. Παρακάτω είναι μια λίστα με test frameworks, εκ των οποίων κανένα δεν συνιστάται πιο πολύ από τα άλλα. * [QUnit](http://github.com/jquery/qunit) * [Jasmine](https://github.com/pivotal/jasmine) * [Vows](https://github.com/cloudhead/vows) * [Mocha](https://github.com/visionmedia/mocha) * [Hiro](http://hirojs.com/) * [JsTestDriver](https://code.google.com/p/js-test-driver/) * [Buster.js](http://busterjs.org/) * [Sinon.js](http://sinonjs.org/) * [Tape](https://github.com/substack/tape) ## Πίνακας περιεχομένων * [Λευκός χώρος](#whitespace) * [Όμορφο Συντακτικό](#spacing) * [Έλεγχος τύπου (ευγενείς οδηγίες jQuery Core Style)](#type) * [Conditional Evaluation](#cond) * [Πρακτικό στυλ](#practical) * [Ονομασία](#naming) * [Διάφορα](#misc) * [Native & Host Objects](#native) * [Σχόλια](#comments) * [Ένας κώδικας γλώσσας](#language) ------------------------------------------------ ## Πρόλογος Τα επόμενα τμήματα δείχνουν ένα _λογικό_ style guide για μοντέρνο JavaScript development και δεν είναι εντεταλμένα. Το πιο σημαντικό στοιχείο να αποκομίσετε είναι ο **νόμος της code style συνέπειας**. Ό,τι και να διαλέξετε για το στυλ του project σας πρέπει λαμβάνεται ως νόμος. ## Ιδιωματικό Style Manifesto 1. Λευκός χώρος - Ποτέ να μην συνδιάζετε κενά και tabs. - Όταν ξεκινάτε ένα project, πριν γράψετε καν κώδικα, διαλέξτε ανάμεσα σε κενά ή tabs και θεωρήστε το **νόμο**. - Για να είναι ευανάγνωστο, πάντα προτείνω να σετάρετε το indent του editor σας σε 2 χαρακτήρες — αυτό σημαίνει πως δυο κενά αντιπροσωπεύουν ένα tab. - Αν το υποστηρίζει ο editor σας, πάντα να δουλεύετε με το "show invisibles" αναμένο. Τα πλεονεκτήματα αυτού είναι: - Ενισχυμένη συνοχή - Εξάλειψη των κενών στο τέλος της γραμμής - Εξάλειψη των κενών γραμμών - Commits και diffs που είναι ευκολότερα να διαβαστούν - Χρησιμοποιείτε [Editorconfig](http://editorconfig.org/) όποτε μπορείτε. Υποστηρίζει τα περισσότερα IDEs και διαχειρίζεται τις πεισσότερες ρυθμίσεις για τους κενούς χώρους. 2. Όμορφο Συντακτικό A. Parens, Braces, Linebreaks ```javascript // if/else/for/while/try πάντα έχουν κενά, braces and span πολλαπλές γραμμές // προωθεί το readability // 2.A.1.1 // παραδείγματα από πραγματικά πυκνό συντακτικό if(condition) doSomething(); while(condition) iterating++; for(var i=0;i<100;i++) someIterativeFn(); // 2.A.1.1 // Χρησιμοποιείστε τα κενά για να προωθήσετε το readability if ( condition ) { // statements } while ( condition ) { // statements } for ( var i = 0; i < 100; i++ ) { // statements } // Ακόμα καλύτερα: var i, length = 100; for ( i = 0; i < length; i++ ) { // statements } // Or... var i = 0, length = 100; for ( ; i < length; i++ ) { // statements } var prop; for ( prop in object ) { // statements } if ( true ) { // statements } else { // statements } ``` B. Assignments, Declarations, Functions ( Named, Expression, Constructor ) ```javascript // 2.B.1.1 // Variables var foo = "bar", num = 1, undef; // Literal notations: var array = [], object = {}; // 2.B.1.2 // Χρησιμοποιώντας ένα `var` ανά scope (function) ή ένα `var` για κάθε μεταβλητή, // προωθείτε το readability και κρατιέται το declaration list χωρίς ακαταστασία. // Χρησιμοποιώντας ένα `var` ανά μεταβλητή έχετε καλύτερο έλεγχο των versions // και κάνει ευκολότερο να μετακινείτε τις γραμμές. // Ένα `var` ανά scope κάνει ευκολότερο το να βρίσκετε undeclared variables // που μπορεί να γίνουν implied globals. // Διαλέξτε καλύτερα για το project σας και ποτέ μην τα αναμιγνύετε. // Κακό var foo = "", bar = ""; var qux; // Καλό var foo = ""; var bar = ""; var qux; // ή αλλιώς.. var foo = "", bar = "", qux; // ή.. var // Comment σε αυτά foo = "", bar = "", quux; // 2.B.1.3 // var statements πρέπει να είναι πάντα στην αρχή του respective scope (function). // κακό function foo() { // some statements here var bar = "", qux; } // καλό function foo() { var bar = "", qux; // all statements after the variables declarations. } // 2.B.1.4 // const και let, από το ECMAScript 6, πρέπει να είναι στην αρχή του scope (block) τους. // κακό function foo() { let foo, bar; if ( condition ) { bar = ""; // statements } } // καλό function foo() { let foo; if ( condition ) { let bar = ""; // statements } } ``` ```javascript // 2.B.2.1 // Named Function Declaration function foo( arg1, argN ) { } // Χρήση foo( arg1, argN ); // 2.B.2.2 // Named Function Declaration function square( number ) { return number * number; } // Χρήση square( 10 ); // Really contrived continuation passing style function square( number, callback ) { callback( number * number ); } square( 10, function( square ) { // callback statements }); // 2.B.2.3 // Function Expression var square = function( number ) { // Return something valuable and relevant return number * number; }; // Function Expression with Identifier // Αυτή η χρήση έχει το πλεονέκτημα ότι μπορεί να καλεσθέι // από τον εαυτό της και έχει ένα identity στα stack traces: var factorial = function factorial( number ) { if ( number < 2 ) { return 1; } return number * factorial( number - 1 ); }; // 2.B.2.4 // Constructor Declaration function FooBar( options ) { this.options = options; } // Χρήση var fooBar = new FooBar({ a: "alpha" }); fooBar.options; // { a: "alpha" } ``` C. Εξαιρέσεις, ελαφρές αποκλίσεις ```javascript // 2.C.1.1 // Functions with callbacks foo(function() { // Προσέξτε ότι δεν υπάρχει έξτρα κενό ανάμεσα στο πρώτο paren // του executing function call και της λέξης "function" }); // Function δεχόμενο ένα array, όχι κενό foo([ "alpha", "beta" ]); // 2.C.1.2 // Function δεχόμενο ένα object, όχι κενό foo({ a: "alpha", b: "beta" }); // Single argument string literal, όχι κενό foo("bar"); // Expression parens, όχι κενό if ( !("foo" in obj) ) { obj = (obj.bar || defaults).baz; } ``` D. Η συνέπεια πάντα κερδίζει Στα κεφάλαια 2.A-2.C, οι κανόνες των κενών ορίζονται ως σύσταση με έναν απλούστερο, ψηλότερο σκοπό: η συνέπεια. Είναι σημαντικό να σημειώσουμε πως τα formatting preferences, όπως το "inner whitespace" πρέπει να θεωρούνται προαιρετικά, αλλά ένα στυλ πρέπει να υπάρχει σε όλο το project σας. ```javascript // 2.D.1.1 if (condition) { // statements } while (condition) { // statements } for (var i = 0; i < 100; i++) { // statements } if (true) { // statements } else { // statements } ``` E. Quotes Είτε προτιμάτε μονά ή διπλά δεν πειράζειμ δεν υπάρχει διαφορά στο πως η Javascript τα διαβάζει. Αυτό που **ΟΠΩΣ ΚΑΙ ΔΗΠΟΤΕ ΠΡΕΠΕΙ** να ενισχυθεί είναι η συνέπεια. **Ποτέ μην χρησιμοποιείτε και τα δυο στο ίδιο project. Διαλέξτε ένα στυλ και ακολουθείστε αυτο.** F. Τέλος γραμμών και κενές γραμμές Το κενό μπορεί να καταστρέψει τα diffs και να τα κάνει αδύνατο να διαβαστούν. Σκεφτείτε να συμπεριλαμβάνετε ένα pre-commit hook που θα διαγράφει το end-of-line κενό και τα blanks spaces στις κενές γραμμές αυτόματα. 3. Έλεγχος τύπου (ευγενείς οδηγίες jQuery Core Style) A. Actual Types String: typeof variable === "string" Number: typeof variable === "number" Boolean: typeof variable === "boolean" Object: typeof variable === "object" Array: Array.isArray( arrayLikeObject ) (wherever possible) Node: elem.nodeType === 1 null: variable === null null or undefined: variable == null undefined: Global Variables: typeof variable === "undefined" Local Variables: variable === undefined Properties: object.prop === undefined object.hasOwnProperty( prop ) "prop" in object B. Coerced Types Σκεφτείτε τις εφαρμογές των παρακάτω... Έχοντας αυτό το HTML: ```html ``` ```javascript // 3.B.1.1 // `foo` έχει γίνει declared με την τιμή `0` και ο τύπος είναι `number` var foo = 0; // typeof foo; // "number" ... // Κάπου αργότερα στον κώδικα, πρέπει να ανανεώσετε το `foo` // με μία καινούρια τιμή από ένα input element foo = document.getElementById("foo-input").value; // Άμα θέλατε να τεστάρετε `typeof foo` τώρα, το αποτέλεσμα θα ήταν `string` // Αυτό σημαίνει πως αν είχατε λογική που να τεστάρει το `foo`: if ( foo === 1 ) { importantTask(); } // `importantTask()` δεν θα γινόταν ποτέ evaluated, ακόμα και αν το `foo` έχει την τιμή "1" // 3.B.1.2 // Μπορείτε να προκατέχετε τέτοια προβλήματα χρησιμοποιώντας smart coercion με unary + ή - operators: foo = +document.getElementById("foo-input").value; // ^ unary + operator θα μετατρέψουν το δεξιά operand σε αριθμό // typeof foo; // "number" if ( foo === 1 ) { importantTask(); } // `importantTask()` θα κληθεί ``` Παρακάτω είναι μερικές συχνές περιπτώσεις με coercions: ```javascript // 3.B.2.1 var number = 1, string = "1", bool = false; number; // 1 number + ""; // "1" string; // "1" +string; // 1 +string++; // 1 string; // 2 bool; // false +bool; // 0 bool + ""; // "false" ``` ```javascript // 3.B.2.2 var number = 1, string = "1", bool = true; string === number; // false string === number + ""; // true +string === number; // true bool === number; // false +bool === number; // true bool === string; // false bool === !!string; // true ``` ```javascript // 3.B.2.3 var array = [ "a", "b", "c" ]; !!~array.indexOf("a"); // true !!~array.indexOf("b"); // true !!~array.indexOf("c"); // true !!~array.indexOf("d"); // false // Παρατηρείστε πως τα παραπάνω πρέπει να θεωρούνται "unnecessarily clever" // Να προτιμάτε την φανερή προσέγγιση συγκρίνοντας την επιστρεφόμενη τιμή του // indexOf, όπως: if ( array.indexOf( "a" ) >= 0 ) { // ... } ``` ```javascript // 3.B.2.4 var num = 2.5; parseInt( num, 10 ); // είναι το ίδιο με... ~~num; num >> 0; num >>> 0; // Όλα επιστρέφουν 2 // Να θυμάστε βέβαια, πως οι αρνητικοί αριθμοί θα αντιμετωπιστούν διαφορετικά... var neg = -2.5; parseInt( neg, 10 ); // είναι το ίδιο με... ~~neg; neg >> 0; // Όλα επιστρέφουν -2 // Όμως... neg >>> 0; // Θα επιστρέψει 4294967294 ``` 4. Conditional Evaluation ```javascript // 4.1.1 // Όταν ελέγχετε αν ένα array έχει length, // αντί για αυτό: if ( array.length > 0 ) ... // ...να ελέγχετε το truthiness, με αυτόν τον τρόπο: if ( array.length ) ... // 4.1.2 // Όταν ελέγχετε ότι ένα array είναι empty, // αντί για αυτό: if ( array.length === 0 ) ... // ...να ελέγχετε το truthiness, με αυτόν τον τρόπο: if ( !array.length ) ... // 4.1.3 // Όταν ελέγχετε ότι ένα string δεν είναι empty, // αντί για αυτό: if ( string !== "" ) ... // ...να ελέγχετε το truthiness, με αυτόν τον τρόπο: if ( string ) ... // 4.1.4 // Όταν ελέγχετε ότι ένα string _είναι_ empty, // αντί για αυτό: if ( string === "" ) ... // ...να ελέγχετε το falsy-ness, με αυτόν τον τρόπο: if ( !string ) ... // 4.1.5 // Όταν ελέγχετε ότι ένα reference είναι true, // αντί για αυτό: if ( foo === true ) ... // ...να το ελέγχετε σαν να το εννωείτε, Επωφεληθείτε από τις ενσωματωμένες δυνατότητες: if ( foo ) ... // 4.1.6 // Όταν ελέγχετε ότι ένα reference είναι false, // αντί για αυτό: if ( foo === false ) ... // ...να χρησιμποιείτε negation για να κάνετε coerce ένα true evaluation if ( !foo ) ... // ...Προσοχή, αυτό θα ισχύει και για: 0, "", null, undefined, NaN // Αν _ΠΡΕΠΕΙ_ να ελέγξετε ένα boolean false, τότε να χρησιμποιείτε if ( foo === false ) ... // 4.1.7 // Όταν ελέγχετε έμα ref που μπορεί να είναι null ή undefined, αλλά ΟΧΙ false, "" or 0, // αντί για αυτό: if ( foo === null || foo === undefined ) ... // ...εκμεταλευτείτε το == type coercion, με αυτόν τον τρόπο: if ( foo == null ) ... // Να θυμάστε πως η χρήση == θα ταιριάξει ένα `null` και στο `null` και στο `undefined` // αλλά όχι `false`, "" ή 0 null == undefined ``` Πάντα να ελέγχετε για το καλύτερο, πιο ακριβές αποτέλεσμα - τα παραπάνω είναι μια κατευθυντήρια γραμμή, όχι ένα δόγμα. ```javascript // 4.2.1 // Type coercion και evaluation notes // Να προτιμάρε `===` αντί για `==` (εκτός και αν αυτή η περίπτωση απαιτεί loose type evaluation) // === δεν κάνει coerce το type, που σημαίνει ότι: "1" === 1; // false // == κάνει coerce type, που σημαίνει ότι: "1" == 1; // true // 4.2.2 // Booleans, Truthies & Falsies // Booleans: true, false // Truthy: "foo", 1 // Falsy: "", 0, null, undefined, NaN, void 0 ``` 5. Πρακτικό στυλ ```javascript // 5.1.1 // Ένα Practical Module (function( global ) { var Module = (function() { var data = "secret"; return { // Αυτό είναι boolean property bool: true, // Ένα string value string: "a string", // Ένα array property array: [ 1, 2, 3, 4 ], // Ένα object property object: { lang: "en-Us" }, getData: function() { // Επιστρέφει την τωρινή τιμή του `data` return data; }, setData: function( value ) { // θέτει την τιμή του `data` και την επιστρέφει return ( data = value ); } }; })(); // Άλλα πράγματα μπορούν να γίνουν εδώ // Έκθεση του module στο global object global.Module = Module; })( this ); ``` ```javascript // 5.2.1 // Ένα Practical Constructor (function( global ) { function Ctor( foo ) { this.foo = foo; return this; } Ctor.prototype.getFoo = function() { return this.foo; }; Ctor.prototype.setFoo = function( val ) { return ( this.foo = val ); }; // Για να καλέσετε constructor χωρίς `new`, μπορείτε να κάνετε αυτό: var ctor = function( foo ) { return new Ctor( foo ); }; // Έκθεση του constructor στο global object global.ctor = ctor; })( this ); ``` 6. Ονομασία A. Δεν είστε code compiler/compressor, οπότε μην προσπαθείτε να είστε ένας. Ο ακόλουθος κώδικας είναι ένα παράδειγμα από ανήκουστη ονομασία: ```javascript // 6.A.1.1 // Παράδειγμα κώδικα με φτωχή ονομασία function q(s) { return document.querySelectorAll(s); } var i,a=[],els=q("#foo"); for(i=0;iΔιάφορα Αυτή η ενότητα θα χρησιμεύσει για να Εικονογραφηθούν ιδέες και έννοιες που δεν πρέπει να θεωρούνται δόγμα, αλλά αντίθετα υπάρχουν για να ενθαρρύνουμε τις πρακτικές αμφισβήτησης σε μια προσπάθεια να βρούμε καλύτερους τρόπους για να κάνουμε κοινές εργασίες προγραμματισμού JavaScript. A. Η χρήση του `switch` πρέπει να αποφεύγεται, ο σύγχρονος εντοπισμός μεθόδων θα περιλαμβάνει μαύρες λίστες με εντολές μεταγωγής Φαίνεται να υπάρχουν δραστικές βελτιώσεις στην εκτέλεση των δηλώσεων `switch` στις τελευταίες εκδόσεις του Firefox και του Chrome. http://jsperf.com/switch-vs-object-literal-vs-module Σημαντικές βελτιώσεις μπορούν να παρατηρηθούν και εδώ: https://github.com/rwldrn/idiomatic.js/issues/13 ```javascript // 7.A.1.1 // Ένα παράδειγμα switch statement switch( foo ) { case "alpha": alpha(); break; case "beta": beta(); break; default: // κάτι στο οποίο να κάνει default break; } // 7.A.1.2 // Μια εναλλακτική προσέγγιση που υποστηρίζει τη δυνατότητα σύνθεσης και επαναχρησιμοποίησης είναι // η χρήση ενός αντικειμένου για την αποθήκευση "cases" και ένα function για την ανάθεση: var cases, delegator; // Παράδειγμα επιστρέφει μόνο για απεικόνιση. cases = { alpha: function() { // statements // ένα return return [ "Alpha", arguments.length ]; }, beta: function() { // statements // ένα return return [ "Beta", arguments.length ]; }, _default: function() { // statements // ένα return return [ "Default", arguments.length ]; } }; delegator = function() { var args, key, delegate; // Μετατρέψτε το arguments list σε ένα array args = [].slice.call( arguments ); // shift το case key από τα arguments key = args.shift(); // Αναθέστε το default case handler delegate = cases._default; // Derive the method to delegate operation to if ( cases.hasOwnProperty( key ) ) { delegate = cases[ key ]; } // Τα scope arg θα μπορούσαν να ανατεθούν σε κάτι συγκεκριμένο, // σε αυτήν την περίπτωση το |null| θα ήταν αρκετό return delegate.apply( null, args ); }; // 7.A.1.3 // Κάντε το API από το 7.A.1.2 να δουλέψει: delegator( "alpha", 1, 2, 3, 4, 5 ); // [ "Alpha", 5 ] // Φυσικά, το `case` key argument θα μπορούσε έυκολα να είναι βασισμένο // σε κάποιο άλλο τυχαίο condition. var caseKey, someUserInput; // Πιθανών κάποιου είδους form input; someUserInput = 9; if ( someUserInput > 10 ) { caseKey = "alpha"; } else { caseKey = "beta"; } // ή... caseKey = someUserInput > 10 ? "alpha" : "beta"; // Ύστερα... delegator( caseKey, someUserInput ); // [ "Beta", 1 ] // Και φυσικά... delegator(); // [ "Default", 0 ] ``` B. Οι πρώτες επιστροφές προάγουν την αναγνωσιμότητα του κώδικα με αμελητέα διαφορά απόδοσης ```javascript // 7.B.1.1 // Κακό: function returnLate( foo ) { var ret; if ( foo ) { ret = "foo"; } else { ret = "quux"; } return ret; } // Καλό: function returnEarly( foo ) { if ( foo ) { return "foo"; } return "quux"; } ``` 8. Native & Host Objects Η βασική αρχή εδώ είναι: ### Μην κάνετε χαζές βλακείες και όλα θα δουλεύουν καλά. Για να ενισχύσετε αυτήν την έννοια, παρακαλούμε δείτε την ακόλουθη παρουσίαση: #### “Everything is Permitted: Extending Built-ins” του Andrew Dupont (JSConf2011, Portland, Oregon) https://www.youtube.com/watch?v=xL3xCO7CLNM 9. Σχόλια #### Μονή γραμμή πάνς από τον κώδικα είναι υποκειμενικό #### Πολλαπλή γραμμή είναι καλή #### Τα σχόλια στο τέλος της γραμμής απαγορεύονται! #### Το JSDoc στυλ είναι καλό, αλλά απαιτεί μια σημαντική επένδυση χρόνου 10. Ένας κώδικας γλώσσας Τα προγράμματα πρέπει να είναι γραμμένα σε μία γλώσσα, όποια και αν είναι αυτή η γλώσσα, όπως υπαγορεύει ο διαχειριστής ή οι συντηρητές. ## Παράρτημα ### Comma First. Οποιοδήποτε project που παραθέτει αυτό το έγγραφο ως βασικό οδηγό στυλ δεν θα δεχτεί μορφοποίηση πρώτου κώδικα με κόμμα, εκτός εάν έχει οριστεί διαφορετικά από τον συντάκτη του project. ---------- Creative Commons License
Principles of Writing Consistent, Idiomatic JavaScript by Rick Waldron and Contributors is licensed under a Creative Commons Attribution 3.0 Unported License.
Based on a work at github.com/rwldrn/idiomatic.js. ================================================ FILE: translations/hi_HI/readme.md ================================================ # जावास्क्रिप्ट लेखन के स्थिर एवं सिद्धप्रयोग सिद्धांत ## यह एक जीवित आलेख है और कोड को उत्तमतर बनाने हेतु नए विचारों का सर्वदा स्वागत है | योगदान: fork, clone, branch, commit, push, pull request. * Rick Waldron [@rwaldron](http://twitter.com/rwaldron), [github](https://github.com/rwaldron) * Mathias Bynens [@mathias](http://twitter.com/mathias), [github](https://github.com/mathiasbynens) * Schalk Neethling [@ossreleasefeed](http://twitter.com/ossreleasefeed), [github](https://github.com/ossreleasefeed/) * Kit Cambridge [@kitcambridge](http://twitter.com/kitcambridge), [github](https://github.com/kitcambridge) * Raynos [github](https://github.com/Raynos) * Matias Arriola [@MatiasArriola](https://twitter.com/MatiasArriola), [github](https://github.com/MatiasArriola/) * John Fischer [@jfroffice](https://twitter.com/jfroffice), [github](https://github.com/jfroffice/) * Idan Gazit [@idangazit](http://twitter.com/idangazit), [github](https://github.com/idan) * Leo Balter [@leobalter](http://twitter.com/leobalter), [github](https://github.com/leobalter) * Breno Oliveira [@garu_rj](http://twitter.com/garu_rj), [github](https://github.com/garu) * Leo Beto Souza [@leobetosouza](http://twitter.com/leobetosouza), [github](https://github.com/leobetosouza) * Ryuichi Okumura [@okuryu](http://twitter.com/okuryu), [github](https://github.com/okuryu) * Pascal Precht [@PascalPrecht](http://twitter.com/PascalPrecht), [github](https://github.com/pascalprecht) * EngForDev [engfordev](https://opentutorials.org/course/245/1788) - Hwan Min Hong / MinTaek Kwon [@leoinsight](http://twitter.com/leoinsight) / Tw Shim [@marocchino](http://twitter.com/marocchino), [github](https://github.com/marocchino) / Nassol Kim [@nassol99](http://twitter.com/nassol99), [github](https://github.com/nassol) / Juntai Park [@rkJun](http://twitter.com/rkJun), [github](https://github.com/rkJun) / Minkyu Shim / Gangmin Won / Justin Yoo [@justinchronicle](http://twitter.com/justinchronicle) / Daeyup Lee * Marco Trulla [@marcotrulla](http://twitter.com/marcotrulla), [github](https://github.com/Ragnarokkr) * Alex Navasardyan [@alexnavasardyan](http://twitter.com/alexnavasardyan), [github](https://github.com/2k00l) * Mihai Paun [@mihaipaun](http://twitter.com/mihaipaun), [github](https://github.com/mihaipaun) * Evgeny Mandrikov [@\_godin\_](http://twitter.com/_godin_), [github](https://github.com/Godin) * Sofish Lin [@sofish](http://twitter.com/sofish), [github](https://github.com/sofish) * Дејан Димић [@dejan_dimic](http://twitter.com/dejan_dimic), [github](https://github.com/rubystream) * Miloš Gavrilović [@gavrisimo](http://twitter.com/gavrisimo), [github](https://github.com/gavrisimo) * Firede [@firede](https://twitter.com/firede) [github](https://github.com/firede) * monkadd [github](https://github.com/monkadd) * Stephan Lindauer [@stephanlindauer](http://twitter.com/stephanlindauer), [github](https://github.com/stephanlindauer) * Thomas P [@dragon5689](https://twitter.com/dragon5689) [github](https://github.com/dragon5689) * Yotam Ofek [@yotamofek](https://twitter.com/yotamofek) [github](https://github.com/yotamofek) * Aleksandr Filatov [@greybax](http://twitter.com/greybax), [github](https://github.com/greybax) * Duc Nguyen [@ducntq](https://twitter.com/ducntq), [github](https://github.com/ducntq) * James Young [@jamsyoung](http://twitter.com/jamsyoung), [github](https://github.com/jamsyoung) * Hao-Wei Jeng [@l0ckys](http://twitter.com/l0ckys), [github](https://github.com/lockys) * Richard Gibson [@gibson042](http://twitter.com/gibson042), [github](https://github.com/gibson042) * Fesuy [github](https://github.com/fesuydev) * Stephane Moreau [github](https://github.com/stmoreau) * Akshat Joshi [@akshat_joshi](http://twitter.com/akshat_joshi), [github](https://https://github.com/akshatjoshii) ## किसी भी कोड-बेस का कोड ऐसा दिखना चाहिए जैसे एक ही व्यक्ति ने मानो पूरा कोड लिखा हो, भले ही कितने लोगों का उसमें योगदान रहा हो | ### निम्नलिखित सूची उन तरीकों को रेखांकित करती है जो मैं अपने कोड मे प्रयोग करता हूँ, जिनका मैं वास्तविक लेखक हूँ ; मेरे द्वारा रचित प्रोजेक्ट्स में दिए गए योगदानों को इन दिशा निर्देशों का पालन करना चाहिए | ### मैं अपनी शैली और उसकी प्राथमिकताओं को दूसरे लोगों के कोड या उनके प्रोजेक्ट पर थोपने की नीयत नहीं रखता हूँ ; यदि कोई समान शैली अस्तित्व रखती है, तो उसका आदर होना चाहिए | > ### "शैली पर तर्क व्यर्थ है। एक स्टाइल गाइड होनी चाहिए, और आपको इसका पालन करना चाहिए" >_Rebecca_ _Murphey_   > ### "स्वयं के लिए कोड करना गलत योजना है, यह अनुभूति एक सफल परियोजना (प्रोजेक्ट) के एक अच्छे प्रबंधक का हिस्सा होनी चाहिए | यदि हजारों लोग आपके कोड का उपयोग कर रहे हैं, तब आपको अधिकतम स्पष्टता के साथ अपना कोड लिखना है, न कि अपनी व्यक्तिगत प्राथमिकता कि कैसे अपने spec के भीतर चालाक हों |" >_Idan_ _Gazit_ ## अनुवाद * [ORIGINAL](https://github.com/rwldrn/idiomatic.js/) * [German](https://github.com/rwldrn/idiomatic.js/tree/master/translations/de_DE) * [French](https://github.com/rwldrn/idiomatic.js/tree/master/translations/fr_FR) * [Spanish](https://github.com/rwldrn/idiomatic.js/tree/master/translations/es_ES) * [Portuguese - Brazil](https://github.com/rwldrn/idiomatic.js/tree/master/translations/pt_BR) * [Korean](https://github.com/rwldrn/idiomatic.js/tree/master/translations/ko_KR) * [日本語](https://github.com/rwldrn/idiomatic.js/tree/master/translations/ja_JP) * [Italian](https://github.com/rwldrn/idiomatic.js/tree/master/translations/it_IT) * [Russian](https://github.com/rwldrn/idiomatic.js/tree/master/translations/ru_RU) * [Romanian](https://github.com/rwldrn/idiomatic.js/tree/master/translations/ro_RO) * [简体中文](https://github.com/rwldrn/idiomatic.js/tree/master/translations/zh_CN) * [Serbian - cyrilic alphabet](https://github.com/rwldrn/idiomatic.js/tree/master/translations/ср_СР) * [Serbian - latin alphabet](https://github.com/rwldrn/idiomatic.js/tree/master/translations/sr_SR) * [繁體中文](https://github.com/rwaldron/idiomatic.js/tree/master/translations/zh_TW) * [Indonesian](https://github.com/rwaldron/idiomatic.js/tree/master/translations/id_ID) * [Greek](https://github.com/rwaldron/idiomatic.js/tree/master/translations/gr_GR) * [Hindi](https://github.com/rwaldron/idiomatic.js/tree/master/translations/hi_HI) ## महत्वपूर्ण, नॉन-इडीओमैटिक स्टफ: ### कोड गुणवत्ता के उपकरण, संसाधन और संदर्भ * [JavaScript Plugin](http://docs.codehaus.org/display/SONAR/JavaScript+Plugin) for [Sonar](http://www.sonarsource.org/) * [Plato](https://github.com/es-analysis/plato) * [jsPerf](http://jsperf.com/) * [jsFiddle](http://jsfiddle.net/) * [Codepen](http://codepen.io/) * [jsbin](http://jsbin.com/) * [JavaScript Lint (JSL)](http://javascriptlint.com/) * [jshint](http://jshint.com/) * [jslint](http://jslint.org/) * [eslint](http://eslint.org/) * [jscs](https://www.npmjs.org/package/jscs) * [jscodesniffer](https://www.npmjs.org/package/jscodesniffer) * [Editorconfig](http://editorconfig.org/) * [Hound](https://houndci.com/) ## स्मार्ट हो जाओ ### [Annotated ECMAScript 5.1](http://es5.github.com/) ### [EcmaScript Language Specification, 5.1 Edition](http://ecma-international.org/ecma-262/5.1/) निम्नलिखित को 1) अपूर्ण, और 2) *आवश्यक पठन* मानना चाहिए | मैं निम्नोक्त लेखकों की शैली से सदैव सहमत नहीं होता हूँ, किन्तु एक चीज निश्चित है: उनमें स्थिरता / निरन्तरता (consistent) हैं | इसके अतिरिक्त, इनका भाषा पर अधिकार है | * [Baseline For Front End Developers: 2015](http://rmurphey.com/blog/2015/03/23/a-baseline-for-front-end-developers-2015/) * [Eloquent JavaScript](http://eloquentjavascript.net/) * [JavaScript, JavaScript](http://javascriptweblog.wordpress.com/) * [Adventures in JavaScript Development](http://rmurphey.com/) * [Perfection Kills](http://perfectionkills.com/) * [Douglas Crockford's Wrrrld Wide Web](http://www.crockford.com) * [JS Assessment](https://github.com/rmurphey/js-assessment) ### बिल्ड एवं डिप्लॉयमेंट प्रोसेस प्रोजेक्ट्स में हमेशा कुछ सामान्य साधनों को शामिल करने का प्रयास करना चाहिए जिस से उत्पादन के उपयोग हेतु स्त्रोत को लिन्ट, टेस्ट और कंप्रेस किया जा सके | इस कार्य के लिए, Ben Alman की [grunt](https://github.com/gruntjs/grunt) अद्वितीय है एवं आधिकारिक रूप से इस रेपोज़ीटरी की "kits/" डाइरेक्टरी को रिप्लेस कर चुकी है | ### परीक्षण के साधन (टेस्ट फेसेलिटी) प्रोजेक्ट में किसी न किसी रूप से यूनिट, रेफरेंस, इम्प्लिमेन्टेशन, अथवा फंगक्शनल टेस्टिंग _अवश्य_ शामिल होनी चाहिए | उपयोगिता के प्रदर्शन हेतु डेमो का प्रयोग "टेस्ट" के मापदंड को पार नहीं करता | नीचे टेस्ट फ्रेमवर्क की सूची दी गई है, जिनमें किसी का भी दूसरे की तुलना में कोई समर्थन नहीं किया गया है | * [QUnit](http://github.com/jquery/qunit) * [Jasmine](https://github.com/pivotal/jasmine) * [Vows](https://github.com/cloudhead/vows) * [Mocha](https://github.com/visionmedia/mocha) * [Hiro](http://hirojs.com/) * [JsTestDriver](https://code.google.com/p/js-test-driver/) * [Buster.js](http://busterjs.org/) * [Sinon.js](http://sinonjs.org/) * [Tape](https://github.com/substack/tape) * [Jest](https://facebook.github.io/jest/) ## विषयसूची * [व्हाइटस्पेस](#whitespace) * [ब्यूटीफुल सिंटेक्स](#spacing) * [टाइप चेकिंग (सौजन्य jQuery कोर स्टाइल दिशानिर्देश)](#type) * [कन्डिशनल ईवैल्यूऐशन](#cond) * [प्रैक्टिकल स्टाइल](#practical) * [नामकरण](#naming) * [विविध](#misc) * [नेटिव एवं होस्ट ऑब्जेक्ट्स](#native) * [टिप्पणी](#comments) * [एक भाषीय कोड](#language) ------------------------------------------------ ## प्रस्तावना निम्नलिखित खंड आधुनिक जावास्क्रिप्ट के विकास के लिए एक _उचित_ शैली की रूपरेखा तैयार करते हैं और इसका अर्थ ये नहीं है कि ये ब्रह्मवाक्य हैं | सबसे महत्वपूर्ण है **कोड शैली मे स्थिरता का कानून** | जो भी कोड शैली आप अपने प्रोजेक्ट मे प्रयोग करते हैं, वो उस प्रोजेक्ट का कानून है | इस आलेख का लिंक आपके प्रोजेक्ट की कोड शैली की स्थिरता, पठनीयता एवं रख-रखाव की प्रतिबद्धता का वचन है | ## सिद्धप्रयोग शैली का घोषणापत्र 1. व्हाइटस्पेस - स्पेस और टैब कभी न मिलाएं | - प्रोजेक्ट शुरू करते समय, कोई भी कोड लिखने से पहले, सॉफ्ट इंडेंट्स (spaces) या वास्तविक टैब के बीच चयन करें, इसको **कानून** मानें | - पठनीयता के लिए, मैं हमेशा आपके एडिटर के इंडेंट साइज को दो अक्षरों में सेट करने की सलाह देता हूं — इसका अर्थ है दो स्पेस (spaces) या दो स्पेस (spaces) एक वास्तविक टैब का प्रतिनिधित्व कर रही हों | - यदि आपका एडिटर इसका सपोर्ट करता है, तो हमेशा "शो इनविसिबल्स (show invisibles)" सेटिंग के साथ काम करें। इस अभ्यास के लाभ हैं: - बाध्य स्थिरता - लाइन के अंत से व्हाइटस्पेस का लुप्त होना - ब्लैंक लाइन व्हाइटस्पेस का लुप्त होना - कामिट (commits) और डिफ़ (diffs) जो पढ़ने मे सरल हों | - जब भी संभव हो इसका प्रयोग करें [Editorconfig](http://editorconfig.org/) | ये लगभग सभी आई-डी-ई को सपोर्ट करता है और ज्यादातर व्हाइटस्पेस सेटिंग्स को हैन्डल करता है | 2. ब्यूटीफुल सिंटेक्स A. पैरेंस, ब्रेसेस, लाइन ब्रेक्स (Parens, Braces, Linebreaks) ```javascript // if/else/for/while/try में हमेशा स्पेस और ब्रेसेस होंगी और एक से अधिक लाइन मे इनका विस्तार होगा | // इस से पठनीयता को प्रोत्साहन मिलता है | // 2.A.1.1 // अत्यंत बुरे सिन्टैक्स के उदाहरण if(condition) doSomething(); while(condition) iterating++; for(var i=0;i<100;i++) someIterativeFn(); // 2.A.1.1 // पठनीयता के लिए व्हाइटस्पेस का प्रयोग if ( condition ) { // कोड वाक्य } while ( condition ) { // कोड वाक्य } for ( var i = 0; i < 100; i++ ) { // कोड वाक्य } // और अधिक उत्तम: var i, length = 100; for ( i = 0; i < length; i++ ) { // कोड वाक्य } // अथवा... var i = 0, length = 100; for ( ; i < length; i++ ) { // कोड वाक्य } var prop; for ( prop in object ) { // कोड वाक्य } if ( true ) { // कोड वाक्य } else { // कोड वाक्य } ``` B. असाइनमेंट, डेक्लरैशन्स, फंगक्शन्स ( नैम्ड, इक्स्प्रेशन, कन्स्ट्रक्टर ) ```javascript // 2.B.1.1 // वेरीअबल्स var foo = "bar", num = 1, undef; // शाब्दिक अधिसूचनाएँ (लिटरल नोटैशन्स): var array = [], object = {}; // 2.B.1.2 // एक `var` का ही प्रत्येक स्कोप (फंगक्शन) मे प्रयोग या एक `var` का प्रत्येक वेरीअबल के लिए प्रयोग, // पठनीयता को बढ़ाता है और डेक्लरैशन्स की सूची को अव्यवस्था से मुक्त रखता है | // एक `var` प्रति वेरीअबल के प्रयोग से आप अपने वर्ज़न का अधिक नियंत्रण ले सकते हैं // और इस से कोड की लाइंस को पुनः व्यवस्थित करना सरल हो जाता है | // एक `var` प्रति स्कोप से अनडिक्लेर्ड वेरीअबल को ढूंढना सरल हो जाता है // जो इमप्लाइड ग्लोबल बन ने की संभावना रखते हैं | // दोनों को मिक्स न करें, और जो बेहतर हो उसका उपयोग करें | // खराब, दोष पूर्ण var foo = "", bar = ""; var qux; // उत्तम var foo = ""; var bar = ""; var qux; // अथवा.. var foo = "", bar = "", qux; // अथवा.. var // टिप्पणी foo = "", bar = "", quux; // 2.B.1.3 // var कथन हमेशा प्रत्येक स्कोप (फ़ंक्शन) की शुरुआत में होना चाहिए । // खराब, दोष पूर्ण function foo() { // कोड वाक्य var bar = "", qux; } // उत्तम function foo() { var bar = "", qux; // वेरीअबल्स घोषणा (डेक्लरैशन्स) के बाद सभी विवरण लिखें | } // 2.B.1.4 // ECMAScript 6 के const और let के लिए भी यही मान्य है । // खराब, दोष पूर्ण function foo() { let foo, bar; if ( condition ) { bar = ""; // कोड वाक्य } } // उत्तम function foo() { let foo; if ( condition ) { let bar = ""; // कोड वाक्य } } ``` ```javascript // 2.B.2.1 // नामित फंक्शन की घोषणा function foo( arg1, argN ) { } // उपयोग foo( arg1, argN ); // 2.B.2.2 // नामित फंक्शन की घोषणा function square( number ) { return number * number; } // उपयोग square( 10 ); // कृतिम कन्टिन्यूऐशन पासिंग स्टाइल function square( number, callback ) { callback( number * number ); } square( 10, function( square ) { // कॉलबैक स्टेटमेंट्स }); // 2.B.2.3 // फंगक्शन इक्स्प्रेशन var square = function( number ) { // कोई महत्वपूर्ण या संबंधित चीज़ रिटर्न करता है return number * number; }; // फंगक्शन इक्स्प्रेशन आइडेंटिफ़ायर के साथ | // इस शैली से यह फायदा होता है कि इसके द्वारा फंगक्शन स्वयं को ही कॉल कर सकता है // एवं स्टैक के चिन्हों मे उसकी पहचान होती है | var factorial = function factorial( number ) { if ( number < 2 ) { return 1; } return number * factorial( number - 1 ); }; // 2.B.2.4 // कन्स्ट्रक्टर की घोषणा (डेक्लरैशन) function FooBar( options ) { this.options = options; } // उपयोग var fooBar = new FooBar({ a: "alpha" }); fooBar.options; // { a: "alpha" } ``` C. अपवाद, मामूली विषयांतरकरण ```javascript // 2.C.1.1 // फंगक्शन के साथ कॉलबैक foo(function() { // ध्यान दें कि निष्पादित फंगक्शन कॉल के पहले पैरं // और "फंगक्शन" शब्द के बीच में कोई रिक्त स्थान (स्पेस) नहीं है }); // फंगक्शन जो एरे स्वीकारता हो, में कोई रिक्त स्थान नहीं foo([ "alpha", "beta" ]); // 2.C.1.2 // फ़ंक्शन जो ऑब्जेक्ट स्वीकारता हो, में कोई रिक्त स्थान नहीं foo({ a: "alpha", b: "beta" }); // एक ही स्ट्रिंग लिटरल आरग्यूमेंट पास होने में कोई रिक्त स्थान नहीं foo("bar"); // कोष्ठकों के अंदर एक्सप्रेशन में कोई रिक्त स्थान नहीं if ( !("foo" in obj) ) { obj = (obj.bar || defaults).baz; } ``` D. स्थिरता सदैव जीतती है खंड 2.A-2.C, व्हाइटस्पेस नियमों को अनुग्रह एक सरल, उच्च उद्देश्य के लिए किया गया है जो है: स्थिरता | यह ध्यान रखना महत्वपूर्ण है कि "आंतरिक व्हाइटस्पेस" जैसी प्राथमिकताओं को वैकल्पिक माना जाना चाहिए, लेकिन आपके प्रोजेक्ट के पूरे स्रोत में केवल एक शैली ही व्याप्त राहनी चाहिए। ```javascript // 2.D.1.1 if (condition) { // कोड वाक्य } while (condition) { // कोड वाक्य } for (var i = 0; i < 100; i++) { // कोड वाक्य } if (true) { // कोड वाक्य } else { // कोड वाक्य } ``` E. क्वोट्स चाहे आप सिंगल या डबल पसंद करते हैं या नहीं, इससे कोई फर्क नहीं पड़ता, दोनों को जावास्क्रिप्ट कैसे पार्स करता है उसमे तनिक भेद नहीं है | जो **अत्यंत आवश्यक** रूप से लागू होना चाहिए वह है स्थिरता (अथवा निरन्तरता). **क्वोट्स को एक ही प्रोजेक्ट मे कदापि मिक्स न करें | एक शैली चुनें और उस पर अड़िग रहें |** F. लाइनों और खाली लाइनों का अंत व्हाइटस्पेस डिफ को बर्बाद कर सकता है और पढ़ने के लिए बदलाव असंभव बना सकता है। एक पूर्व-प्रतिबद्ध हुक को शामिल करने पर विचार करें जो अंत में लाइन के अंत मे आने वाले व्हाइटस्पेस और खाली लाइनों मे उपस्थित रिक्त स्थानों (स्पेसेस) को स्वचालित रूप से हटा देता है। 3. टाइप चेकिंग (जेक्वेरी कोर स्टाइल दिशानिर्देश के सौजन्य से) A. वास्तविक टाइप्स स्ट्रिंग: typeof variable === "string" नंबर: typeof variable === "number" बूलियन: typeof variable === "boolean" ऑब्जेक्ट: typeof variable === "object" एरे: Array.isArray( arrayLikeObject ) (जब भी संभव हो) नोड: elem.nodeType === 1 नल: variable === null नल or अंडीफाइंड: variable == null अंडीफाइंड: ग्लोबल वेरीअबल: typeof variable === "undefined" लोकल वेरीअबल: variable === undefined प्रॉपर्टीज़: object.prop === undefined object.hasOwnProperty( prop ) "prop" in object B. कोअर्सड (Coerced) टाइप्स निम्नलिखित के निहितार्थों पर विचार करें... इस एचटीएमएल को देखते हुए: ```html ``` ```javascript // 3.B.1.1 // `foo` को `0` से घोषित किया गया है और उसका टाइप है `number` var foo = 0; // typeof foo; // "number" ... // आपके कोड मे कहीं आगे जा के, आपको आवश्यकता होती है `foo` // को अपडेट करने की, एक नई वैल्यू से जो कि एक इनपुट एलीमेंट से प्राप्त हुई है foo = document.getElementById("foo-input").value; // यदि अब आप टेस्ट करें `typeof foo`, तो परिणाम होगा `string` // इसका अर्थ यह है कि यदि आपके कोड मे ये लॉजिक था जिसमे 'foo का कुछ इस तरह तरह परीक्षण किया गया था: if ( foo === 1 ) { importantTask(); } // `importantTask()` काभी भी नहीं किया चलेगा, भले ही 'foo' की वैल्यू "1" है // 3.B.1.2 // आप समस्याओं को दूर कर सकते हैं यूनरी + अथवा - ऑपरेटर्स के स्मार्ट कोअर्सन के प्रयोग से: foo = +document.getElementById("foo-input").value; // ^ यूनरी + ऑपरेटर दाईं तरफ के आपरैन्ड को नंबर मे परिवर्तित कर देगा // typeof foo; // "number" if ( foo === 1 ) { importantTask(); } // `importantTask()` अब क्रियान्वित होगा ``` यहाँ कोअर्सन के कुछ सामान्य उद्धरण हैं ```javascript // 3.B.2.1 var number = 1, string = "1", bool = false; number; // 1 number + ""; // "1" string; // "1" +string; // 1 +string++; // 1 string; // 2 bool; // false +bool; // 0 bool + ""; // "false" ``` ```javascript // 3.B.2.2 var number = 1, string = "1", bool = true; string === number; // false string === number + ""; // true +string === number; // true bool === number; // false +bool === number; // true bool === string; // false bool === !!string; // true ``` ```javascript // 3.B.2.3 var array = [ "a", "b", "c" ]; !!~array.indexOf("a"); // true !!~array.indexOf("b"); // true !!~array.indexOf("c"); // true !!~array.indexOf("d"); // false // ध्यान दें कि उपरोक्त को "अनावश्यक रूप से चतुर" माना जाना चाहिए // indexOf की रिटर्ण्ड वैल्यू के कम्पैरिसन के लिए स्पष्ट तरीकों का ही प्रयोग उचित है // जैसे: if ( array.indexOf( "a" ) >= 0 ) { // ... } ``` ```javascript // 3.B.2.4 var num = 2.5; parseInt( num, 10 ); // यह निम्न के ही समान है ~~num; num >> 0; num >>> 0; // सभी का परिणाम होगा 2 // हालांकि, ध्यान रखें कि नेगटिव संख्याओं को अलग तरह से माना जाएगा... var neg = -2.5; parseInt( neg, 10 ); // यह निम्न के ही समान है... ~~neg; neg >> 0; // सभी का परिणाम होगा -2 // हालांकि... neg >>> 0; // परिणाम होगा 4294967294 ``` 4. कन्डिशनल ईवैल्यूऐशन ```javascript // 4.1.1 // जब केवल यह मूल्यांकन करना कि किसी एरे में कुछ लंबाई है, // बजाए इसके: if ( array.length > 0 ) ... // ...इस प्रकार से सत्यता का मूल्यांकन करें: if ( array.length ) ... // 4.1.2 // जब केवल यह मूल्यांकन करना कि किसी एरे खाली है,, // तो बजाए इसके: if ( array.length === 0 ) ... // ...इस प्रकार से सत्यता का मूल्यांकन करें: if ( !array.length ) ... // 4.1.3 // जब केवल यह मूल्यांकन करना कि स्ट्रिंग रिक्त नहीं है, // तो बजाए इसके: if ( string !== "" ) ... // ...इस प्रकार से सत्यता का मूल्यांकन करें: if ( string ) ... // 4.1.4 // जब केवल यह मूल्यांकन करना कि स्ट्रिंग _रिक्त_ है,, // तो बजाए इसके: if ( string === "" ) ... // ...इस प्रकार से असत्यता का मूल्यांकन करें: if ( !string ) ... // 4.1.5 // जब केवल मूल्यांकन करना है कि एक रेफेरेंस सत्य है, // तो बजाए इसके: if ( foo === true ) ... // ...इस तरह मूल्यांकन करें जैसा कि आप देख सकते हैं, अंतर्निहित क्षमताओं का लाभ उठाएं: if ( foo ) ... // 4.1.6 // जब मूल्यांकन करना है कि एक रेफेरेंस असत्य है, // तो बजाए इसके: if ( foo === false ) ... // ...सही मूल्यांकन के लिए निषेध (निगेशन) का उपयोग करें if ( !foo ) ... // ...सावधान रहें, यह भी मैच होगा: 0, "", null, undefined, NaN // यदि बूलियन फाल्स के लिए परीक्षण करना _अवश्यंभावी_ हो ही गया है, तो उपगयोग करें: if ( foo === false ) ... // 4.1.7 // जब रेफ का मूल्यांकन करना हो जो null या undefined हो सकता है, लेकिन false, "" या 0 नहीं // तो बजाए इसके: if ( foo === null || foo === undefined ) ... // ...टाइप कोअर्सन == का लाभ उठायें, जैसे: if ( foo == null ) ... // याद रखें, == का उपयोग `null` को दोनों `null` एवं `undefined`से मैच करेगा // किन्तु `false`, "" या 0 से नहीं null == undefined ``` सदैव उत्तम और सटीक परिणामों के लिए मूल्यांकन करें - उपरोक्त दिशानिर्देश हैं, हठधर्मिता नहीं। ```javascript // 4.2.1 // टाईप कोअर्सन और ईवैल्यूऐशन के नोट्स // `===` को `==` पर वरीयता दें (जब तक कि लूज टाइप ईवैल्यूऐशन की अनिवार्यता नहीं है) // === यह कोअर्स टाइप नहीं है, अर्थात: "1" === 1; // false // == यह कोअर्स टाइप है, अर्थात: "1" == 1; // true // 4.2.2 // बूलियन्स, ट्रूथीज़ एवं फाल्सीज़ // बूलियन्स: true, false // ट्रूथी: "foo", 1 // फाल्सी: "", 0, null, undefined, NaN, void 0 ``` 5. प्रैक्टिकल स्टाइल (व्यावहारिक शैली) ```javascript // 5.1.1 // एक व्यावहारिक मॉड्यूल (function( global ) { var Module = (function() { var data = "secret"; return { // यह बूलियन प्रॉपर्टी है bool: true, // कुछ स्ट्रिंग वैल्यू string: "a string", // एक एरे प्रॉपर्टी array: [ 1, 2, 3, 4 ], // एक ऑब्जेक्ट प्रॉपर्टी object: { lang: "en-Us" }, getData: function() { // `data` की वर्तमान वैल्यू लेता है return data; }, setData: function( value ) { // `data` में वैल्यू डालता यही और उसको और उसको लौटाता (रिटर्न करता) है return ( data = value ); } }; })(); // अन्यादि चीजें जो हो सकती हैं // मॉड्यूल को ग्लोबल ऑब्जेक्ट के लिए दृश्यमान बनाने के लिए global.Module = Module; })( this ); ``` ```javascript // 5.2.1 // एक प्रैक्टिकल कंस्ट्रक्टर (function( global ) { function Ctor( foo ) { this.foo = foo; return this; } Ctor.prototype.getFoo = function() { return this.foo; }; Ctor.prototype.setFoo = function( val ) { return ( this.foo = val ); }; // `new` का उपयोग किए बिना कंस्ट्रक्टर को कॉल करने के लिए: var ctor = function( foo ) { return new Ctor( foo ); }; // कंस्ट्रक्टर को ग्लोबल ऑब्जेक्ट के लिए दृश्यमान बनाने के लिए global.ctor = ctor; })( this ); ``` 6. नामकरण A. आप एक मानव कोड कंपाइलर/कंप्रेसर नहीं हैं, इसलिए वैसा बनने का प्रयत्न भी न करें | निम्नलिखित कोड सदोष (दोषपूर्ण) नामकरण का एक उदाहरण है:: ```javascript // 6.A.1.1 // खराब नामों वाले कोड का उदाहरण function q(s) { return document.querySelectorAll(s); } var i,a=[],els=q("#foo"); for(i=0;iMisc यह खंड उन विचारों और अवधारणाओं को चित्रित करता है जिन्हें हठधर्मिता नहीं माना जाना चाहिए, अपितु इसका प्रयोजन जावास्क्रिप्ट प्रोग्रामिंग को करने के तरीकों को बेहतर बनाने के प्रयास में प्रश्न आदि पूछने की प्रक्रियाओं को प्रोत्साहित करना है । A. `switch` के प्रयोग से बचना चाहिए, आधुनिक मेथड अनुरेखण (ट्रैसिंग) उन फंगक्शन को वर्जित करेगी जिनमें स्विच का प्रयोग है | फ़ायरफ़ॉक्स और क्रोम के नवीनतम रिलीज़ में `switch` स्टेटमेंट के निष्पादन में भारी सुधार प्रतीत होता है | http://jsperf.com/switch-vs-object-literal-vs-module उल्लेखनीय सुधार यहां भी देखे जा सकते हैं: https://github.com/rwldrn/idiomatic.js/issues/13 ```javascript // 7.A.1.1 // स्विच स्टेटमेंट का एक उदाहरण switch( foo ) { case "alpha": alpha(); break; case "beta": beta(); break; default: // something to default to break; } // 7.A.1.2 // एक वैकल्पिक तरीका जो रचनाशीलता और पुनर्प्रयोग को सपोर्ट करता है // ऑब्जेक्ट में "cases" को सहेजें एवं फंगक्शन की ओर प्रेषित कर दें: var cases, delegator; // उदाहरण केवल चित्रण के लिए रिटर्न कर रहा है | cases = { alpha: function() { // कोड वाक्य // रिटर्न वाक्य return [ "Alpha", arguments.length ]; }, beta: function() { // कोड वाक्य // रिटर्न वाक्य return [ "Beta", arguments.length ]; }, _default: function() { // कोड वाक्य // रिटर्न वाक्य return [ "Default", arguments.length ]; } }; delegator = function() { var args, key, delegate; // आर्ग्यमन्ट की सूची को एरे मे परिवर्तित करता है args = [].slice.call( arguments ); // आर्ग्यमन्ट की सूची से केस की को शिफ्ट करता (हटाता) है key = args.shift(); // डिफ़ॉल्ट केस हैंडलर को असाइन करता है delegate = cases._default; // ऑपरेशन को प्रेषित करने हेतु मेथड को डिराइव करता है if ( cases.hasOwnProperty( key ) ) { delegate = cases[ key ]; } // स्कोप आर्ग्यमन्ट मे विशिष्ट वैल्यू सेट की जा सकती है , // इस उदाहरण में, |null| पर्याप्त होगा return delegate.apply( null, args ); }; // 7.A.1.3 // क्रियाशील करने के लिए एपीआई को 7.A.1.2 में डालते हैं: delegator( "alpha", 1, 2, 3, 4, 5 ); // [ "Alpha", 5 ] // निःसंदेह, `case` key आर्ग्यमन्ट किसी भी अन्य // यादृच्छिक परिस्थिति पर आधारित हो सकता है | var caseKey, someUserInput; // संभवतः किसी तरह का फॉर्म इनपुट? someUserInput = 9; if ( someUserInput > 10 ) { caseKey = "alpha"; } else { caseKey = "beta"; } // अथवा... caseKey = someUserInput > 10 ? "alpha" : "beta"; // तत्पश्चात... delegator( caseKey, someUserInput ); // [ "Beta", 1 ] // और बेशक... delegator(); // [ "Default", 0 ] ``` B. प्रारम्भिक रिटर्न नगण्य परफॉरमेंस के अंतर के साथ कोड पठनीयता को बढ़ावा देते हैं | ```javascript // 7.B.1.1 // सदोष, खराब: function returnLate( foo ) { var ret; if ( foo ) { ret = "foo"; } else { ret = "quux"; } return ret; } // उत्तम: function returnEarly( foo ) { if ( foo ) { return "foo"; } return "quux"; } ``` 8. नेटिव एवं होस्ट ऑब्जेक्ट्स यहां मूल सिद्धांत यह है कि: ### बेवकूफी न करें तो सब कुछ ठीक हो जाएगा इस अवधारणा को सुदृढ़ करने हेतु, कृपया निम्नलिखित प्रस्तुति देखें: #### “Everything is Permitted: Extending Built-ins” by Andrew Dupont (JSConf2011, Portland, Oregon) https://www.youtube.com/watch?v=xL3xCO7CLNM 9. टिप्पणी #### विषय को कोड के ऊपर एक पंक्ति में लिखें #### मल्टीलाइन अच्छी है #### लाइन के अंत में टिप्पणियाँ निषिद्ध हैं! #### JSDoc शैली अच्छी है किन्तु इसमें बहुत समय लगता है 10. एक भाषीय कोड प्रोग्राम को एक भाषा में लिखा जाना चाहिए, जो भी भाषा हो, जैसा कि अनुरक्षक या अनुरक्षकों द्वारा तय किया गया हो | ## परिशिष्ट ### कोमा फर्स्ट | कोई भी प्रोजेक्ट जो इस आलेख को अपनी आधार शैली मार्गदर्शिका के रूप में उद्धृत करता है, कोमा फर्स्ट कोड फार्मेट को स्वीकार नहीं करेगा, जब तक कि उस प्रोजेक्ट के लेखक द्वारा स्पष्ट रूप से अन्यथा निर्दिष्ट न हो । ---------- Creative Commons License
रिक वाल्ड्रॉन और योगदानकर्ताओं द्वारा रचित जावास्क्रिप्ट लेखन के स्थिर एवं सिद्धप्रयोग सिद्धांत Creative Commons Attribution 3.0 Unported License के तहत लाइसेन्स्ड है |
github.com/rwldrn/idiomatic.js पर आधारित है | ================================================ FILE: translations/id_ID/readme.md ================================================ # Principles of Writing Consistent, Idiomatic JavaScript ## This is a living document and new ideas for improving the code around us are always welcome. Contribute: fork, clone, branch, commit, push, pull request. * Rick Waldron [@rwaldron](http://twitter.com/rwaldron), [github](https://github.com/rwaldron) * Mathias Bynens [@mathias](http://twitter.com/mathias), [github](https://github.com/mathiasbynens) * Schalk Neethling [@ossreleasefeed](http://twitter.com/ossreleasefeed), [github](https://github.com/ossreleasefeed/) * Kit Cambridge [@kitcambridge](http://twitter.com/kitcambridge), [github](https://github.com/kitcambridge) * Raynos [github](https://github.com/Raynos) * Matias Arriola [@MatiasArriola](https://twitter.com/MatiasArriola), [github](https://github.com/MatiasArriola/) * John Fischer [@jfroffice](https://twitter.com/jfroffice), [github](https://github.com/jfroffice/) * Idan Gazit [@idangazit](http://twitter.com/idangazit), [github](https://github.com/idan) * Leo Balter [@leobalter](http://twitter.com/leobalter), [github](https://github.com/leobalter) * Breno Oliveira [@garu_rj](http://twitter.com/garu_rj), [github](https://github.com/garu) * Leo Beto Souza [@leobetosouza](http://twitter.com/leobetosouza), [github](https://github.com/leobetosouza) * Ryuichi Okumura [@okuryu](http://twitter.com/okuryu), [github](https://github.com/okuryu) * Pascal Precht [@PascalPrecht](http://twitter.com/PascalPrecht), [github](https://github.com/pascalprecht) * EngForDev [engfordev](http://www.opentutorials.org/course/167/1363) - Hwan Min Hong / MinTaek Kwon [@leoinsight](http://twitter.com/leoinsight) / Tw Shim [@marocchino](http://twitter.com/marocchino), [github](https://github.com/marocchino) / Nassol Kim [@nassol99](http://twitter.com/nassol99), [github](https://github.com/nassol) / Juntai Park [@rkJun](http://twitter.com/rkJun), [github](https://github.com/rkJun) / Minkyu Shim / Gangmin Won / Justin Yoo [@justinchronicle](http://twitter.com/justinchronicle) / Daeyup Lee * Marco Trulla [@marcotrulla](http://twitter.com/marcotrulla), [github](https://github.com/Ragnarokkr) * Alex Navasardyan [@alexnavasardyan](http://twitter.com/alexnavasardyan), [github](https://github.com/2k00l) * Mihai Paun [@mihaipaun](http://twitter.com/mihaipaun), [github](https://github.com/mihaipaun) * Evgeny Mandrikov [@\_godin\_](http://twitter.com/_godin_), [github](https://github.com/Godin) * Sofish Lin [@sofish](http://twitter.com/sofish), [github](https://github.com/sofish) * Дејан Димић [@dejan_dimic](http://twitter.com/dejan_dimic), [github](https://github.com/rubystream) * Miloš Gavrilović [@gavrisimo](http://twitter.com/gavrisimo), [github](https://github.com/gavrisimo) * Firede [@firede](https://twitter.com/firede) [github](https://github.com/firede) * monkadd [github](https://github.com/monkadd) * Stephan Lindauer [@stephanlindauer](http://twitter.com/stephanlindauer), [github](https://github.com/stephanlindauer) * Thomas P [@dragon5689](https://twitter.com/dragon5689) [github](https://github.com/dragon5689) * Yotam Ofek [@yotamofek](https://twitter.com/yotamofek) [github](https://github.com/yotamofek) * Aleksandr Filatov [@greybax](http://twitter.com/greybax), [github](https://github.com/greybax) * Duc Nguyen [@ducntq](https://twitter.com/ducntq), [github](https://github.com/ducntq) * James Young [@jamsyoung](http://twitter.com/jamsyoung), [github](https://github.com/jamsyoung) * Hao-Wei Jeng [@l0ckys](http://twitter.com/l0ckys), [github](https://github.com/lockys) * Richard Gibson [@gibson042](http://twitter.com/gibson042), [github](https://github.com/gibson042) * Fesuy [github](https://github.com/fesuydev) * Stephane Moreau [github](https://github.com/stmoreau) * Boris Nekezov [github](https://github.com/boris-nekezov) * Akshat Joshi [@akshat_joshi](http://twitter.com/akshat_joshi), [github](https://https://github.com/akshatjoshii) ## Semua kode dalam kode-base akan terlihat seperti satu orang mengetik itu, tidak peduli berapa banyak orang memberikan kontribusi. ### Daftar berikut menguraikan praktik yang digunakan dalam semua kode milik penulis asli; kontribusi untuk proyek-proyek yang saya buat harus mengikuti panduan ini. ### Saya tidak berniat untuk memaksakan preferensi gaya saya pada kode orang lain atau proyek; jika gaya umum sudah ada, itu harus dihormati. > ### "Arguments over style are pointless. There should be a style guide, and you should follow it" >_Rebecca_ _Murphey_   > ### "Part of being a good steward to a successful project is realizing that writing code for yourself is a Bad Idea™. If thousands of people are using your code, then write your code for maximum clarity, not your personal preference of how to get clever within the spec." >_Idan_ _Gazit_ ## Translations * [ORIGINAL](https://github.com/rwldrn/idiomatic.js/) * [Bulgarian](https://github.com/rwldrn/idiomatic.js/tree/master/translations/bg_BG) * [German](https://github.com/rwldrn/idiomatic.js/tree/master/translations/de_DE) * [French](https://github.com/rwldrn/idiomatic.js/tree/master/translations/fr_FR) * [Spanish](https://github.com/rwldrn/idiomatic.js/tree/master/translations/es_ES) * [Portuguese - Brazil](https://github.com/rwldrn/idiomatic.js/tree/master/translations/pt_BR) * [Korean](https://github.com/rwldrn/idiomatic.js/tree/master/translations/ko_KR) * [日本語](https://github.com/rwldrn/idiomatic.js/tree/master/translations/ja_JP) * [Italian](https://github.com/rwldrn/idiomatic.js/tree/master/translations/it_IT) * [Russian](https://github.com/rwldrn/idiomatic.js/tree/master/translations/ru_RU) * [Romanian](https://github.com/rwldrn/idiomatic.js/tree/master/translations/ro_RO) * [简体中文](https://github.com/rwldrn/idiomatic.js/tree/master/translations/zh_CN) * [Serbian - cyrilic alphabet](https://github.com/rwldrn/idiomatic.js/tree/master/translations/ср_СР) * [Serbian - latin alphabet](https://github.com/rwldrn/idiomatic.js/tree/master/translations/sr_SR) * [繁體中文](https://github.com/rwaldron/idiomatic.js/tree/master/translations/zh_TW) * [Indonesian](https://github.com/rwaldron/idiomatic.js/tree/master/translations/id_ID) * [Greek](https://github.com/rwaldron/idiomatic.js/tree/master/translations/gr_GR) * [Hindi](https://github.com/rwaldron/idiomatic.js/tree/master/translations/hi_HI) ## Penting, Non-idiomatic Stuff: ### Code Quality Tools, Resources dan Referensi * [JavaScript Plugin](http://docs.codehaus.org/display/SONAR/JavaScript+Plugin) for [Sonar](http://www.sonarsource.org/) * [Plato](https://github.com/es-analysis/plato) * [jsPerf](http://jsperf.com/) * [jsFiddle](http://jsfiddle.net/) * [Codepen](http://codepen.io/) * [jsbin](http://jsbin.com/) * [JavaScript Lint (JSL)](http://javascriptlint.com/) * [jshint](http://jshint.com/) * [jslint](http://jslint.org/) * [eslint](http://eslint.org/) * [jscs](https://www.npmjs.org/package/jscs) * [jscodesniffer](https://www.npmjs.org/package/jscodesniffer) * [Editorconfig](http://editorconfig.org/) * [Hound](https://houndci.com/) ## Ayo Pintar ### [Annotated ECMAScript 5.1](http://es5.github.com/) ### [EcmaScript Language Specification, 5.1 Edition](http://ecma-international.org/ecma-262/5.1/) berikut harus dipertimbangkan 1) tidak lengkap, dan 2) * DIBUTUHKAN MEMBACA *. Saya tidak selalu setuju dengan gaya yang ditulis oleh penulis di bawah ini, tapi satu hal yang pasti: Mereka konsisten. Selanjutnya, ini adalah otoritas pada bahasa. * [Baseline For Front End Developers: 2015](http://rmurphey.com/blog/2015/03/23/a-baseline-for-front-end-developers-2015/) * [Eloquent JavaScript](http://eloquentjavascript.net/) * [JavaScript, JavaScript](http://javascriptweblog.wordpress.com/) * [Adventures in JavaScript Development](http://rmurphey.com/) * [Perfection Kills](http://perfectionkills.com/) * [Douglas Crockford's Wrrrld Wide Web](http://www.crockford.com) * [JS Assessment](https://github.com/rmurphey/js-assessment) ### Build dan Deployment Proses Proyek harus selalu berusaha untuk memasukkan beberapa cara generik dimana sumber dapat di lint, diuji dan dikompresi dalam persiapan untuk penggunaan produksi. Untuk tugas ini, [grunt](https://github.com/gruntjs/grunt) oleh Ben Alman terbaik dan telah resmi menggantikan "kit /" direktori dari repo ini. ### Test Fasilitas Proyek _must_ mencakup beberapa bentuk unit, referensi, implementasi atau uji fungsional. Demo kasus penggunaan tidak memenuhi syarat sebagai "test". Berikut ini adalah daftar test frameworks, yang mendukung lebih dari yang lain. * [QUnit](http://github.com/jquery/qunit) * [Jasmine](https://github.com/pivotal/jasmine) * [Vows](https://github.com/cloudhead/vows) * [Mocha](https://github.com/visionmedia/mocha) * [Hiro](http://hirojs.com/) * [JsTestDriver](https://code.google.com/p/js-test-driver/) * [Buster.js](http://busterjs.org/) * [Sinon.js](http://sinonjs.org/) * [Tape](https://github.com/substack/tape) ## Daftar Isi * [Spasi](#whitespace) * [Keindahan Syntax](#spacing) * [Pemeriksaan Type (Courtesy jQuery Core Style Guidelines)](#type) * [Evaluasi Kondisional](#cond) * [Practical Style](#practical) * [Naming](#naming) * [Misc](#misc) * [Native dan Host Objects](#native) * [Komentar](#comments) * [One Language Code](#language) ------------------------------------------------ ## Kata Pengantar Bagian berikut menguraikan panduan gaya _reasonable_ untuk pengembangan JavaScript modern dan tidak dimaksudkan untuk menjadi preskriptif. Yang paling penting dibawa pulang adalah hukum ** konsistensi kode gaya **. Apa pun yang Anda pilih sebagai gaya untuk proyek Anda harus dipertimbangkan hukum. Link ke dokumen ini sebagai pernyataan komitmen proyek Anda untuk kode gaya konsistensi, pembacaan dan rawatan. ## Manifesto Gaya Idiomatic 1. Spasi - Jangan pernah mencampur spasi dan tab. - Ketika awal proyek, sebelum Anda menulis kode apapun, memilih antara indentasi lunak (spasi) atau tab nyata, pertimbangkan **hukum ini**. - Untuk dibaca, saya selalu merekomendasikan pengaturan ukuran indent editor untuk dua karakter — ini berarti dua ruang atau dua ruang mewakili tab nyata. - Jika editor mendukungnya, selalu bekerja dengan pengaturan "show invisibles" diaktifkan. Manfaat dari latihan ini adalah: - Konsistensi - Menghilangkan akhir baris spasi - Menghilangkan kosong baris spasi - Commits dan diffs yang mudah dibaca - Gunakan [Editorconfig](http://editorconfig.org/) bila memungkinkan. Mendukung sebagian IDE dan menangani pengaturan penting spasi. 2. Keindahan Syntax A. Parens, Braces, Linebreaks ```javascript // if/else/for/while/try selalu memiliki ruang, kurung, dan renggang beberapa baris // ini mendorong kemudahan membaca // 2.A.1.1 // Contoh dari syntax yang sukar dibaca if(condition) doSomething(); while(condition) iterating++; for(var i=0;i<100;i++) someIterativeFn(); // 2.A.1.1 // Gunakan spasi untuk mempermudah pembacaan if ( condition ) { // statements } while ( condition ) { // statements } for ( var i = 0; i < 100; i++ ) { // statements } // Bahkan lebih baik: var i, length = 100; for ( i = 0; i < length; i++ ) { // statements } // Atau... var i = 0, length = 100; for ( ; i < length; i++ ) { // statements } var prop; for ( prop in object ) { // statements } if ( true ) { // statements } else { // statements } ``` B. Assignments, Declarations, Functions ( Named, Expression, Constructor ) ```javascript // 2.B.1.1 // Variables var foo = "bar", num = 1, undef; // Literal notations: var array = [], object = {}; // 2.B.1.2 // Menggunakan hanya satu `var` per lingkup (fungsi) atau satu` var` untuk setiap variabel, // Mempermudah pembacaan dan membuat daftar deklarasi Anda bebas dari kekacauan. // Menggunakan satu `var` per variabel Anda dapat mengambil kontrol yang lebih dari versi Anda // Dan membuatnya lebih mudah untuk menyusun ulang baris. // Satu `var` per lingkup membuatnya lebih mudah untuk mendeteksi variabel terdeklarasikan // Yang mungkin menjadi akan menjadi globals. // Pilih baik untuk proyek Anda dan jangan pernah mencampur mereka. // Buruk var foo = "", bar = ""; var qux; // Baik var foo = ""; var bar = ""; var qux; // atau.. var foo = "", bar = "", qux; // atau.. var // Komentar disini foo = "", bar = "", quux; // 2.B.1.3 // var statements harus selalu di awal lingkup masing-masing (fungsi). // Buruk function foo() { // beberapa statement disini var bar = "", qux; } // Baik function foo() { var bar = "", qux; // semua statement setelah variabel dideklarasikan. } // 2.B.1.4 // const dan let, dari ECMAScript 6, juga harus berada di bagian atas ruang lingkup mereka (blok). // Buruk function foo() { let foo, bar; if ( condition ) { bar = ""; // statements } } // Baik function foo() { let foo; if ( condition ) { let bar = ""; // statements } } ``` ```javascript // 2.B.2.1 // Deklarasi nama fungsi function foo( arg1, argN ) { } // Penggunaan foo( arg1, argN ); // 2.B.2.2 // Deklarasi nama fungsi function square( number ) { return number * number; } // Penggunaan square( 10 ); // Benar-benar dibuat dengam gaya passing berkelanjutan function square( number, callback ) { callback( number * number ); } square( 10, function( square ) { // callback statements }); // 2.B.2.3 // Ekspresi fungsi var square = function( number ) { // Mengembalikan suatu nilai yang valuable dan relevan return number * number; }; // Ekspresi fungsi dengan Identifier // Bentuk yang disukai ini memiliki nilai tambah yang // Mampu menyebut dirinya dan memiliki identitas di stack traces: var factorial = function factorial( number ) { if ( number < 2 ) { return 1; } return number * factorial( number - 1 ); }; // 2.B.2.4 // Deklarasi Constructor function FooBar( options ) { this.options = options; } // Penggunaan var fooBar = new FooBar({ a: "alpha" }); fooBar.options; // { a: "alpha" } ``` C. Exceptions, Slight Deviations ```javascript // 2.C.1.1 // Fungsi demham callbacks foo(function() { // Catatan: tidak ada ruang ekstra antara parent pertama // Dari pelaksanaan pemanggilan fungsi dan kata "function" }); // Fungsi menerima sebuah array, tidak ada ruang foo([ "alpha", "beta" ]); // 2.C.1.2 // Fungsi menerima sebuah objek, tidak ada ruang foo({ a: "alpha", b: "beta" }); // Satu argumen string literal, tidak ada ruang foo("bar"); // Ekspresi parents, tidak ada ruang if ( !("foo" in obj) ) { obj = (obj.bar || defaults).baz; } ``` D. Konsistensi Selalu Menang Di bagian 2.A-2.C, aturan spasi yang ditetapkan sebagai rekomendasi dengan sederhana, tujuan yang lebih tinggi: konsistensi. Sangat penting untuk dicatat bahwa format preferensi, seperti "inner whitespace" harus dipertimbangkan opsional, tetapi hanya satu gaya harus ada di seluruh sumber proyek Anda. ```javascript // 2.D.1.1 if (condition) { // statements } while (condition) { // statements } for (var i = 0; i < 100; i++) { // statements } if (true) { // statements } else { // statements } ``` E. Tanda Kutip Apakah Anda lebih suka tunggal atau ganda seharusnya tidak masalah, tidak ada perbedaan dalam cara JavaScript mem-parsing mereka. Apa **BENAR-BENAR HARUS** harus ditegakkan adalah konsistensi. **Jangan pernah mencampur kutipan dalam proyek yang sama. Pilih satu gaya dan tetap dengan itu.** F. Akhir Baris dan Garis Kosong Spasi dapat merusak diffs dan membuat changesets mungkin untuk dibaca. Pertimbangkan menggabungkan hook pre-commit yang menghilangkan end-of-line spasi dan ruang kosong di baris kosong secara otomatis. 3. Pemeriksaan type(Courtesy jQuery Core Style Guidelines) A. Actual Types String: typeof variable === "string" Number: typeof variable === "number" Boolean: typeof variable === "boolean" Object: typeof variable === "object" Array: Array.isArray( arrayLikeObject ) (wherever possible) Node: elem.nodeType === 1 null: variable === null null or undefined: variable == null undefined: Global Variables: typeof variable === "undefined" Local Variables: variable === undefined Properties: object.prop === undefined object.hasOwnProperty( prop ) "prop" in object B. Coerced Types Mempertimbangkan implikasi dari berikut ... Mengingat HTML ini: ```html ``` ```javascript // 3.B.1.1 // `Foo` telah dinyatakan dengan nilai `0` dan jenisnya adalah `number` var foo = 0; // typeof foo; // "number" ... // Di suatu tempat dalam kode anda kemudian, Anda perlu memperbarui `foo` // Dengan nilai baru yang berasal dari unsur masukan foo = document.getElementById("foo-input").value; // Jika Anda menguji `typeof foo` sekarang, hasilnya akan `string` // Ini berarti bahwa jika Anda memiliki logika yang diuji `foo` seperti: if ( foo === 1 ) { importantTask(); } // `importantTask()` tidak akan pernah dievaluasi, meskipun `foo` memiliki nilai "1" // 3.B.1.2 // Anda dapat mendahului masalah dengan menggunakan smart coercion dengan unary + atau - operators: foo = +document.getElementById("foo-input").value; // ^ unary + operator akan mengkonversi sisi operan haknya untuk nomor // typeof foo; // "number" if ( foo === 1 ) { importantTask(); } // `importantTask()` akan terpanggil ``` Berikut adalah beberapa kasus yang umum bersama dengan coercions: ```javascript // 3.B.2.1 var number = 1, string = "1", bool = false; number; // 1 number + ""; // "1" string; // "1" +string; // 1 +string++; // 1 string; // 2 bool; // false +bool; // 0 bool + ""; // "false" ``` ```javascript // 3.B.2.2 var number = 1, string = "1", bool = true; string === number; // false string === number + ""; // true +string === number; // true bool === number; // false +bool === number; // true bool === string; // false bool === !!string; // true ``` ```javascript // 3.B.2.3 var array = [ "a", "b", "c" ]; !!~array.indexOf("a"); // true !!~array.indexOf("b"); // true !!~array.indexOf("c"); // true !!~array.indexOf("d"); // false // Perhatikan: bahwa di atas harus dipertimbangkan "unnecessarily clever" // Memilih pendekatan yang jelas dari membandingkan nilai kembali dari // IndexOf, seperti: if ( array.indexOf( "a" ) >= 0 ) { // ... } ``` ```javascript // 3.B.2.4 var num = 2.5; parseInt( num, 10 ); // sama seperti... ~~num; num >> 0; num >>> 0; // All result in 2 // Namun diingat, bahwa angka negatif akan diperlakukan berbeda... var neg = -2.5; parseInt( neg, 10 ); // sama seperti... ~~neg; neg >> 0; // Semua hasil di -2 // Namun ... neg >>> 0; // Akan menghasilkan 4294967294 ``` 4. Evaluasi Kondisional ```javascript // 4.1.1 // Ketika hanya mengevaluasi bahwa array memiliki panjang, // maka seperti dibawah ini: if ( array.length > 0 ) ... // ...mengevaluasi truthiness, seperti ini: if ( array.length ) ... // 4.1.2 // Ketika hanya mengevaluasi bahwa array itu kosong, // maka seperti dibawah ini: if ( array.length === 0 ) ... // ...mengevaluasi truthiness, seperti ini: if ( !array.length ) ... // 4.1.3 // Ketika hanya mengevaluasi bahwa string tidak kosong, // maka seperti dibawah ini: if ( string !== "" ) ... // ...mengevaluasi truthiness, seperti ini: if ( string ) ... // 4.1.4 // Ketika hanya mengevaluasi bahwa string itu kosong, // maka seperti dibawah ini: if ( string === "" ) ... // ...mengevaluasi falsy-ness, seperti ini: if ( !string ) ... // 4.1.5 // Ketika hanya mengevaluasi bahwa referensi benar, // maka seperti dibawah ini: if ( foo === true ) ... // ...mengevaluasi seperti yang Anda maksud itu, mengambil keuntungan dari dibangun pada kemampuan: if ( foo ) ... // 4.1.6 // Ketika mengevaluasi bahwa referensi adalah salah, // maka seperti dibawah ini: if ( foo === false ) ... // ...menggunakan negasi untuk memaksa evaluasi yang benar if ( !foo ) ... // ...Hati-hati, ini juga akan cocok: 0, "", null, undefined, NaN // Jika Anda _HARUS_ test untuk false boolean, maka gunakan if ( foo === false ) ... // 4.1.7 // Ketika hanya mengevaluasi ref yang mungkin nol atau undefined, tapi tidak false, "" atau 0, // maka seperti dibawah ini: if ( foo === null || foo === undefined ) ... // ...mengambil keuntungan dari == type coercion, seperti ini: if ( foo == null ) ... // Ingat, menggunakan == akan cocok dengan `null` untuk KEDUA` null` dan `undefined` // tetapi tidak `false`," "atau 0 null == undefined ``` SELALU mengevaluasi untuk yang terbaik, hasil yang paling akurat - di atas merupakan pedoman, bukan dogma. ```javascript // 4.2.1 // Type coercion dan catatan evaluasi // Prefer `===` over `==` (kecuali kasus memerlukan evaluasi jenis longgar) // === menyamakan type, yang berarti bahwa: "1" === 1; // false // == tidak menyamakan type, yang berarti bahwa:: "1" == 1; // true // 4.2.2 // Booleans, Truthies & Falsies // Booleans: true, false // Truthy: "foo", 1 // Falsy: "", 0, null, undefined, NaN, void 0 ``` 5. Practical Style ```javascript // 5.1.1 // Sebuah Modul Praktis (function( global ) { var Module = (function() { var data = "secret"; return { // Ini adalah beberapa properti boolean bool: true, // Beberapa nilai string string: "a string", // Properti Array array: [ 1, 2, 3, 4 ], // Properti objek object: { lang: "en-Us" }, getData: function() { // mendapatkan nilai saat ini dari `data` return data; }, setData: function( value ) { // menetapkan nilai `data` dan mengembalikannya return ( data = value ); } }; })(); // Hal-hal lain yang mungkin terjadi di sini // mengekspos modul ke obyek global global.Module = Module; })( this ); ``` ```javascript // 5.2.1 // Sebuah Constructor Praktis (function( global ) { function Ctor( foo ) { this.foo = foo; return this; } Ctor.prototype.getFoo = function() { return this.foo; }; Ctor.prototype.setFoo = function( val ) { return ( this.foo = val ); }; // Untuk memanggil konstruktor tanpa `new`, Anda mungkin melakukan hal ini: var ctor = function( foo ) { return new Ctor( foo ); }; // mengekspos konstruktor untuk obyek global global.ctor = ctor; })( this ); ``` 6. Naming A. Anda bukan manusia kode compiler/kompresor, jadi jangan mencoba untuk menjadi salah satu. Kode berikut adalah contoh mengerikan penamaan: ```javascript // 6.A.1.1 // Contoh kode dengan nama yang buruk function q(s) { return document.querySelectorAll(s); } var i,a=[],els=q("#foo"); for(i=0;iMisc Bagian ini akan berfungsi untuk menggambarkan ide-ide dan konsep-konsep yang tidak boleh dianggap dogma, melainkan ada untuk mendorong praktik mempertanyakan dalam upaya untuk menemukan cara yang lebih baik untuk melakukan tugas-tugas pemrograman umum JavaScript. A. Menggunakan `switch` harus dihindari, cara modern tracing akan blacklist fungsi dengan switch statements Tampaknya ada peningkatan drastis untuk pelaksanaan `switch` dalam rilis terbaru dari Firefox dan Chrome. http://jsperf.com/switch-vs-object-literal-vs-module Perbaikan penting dapat dilihat di sini juga: https://github.com/rwldrn/idiomatic.js/issues/13 ```javascript // 7.A.1.1 // Contoh switch statement switch( foo ) { case "alpha": alpha(); break; case "beta": beta(); break; default: // sesuatu untuk default break; } // 7.A.1.2 // Pendekatan alternatif yang mendukung composability dan usabilitas adalah untuk // menggunakan objek untuk menyimpan "cases" dan fungsi untuk mendelegasikan: var cases, delegator; // Contoh return hanya untuk ilustrasi. cases = { alpha: function() { // statements // sebuah return return [ "Alpha", arguments.length ]; }, beta: function() { // statements // sebuah return return [ "Beta", arguments.length ]; }, _default: function() { // statements // sebuah return return [ "Default", arguments.length ]; } }; delegator = function() { var args, key, delegate; // Transform daftar argumen ke dalam array args = [].slice.call( arguments ); // menggeser key cases dari argumen key = args.shift(); // Menetapkan default case handler delegate = cases._default; // Mengambil metode untuk mendelegasikan operasi if ( cases.hasOwnProperty( key ) ) { delegate = cases[ key ]; } // Ruang lingkup arg bisa diatur untuk sesuatu yang spesifik, // dalam hal ini, | null | akan cukup return delegate.apply( null, args ); }; // 7.A.1.3 // Menempatkan API dalam 7.A.1.2 untuk bekerja: delegator( "alpha", 1, 2, 3, 4, 5 ); // [ "Alpha", 5 ] // Tentu saja, `case` argumen key bisa dengan mudah didasarkan // pada beberapa kondisi yang sewenang-wenang lainnya. var caseKey, someUserInput; // Mungkin semacam masukan form? someUserInput = 9; if ( someUserInput > 10 ) { caseKey = "alpha"; } else { caseKey = "beta"; } // atau... caseKey = someUserInput > 10 ? "alpha" : "beta"; // Dan Kemudian... delegator( caseKey, someUserInput ); // [ "Beta", 1 ] // Dan Tentu saja... delegator(); // [ "Default", 0 ] ``` B. Awal kembali mempromosikan pembacaan kode dengan perbedaan kinerja diabaikan ```javascript // 7.B.1.1 // Buruk: function returnLate( foo ) { var ret; if ( foo ) { ret = "foo"; } else { ret = "quux"; } return ret; } // Baik: function returnEarly( foo ) { if ( foo ) { return "foo"; } return "quux"; } ``` 8. Native dan Host Objects Prinsip dasar: ### Jangan melakukan omong kosong bodoh dan semuanya akan ok. Untuk memperkuat konsep ini, silahkan menonton presentasi berikut: #### “Semuanya yang Diizinkan: Memperluas Built-in” by Andrew Dupont (JSConf2011, Portland, Oregon) https://www.youtube.com/watch?v=xL3xCO7CLNM 9. Komentar #### Satu baris dibawah kode itu adalah subjek #### Multiline itu baik #### Akhir dari line komentar terlarang! #### Gaya JSDoc baik, tetapi membutuhkan waktu investasi yang signifikan 10. One Language Code Program harus ditulis dalam satu bahasa, apa pun bahasa yang mungkin, seperti yang ditentukan oleh pengelola atau pengelola. ## Lampiran ### Koma Pertama. Setiap proyek yang mengutip dokumen ini sebagai panduan dasar gaya yang tidak akan menerima format koma kode pertama, kecuali secara eksplisit ditentukan lain oleh penulis proyek ini. ---------- Creative Commons License
Principles of Writing Consistent, Idiomatic JavaScript by Rick Waldron and Contributors is licensed under a Creative Commons Attribution 3.0 Unported License.
Based on a work at github.com/rwldrn/idiomatic.js. ================================================ FILE: translations/it_IT/readme.md ================================================ # Princìpi per la scrittura di JavaScript consistente ed idiomatico ## Questo è un documento in continua evoluzione e nuove idee sono sempre bene accette. Per contribuire: fork, clone, branch, commit, push, pull request. * Rick Waldron [@rwaldron](http://twitter.com/rwaldron), [github](https://github.com/rwaldron) * Mathias Bynens [@mathias](http://twitter.com/mathias), [github](https://github.com/mathiasbynens) * Schalk Neethling [@ossreleasefeed](http://twitter.com/ossreleasefeed), [github](https://github.com/ossreleasefeed/) * Kit Cambridge [@kitcambridge](http://twitter.com/kitcambridge), [github](https://github.com/kitcambridge) * Raynos [github](https://github.com/Raynos) * Matias Arriola [@MatiasArriola](https://twitter.com/MatiasArriola), [github](https://github.com/MatiasArriola/) * John Fischer [@jfroffice](https://twitter.com/jfroffice), [github](https://github.com/jfroffice/) * Idan Gazit [@idangazit](http://twitter.com/idangazit), [github](https://github.com/idan) * Leo Balter [@leobalter](http://twitter.com/leobalter), [github](https://github.com/leobalter) * Breno Oliveira [@garu_rj](http://twitter.com/garu_rj), [github](https://github.com/garu) * Leo Beto Souza [@leobetosouza](http://twitter.com/leobetosouza), [github](https://github.com/leobetosouza) * Ryuichi Okumura [@okuryu](http://twitter.com/okuryu), [github](https://github.com/okuryu) * Pascal Precht [@PascalPrecht](http://twitter.com/PascalPrecht), [github](https://github.com/pascalprecht) * EngForDev [engfordev](http://www.opentutorials.org/course/167/1363) - Hwan Min Hong / MinTaek Kwon [@leoinsight](http://twitter.com/leoinsight) / Tw Shim [@marocchino](http://twitter.com/marocchino), [github](https://github.com/marocchino) / Nassol Kim [@nassol99](http://twitter.com/nassol99), [github](https://github.com/nassol) / Juntai Park [@rkJun](http://twitter.com/rkJun), [github](https://github.com/rkJun) / Minkyu Shim / Gangmin Won / Justin Yoo [@justinchronicle](http://twitter.com/justinchronicle) / Daeyup Lee * Marco Trulla [@marcotrulla](http://twitter.com/marcotrulla), [github](https://github.com/Ragnarokkr) * Alex Navasardyan [@alexnavasardyan](http://twitter.com/alexnavasardyan), [github](https://github.com/2k00l) * Mihai Paun [@mihaipaun](http://twitter.com/mihaipaun), [github](https://github.com/mihaipaun) * Evgeny Mandrikov [@\_godin\_](http://twitter.com/_godin_), [github](https://github.com/Godin) * Sofish Lin [@sofish](http://twitter.com/sofish), [github](https://github.com/sofish) * Дејан Димић [@dejan_dimic](http://twitter.com/dejan_dimic), [github](https://github.com/rubystream) * Miloš Gavrilović [@gavrisimo](http://twitter.com/gavrisimo), [github](https://github.com/gavrisimo) * Firede [@firede](https://twitter.com/firede) [github](https://github.com/firede) * monkadd [github](https://github.com/monkadd) * Stephan Lindauer [@stephanlindauer](http://twitter.com/stephanlindauer), [github](https://github.com/stephanlindauer) * Thomas P [@dragon5689](https://twitter.com/dragon5689) [github](https://github.com/dragon5689) * Yotam Ofek [@yotamofek](https://twitter.com/yotamofek) [github](https://github.com/yotamofek) * Duc Nguyen [@ducntq](https://twitter.com/ducntq), [github](https://github.com/ducntq) * James Young [@jamsyoung](http://twitter.com/jamsyoung), [github](https://github.com/jamsyoung) * Stephane Moreau [github](https://github.com/stmoreau) * Boris Nekezov [github](https://github.com/boris-nekezov) * Akshat Joshi [@akshat_joshi](http://twitter.com/akshat_joshi), [github](https://https://github.com/akshatjoshii) ## Tutto il codice, in qualsiasi linguaggio sia, dovrebbe sembrare come scritto da un'unica persona, non importa quante persone vi abbiano contribuito. ### Il seguente elenco, evidenzia le pratiche che utilizzo in tutto il codice di cui sono l'autore originale; contributi ai progetti da me creati dovrebbero seguire queste linee guida. ### Non è mia intenzione imporre il mio stile su codice o progetti altrui; se esiste già uno stile comune, esso dovrebbe essere rispettato. > ### "Discussioni sullo stile sono inutili. Ci dovrebbe essere una guida di stile, e voi dovreste seguirla" >_Rebecca_ _Murphey_   > ### "Parte dell'essere un buon amministratore in un progetto votato al successo è capire che la scrittura di codice per sé stessi è una Cattiva Idea™. Se migliaia di persone usano il tuo codice, allora scrivi il tuo codice in modo che abbia la massima chiarezza, e non seguendo i tuoi gusti personali su come renderlo chiaro all'interno delle specifiche." >_Idan_ _Gazit_ ## Traduzioni * [ORIGINAL](https://github.com/rwldrn/idiomatic.js/) * [Bulgarian](https://github.com/rwldrn/idiomatic.js/tree/master/translations/bg_BG) * [German](https://github.com/rwldrn/idiomatic.js/tree/master/translations/de_DE) * [French](https://github.com/rwldrn/idiomatic.js/tree/master/translations/fr_FR) * [Spanish](https://github.com/rwldrn/idiomatic.js/tree/master/translations/es_ES) * [Portuguese - Brazil](https://github.com/rwldrn/idiomatic.js/tree/master/translations/pt_BR) * [Korean](https://github.com/rwldrn/idiomatic.js/tree/master/translations/ko_KR) * [Japanese](https://github.com/rwldrn/idiomatic.js/tree/master/translations/ja_JP) * [Italian](https://github.com/rwldrn/idiomatic.js/tree/master/translations/it_IT) * [Russian](https://github.com/rwldrn/idiomatic.js/tree/master/translations/ru_RU) * [Romanian](https://github.com/rwldrn/idiomatic.js/tree/master/translations/ro_RO) * [简体中文](https://github.com/rwldrn/idiomatic.js/tree/master/translations/zh_CN) * [Serbian - cyrilic alphabet](https://github.com/rwldrn/idiomatic.js/tree/master/translations/ср_СР) * [Serbian - latin aplphabet](https://github.com/rwldrn/idiomatic.js/tree/master/translations/sr_SR) * [Greek](https://github.com/rwaldron/idiomatic.js/tree/master/translations/gr_GR) * [Hindi](https://github.com/rwaldron/idiomatic.js/tree/master/translations/hi_HI) ## Cose importanti, non idiomatiche: ### Strumenti per la qualità del codice, risorse e guide * [JavaScript Plugin](http://docs.codehaus.org/display/SONAR/JavaScript+Plugin) per [Sonar](http://www.sonarsource.org/) * [Plato](https://github.com/jsoverson/plato) * [jsPerf](http://jsperf.com/) * [jsFiddle](http://jsfiddle.net/) * [jsbin](http://jsbin.com/) * [JavaScript Lint (JSL)](http://javascriptlint.com/) * [jshint](http://jshint.com/) * [jslint](http://jslint.org/) * [jscs](https://www.npmjs.org/package/jscs) * [Editorconfig](http://editorconfig.org/) ### Impara ### [ECMAScript 5.1 con Annotazioni](http://es5.github.com/) ### [Specifiche Linguaggio EcmaScript, edizione 5.1](http://ecma-international.org/ecma-262/5.1/) I seguenti dovrebbero essere considerati come 1) incompleti e 2) *LETTURE NECESSARIE*. Non sempre sono d'accordo con lo stile scritto dagli autori qui sotto, ma una cosa è certa: sono consistenti. Quindi, sono da considerare delle autorità per questo linguaggio. * [Baseline For Front End Developers](http://rmurphey.com/blog/2012/04/12/a-baseline-for-front-end-developers/) * [Eloquent JavaScript](http://eloquentjavascript.net/) * [JavaScript, JavaScript](http://javascriptweblog.wordpress.com/) * [Adventures in JavaScript Development](http://rmurphey.com/) * [Perfection Kills](http://perfectionkills.com/) * [Douglas Crockford's Wrrrld Wide Web](http://www.crockford.com) * [JS Assessment](https://github.com/rmurphey/js-assessment) ### Processo di costruzione e distribuzione Ogni progetto dovrebbe sempre cercare di fornire un qualche strumento generico, per mezzo del quale i sorgenti possano venire validati, testati e compressi per il successivo utilizzo in ambiente di produzione. Per questo lavoro, [grunt](https://github.com/gruntjs/grunt) di Ben Alman non è secondo a nessuno e ha ufficialmente rimpiazzato la directory "kits/" di questo repo. ### Processo di testing I progetti _devono_ includere una qualche sorta di unità, guida o implementazione di test oppure un test funzionale. Dimostrazioni di casi d'uso NON SONO QUALIFICATI come "test". La seguente è una lista di framework per il testing, nessuno dei quali è preferito rispetto all'altro. * [QUnit](http://github.com/jquery/qunit) * [Jasmine](https://github.com/pivotal/jasmine) * [Vows](https://github.com/cloudhead/vows) * [Mocha](https://github.com/visionmedia/mocha) * [Hiro](http://hirojs.com/) * [JsTestDriver](https://code.google.com/p/js-test-driver/) * [Buster.js](http://busterjs.org/) * [Sinon.js](http://sinonjs.org/) ## Tavola dei contenuti * [Spazio vuoto](#whitespace) * [Bella sintassi](#spacing) * [Controllo dei tipi (offerto dalle linee guida della jQuery Core Style)](#type) * [Esecuzione condizionale](#cond) * [Stile pratico](#practical) * [Nomenclatura](#naming) * [Varie](#misc) * [Oggetti nativi e ospite](#native) * [Commenti](#comments) * [Un codice di linguaggio](#language) ------------------------------------------------ ## Prefazione Le seguenti sezioni evidenziano una _ragionevole_ guida di stile per il moderno sviluppo di JavaScript, e non sono intese per essere obbligatorie. Il concetto più importante è la **legge sulla consistenza dello stile nel codice**. Qualsiasi stile scegliate per i vostri progetti dovrebbe essere considerato legge. Potete mettere un link a questo documento come espressione di impegno alla consistenza, leggibilità e manutenibilità del codice del vostro progetto. ## Manifesto dello stile idiomatico 1. Spazio vuoto - Mai mischiare spazi e tabulazioni. - Quando iniziate un progetto, prima di cominciare a scrivere il codice, scegliete tra indentazione soft (spazi) o tabulazioni reali, e considerate questa scelta **legge**. - Per la leggibilità, raccomando sempre di impostare la dimensione dei rientri del proprio editor a due caratteri — questo significa, due spazi o due spazi rappresentanti una tabulazione reale. - Se il vostro editor lo supporta, lavorate sempre con l'impostazione "mostra caratteri invisibili" attiva. I benefici di questa pratica sono: - Rafforzata consistenza - Eliminazione di spazi vuoti alla fine delle linee - Eliminazione di linee vuote - Commit e diff più facili da leggere - Usate [Editorconfig](http://editorconfig.org/) quando possibile. Supporta la maggior parte degli IDE e gestisce la maggior parte delle impostazioni per gli spazi vuoti. 2. Bella sintassi A. Parentesi, parentesi graffe, interruzioni di linea ```javascript // if/else/for/while/try hanno sempre spazi, parentesi graffe e sono suddivisi su // più linee, questo incoragga la leggibilità // 2.A.1.1 // Esempi di sintassi veramente illeggibile if(condition) doSomething(); while(condition) iterating++; for(var i=0;i<100;i++) someIterativeFn(); // 2.A.1.1 // Uso degli spazi vuoti per incrementare la leggibilità if ( condizione ) { // istruzioni } while ( condizione ) { // istruzioni } for ( var i = 0; i < 100; i++ ) { // istruzioni } // Ancora meglio: var i, length = 100; for ( i = 0; i < length; i++ ) { // istruzioni } // Oppure... var i = 0, length = 100; for ( ; i < length; i++ ) { // istruzioni } var prop; for ( prop in object ) { // istruzioni } if ( true ) { // istruzioni } else { // istruzioni } ``` B. Assegnazioni, dichiarazioni, funzioni ( non anonima, espressione, costruttore ) ```javascript // 2.B.1.1 // Variabili var foo = "bar", num = 1, undef; // Notazioni literal: var array = [], object = {}; // 2.B.1.2 // L'utilizzo di una sola `var` per scope (funzione) incrementa la leggibilità // e mantiene la tua lista di dichiarazioni ordinata (inoltre riduce il numero di digitazioni) // Sbagliato var foo = ""; var bar = ""; var qux; // Corretto var foo = "", bar = "", quux; // oppure... var // Commento su questa linea foo = "", bar = "", quux; // 2.B.1.3 // le dichiarazioni var dovrebbero sempre risiedere all'inizio del rispettivo scope (funzione). // Lo stesso vale per const e let di ECMAScript 6. // Sbagliato function foo() { // alcune istruzioni qui var bar = "", qux; } // Corretto function foo() { var bar = "", qux; // tutto il codice dopo le dichiarazioni delle variabili. } // 2.B.1.4 // const e let, da ECMAScript 6, dovrebbero essere posizionate all'inizio del loro scope (blocco). // Sbagliato function foo() { let foo, bar; if ( condition ) { bar = ""; // istruzioni } } // Corretto function foo() { let foo; if ( condition ) { let bar = ""; // istruzioni } } ``` ```javascript // 2.B.2.1 // Dichiarazione di funzione non anonima function foo( arg1, argN ) { } // Utilizzo foo( arg1, argN ); // 2.B.2.2 // Dichiarazione di funzione non anonima function square( number ) { return number * number; } // Utilizzo square( 10 ); // Stile forzato di passaggio dei parametri a cascata function square( number, callback ) { callback( number * number ); } square( 10, function( square ) { // istruzioni di callback }); // 2.B.2.3 // Funzione espressione var square = function( number ) { // Ritorna qualcosa di importante e rilevante return number * number; }; // Funzione espressione con identificatore // Questa è la variante preferita, ha il valore aggiunto di essere in grado // di richiamare sé stessa ed ha un'identità nelle tracce dello stack: var factorial = function factorial( number ) { if ( number < 2 ) { return 1; } return number * factorial( number - 1 ); }; // 2.B.2.4 // Dichiarazione di costruttore function FooBar( options ) { this.options = options; } // Utilizzo var fooBar = new FooBar({ a: "alpha" }); fooBar.options; // { a: "alpha" } ``` C. Eccezioni, lievi deviazioni ```javascript // 2.C.1.1 // Funzioni con callback foo(function() { // Nota che non ci sono spazi tra la prima parentesi // della funzione chiamata in esecuzione e la parola "function" }); // Funzione che accetta un array, nessuno spazio foo([ "alpha", "beta" ]); // 2.C.1.2 // Funzione che accetta un oggetto, nessuno spazio foo({ a: "alpha", b: "beta" }); // Singolo argomento stringa, nessuno spazio foo("bar"); // Parentesi interne di raggruppamento, nessuno spazio if ( !("foo" in obj) ) { } ``` D. La consistenza vince sempre Nelle sezioni da 2.A a 2.C, le regole per lo spazio vuoto vengono stabilite come raccomandazione per un motivo semplice ed importante: la consistenza. È importante notare che le preferenze di formattazione, come lo "spazio vuoto interno" dovrebbero essere considerate opzionali, ma solo uno stile dovrebbe esistere per l'intero sorgente del vostro progetto. ```javascript // 2.D.1.1 if (condizione) { // istruzioni } while (condizione) { // istruzioni } for (var i = 0; i < 100; i++) { // istruzioni } if (true) { // istruzioni } else { // istruzioni } ``` E. Apici Che preferiate singoli o doppi apici non importa, non c'è differenza di gestione da parte di JavaScript. Ciò che **DEVE ASSOLUTAMENTE** essere mantenuta è la consistenza. **Mai mischiare gli apici nello stesso progetto. Scegliete uno stile e proseguite con esso.** F. Fine delle linee e linee vuote Lo spazio vuoto può complicare le diff e rendere le modifiche impossibili da leggere. Considerate di implementare un hook di pre-commit che rimuova automaticamente lo spazio vuoto alla fine delle linee e gli spazi vuoti nelle linee vuote. 3. Controllo di tipo (offerto dalle linee guida della jQuery Core Style) A. Tipi attuali Stringa: typeof variable === "string" Numero: typeof variable === "number" Booleano: typeof variable === "boolean" Oggetto: typeof variable === "object" Array: Array.isArray( arrayLikeObject ) (dove possibile) Nodo: elem.nodeType === 1 Nullo: variable === null Nullo o non definito (undefined): variable == null Non definito: Variabili globali: typeof variable === "undefined" Variabili locali: variable === undefined Proprietà: object.prop === undefined object.hasOwnProperty( prop ) "prop" in object B. Tipi forzati Considerate le implicazioni di ciò che segue... Dato questo codice HTML: ```html ``` ```javascript // 3.B.1.1 // `foo` è stato dichiarato di valore `0` ed il suo tipo è `number` var foo = 0; // typeof foo; // "number" ... // Successivamente, in qualche altra parte del codice, necessitate di aggiornare `foo` // con un nuovo valore derivato da un elemento input foo = document.getElementById("foo-input").value; // Se testaste `typeof foo` adesso, il risultato sarebbe `string` // Ciò significa che se aveste del codice che testa `foo` in questo modo: if ( foo === 1 ) { importantTask(); } // `importantTask()` non verrebbe mai eseguito, anche se `foo` fosse di valore "1" // 3.B.1.2 // Potete prevenire questi problemi usando la forzatura intelligente con gli operatori unari + o -: foo = +document.getElementById("foo-input").value; // ^ l'operatore + unario convertirà il suo operando destro in un numero // typeof foo; // "number" if ( foo === 1 ) { importantTask(); } // `importantTask()` verrà eseguito ``` Ecco alcuni casi comuni con forzature: ```javascript // 3.B.2.1 var number = 1, string = "1", bool = false; number; // 1 number + ""; // "1" string; // "1" +string; // 1 +string++; // 1 string; // 2 bool; // false +bool; // 0 bool + ""; // "false" ``` ```javascript // 3.B.2.2 var number = 1, string = "1", bool = true; string === number; // false string === number + ""; // true +string === number; // true bool === number; // false +bool === number; // true bool === string; // false bool === !!string; // true ``` ```javascript // 3.B.2.3 var array = [ "a", "b", "c" ]; !!~array.indexOf("a"); // true !!~array.indexOf("b"); // true !!~array.indexOf("c"); // true !!~array.indexOf("d"); // false // Tenete presente che i summenzionati esempi dovrebbero essere considerati come "eccessivamente chiari" // È da preferire il più ovvio approccio di comparazione del valore ritornato // da indexOf, cioè: if ( array.indexOf( "a" ) >= 0 ) { // ... } ``` ```javascript // 3.B.2.4 var num = 2.5; parseInt( num, 10 ); // è l'equivalente di... ~~num; num >> 0; num >>> 0; // Tutti danno come risultato 2 // Comunque ricordate che i numeri negativi verranno trattati differentemente... var neg = -2.5; parseInt( neg, 10 ); // è l'equivalente di... ~~neg; neg >> 0; // Tutti danno come risultato -2 // Ma... neg >>> 0 // Darà come risultato 4294967294 ``` 4. Esecuzione condizionale ```javascript // 4.1.1 // Quando si deve solo stabilire se un array ha una dimensione, // invece di questo: if ( array.length > 0 ) ... // ...verificate la verità condizionale, in questo modo: if ( array.length ) ... // 4.1.2 // Quando si deve solo stabilire che un array è vuoto, // invece di questo: if ( array.length === 0 ) ... // ...verificate la verità condizionale, in questo modo: if ( !array.length ) ... // 4.1.3 // Quando si deve solo stabilire che una stringa non è vuota, // invece di questo: if ( string !== "" ) ... // ...verificate la verità condizionale, in questo modo: if ( string ) ... // 4.1.4 // Quando si deve solo stabilire che una stringa _è_ vuota, // invece di questo: if ( string === "" ) ... // ...verificate la verità condizionale, in questo modo: if ( !string ) ... // 4.1.5 // Quando si deve solo stabilire che un riferimento è vero, // invece di questo: if ( foo === true ) ... // ...verificatelo per il suo significato, avvantaggiatevi delle funzionalità proprie del linguaggio: if ( foo ) ... // 4.1.6 // Quando si deve solo stabilire che un riferimento è falso, // invece di questo: if ( foo === false ) ... // ...usate la negazione per forzare una valutazione vera if ( !foo ) ... // ...ma state attenti, questo varrà anche per: 0, "", null, undefined, NaN // Se _DOVETE_ testare per un falso booleano, allora usate if ( foo === false ) ... // 4.1.7 // Quando si deve solo stabilire che un riferimento potrebbe essere null o undefined, // ma NON falso, "" o 0, invece di questo: if ( foo === null || foo === undefined ) ... // ...avvantaggiatevi della forzatura di tipo fatta da ==, in questo modo: if ( foo == null ) ... // Ricordate, l'uso di == farà corrispondere un `null` SIA a `null` che a `undefined` // ma non a `false`, "" o 0 null == undefined ``` Valutate SEMPRE per il risultato migliore e più accurato - quella sopra è una linea guida, non un dogma. ```javascript // 4.2.1 // Note sulla forzatura di tipo e sulla valutazione // Preferite `===` a `==` (a meno che il caso non richieda una valutazione di tipo meno restrittiva) // === non forza il tipo, ciò significa che: "1" === 1: // false // == forza il tipo, ciò significa che: "1" == 1; // true // 4.2.2 // Booleani, verità e falsità // Booleani: true, false // Verità: "foo", 1 // Falsità: "", 0, null, undefined, NaN, void 0 ``` 5. Stile pratico ```javascript // 5.1.1 // Un modulo pratico (function( global ) { var Module = (function() { var data = "secret"; return { // Proprietà booleana bool: true, // Un valore stringa string: "a string", // Una proprietà array array: [ 1, 2, 3, 4 ], // Una proprietà oggetto object: { lang: "en-US" }, getData: function() { // ottiene il valore corrente di `data` return data; }, setData: function( value ) { // imposta il valore di `data` e lo ritorna return ( data = value ); } }; })(); // Altre istruzioni // esponiamo il nostro modulo all'oggetto globale global.Module = Module; })( this ); ``` ```javascript // 5.2.1 // Un costruttore pratico (function( global ) { function Ctor( foo ) { this.foo = foo; return this; } Ctor.prototype.getFoo = function() { return this.foo; }; Ctor.prototype.setFoo = function( val ) { return ( this.foo = val ); }; // Per richiamare il costruttore senza `new`, potreste fare così: var ctor = function( foo ) { return new Ctor( foo ); }; // esponiamo il nostro costruttore all'oggetto globale global.ctor = ctor; })( this ); ``` 6. Nomenclatura A. Non siete un compilatore/compressore umano di codice, quindi non cercate di esserlo. Il seguente codice è un esempio di tremenda nomenclatura: ```javascript // 6.A.1.1 // Esempio di codice con nomi per nulla chiari function q(s) { return document.querySelectorAll(s); } var i,a=[],els=q("#foo"); for(i=0;iVarie Questa sezione servirà ad illustrare idee e concetti che non dovrebbero essere considerati un dogma, ma che invece esistono per incoraggiare pratiche di analisi nel tentativo di ricercare le migliori modalità per eseguire attività comuni di programmazione JavaScript. A. L'utilizzo di `switch` dovrebbe essere evitato, il metodo moderno di analisi metterà nella lista nera le funzioni con istruzioni switch Sembra che ci siano drastici miglioramenti nell'esecuzione di istruzioni `switch` nelle ultime release di Firefox e Chrome. http://jsperf.com/switch-vs-object-literal-vs-module Visibili miglioramenti vengono riportati anche qui: https://github.com/rwldrn/idiomatic.js/issues/13 ```javascript // 7.A.1.1 // Un esempio di istruzione switch switch( foo ) { case "alpha": alpha(); break; case "beta": beta(); break; default: // qualcosa da eseguire di default break; } // 7.A.1.2 // Un approccio alternativo che supporta componibilità e riusabilità è di // usare un oggetto come magazzino dei "casi" ed una funzione per delegare: var cases, delegator; // I return sono solo a titolo esplicativo. cases = { alpha: function() { // istruzioni // un return return [ "Alpha", arguments.length ]; }, beta: function() { // istruzioni // un return return [ "Beta", arguments.length ]; }, _default: function() { // istruzioni // un return return [ "Default", arguments.length ] } }; delegator = function() { var args, key, delegate; // Trasforma la lista degli argomenti in un array args = [].slice.call( arguments ); // Estrae la chiave del caso dagli argomenti key = args.shift(); // Assegna il gestore del caso di default delegate = cases._default; // Risale al metodo al quale delegare l'esecuzione if ( cases.hasOwnProperties( key ) ) { delegate = cases[ key ]; } // L'argomento dello scope può essere impostato a qualcosa di specifico, // in questo caso, |null| sarà sufficiente return delegate.apply( null, args ); }; // 7.A.1.3 // Per funzionare prendiamo la API di 7.A.1.2: delegator( "alpha", 1, 2, 3, 4, 5 ); // [ "Alpha", 5 ] // Ovviamente, l'argomento chiave `case` può facilmente essere basato // su qualche altra condizione arbitraria. var caseKey, someUserInput; // Qualche possibile tipo di input da un form? someUserInput = 9; if ( someUserInput > 10 ) { caseKey = "alpha"; } else { caseKey = "beta"; } // oppure... caseKey = someUserInput > 10 ? "alpha" : "beta"; // E quindi... delegator( caseKey, someUserInput ); // [ "Beta", 1 ] // E ovviamente... delegator(); // [ "Default", 0 ] ``` B. I ritorni da funzione anticipati promuovono la leggibilità del codice a fronte di una differenza di performance trascurabile ```javascript // 7.B.1.1 // Sbagliato: function returnLate( foo ) { var ret; if ( foo ) { ret = "foo"; } else { ret = "quux"; } return ret; } // Corretto: function returnEarly( foo ) { if ( foo ) { return "foo"; } return "quux"; } ``` 8. Oggetti nativi e ospite Il principio base qui è: ### Non fare cose stupide e tutto andrà per il meglio. Per rafforzare questo concetto, date un'occhiata alla seguente presentazione: #### “Everything is Permitted: Extending Built-ins” di Andrew Dupont (JSConf2011, Portland, Oregon) https://www.youtube.com/watch?v=xL3xCO7CLNM 9. Commenti #### Linea singola sopra il codice a cui ci si riferisce #### Multilinea va bene #### Commenti a fine linea sono proibiti! #### Lo stile JSDoc va bene, ma richiede un significante investimento di tempo 10. Un codice di linguaggio I programmi dovrebbero essere scritti in un linguaggio, qualsiasi esso sia, come richiesto dal mantenitore o dai mantenitori. ## Appendice ### Comma First. Qualsiasi progetto che citi questo documento come sua guida base di stile non accetterà la formattazione comma first del codice, a meno che non sia esplicitamente specificato dall'autore del progetto. ---------- Creative Commons License
Principles of Writing Consistent, Idiomatic JavaScript by Rick Waldron and Contributors is licensed under a Creative Commons Attribution 3.0 Unported License.
Based on a work at github.com/rwldrn/idiomatic.js. ================================================ FILE: translations/ja_JP/readme.md ================================================ # 一貫性のある慣用的なJavaScriptの書き方 ## これは継続しているドキュメントであるため、私たちのコードを改善できる新しいアイデアを常に歓迎します。貢献方法: fork、clone、branch、commit、push、pull request。 * Rick Waldron [@rwaldron](http://twitter.com/rwaldron), [github](https://github.com/rwaldron) * Mathias Bynens [@mathias](http://twitter.com/mathias), [github](https://github.com/mathiasbynens) * Schalk Neethling [@ossreleasefeed](http://twitter.com/ossreleasefeed), [github](https://github.com/ossreleasefeed/) * Kit Cambridge [@kitcambridge](http://twitter.com/kitcambridge), [github](https://github.com/kitcambridge) * Raynos [github](https://github.com/Raynos) * Matias Arriola [@MatiasArriola](https://twitter.com/MatiasArriola), [github](https://github.com/MatiasArriola/) * John Fischer [@jfroffice](https://twitter.com/jfroffice), [github](https://github.com/jfroffice/) * Idan Gazit [@idangazit](http://twitter.com/idangazit), [github](https://github.com/idangazit) * Leo Balter [@leobalter](http://twitter.com/leobalter), [github](https://github.com/leobalter) * Breno Oliveira [@garu_rj](http://twitter.com/garu_rj), [github](https://github.com/garu) * Leo Beto Souza [@leobetosouza](http://twitter.com/leobetosouza), [github](https://github.com/leobetosouza) * Ryuichi Okumura [@okuryu](http://twitter.com/okuryu), [github](https://github.com/okuryu) * Pascal Precht [@PascalPrecht](http://twitter.com/PascalPrecht), [github](https://github.com/pascalprecht) * EngForDev [engfordev](http://www.opentutorials.org/course/167/1363) - Hwan Min Hong / MinTaek Kwon [@leoinsight](http://twitter.com/leoinsight) / Tw Shim [@marocchino](http://twitter.com/marocchino), [github](https://github.com/marocchino) / Nassol Kim [@nassol99](http://twitter.com/nassol99), [github](https://github.com/nassol) / Juntai Park [@rkJun](http://twitter.com/rkJun), [github](https://github.com/rkJun) / Minkyu Shim / Gangmin Won / Justin Yoo [@justinchronicle](http://twitter.com/justinchronicle) / Daeyup Lee * Marco Trulla [@marcotrulla](http://twitter.com/marcotrulla), [github](https://github.com/Ragnarokkr) * Alex Navasardyan [@alexnavasardyan](http://twitter.com/alexnavasardyan), [github](https://github.com/2k00l) * Mihai Paun [@mihaipaun](http://twitter.com/mihaipaun), [github](https://github.com/mihaipaun) * Evgeny Mandrikov [@\_godin\_](http://twitter.com/_godin_), [github](https://github.com/Godin) * Sofish Lin [@sofish](http://twitter.com/sofish), [github](https://github.com/sofish) * Дејан Димић [@dejan_dimic](http://twitter.com/dejan_dimic), [github](https://github.com/rubystream) * Miloš Gavrilović [@gavrisimo](http://twitter.com/gavrisimo), [github](https://github.com/gavrisimo) * Duc Nguyen [@ducntq](https://twitter.com/ducntq), [github](https://github.com/ducntq) * James Young [@jamsyoung](http://twitter.com/jamsyoung), [github](https://github.com/jamsyoung) * Stephane Moreau [github](https://github.com/stmoreau) * Boris Nekezov [github](https://github.com/boris-nekezov) * Akshat Joshi [@akshat_joshi](http://twitter.com/akshat_joshi), [github](https://https://github.com/akshatjoshii) ## どんなに多くの人が貢献したとしても、どのコードも一人で書いたようにするべきです。 ### 次の項目では私のすべてのコードで使用しているプラクティスを説明しているため、私のプロジェクトに貢献する場合はこれらのガイドラインを理解していなければなりません。 ### 私は皆さんのコードやプロジェクトに私のスタイルを押し付けるつもりはありませんし、もしすでに共通のスタイルがあるのであればそちらを順守すべきです。 > ### "スタイルに関する議論は無意味です。ここにあるスタイルガイドにあなたは従うべきです。" >_Rebecca_ _Murphey_   > ### "成功を収めるプロジェクトをうまく管理することの一つが自分でコードを書いて実現するということではありません。もし多くの人があなたのコードを利用しているなら、仕様の中にはあなたの好みではなく、最大限に明確なコードを書きましょう。" - Idan Gazit >_Idan_ _Gazit_ ## 翻訳 * [ORIGINAL](https://github.com/rwldrn/idiomatic.js/) * [Bulgarian](https://github.com/rwldrn/idiomatic.js/tree/master/translations/bg_BG) * [German](https://github.com/rwldrn/idiomatic.js/tree/master/translations/de_DE) * [French](https://github.com/rwldrn/idiomatic.js/tree/master/translations/fr_FR) * [Spanish](https://github.com/rwldrn/idiomatic.js/tree/master/translations/es_ES) * [Portuguese - Brazil](https://github.com/rwldrn/idiomatic.js/tree/master/translations/pt_BR) * [Korean](https://github.com/rwldrn/idiomatic.js/tree/master/translations/ko_KR) * [Japanese](https://github.com/rwldrn/idiomatic.js/tree/master/translations/ja_JP) * [Italian](https://github.com/rwldrn/idiomatic.js/tree/master/translations/it_IT) * [Russian](https://github.com/rwldrn/idiomatic.js/tree/master/translations/ru_RU) * [Romanian](https://github.com/rwldrn/idiomatic.js/tree/master/translations/ro_RO) * [简体中文](https://github.com/rwldrn/idiomatic.js/tree/master/translations/zh_CN) * [Serbian - cyrilic alphabet](https://github.com/rwldrn/idiomatic.js/tree/master/translations/ср_СР) * [Serbian - latin aplphabet](https://github.com/rwldrn/idiomatic.js/tree/master/translations/sr_SR) * [Greek](https://github.com/rwaldron/idiomatic.js/tree/master/translations/gr_GR) * [Hindi](https://github.com/rwaldron/idiomatic.js/tree/master/translations/hi_HI) ## 慣用的ではないもの(重要): ### コードの品質ツールや情報とリファレンス * [JavaScript Plugin](http://docs.codehaus.org/display/SONAR/JavaScript+Plugin) for [Sonar](http://www.sonarsource.org/) * [Plato](https://github.com/jsoverson/plato) * [jsPerf](http://jsperf.com/) * [jsFiddle](http://jsfiddle.net/) * [jsbin](http://jsbin.com/) * [JavaScript Lint (JSL)](http://javascriptlint.com/) * [jshint](http://jshint.com/) * [jslint](http://jslint.org/) * [Editorconfig](http://editorconfig.org/) ## 賢くなろう ### [Annotated ECMAScript 5.1](http://es5.github.com/) ### [EcmaScript Language Specification, 5.1 Edition](http://ecma-international.org/ecma-262/5.1/) 下記の事項は 1) 不完全、2) *必読*ということを熟考しなければなりません。私はこれらの作者によるスタイルに常に同意はしていませんが、彼らは一貫性があるため信頼できるのも確かです。その上、これらは言語の世界では権威があるものです。 * [Baseline For Front End Developers](http://rmurphey.com/blog/2012/04/12/a-baseline-for-front-end-developers/) * [Eloquent JavaScript](http://eloquentjavascript.net/) * [JavaScript, JavaScript](http://javascriptweblog.wordpress.com/) * [Adventures in JavaScript Development](http://rmurphey.com/) * [Perfection Kills](http://perfectionkills.com/) * [Douglas Crockford's Wrrrld Wide Web](http://www.crockford.com) * [JS Assessment](https://github.com/rmurphey/js-assessment) * [Leveraging Code Quality Tools by Anton Kovalyov](http://anton.kovalyov.net/slides/gothamjs/) ### ビルドとデプロイのプロセス プロジェクトは常にプロダクションで使うための準備の中にチェックやテスト、圧縮などをするためのいくつかの包括的な手法を含めるように努力するべきです。このタスクのために、Ben Almanによる[grunt](https://github.com/cowboy/grunt)は他と比べようもないほど素晴らしく、このレポジトリの "kits/" ディレクトリも正式に置き換えられました。 ### テストする仕組み ユースケースデモを"テスト"として見なしてはいけません。下記の事項はテストフレームワークのリストで、どれも他の何よりも支持されているものです。 * [QUnit](http://github.com/jquery/qunit) * [Jasmine](https://github.com/pivotal/jasmine) * [Vows](https://github.com/cloudhead/vows) * [Mocha](https://github.com/visionmedia/mocha) * [Hiro](http://hirojs.com/) * [JsTestDriver](https://code.google.com/p/js-test-driver/) * [Buster.js](http://busterjs.org/) ## 目次 * [スペース](#whitespace) * [美しい構文](#spacing) * [型のチェック(jQeury Core Style Guidelinesの作法)](#type) * [条件文の評価](#cond) * [実際のスタイル](#practical) * [ネーミング](#naming) * [雑則](#misc) * [ネイティブオブジェクトとホストオブジェクト](#native) * [コメント](#comments) * [1つの言語としてのコード](#language) ------------------------------------------------ ## 序文 下記のセクションではモダンなJavaScriptの開発のための_合理的な_スタイルガイドを説明していますが、規範的になれという意味ではありません。最も重要なことは**一貫性のあるコードスタイル法則**ということです。どんなものでもあなたのプロジェクトのために選ぶスタイルは一貫性のある法則であるべきです。一貫性、可読性、メンテナンス性のあるコードスタイルにするためにあなたのプロジェクトのコミットメントとしてこのドキュメントへリンクしてください。 ## 一貫性のあるスタイル宣言 1. スペース - スペースとタブを混ぜてはいけません。 - プロジェクトの新しく始める時、コードを書く前にソフトインデント(スペース)かタブか選択するようにこの法則を検討してください。 - 可読性をのために、私はエディターのインデントサイズを2文字にするようにいつも推奨しています — これは2つのスペースまたはタブを2つのスペースに表現することを意味しています。 - もしあなたのエディターが"不可視文字を表示する"設定があるなら常にオンにしてください。このプラクティスのメリットは: - 一貫性を強制できる - 行末のスペースをなくせる - スペースの空行をなくせる - コミットと差分が読みやすくなる 2. 美しい構文 A. 丸括弧、中括弧、改行 ```javascript // if/else/for/while/try は常にスペースをもち、波括弧が複数の行に架かるようにします // これは可読性を促進します // 2.A.1.1 // あまりに読みにくい構文の例 if(condition) doSomething(); while(condition) iterating++; for(var i=0;i<100;i++) someIterativeFn(); // 2.A.1.1 // 可読性を促進するためにスペースを使います if ( condition ) { // 文 } while ( condition ) { // 文 } for ( var i = 0; i < 100; i++ ) { // 文 } // より良い例: var i, length = 100; for ( i = 0; i < length; i++ ) { // 文 } // または... var i = 0, length = 100; for ( ; i < length; i++ ) { // 文 } var prop; for ( prop in object ) { // 文 } if ( true ) { // 文 } else { // 文 } ``` B. 割り当て、宣言、関数(名前、式、コンストラクター) ```javascript // 2.B.1.1 // 変数 var foo = "bar", num = 1, undef; // リテラル表記: var array = [], object = {}; // 2.B.1.2 // 可読性を促進するためにスコープ(関数)ごとに1つだけ `var` を使用します // 宣言するリストはすっきりしている状態を保ちます(同様に少ないキーストロークを守ります) // 悪い例 var foo = ""; var bar = ""; var qux; // 良い例 var foo = "", bar = "", quux; // または var // ここにコメントをつけます foo = "", bar = "", quux; // 2.B.1.3 // var文は常にそれぞれのスコープ(関数)の最初になくてはなりません。 // 悪い例 function foo() { // ここにいくつかの文を書きます var bar = "", qux; } // 良い例 function foo() { var bar = "", qux; // すべての文は変数の宣言の後に書きます } // 2.B.1.4 // ECMAScript 6のconstやletもまた同様です。 // 悪い例 function foo() { let foo, bar; if ( condition ) { bar = ""; // statements } } // 良い例 function foo() { let foo; if ( condition ) { let bar = ""; // statements } } ``` ```javascript // 2.B.2.1 // 名前つきの関数の宣言 function foo( arg1, argN ) { } // 関数の使い方 foo( arg1, argN ); // 2.B.2.2 // 名前つきの関数の宣言 function square( number ) { return number * number; } // 関数の使い方 square( 10 ); // とても不自然な継続渡しスタイル function square( number, callback ) { callback( number * number ); } square( 10, function( square ) { // コールバック関数の文 }); // 2.B.2.3 // 式による関数の宣言 var square = function( number ) { // 値や関連する何かを返します return number * number; }; // 識別子と式による関数の宣言 // この望ましい形では、スタックトレースの中で自ら呼び出せる識別子を // 持つことができます var factorial = function factorial( number ) { if ( number < 2 ) { return 1; } return number * factorial( number-1 ); }; // 2.B.2.4 // コンストラクターの宣言 function FooBar( options ) { this.options = options; } // コンストラクターの使い方 var fooBar = new FooBar({ a: "alpha" }); fooBar.options; // { a: "alpha" } ``` C. 例外や些細なこと ```javascript // 2.C.1.1 // コールバックと関数 foo(function() { // ここには実行される関数の最初の括弧と"function"との間には // スペースがないことを注意してください }); // 配列を受け取る関数、スペースはなし foo([ "alpha", "beta" ]); // 2.C.1.2 // オブジェクトを受け取る関数、スペースなし foo({ a: "alpha", b: "beta" }); // 1つの文字列を受け取る場合、スペースなし foo("bar"); // 中でグループ化された括弧、スペースなし if ( !("foo" in obj) ) { } ``` D. 一貫性が常に勝つ セクション2.A-2.Cのスペースのルールはよりシンプルで高い目的のための提案としたセットで一貫性に繋がるものです。 "中のスペース"のようなフォーマットの好みは任意で検討するように気をつけなければいけませんが、1つのスタイルがあなたのプロジェクトのソース全体で揃っていなければなりません。 ```javascript // 2.D.1.1 if (condition) { // 文 } while (condition) { // 文 } for (var i = 0; i < 100; i++) { // 文 } if (true) { // 文 } else { // 文 } ``` E. クオート あなたの好みがシングルクオートだろうとダブルクオートだろうとどうでもいい事です。これらはJavaScriptの解析においては違いはありません。**絶対に**強制されることは一貫性に繋がります。**同じプロジェクトの中でクオートを混ぜないでください。1つのスタイルを選び、それにこだわってください。** F. 行末と空行 スペースは読めない変更点を生み、差分を壊します。コミット前に、自動で行末のスペースや空行のスペースを削除する処理を行うことを検討してください。 3. 型のチェック(jQeury Core Style Guidelinesの作法) A. 実際の型 文字列: typeof variable === "string" 数値: typeof variable === "number" ブール値: typeof variable === "boolean" オブジェクト: typeof variable === "object" 配列: Array.isArray( arrayLikeObject ) (可能な限り) ノード: elem.nodeType === 1 null: variable === null nullまたはundefined: variable == null undefined: グローバル変数: typeof variable === "undefined" ローカル変数: variable === undefined プロパティ: object.prop === undefined object.hasOwnProperty( prop ) "prop" in object B. 強制された型 次の実装を考えてみてください。 こういうHTMLがあったとします: ```html ``` ```javascript // 3.B.1.1 // `foo` は `0` という値で宣言されて、型は `number` になります var foo = 0; // typeof foo; // "number" ... // あなたのコードのどこかで、input要素から値を取得して // `foo` を更新する必要があります foo = document.getElementById("foo-input").value; // もしあなたがこの時点で `typeof foo` をテストした場合、次のような // ロジックがあるとその結果は `string` となることを意味します。 if ( foo === 1 ) { importantTask(); } // `importantTask()` はたとえ `foo` が "1" だとしても評価されないでしょう。 // 3.B.1.2 // + または - といった単項演算子による型強制を使って、この問題を回避できます: foo = +document.getElementById("foo-input").value; // ^ この + 演算子は右側の値をnumberに変換します // typeof foo; // "number" if ( foo === 1 ) { importantTask(); } // こうすれば `importantTask()` は呼び出されます ``` これらは同じように強制的に変換するいくつかの方法です: ```javascript // 3.B.2.1 var number = 1, string = "1", bool = false; number; // 1 number + ""; // "1" string; // "1" +string; // 1 +string++; // 1 string; // 2 bool; // false +bool; // 0 bool + ""; // "false" ``` ```javascript // 3.B.2.2 var number = 1, string = "1", bool = true; string === number; // false string === number + ""; // true +string === number; // true bool === number; // false +bool === number; // true bool === string; // false bool === !!string; // true ``` ```javascript // 3.B.2.3 var array = [ "a", "b", "c" ]; !!~array.indexOf("a"); // true !!~array.indexOf("b"); // true !!~array.indexOf("c"); // true !!~array.indexOf("d"); // false // 上記のやり方は"無駄に賢すぎる"と考えるべきです // 次のように、indexOfが返した値を比較する明確なアプローチに // してみましょう。 if ( array.indexOf( "a" ) >= 0 ) { // ... } ``` ```javascript // 3.B.2.3 var num = 2.5; parseInt( num, 10 ); // これは次の場合と同じです ~~num; num >> 0; num >>> 0; // どれも結果は2になります // しかし、負の値の場合は異なった扱いをされることを覚えておきましょう var neg = -2.5; parseInt( neg, 10 ); // これは次の場合と同じです ~~neg; neg >> 0; // これはどれも-2になります // 一方で... neg >>> 0; // この結果は4294967294となります ``` 4. 条件文の評価 ```javascript // 4.1.1 // 配列の長さがあるかだけを評価する場合は、次の代わりに: if ( array.length > 0 ) ... // このように真偽を評価すればいいでしょう: if ( array.length ) ... // 4.1.2 // 配列が空かどうかだけを評価する場合は次の代わりに: if ( array.length === 0 ) ... // このように真偽を評価すればいいでしょう: if ( !array.length ) ... // 4.1.3 // 文字列が空ではないことだけを評価する場合は次の代わりに: if ( string !== "" ) ... // このように評価すればいいでしょう: if ( string ) ... // 4.1.4 // 文字列が空であることだけを評価する場合は次の代わりに: if ( string === "" ) ... // このように真偽を評価すればいいでしょう: if ( !string ) ... // 4.1.5 // 参照先がtrueかどうかだけ評価する場合は次の代わりに: if ( foo === true ) ... // このように評価します(おわかりのとおり、これは組み込まれた機能です): if ( foo ) ... // 4.1.6 // 参照先がfalseかどうかを評価する場合は次の代わりに: if ( foo === false ) ... // trueでの評価を強制させるため、ネゲートします if ( !foo ) ... // 注意点としてこの場合は0、""、null、undefined、NaNといった値にも // マッチします。もしfalseに限定する必要があるのであれば次のようにします if ( foo === false ) ... // 4.1.7 // 参照先がfalse、""、0ではなく、nullまたはundefinedかどうかだけを // 評価する場合は次の代わりに: if ( foo === null || foo === undefined ) ... // 次のように==を使用して型の変換を利用します if ( foo == null ) ... // 覚えておいてください: ==を使うと、nullはnullおよびundefinedの両方とマッチします。 // しかし、falseと0にはマッチしません null == undefined ``` 常にベストで正確な結果のための評価をしましょう - 上記はガイドラインであって、ドグマではありません。 ```javascript // 4.2.1 // 型の変換と評価の注意書き // `==` よりも `===` を選びましょう(あいまいな型の評価が必要でない限り) // ===は次のように型を変換しません: "1" === 1; // false // ==は次のように型を変換します: "1" == 1; // true // 4.2.2 // ブール値、trueな値とfalseな値 // ブール値: true, false // truthy(訳注:真のような)値: "foo", 1 // falsy(訳注:偽のような)値: "", 0, null, undefined, NaN, void 0 ``` 5. 実践的なスタイル ```javascript // 5.1.1 // 実践的なモジュール (function( global ) { var Module = (function() { var data = "secret"; return { // 何らかのブール値のプロパティ bool: true, // 何らかの文字列の値 string: "a string", // 配列のプロパティ array: [ 1, 2, 3, 4 ], // オブジェクトのプロパティ object: { lang: "en-Us" }, getData: function() { // 現在の`data`の値を取得する return data; }, setData: function( value ) { // `data`の値をセットしてそれを返す return ( data = value ); } }; })(); // その他のコードがここに入る // グローバルオブジェクトからモジュールが見えるようにします global.Module = Module; })( this ); ``` ```javascript // 5.2.1 // 実践的なコンストラクター (function( global ) { function Ctor( foo ) { this.foo = foo; return this; } Ctor.prototype.getFoo = function() { return this.foo; }; Ctor.prototype.setFoo = function( val ) { return ( this.foo = val ); }; // `new`を使わずにコンストラクターを呼び出すにはこのようにします: var ctor = function( foo ) { return new Ctor( foo ); }; // グローバルオブジェクトからモジュールが見えるようにします global.ctor = ctor; })( this ); ``` 6. ネーミング A. あなたは人間コンパイラではありません。そうなろうとしてはいけません。 次のコードはひどいネーミングの例です: ```javascript // 6.A.1.1 // 悪い名前を使ったコードの例 function q(s) { return document.querySelectorAll(s); } var i,a=[],els=q("#foo"); for(i=0;i雑則 このセクションは、ドグマとはいえないまでも、JavaScriptプログラミングをより良くこなすための、探究的なプラクティスの助けとなるアイデアおよびコンセプトを提供します。 A. `switch` の使用はできるだけ避けるべきです。モダンなメソッドトレースは、switchを含む関数をブラックリスト入りさせるでしょう これは最新のFirefoxとChromeでの `switch` 文の実行の大幅な改善です。 http://jsperf.com/switch-vs-object-literal-vs-module 注目すべき改善点はここでも確認できます: https://github.com/rwldrn/idiomatic.js/issues/13 ```javascript // 7.A.1.1 // switch文の例 switch( foo ) { case "alpha": alpha(); break; case "beta": beta(); break; default: // デフォルトのための何か break; } // 7.A.1.2 // `cases`とデリゲートする関数をオブジェクトに保存する代わりのやり方 // 再利用と再構成が可能になる var cases, delegator; // 説明用にreturnのみ記載 cases = { alpha: function() { // ステートメント // リターン return [ "Alpha", arguments.length ]; }, beta: function() { // ステートメント // リターン return [ "Beta", arguments.length ]; }, _default: function() { // ステートメント // リターン return [ "Default", arguments.length ]; } }; delegator = function() { var args, key, delegate; // 引数を配列に変換 args = [].slice.call( arguments ); // caseの部分を引数からとりだす key = args.shift(); // まずデフォルトケースをアサインする delegate = cases._default; // 処理をデリゲートする関数を取り出す if ( cases.hasOwnProperty( key ) ) { delegate = cases[ key ]; } // スコープ引数も指定可能 // この例では |null| にしている return delegate.apply( null, args ); }; // 7.A.1.3 // (7.A.1.2のAPIを使っています) delegator( "alpha", 1, 2, 3, 4, 5 ); // [ "Alpha", 5 ] // もちろん、`case`には簡単に算術条件も使える var caseKey, someUserInput; // たとえばフォーム入力値 someUserInput = 9; if ( someUserInput > 10 ) { caseKey = "alpha"; } else { caseKey = "beta"; } // または caseKey = someUserInput > 10 ? "alpha" : "beta"; // そして delegator( caseKey, someUserInput ); // [ "Beta", 1 ] // そしてもちろん delegator(); // [ "Default", 0 ] ``` B. すぐにReturnすることで、コードの可読性が上がり、わずかにパフォーマンスも向上します ```javascript // 7.B.1.1 // 悪い例: function returnLate( foo ) { var ret; if ( foo ) { ret = "foo"; } else { ret = "quux"; } return ret; } // 良い例: function returnEarly( foo ) { if ( foo ) { return "foo"; } return "quux"; } ``` 8. ネガティブオブジェクトとホストオブジェクト 基本的な原則はここにある通りです: ### 愚かなことをしなければ、すべてうまくいく。 このコンセプトを補足するために、次のプレゼンテーションを見てください: #### Andrew Dupontによる“Everything is Permitted: Extending Built-ins”(JSConf2011、ポートランド、オレゴン州) https://www.youtube.com/watch?v=xL3xCO7CLNM 9. コメント * 主題としてコード上に単一行で書きます * 複数行でも良い * 行末のコメントは禁止! * JSDocのスタイルは良いですが大幅な時間を要します 10. 1言語でのコード 保守する人が要求するとおり、その言語が何であれ、プログラムは1つの言語によって書かれるべきです。 ## 付録 ### 最初にコンマを置くこと このドキュメントを基本的なスタイルガイドとして引用しているいくつかのプロジェクトは、そのプロジェクトの作者が特別に指定しない限りコンマを最初に置くコードフォーマットを受け入れません。 ================================================ FILE: translations/ko_KR/readme.md ================================================ # 자연스럽고 일관성 있게 자바스크립트 코딩하는 원칙 ## 이 문서는 계속 바뀝니다. 주변의 코드를 더 낫게 만들기 위한 좋은 아이디어가 있으시면 알려주세요. Github에서 fork, clone, branch, commit, push, pull request 하는 방법으로 참여해 보세요. * Rick Waldron [@rwaldron](http://twitter.com/rwaldron), [github](https://github.com/rwaldron) * Mathias Bynens [@mathias](http://twitter.com/mathias), [github](https://github.com/mathiasbynens) * Schalk Neethling [@ossreleasefeed](http://twitter.com/ossreleasefeed), [github](https://github.com/ossreleasefeed/) * Kit Cambridge [@kitcambridge](http://twitter.com/kitcambridge), [github](https://github.com/kitcambridge) * Raynos [github](https://github.com/Raynos) * Matias Arriola [@MatiasArriola](https://twitter.com/MatiasArriola), [github](https://github.com/MatiasArriola/) * John Fischer [@jfroffice](https://twitter.com/jfroffice), [github](https://github.com/jfroffice/) * Idan Gazit [@idangazit](http://twitter.com/idangazit), [github](https://github.com/idangazit) * Leo Balter [@leobalter](http://twitter.com/leobalter), [github](https://github.com/leobalter) * Breno Oliveira [@garu_rj](http://twitter.com/garu_rj), [github](https://github.com/garu) * Leo Beto Souza [@leobetosouza](http://twitter.com/leobetosouza), [github](https://github.com/leobetosouza) * Ryuichi Okumura [@okuryu](http://twitter.com/okuryu), [github](https://github.com/okuryu) * Pascal Precht [@PascalPrecht](http://twitter.com/PascalPrecht), [github](https://github.com/pascalprecht) * EngForDev [engfordev](http://www.opentutorials.org/course/167/1363) - Hwan Min Hong / MinTaek Kwon [@leoinsight](http://twitter.com/leoinsight) / Tw Shim [@marocchino](http://twitter.com/marocchino), [github](https://github.com/marocchino) / Nassol Kim [@nassol99](http://twitter.com/nassol99), [github](https://github.com/nassol) / Juntai Park [@rkJun](http://twitter.com/rkJun), [github](https://github.com/rkJun) / Minkyu Shim / Gangmin Won / Justin Yoo [@justinchronicle](http://twitter.com/justinchronicle) / Daeyup Lee * Marco Trulla [@marcotrulla](http://twitter.com/marcotrulla), [github](https://github.com/Ragnarokkr) * Alex Navasardyan [@alexnavasardyan](http://twitter.com/alexnavasardyan), [github](https://github.com/2k00l) * Mihai Paun [@mihaipaun](http://twitter.com/mihaipaun), [github](https://github.com/mihaipaun) * Evgeny Mandrikov [@\_godin\_](http://twitter.com/_godin_), [github](https://github.com/Godin) * Sofish Lin [@sofish](http://twitter.com/sofish), [github](https://github.com/sofish) * Дејан Димић [@dejan_dimic](http://twitter.com/dejan_dimic), [github](https://github.com/rubystream) * Miloš Gavrilović [@gavrisimo](http://twitter.com/gavrisimo), [github](https://github.com/gavrisimo) * Duc Nguyen [@ducntq](https://twitter.com/ducntq), [github](https://github.com/ducntq) * James Young [@jamsyoung](http://twitter.com/jamsyoung), [github](https://github.com/jamsyoung) * Stephane Moreau [github](https://github.com/stmoreau) * Boris Nekezov [github](https://github.com/boris-nekezov) * Akshat Joshi [@akshat_joshi](http://twitter.com/akshat_joshi), [github](https://https://github.com/akshatjoshii) ## 코드 기반에 있는 모든 코드는 마치 한 사람이 작성한 것처럼 보여야 합니다. 많은 사람이 코드 작성에 참여했더라도 말이죠. ### 제가 원저자인 프로젝트의 코드를 작성할 때는 몇 가지 원칙을 따르는데요, 아래의 목록에 그 원칙들을 나열하였습니다. 이 프로젝트의 코드작성에 참여할 때에는 다음의 가이드라인을 따라야 합니다. ### 다른 사람들에게 제 코드 작성 스타일을 따르라고 강요하려는 의도는 아닙니다. 이미 준수하는 코드작성 스타일이 있다면, 그것을 따라야 하겠지요. > ### "스타일에 관한 논쟁은 무의미하다. 스타일 가이드가 있을테니, 거기에 따르기만 해라" >_Rebecca_ _Murphey_   > ### "성공적인 프로젝트의 멋진 일원이 되기 위해서는 여러분 마음대로 코드를 작성하는 것이 나쁜 생각™임을 깨닫는 것이지요. 수천만 사람들이 여러분의 코드를 사용한다면, 가장 명확하게 코딩해야 합니다. 언어 명세가 허용하는 한 가장 똑똑한 코드를 만들겠다는 당신의 개인적인 선호에 따라서가 아니라" >_Idan_ _Gazit_ ## 번역 * [ORIGINAL](https://github.com/rwldrn/idiomatic.js/) * [Bulgarian](https://github.com/rwldrn/idiomatic.js/tree/master/translations/bg_BG) * [German](https://github.com/rwldrn/idiomatic.js/tree/master/translations/de_DE) * [French](https://github.com/rwldrn/idiomatic.js/tree/master/translations/fr_FR) * [Spanish](https://github.com/rwldrn/idiomatic.js/tree/master/translations/es_ES) * [Portuguese - Brazil](https://github.com/rwldrn/idiomatic.js/tree/master/translations/pt_BR) * [Korean](https://github.com/rwldrn/idiomatic.js/tree/master/translations/ko_KR) * [Japanese](https://github.com/rwldrn/idiomatic.js/tree/master/translations/ja_JP) * [Italian](https://github.com/rwldrn/idiomatic.js/tree/master/translations/it_IT) * [Russian](https://github.com/rwldrn/idiomatic.js/tree/master/translations/ru_RU) * [Romanian](https://github.com/rwldrn/idiomatic.js/tree/master/translations/ro_RO) * [简体中文](https://github.com/rwldrn/idiomatic.js/tree/master/translations/zh_CN) * [Serbian - cyrilic alphabet](https://github.com/rwldrn/idiomatic.js/tree/master/translations/ср_СР) * [Serbian - latin aplphabet](https://github.com/rwldrn/idiomatic.js/tree/master/translations/sr_SR) * [Greek](https://github.com/rwaldron/idiomatic.js/tree/master/translations/gr_GR) * [Hindi](https://github.com/rwaldron/idiomatic.js/tree/master/translations/hi_HI) ## 관련은 없지만, 중요한 자료: ### 코드 품질: 멋진 툴들, 리소스 & 참고자료 * [JavaScript Plugin](http://docs.codehaus.org/display/SONAR/JavaScript+Plugin) for [Sonar](http://www.sonarsource.org/) * [Plato](https://github.com/jsoverson/plato) * [jsPerf](http://jsperf.com/) * [jsFiddle](http://jsfiddle.net/) * [jsbin](http://jsbin.com/) * [JavaScript Lint (JSL)](http://javascriptlint.com/) * [jshint](http://jshint.com/) * [jslint](http://jslint.org/) * [Editorconfig](http://editorconfig.org/) ## 똑똑해지기 ### [Annotated ECMAScript 5.1](http://es5.github.com/) ### [EcmaScript Language Specification, 5.1 Edition](http://ecma-international.org/ecma-262/5.1/) 아래 리스트는 1) 이 주제의 모든 지식들을 포괄하지는 않습니다. 2) *반드시 읽기를 권합니다*. 저는 아래 저자들이 말하는 코딩 스타일에 대해 항상 찬성하는 것은 아니지만, 분명한 것은 그들이 일관성 있단 겁니다. 게다가 이들은 프로그래밍 언어의 권위자들입니다. * [Baseline For Front End Developers](http://rmurphey.com/blog/2012/04/12/a-baseline-for-front-end-developers/) * [유창한 자바스크립트(Eloquent JavaScript)](http://eloquentjavascript.net/) * [JavaScript, JavaScript](http://javascriptweblog.wordpress.com/) * [자바스크립트 개발 모험(Adventures in JavaScript Development)](http://rmurphey.com/) * [Perfection Kills](http://perfectionkills.com/) * [더글라스 크록포드의 월드와이드웹(Douglas Crockford's Wrrrld Wide Web)](http://www.crockford.com) * [JS Assessment](https://github.com/rmurphey/js-assessment) * [Leveraging Code Quality Tools by Anton Kovalyov](http://anton.kovalyov.net/slides/gothamjs/) ### 빌드 & 배포 프로세스 프로젝트는 배포를 위해 소스코드를 압축하는 방법을 마련해두어야 합니다. 이렇게 하기 위해, Ben Alman의 [grunt](https://github.com/cowboy/grunt) 는 둘째가라면 서러운 솔루션이며 공식적으로 이 레포지터리의 "kits/" 디랙토리를 대체 하고있습니다. ### 테스트 Facility 프로젝트에는 유닛, 참조, 구현, 기능에 관한 테스트가 _들어가 있어야_ 합니다. 유스 케이스를 "테스트"로 **한정하지 마세요.** 아래에는 테스트를 하는 프레임워크의 목록을 나열해 두었습니다. 이 중에 어느 하나를 더욱 추천하는 것은 아닙니다. * [QUnit](http://github.com/jquery/qunit) * [Jasmine](https://github.com/pivotal/jasmine) * [Vows](https://github.com/cloudhead/vows) * [Mocha](https://github.com/visionmedia/mocha) * [Hiro](http://hirojs.com/) * [JsTestDriver](https://code.google.com/p/js-test-driver/) * [Buster.js](http://busterjs.org/) * [Sinon.js](http://sinonjs.org/) ## 목차 * [공백](#whitespace) * [구문(Syntax)을 아름답게 작성하기](#spacing) * [데이터형을 확인하기(Type Checking) (Courtesy jQuery Core Style Guidelines)](#type) * [조건을 판정하기(Conditional Evaluation)](#cond) * [실용적인 스타일](#practical) * [이름을 짓는 방법](#naming) * [자잘한 것들](#misc) * [네이티브 & 호스트 객체](#native) * [주석 달기](#comments) * [한 언어로 작성하기](#language) ------------------------------------------------ ## 서문 이 글의 섹션은 현대적인 자바스크립트 개발을 위한 _합리적인_ 스타일가이드를 제시하고 있지만, 그게 규정이라는 의미는 아닙니다. 제일 중요한 것은 **일관성 있는 코딩 스타일을 위한 규칙** 입니다. 프로젝트에 어떤 스타일을 사용하던간에 반드시 지켜져야 합니다. 이 문서를 프로젝트의 일관성, 가독성, 유지보수용이성을 위한 참고자료로써 링크해 주세요. ## 자연스러운 스타일에 관한 선언문 1. 공백 - 절대 스페이스와 탭을 섞어 쓰지 마세요. - 프로젝트를 시작할 때, 코드를 작성하기 전에 먼저 스페이스와 탭 중의 하나를 선택하여야 합니다. 이것이 **규칙** 입니다. - 가독성을 위해서 저는 항상 편집기의 들여쓰기 크기를 2 문자로 설정하기를 권장합니다. — 2 문자란 2 스페이스 또는 탭으로 표현되는 2칸 공간을 의미합니다. - 에디터가 들여쓰기 설정을 지원한다면, 저는 "show invisibles" 설정을 켜고 작업합니다. 이렇게 했을 때의 장점은 다음과 같아요: - 일관성을 강제할 수 있어요. - 줄 끝의 공백문자 제거하기 좋아요. - 빈 줄 공백문자를 제거하기 좋아요. - 커밋하고 비교(diff)할 때 읽기 편해요. 2. 아름답게 구문 작성하기 A. 중괄호{}, 괄호(), 줄 바꾸기 ```javascript // if나 else, for while, try를 쓸 때에는 항상 빈 칸을 띠우고, 괄호를 사용하고, 여러 줄로 나누어 쓰세요. // 이렇게 하면 가독성이 더 좋아집니다. // 2.A.1.1 // 빼곡해서 알아보기 어려운 구문의 예 if(condition) doSomething(); while(condition) iterating++; for(var i=0;i<100;i++) someIterativeFn(); // 2.A.1.1 // 가독성이 높아지도록 빈 칸을 띠워주세요. if ( condition ) { // 코드 } while ( condition ) { // 코드 } for ( var i = 0; i < 100; i++ ) { // 코드 } // 아래처럼 하면 더 좋습니다: var i, length = 100; for ( i = 0; i < length; i++ ) { // 코드 } // 아니면 이렇게 할 수도 있죠... var i = 0, length = 100; for ( ; i < length; i++ ) { // 코드 } var prop; for ( prop in object ) { // 코드 } if ( true ) { // 코드 } else { // 코드 } ``` B. 할당, 선언, 함수(일반, 표현식, 생성자) ```javascript // 2.B.1.1 // 변수 var foo = "bar", num = 1, undef; // 리터럴 표기법: var array = [], object = {}; // 2.B.1.2 // 함수 같은 유효 범위에 `var` 를 하나만 사용하면 가독성이 높아집니다. // 이렇게 하면 선언 목록도 깔끔해집니다(아울러 키보드로 입력해야 할 양도 줄어들지요) // 나쁜 스타일 var foo = ""; var bar = ""; var qux; // 좋은 스타일 var foo = "", bar = "", quux; // 또는.. var // 아래 변수에 대한 설명 foo = "", bar = "", quux; // 2.B.1.3 // var 문은 관련있는 스코프(함수) 안의 시작하는 곳에 있어야합니다. // ECMAScript 6의 const, let도 같은 맥락으로 이 규칙이 적용됩니다. // 나쁜 스타일 function foo() { // 여기에 어떤 구문이 있음 var bar = "", qux; } // 좋은 스타일 function foo() { var bar = "", qux; // 변수 선언이후에 모든 구문들이 옴. } ``` ```javascript // 2.B.2.1 // 일반 함수 선언 function foo( arg1, argN ) { } // 사용법 foo( arg1, argN ); // 2.B.2.2 // 일반 함수 선언 function square( number ) { return number * number; } // 사용법 square( 10 ); // 아주 부자연스러운 연속 전달 스타일(continuation passing style) (CPS에 대해서는 http://goo.gl/TA32o를 참고) function square( number, callback ) { callback( number * number ); } square( 10, function( square ) { // 콜백 문장 }); // 2.B.2.3 // 함수 표현식 var square = function( number ) { // 가치 있고 의미 있는 뭔가를 반환합니다 return number * number; }; // 식별자를 지닌 함수 표현식 // 아래와 같은 형태는 자기 자신을 호출할 수 있으면서 // 스택 트레이스상에서 식별할 수 있다는 부가적인 장점이 있습니다: var factorial = function factorial( number ) { if ( number < 2 ) { return 1; } return number * factorial( number-1 ); }; // 2.B.2.4 // 생성자 선언 function FooBar( options ) { this.options = options; } // 사용법 var fooBar = new FooBar({ a: "alpha" }); fooBar.options; // { a: "alpha" } ``` C. 예외 사항, 약간의 탈선 ```javascript // 2.C.1.1 // 콜백을 포함한 함수 foo(function() { // 참고로 함수 호출을 실행하는 첫 괄호와 "function"이라는 // 단어 사이에는 별도의 공백이 없습니다. }); // 배열을 받는 함수일 때에는 공백 없음 foo([ "alpha", "beta" ]); // 2.C.1.2 // 객체를 받는 함수일 때에는 공백 없음 foo({ a: "alpha", b: "beta" }); // 괄호안에 괄호가 있을 때에는 공백 없음 if ( !("foo" in obj) ) { } ``` D. 일관성을 지키는 편이 항상 좋습니다. 섹션2.A-2.C에서는 우선 공백을 사용하는 규칙을 제시하고 있습니다. 공백을 사용하는 원칙은 단순하면서도 우선순위가 높습니다. 바로 일관성이에요. "inner whitespace"를 쓰라는 등의 포맷방식을 모두에게 강요할 수는 없겠지요. 그러나 여러분의 프로젝트 전체에 걸쳐서 단 한 가지의 스타일이 적용되어야 합니다. 이 점이 중요합니다. ```javascript // 2.D.1.1 if (조건) { // 코드 } while (조건) { // 코드 } for (var i = 0; i < 100; i++) { // 코드 } if (true) { // 코드 } else { // 코드 } ``` E. 따옴표 작은 따옴표로 하냐 큰 따옴표로 하냐는 별로 중요하지않습니다, 자바스크립트에서는 그둘은 파싱하는 과정에서 전혀 차이가 없으니까요. 중요한것은 **절대적인 일관성** 이 있어야 한다는 점입니다. **같은 프로젝트에서는 절대로 큰따옴표와 작은따옴표를 섞지 마세요. 한 스타일을 정해서 고수하세요.** F. 각 줄의 끝부분, 빈 줄 여백이 있으면 바뀐 내용들을 읽을 수가 없게 됩니다. 또한 diff툴이 제대로 작동하지 않습니다. 줄의 끝에 있는 여백이나 빈 줄에 들어있는 공백을 자동적으로 제거해주는 ‘pre-commit hook'을 사용해 보세요. 3. 자료형 확인하기 (Courtesy jQuery Core Style Guidelines) A. 실제 타입 스트링: typeof variable === "string" 숫자: typeof variable === "number" 불린: typeof variable === "boolean" 오브젝트: typeof variable === "object" 배열: Array.isArray(arrayObject) (가능한 곳이면 어디든지) 노드: elem.nodeType === 1 널(null): variable === null 널(null), 미할당(undefined): variable == null 미할당(undefined): 전역변수들: typeof variable === "undefined" 지역변수들: variable === undefined 프로퍼티: object.prop === undefined object.hasOwnProperty( prop ) "prop" in object B. 강제변환된 타입 다음의 결과를 생각해 보죠... 아래와 같은 HTML 코드가 있어요: ```html ``` ```javascript // 3.B.1.1 // `foo` 라는 변수를 `0` 값을 갖는 상태로 선언하였습니다. 그리고 자료형은 `수(number)` 이고요. var foo = 0; // typeof foo; // "number" ... // 나중에 입력요소(input element)에서 받은 새로운 값을 // `foo` 변수에다가 넣어야 합니다. foo = document.getElementById("foo-input").value; // (역자주 : 아, `foo` 변수에 원래는 숫자형 자료가 들어가 있었는데, 이번에는 문자형 자료가 들어가네요.) // 자, 이제 `typeof foo` 라고 쳐서 `foo` 의 자료형을 확인해보면, 결과는 `문자열` 이 // 나올 겁니다. 즉 `foo` 의 자료형을 알아볼 때, 아래와 같이 했다면: if ( foo === 1 ) { importantTask(); } // `importantTask()` 함수는 절대로 실행이 안될 겁니다. `foo` 의 값이 "1" 이라고 하더라도 말이죠. // 3.B.1.2 // 1진법의 +나 - 단항 연산자를 사용한 smart 강제변환으로 문제를 해결할 수 있습니다: foo = +document.getElementById("foo-input").value; ^ 1진법의 단항연산자 +는 오른쪽에 있는 부분을 숫자로 바꿉니다. // typeof foo; // "number" if ( foo === 1 ) { importantTask(); } // `importantTask()` 가 호출됩니다. ``` 아래에는 자료형을 강제로 변환하는 흔한 사례들이 나와 있습니다.: ```javascript // 3.B.2.1 var number = 1, string = "1", bool = false; number; // 1 number + ""; // "1" string; // "1" +string; // 1 +string++; // 1 string; // 2 bool; // false +bool; // 0 bool + ""; // "false" ``` ```javascript // 3.B.2.2 var number = 1, string = "1", bool = true; string === number; // false string === number + ""; // true +string === number; // true bool === number; // false +bool === number; // true bool === string; // false bool === !!string; // true ``` ```javascript // 3.B.2.3 var array = [ "a", "b", "c" ]; !!~array.indexOf( "a" ); // true !!~array.indexOf( "b" ); // true !!~array.indexOf( "c" ); // true !!~array.indexOf( "d" ); // false // 주의: 위의 구문들은 "과도하게 영리"한 방법이 아닌지 생각해 보아야 합니다 // 다음 구문처럼 비교되는 indexOf의 리턴 값이 더 명확한 쪽이 // 좋지 않을까요? if ( array.indexOf( "a" ) >= 0 ) { // ... } ``` ```javascript // 3.B.2.4 var num = 2.5; parseInt( num, 10 ); // 위처럼 쓴 것은, 아래에 쓴 것과 같은 의미입니다. ~~num; num >> 0; num >>> 0; // 전부 2가 됩니다. // 하지만 음수는 다르게 취급되는것도 명심하셔야 합니다... var neg = -2.5; parseInt( neg, 10 ); // 위처럼 쓴 것은, 아래에 쓴 것과 같은 의미입니다. ~~neg; neg >> 0; // 전부 -2가 됩니다. // 하지만... neg >>> 0; // 이경우엔 4294967294가 나옵니다. ``` 4. 조건문으로 확인하는 코드 ```javascript // 4.1.1 // 배열에 뭔가가 들어있는지 여부를 확인하려는 거라면, // 다음과 같이 코드를 작성하는 대신에: if ( array.length > 0 ) ... // 다음과 같이 작성하세요: if ( array.length ) ... // 4.1.2 // 배열이 비어있다는 것만을 확인할 때에는, // 아래처럼 작성하지 마시고: if ( array.length === 0 ) ... // ...다음처럼 작성하세요: if ( !array.length ) ... // 4.1.3 // 문자열이 비어있지 않다는 것을 확인할 때에는, // 다음처럼 작성하지 마시고: if ( string !== "" ) ... // ...다음과 같이 작성하세요: if ( string ) ... // 4.1.4 // 문자열이 _비어있다는 것_을 확인만 하는 경우라면, // 다음처럼 작성하지 마시고: if ( string === "" ) ... // ...다음과 같이 작성해서, 거짓인지를 확인하세요. : if ( !string ) ... // 4.1.5 // 참조 변수가 true인지 확인하려면, // 다음처럼 작성하지 마시고: if ( foo === true ) ... // ...그냥 아래처럼 써주세요. 기본 기능을 활용하면 됩니다: if ( foo ) ... // 4.1.6 // 어떤 참조 변수가 false인지 판정할 때에는, // 다음처럼 작성하지 마시고: if ( foo === false ) ... // ...true인지를 확인하도록 부정(!)을 사용하세요. if ( !foo ) ... // ...주의하세요. 이렇게 제안하면 foo의 값이 0, “”, null, undefined, NaN인 경우에도 참을 반환할 겁니다. // foo가 불린값 false를 갖는지를 확인하는 경우라면, 아래와 같이 사용하세요. if ( foo === false ) ... // 4.1.7 // 어떤 변수가 있다고 하죠. 이 변수의 값은 null이나 undefined일 수는 있지만 false나 "", 또는 0의 값은 가지지 않습니다. 이런 변수를 판정할 때에는, // 아래처럼 작성하지 마시고: if ( foo === null || foo === undefined ) ... // ...강제형변환되는 ==를 사용하세요. 다음과 같이요: if ( foo == null ) ... // 그리고 이 점을 기억하세요. == 를 사용하면, 판정하려는 변수의 값이 `null` 이나 `undefined` 일 때, 참을 반환할 것입니다. // 하지만 `false` 나 "" 나 0 값을 가질 때에는 거짓을 반환할 것입니다. null == undefined ``` **항상** 최선의 결과를 내는 비교가 무엇인지 고민하세요. - 위에 것들은 다 가이드라인입니다, 교리같은건 아니죠. ```javascript // 4.2.1 // 형변환 과 비교에 관한 메모 `===` 가 `==` 보다 좋습니다. (느슨한 형 비교가 필요하지 않는 이상) === 는 형변환을 하지 않습니다. 무슨뜻인가 하면: "1" === 1; // false == 는 형변환을 합니다, 무슨 뜻인가 하면: "1" == 1; // true // 4.2.2 // 불린값, 참(true)으로 간주되는 것, 거짓(false)으로 간주되는 것 불린값: true, false 참(true)으로 간주되는 것: "foo", 1 거짓(false)으로 간주되는 것: "", 0, null, undefined, NaN, void 0 ``` 5. 실용적인 스타일 ```javascript // 5.1.1 // 실용적인 모듈 (function( global ) { var Module = (function() { var data = "secret"; return { // 이것은 불린 속성입니다 bool: true, // 문자열 값 string: "a string", // 배열 속성 array: [ 1, 2, 3, 4 ], // 객체 속성 object: { lang: "en-Us" }, getData: function() { // `data` 의 현재 값을 알아내고 반환합니다 return data; }, setData: function( value ) { // `data` 의 값을 설정하고 반환합니다 return ( data = value ); } }; })(); // 여기에 다른 내용이 들어갈 수도 있습니다 // 전역 객체에 모듈을 노출시키세요. global.Module = Module; })( this ); ``` ```javascript // 5.2.1 // 실용적인 생성자 (function( global ) { function Ctor( foo ) { this.foo = foo; return this; } Ctor.prototype.getFoo = function() { return this.foo; }; Ctor.prototype.setFoo = function( val ) { return ( this.foo = val ); }; // `new`없이 생성자를 호출하려면, 이렇게 할 수 도 있습니다: var ctor = function( foo ) { return new Ctor( foo ); }; // 전역 개체에 생성자를 노출합니다 global.ctor = ctor; })( this ); ``` 6. 이름 짓기 A. 여러분은 컴파일러나 압축기(compressor)가 아닙니다. 그렇게 되려고 시도하지 마세요. 다음은 이름을 심하게 안 좋게 지은 코드 작성 사례입니다: ```javascript // 6.A.1.1 // 이름을 안 좋게 지은 코드 작성 사례 function q(s) { return document.querySelectorAll(s); } var i,a=[],els=q("#foo"); for(i=0;i자잘한 것들 이번 섹션에서는 몇 가지 아이디어와 개념에 대해서 다룰 겁니다. 아이디어와 개념의 목적은 자바스크립트로 프로그래밍하는 데 있어 좀더 나은 방법을 찾을 수 있도록 기존에 사용하던 관행에 의문을 제기하게 만드는 것입니다. A. `switch` 사용을 피해야 합니다. 현대의 방법론에서는, switch문이 들어간 함수를 블랙리스트에 올릴 겁니다. 파이어폭스와 크롬 최신 버전에서 `switch` 구문의 실행에 관한 눈부신 발전이 이루어진 듯 합니다. http://jsperf.com/switch-vs-object-literal-vs-module 개선된 것들 중에 주목할 만한 것은 이곳에서도 볼 수 있습니다: https://github.com/rwldrn/idiomatic.js/issues/13 ```javascript // 7.A.1.1 // switch 구문을 사용한 코드 작성 예 switch( foo ) { case "alpha": alpha(); break; case "beta": beta(); break; default: // 기본적으로 수행할 것 break; } // 7.A.1.2 // 객체 리터럴(object lieteral)이나 모듈을 사용하여 접근하는 방식이 더 좋습니다: var switchObj = { alpha: function() { // 구문들 // 반환문 }, beta: function() { // 구문들 // 반환문 }, _default: function() { // 구문들 // 반환문 } }; var switchModule = (function () { return { alpha: function() { // 구문들 // 반환문 }, beta: function() { // 구문들 // 반환문 }, _default: function() { // 구문들 // 반환문 } }; })(); // 7.A.1.3 // `foo`가 `switchObj` 또는 `switchModule`의 속성이라고 할 때, 아래 메서드처럼 실행합니다... ( Object.hasOwnProperty.call( switchObj, foo ) && switchObj[ foo ] || switchObj._default )( args ); ( Object.hasOwnProperty.call( switchObj, foo ) && switchModule[ foo ] || switchModule._default )( args ); // `foo` 의 값을 알고 있고 확신한다면 // 실행만 남겨 둔 채 OR 체크를 생략할 수도 있습니다: switchObj[ foo ]( args ); switchModule[ foo ]( args ); // 이 패턴은 코드의 재사용성도 높여줘요. ``` B. 값을 일찍 반환하면 코드의 가독성이 높아져요. 성능 차이는 무시할 정도밖에 안돼죠. ```javascript // 7.B.1.1 // 안좋은 예: function returnLate( foo ) { var ret; if ( foo ) { ret = "foo"; } else { ret = "quux"; } return ret; } // 좋은 예: function returnEarly( foo ) { if ( foo ) { return "foo"; } return "quux"; } ``` 8. 네이티브 & 호스트 객체 기본적으로 중요한 것은 이겁니다: ### 바보같은 짓은 하지마세요. 다 괜찮을 겁니다. 이 개념에 대해 좀 더 알고 싶으시면, 다음 프리젠테이션을 보세요: #### “Everything is Permitted: Extending Built-ins(모든 게 다 가능해진, 내장기능 확장)” by Andrew Dupont (JSConf2011, Portland, Oregon) https://www.youtube.com/watch?v=xL3xCO7CLNM 9. 주석 달기 * JSDoc 스타일이 좋아요 (Closure Compiler type hints++) * 주제를 가진 코드위에는 한 줄로 주석을 달아요. * 보통은 여러줄로 주석을 다는게 좋고요. * 코드의 맨 마지막 줄에 주석을 다는 것은 금물이에요! 10. 한 언어로 작성하기 프로그램은 유지보수 하는 사람들에 의해 가급적 하나의 언어(영어이든 아니든 무슨 언어로든 간에 - 역자 주)로 쓰이는 것이 좋습니다. ## 부록 ### 쉼표를 맨 앞에 쓰는 것에 대하여. 이 문서를 기본 스타일 가이드로 인용하는 모든 프로젝트는 달리 명시하지 않는 한, 쉼표를 맨 앞에 쓰는 코드 포맷은 허락되지 않습니다. ================================================ FILE: translations/pl_PL/readme.md ================================================ # Zasady pisania zwartego, idiomatycznego kodu JavaScript ## Dokument który czytasz powstał dzięki współpracy wielu ludzi, wszelkie działania aby uduskonalać kod dookoła nas jest są mile widziane. Dołącz się: fork, clone, branch, commit, push, pull request. * Rick Waldron [@rwaldron](http://twitter.com/rwaldron), [github](https://github.com/rwldrn) * Mathias Bynens [@mathias](http://twitter.com/mathias), [github](https://github.com/mathiasbynens) * Schalk Neethling [@ossreleasefeed](http://twitter.com/ossreleasefeed), [github](https://github.com/ossreleasefeed/) * Kit Cambridge [@kitcambridge](http://twitter.com/kitcambridge), [github](https://github.com/kitcambridge) * Raynos [github](https://github.com/Raynos) * Matias Arriola [@MatiasArriola](https://twitter.com/MatiasArriola), [github](https://github.com/MatiasArriola/) * John Fischer [@jfroffice](https://twitter.com/jfroffice), [github](https://github.com/jfroffice/) * Idan Gazit [@idangazit](http://twitter.com/idangazit), [github](https://github.com/idan) * Leo Balter [@leobalter](http://twitter.com/leobalter), [github](https://github.com/leobalter) * Breno Oliveira [@garu_rj](http://twitter.com/garu_rj), [github](https://github.com/garu) * Leo Beto Souza [@leobetosouza](http://twitter.com/leobetosouza), [github](https://github.com/leobetosouza) * Ryuichi Okumura [@okuryu](http://twitter.com/okuryu), [github](https://github.com/okuryu) * Pascal Precht [@PascalPrecht](http://twitter.com/PascalPrecht), [github](https://github.com/pascalprecht) * EngForDev [engfordev](http://www.opentutorials.org/course/167/1363) - Hwan Min Hong / MinTaek Kwon [@leoinsight](http://twitter.com/leoinsight) / Tw Shim [@marocchino](http://twitter.com/marocchino), [github](https://github.com/marocchino) / Nassol Kim [@nassol99](http://twitter.com/nassol99), [github](https://github.com/nassol) / Juntai Park [@rkJun](http://twitter.com/rkJun), [github](https://github.com/rkJun) / Minkyu Shim / Gangmin Won / Justin Yoo [@justinchronicle](http://twitter.com/justinchronicle) / Daeyup Lee * Marco Trulla [@marcotrulla](http://twitter.com/marcotrulla), [github](https://github.com/Ragnarokkr) * Alex Navasardyan [@alexnavasardyan](http://twitter.com/alexnavasardyan), [github](https://github.com/2k00l) * Mihai Paun [@mihaipaun](http://twitter.com/mihaipaun), [github](https://github.com/mihaipaun) * Evgeny Mandrikov [@\_godin\_](http://twitter.com/_godin_), [github](https://github.com/Godin) * Sofish Lin [@sofish](http://twitter.com/sofish), [github](https://github.com/sofish) * Дејан Димић [@dejan_dimic](http://twitter.com/dejan_dimic), [github](https://github.com/rubystream) * Miloš Gavrilović [@gavrisimo](http://twitter.com/gavrisimo), [github](https://github.com/gavrisimo) * Firede [@firede](https://twitter.com/firede) [github](https://github.com/firede) * monkadd [github](https://github.com/monkadd) * Stephan Lindauer [@stephanlindauer](http://twitter.com/stephanlindauer), [github](https://github.com/stephanlindauer) * Thomas P [@dragon5689](https://twitter.com/dragon5689) [github](https://github.com/dragon5689) * Yotam Ofek [@yotamofek](https://twitter.com/yotamofek) [github](https://github.com/yotamofek) * Aleksandr Filatov [@greybax](http://twitter.com/greybax), [github](https://github.com/greybax) * Duc Nguyen [@ducntq](https://twitter.com/ducntq), [github](https://github.com/ducntq) * James Young [@jamsyoung](http://twitter.com/jamsyoung), [github](https://github.com/jamsyoung) * Wojciech Adaszyński [github](https://github.com/wojciechAdaszynski) * Stephane Moreau [github](https://github.com/stmoreau) * Boris Nekezov [github](https://github.com/boris-nekezov) * Akshat Joshi [@akshat_joshi](http://twitter.com/akshat_joshi), [github](https://https://github.com/akshatjoshii) ## Cały kod w projekcie powinien wyglądać jakby pisała go jedna osoba, bez względu na to ile osób pracowało przy nim. ### Poniższa lista zasad została spisana przez orginalnego autora. Wszelkie poprawki czy tłumaczenia nie mogą naruszać pierwotnych zasad i logiki. ### Celem tego poradnika nie jest wymuszenie jedynego słusznego stylu pisania, jeżeli istnieją jakiekolwiek inne powszechnie używane zasady - należy je uszanować. > ### "Spory dotyczące stylu kodu są bezsensowne. Powinny istnieć jasne zasady pisania czystego kodu, a programista powinien ich przestrzegać." >_Rebecca_ _Murphey_   > ### "Częścią bycia dobrym zarządcą projektu jest zdanie sobie sprawy, że pisanie kodu pod siebie jest złym pomysłem. Jeżeli tysiące osób pracują nad jednym projektem, maksymalna czytelność powinna być twoim priorytetem, a nie twoje osobiste preferencje." >_Idan_ _Gazit_ ## Tłumaczenia * [ORIGINAL](https://github.com/rwldrn/idiomatic.js/) * [Bulgarian](https://github.com/rwldrn/idiomatic.js/tree/master/translations/bg_BG) * [German](https://github.com/rwldrn/idiomatic.js/tree/master/translations/de_DE) * [French](https://github.com/rwldrn/idiomatic.js/tree/master/translations/fr_FR) * [Spanish](https://github.com/rwldrn/idiomatic.js/tree/master/translations/es_ES) * [Portuguese - Brazil](https://github.com/rwldrn/idiomatic.js/tree/master/translations/pt_BR) * [Korean](https://github.com/rwldrn/idiomatic.js/tree/master/translations/ko_KR) * [日本語](https://github.com/rwldrn/idiomatic.js/tree/master/translations/ja_JP) * [Italian](https://github.com/rwldrn/idiomatic.js/tree/master/translations/it_IT) * [Russian](https://github.com/rwldrn/idiomatic.js/tree/master/translations/ru_RU) * [Romanian](https://github.com/rwldrn/idiomatic.js/tree/master/translations/ro_RO) * [简体中文](https://github.com/rwldrn/idiomatic.js/tree/master/translations/zh_CN) * [Serbian - cyrilic alphabet](https://github.com/rwldrn/idiomatic.js/tree/master/translations/ср_СР) * [Serbian - latin aplphabet](https://github.com/rwldrn/idiomatic.js/tree/master/translations/sr_SR) * [Greek](https://github.com/rwaldron/idiomatic.js/tree/master/translations/gr_GR) * [Hindi](https://github.com/rwaldron/idiomatic.js/tree/master/translations/hi_HI) ## Ważne, nieidiomatyczne rzeczy: ### Narzędzia poprawiające jakość kodu, źródła i odnośniki * [JavaScript Plugin](http://docs.codehaus.org/display/SONAR/JavaScript+Plugin) for [Sonar](http://www.sonarsource.org/) * [Plato](https://github.com/es-analysis/plato) * [jsPerf](http://jsperf.com/) * [jsFiddle](http://jsfiddle.net/) * [jsbin](http://jsbin.com/) * [JavaScript Lint (JSL)](http://javascriptlint.com/) * [jshint](http://jshint.com/) * [jslint](http://jslint.org/) * [eslint](http://eslint.org/) * [jscs](https://www.npmjs.org/package/jscs) * [Editorconfig](http://editorconfig.org/) ## Dodatkowe materiały do nauki ### [Annotated ECMAScript 5.1](http://es5.github.com/) ### [EcmaScript Language Specification, 5.1 Edition](http://ecma-international.org/ecma-262/5.1/) Poniższe materiały są: 1) niekompletne, lub 2) mimo tego, że kod jest spójny nie zgadzam się ze stylem autorów. Są oni jednak odpowiedzialni za bieżący standard języka JavaScript. * [Baseline For Front End Developers](http://rmurphey.com/blog/2012/04/12/a-baseline-for-front-end-developers/) * [Eloquent JavaScript](http://eloquentjavascript.net/) * [JavaScript, JavaScript](http://javascriptweblog.wordpress.com/) * [Adventures in JavaScript Development](http://rmurphey.com/) * [Perfection Kills](http://perfectionkills.com/) * [Douglas Crockford's Wrrrld Wide Web](http://www.crockford.com) * [JS Assessment](https://github.com/rmurphey/js-assessment) ### Uruchamianie i wdrażanie Projekty powinny zawsze zawierać środki umożliwiające testowanie, optymalizacje i kompresję do kodu produkcyjnego. Najlepszym do tego narzędziem jest [grunt](https://github.com/gruntjs/grunt) autorstwa Bena Almana. ### Testowanie aplikacji Projekty _muszą_ zawierać w jakiejkolwiek postaci testy: jednostkowe, funkcjonalne i implementacyjne. Prezentacje przypadków użycia nie kwalifikują się pod "testy". Kolejność poniżysz frameworków do testów jest przypadkowa. * [QUnit](http://github.com/jquery/qunit) * [Jasmine](https://github.com/pivotal/jasmine) * [Vows](https://github.com/cloudhead/vows) * [Mocha](https://github.com/visionmedia/mocha) * [Hiro](http://hirojs.com/) * [JsTestDriver](https://code.google.com/p/js-test-driver/) * [Buster.js](http://busterjs.org/) * [Sinon.js](http://sinonjs.org/) ## Spis treści * [Białe znaki](#whitespace) * [Piękna składnia](#spacing) * [Sprawdzanie typów](#type) * [Instrukcje warunkowe](#cond) * [Praktyczny styl](#practical) * [Nazewnictwo](#naming) * [Pozostałe](#misc) * [Native & Host Objects](#native) * [Komentarze](#comments) * [Jeden język](#language) ------------------------------------------------ ## Przedmowa Poniższe rozdziały są jedynie sugestią jak pisać _rozsądny_ oraz nowoczesny kod w języku JavaScript. Najważniejszą z nich jest **nakaz spójności kodu**. Niezależnie od obranego stylu w projekcie, pownien on być przestrzegany przez przystkich programistów. ## Manifest idiomatycznego kodu 1. Białe znaki - Nigdy nie używaj znaków spacji razem ze znakami tabulacji. - Przed rozpoczęciem projektu ustal jeden znak indentacji (spacje lub tabulator). - Dla czytelności sugeruję tobie ustawienie w środowsku programistycznym indentacji na 2 spacje. —. - Jeżeli twój edytor obsługuje tę opcję, włącz wyświetlanie wszystkich znaków aby: - Wymusić spójność - Uniknąć białych znaków na końcu linii - Uniknąć białych znaków w pustych liniach - Wymusić czytelność Commitów i diffów - Używaj [Editorconfig](http://editorconfig.org/) jeżeli tylko jest to możliwe. Wspiera on większość środowisk programistycznych oraz załatwia większość problemów związanych z białymi znakami. 2. Piękna składnia A. Nawiasy, nawiasy klamrowe, znaki nowej linii ```javascript // if/else/for/while/try zawsze występują ze spacją oraz nawiasami klamrowymi. Rozpinją się zawsze na kilka linii. // Zwiększa to czytelność. // 2.A.1.1 // Przykłady zagęszczonego kodu. if(condition) doSomething(); while(condition) iterating++; for(var i=0;i<100;i++) someIterativeFn(); // 2.A.1.1 // Używaj białych znaków, aby zwiększyć czytelność. if ( condition ) { // statements } while ( condition ) { // statements } for ( var i = 0; i < 100; i++ ) { // statements } // Lub nawet: var i, length = 100; for ( i = 0; i < length; i++ ) { // statements } // Lub... var i = 0, length = 100; for ( ; i < length; i++ ) { // statements } var prop; for ( prop in object ) { // statements } if ( true ) { // statements } else { // statements } ``` B. Przypisania, Deklaracje, Funkcje ( Named, Expression, Constructor ) ```javascript // 2.B.1.1 // Zmienne var foo = "bar", num = 1, undef; // Literal notations: var array = [], object = {}; // 2.B.1.2 // `var` powinno być używte tylko raz w fukcjach, aby zwiększyć czytelność kodu // oraz ujednolicić twój kod (redukuje to również ilość kodu) // Źle var foo = ""; var bar = ""; var qux; // Dobrze var foo = "", bar = "", qux; // lub.. var // Komentarze dot. zmiennych foo = "", bar = "", quux; // 2.B.1.3 // `var` powinno znajdować się zawsze na początku funkcji. // Źle function foo() { // instrukcje var bar = "", qux; } // Dobrze function foo() { var bar = "", qux; // wszelkie instrukcje funkcji } // 2.B.1.4 // const oraz let, z ECMAScript 6, powinny znajdować się na górze bloku(scope). // Źle function foo() { let foo, bar; if ( condition ) { bar = ""; // instrukcje } } // Dobrze function foo() { let foo; if ( condition ) { let bar = ""; // instrukcje } } ``` ```javascript // 2.B.2.1 // Deklaracje funkcji (Named Functions Declarations) function foo( arg1, argN ) { } // Użycie foo( arg1, argN ); // 2.B.2.2 // Deklaracje funkcji (Named Functions Declarations) function square( number ) { return number * number; } // Użycie square( 10 ); // Wywoływanie funkcji z funkcji function square( number, callback ) { callback( number * number ); } square( 10, function( square ) { // callback statements }); // 2.B.2.3 // Wyrażenia funkcyjne var square = function( number ) { // zwróć bardzo istotną wartość return number * number; }; // Wyrażenia funkcyjne z identyfikatorem // Jest to preferowana forma deklaracji wyrażeń funkcyjnych. // Umożliwia ona wołanie samej siebie oraz posiada identyfikator na Stack Trace var factorial = function factorial( number ) { if ( number < 2 ) { return 1; } return number * factorial( number - 1 ); }; // 2.B.2.4 // Deklarowanie konstruktora function FooBar( options ) { this.options = options; } // Użycie var fooBar = new FooBar({ a: "alpha" }); fooBar.options; // { a: "alpha" } ``` C. Wyjątki od poprzednich reguł ```javascript // 2.C.1.1 // Fukcje z callbackami foo(function() { // Zwróć uwagę na brak spacji między 'function', // a pierwszym nawiasem }); // Funkcje przyjmujące tablicę jako argument foo([ "alpha", "beta" ]); // 2.C.1.2 // Funkcje przyjmujące obiekt foo({ a: "alpha", b: "beta" }); // Funkcje przyjmujące pojedynczy string foo("bar"); // Nawiasy grupujące wewnętrze wyrażenie if ( !("foo" in obj) ) { } ``` D. Spójność jest najważniejsza W rozdziałach 2.A-2.C zasady dotyczące białych znaków służą jako wskazówki do utrzymania spójnego kodu. Najważniejszym wnioskiem idącym z tego poradnika jest to, aby niezależnie od obranych preferencji(np. spacje wewnątrz ciała funkcji) utrymywane one były w całym projekcie. ```javascript // 2.D.1.1 if (condition) { // statements } while (condition) { // statements } for (var i = 0; i < 100; i++) { // statements } if (true) { // statements } else { // statements } ``` E. Cudzysłów czy apostrof? Wybór ten nie wpływa w żaden sposób na działanie parsera JavaScript. **Należy** jednak używać tylko jednego z tych znaków w całym projekcie. **Nigdy nie mieszaj cudzysłowów z apostrowami.** F. Koniec linii oraz puste linie. Białe znaki potrafią w znaccy sposób utrudnić pracę programistów. Operacje *diff* stają się przez nie nieczytelne, a changeset projektu powoli zamienia się w śmietnik. Dobrym pomysłem jest używanie oprogramowania usuwającego białe znaki na końcu oraz w pustych liniach. 3. Sprawdzanie typu A. Typy podstawowe String: typeof variable === "string" Number: typeof variable === "number" Boolean: typeof variable === "boolean" Object: typeof variable === "object" Array: Array.isArray( arrayLikeObject ) (gdziekolwiek możliwe) Node: elem.nodeType === 1 null: variable === null null or undefined: variable == null undefined: Global Variables: typeof variable === "undefined" Lokalne Zmienne: variable === undefined Properties: object.prop === undefined object.hasOwnProperty( prop ) "prop" in object B. Rzutowane typy Rozważmy następujący przypadek... Mając dany element: ```html ``` ```javascript // 3.B.1.1 // deklarujemy `foo` i przypisujemy mu wartość 0, jego typ to Number var foo = 0; // typeof foo; // "number" ... // Aktualizujemy `foo` wartością z elementu HTML foo = document.getElementById("foo-input").value; // Jeżeli teraz sprawdzilibyśmy wartość `typeof foo` wynosiła by ona String if ( foo === 1 ) { importantTask(); } // `importantTask()` nigdy nie zostałby wykonany, mimo że `foo` ma wartość "1" // 3.B.1.2 // Dzięki operatorom + i - możemy zastosować sprytne rzutowanie: foo = +document.getElementById("foo-input").value; // ^ jednoargumentowy operator + zrzutuje nam wartość Number na String // typeof foo; // "number" if ( foo === 1 ) { importantTask(); } // `importantTask()` będzie wtedy wykonany ``` Kilka przykładów zastosowania sprytnego rzutowania: ```javascript // 3.B.2.1 var number = 1, string = "1", bool = false; number; // 1 number + ""; // "1" string; // "1" +string; // 1 +string++; // 1 string; // 2 bool; // false +bool; // 0 bool + ""; // "false" ``` ```javascript // 3.B.2.2 var number = 1, string = "1", bool = true; string === number; // false string === number + ""; // true +string === number; // true bool === number; // false +bool === number; // true bool === string; // false bool === !!string; // true ``` ```javascript // 3.B.2.3 var array = [ "a", "b", "c" ]; !!~array.indexOf("a"); // true !!~array.indexOf("b"); // true !!~array.indexOf("c"); // true !!~array.indexOf("d"); // false // Ostatnie przykłady mogą okazać się w póżniejszych etapach //prac nad projektem uciążliwe. // Polecanym zapisem powyższego przykładu jest: if ( array.indexOf( "a" ) >= 0 ) { // ... } ``` ```javascript // 3.B.2.4 var num = 2.5; parseInt( num, 10 ); // jest równoważne z: ~~num; num >> 0; num >>> 0; // wszystkie powyższe dają 2 // Ujemne wartości dają jednak dla tych operacji różne wyniki. var neg = -2.5; parseInt( neg, 10 ); // to to samo co... ~~neg; neg >> 0; // wszystkie dają -2 // Ale... neg >>> 0; // da nam wynik 4294967294 ``` 4. Instrukcje warunkowe ```javascript // 4.1.1 // Kiedy sprawdzamy czy tablica jest niepusta, // zamiast zapisu: if ( array.length > 0 ) ... // ...lepiej sprawdzić czy zadana wartość jest *Truthy*: if ( array.length ) ... // 4.1.2 // Kiedy sprawdzamy czy tablica jest pusta, // zamiast zapisu: if ( array.length === 0 ) ... // ...lepiej sprawdzić czy wartość jest *Falsy*: if ( !array.length ) ... // 4.1.3 // Kiedy sprawdzamy czy string jest niepusty // zamiast zapisu: if ( string !== "" ) ... // ...sprawdź czy zmienna jest *Truthy*: if ( string ) ... // 4.1.4 // Kiedy sprawdzamy czy string jest pusty: // zamiast... if ( string === "" ) ... // ...sprawdź czy wyrażenie jest *Falsy*: if ( !string ) ... // 4.1.5 // Kiedy sprawdzamy czy typ logiczne jest prawdą, // zamiast zapisu... if ( foo === true ) ... // ...skorzystajmy z wyrażenia: if ( foo ) ... // 4.1.6 // Kiedy sprawdzamy czy typ logiczne jest fałszem, // zamiast zapisu... if ( foo === false ) ... // ...skorzystajmy z negacji: if ( !foo ) ... // ...wyrażenie to jednak będzie prawdziwe również dla wartości: 0, null, undefined, NaN, "" // jeżeli chcesz sprawdzić czy wyrażenie jest rzeczywiście fałszem: if ( foo === false ) ... // 4.1.7 // Kiedy sprawdzasz czy zmienna ma wartość null lub undefined // zamiast zapisu: if ( foo === null || foo === undefined ) ... // ...zastosuj operator ==: if ( foo == null ) ... // Pamiętaj, użycie == dopasuje `null` do `null` i `undefined` // ale nie `false`, "" or 0 null == undefined ``` Zawsze stosuj najdokładniejsze porównania, unikniesz dzięki temu wielu niechcianych rzutowań. ```javascript // 4.2.1 // Uwagi odnoście rzutowania typów i ich wartości // Wybieraj `===` nad `==` (chyba że przypadek dopuszcza domyślne rzutowanie) // === nie rzutuje typu, tzn.: "1" === 1; // false // == rzutuje typ, tzn.: "1" == 1; // true // 4.2.2 // Typy logiczne, wartości Truthy i Falsy // Booleans: true, false // Truthy: "foo", 1 // Falsy: "", 0, null, undefined, NaN, void 0 ``` 5. Praktyczny styl ```javascript // 5.1.1 // Praktyczny moduł (function( global ) { var Module = (function() { var data = "secret"; return { // wartość logiczna bool: true, // Zmienna typu string string: "a string", // tablica jako pole obiektu array: [ 1, 2, 3, 4 ], // obiekt jako pole obiektu object: { lang: "en-Us" }, getData: function() { // funkcja zwracająca `data` return data; }, setData: function( value ) { // funkcja ustawiająca `data` i zwracająca ją return ( data = value ); } }; })(); // pozostała część kodu // upubliczniamy moduł w zmiennej `global` global.Module = Module; })( this ); ``` ```javascript // 5.2.1 // Praktyczny konstruktor (function( global ) { function Ctor( foo ) { this.foo = foo; return this; } Ctor.prototype.getFoo = function() { return this.foo; }; Ctor.prototype.setFoo = function( val ) { return ( this.foo = val ); }; // Aby wywołać konstruktor bez słowa kluczowego `new` var ctor = function( foo ) { return new Ctor( foo ); }; // upubliczniamy moduł w zmiennej `global` global.ctor = ctor; })( this ); ``` 6. Nazewnictwo A. Nie próbuj być kompilatorem. Poniżej przedstawiony jest niedopuszczalny kod: ```javascript // 6.A.1.1 // Przykład złych nazw function q(s) { return document.querySelectorAll(s); } var i,a=[],els=q("#foo"); for(i=0;iPozostałe This section will serve to illustrate ideas and concepts that should not be considered dogma, but instead exists to encourage questioning practices in an attempt to find better ways to do common JavaScript programming tasks. Ten rozdział opisuje metody, które nie powinne być traktowane jako żelazne zasady, lecz jako style które programista w miarę swoich preferencji może przyjąć lub nie. Jest to również próba zachęcenia do znajdowania lepszych sposobów realizacji bardzo często spotykanych problemów w kodzie JavaScript. A. Używanie instrukcji `switch` powinno być ograniczone do minimum. Śledzenie wywołań funkcji w kodzie może ignorować te wywołane ze `switch`. ```javascript // 7.A.1.1 // Przykład użycia `switch` switch( foo ) { case "alpha": alpha(); break; case "beta": beta(); break; default: // domyślny kod break; } // 7.A.1.2 // innym sposobem jest trzymanie przypadków w obiekcie: var cases, delegator; // Przykład: cases = { alpha: function() { // instrukcje return [ "Alpha", arguments.length ]; }, beta: function() { // instrukcje return [ "Beta", arguments.length ]; }, _default: function() { // instrukcje return [ "Default", arguments.length ]; } }; delegator = function() { var args, key, delegate; // zamiana listy arguments na tablicę args = [].slice.call( arguments ); // przesunięcie klucza(przypadku) w argumentach key = args.shift(); // przypisz domyślny handler delegate = cases._default; if ( cases.hasOwnProperty( key ) ) { delegate = cases[ key ]; } return delegate.apply( null, args ); }; // 7.A.1.3 // Przykład użycia kodu z 7.A.1.2: delegator( "alpha", 1, 2, 3, 4, 5 ); // [ "Alpha", 5 ] // Oczywiście zmienna `case` może też być zależna od innych warunków. var caseKey, someUserInput; // Albo od danych od użytkownika. someUserInput = 9; if ( someUserInput > 10 ) { caseKey = "alpha"; } else { caseKey = "beta"; } // lub... caseKey = someUserInput > 10 ? "alpha" : "beta"; delegator( caseKey, someUserInput ); // [ "Beta", 1 ] // And of course... delegator(); // [ "Default", 0 ] ``` B. Wcześniejsze wyjścia z funkcji zwiększają przejrzystość kodu. ```javascript // 7.B.1.1 // Źle: function returnLate( foo ) { var ret; if ( foo ) { ret = "foo"; } else { ret = "quux"; } return ret; } // Dobrze: function returnEarly( foo ) { if ( foo ) { return "foo"; } return "quux"; } ``` 8. Native & Host Objects Podstawowo zasada: ### Nie rób głupot, a wszystko będzie ok. Aby lepiej przyswoić tę zasadę obejrzyj prezentacje: #### “Everything is Permitted: Extending Built-ins” by Andrew Dupont (JSConf2011, Portland, Oregon) https://www.youtube.com/watch?v=xL3xCO7CLNM 9. Komentarze #### Pojedyncza linia nad kodem stanowi tytuł. #### Wieloliniowe komentarze są ok. #### Zakańczanie komentarzy jednoliniowych jest zabronione #### styl JSDoc jest poprawny, ale ciężki do opanowania 10. Jeden język Wszystkie programy powinny być pisane w jednym języku. ---------- Creative Commons License
Principles of Writing Consistent, Idiomatic JavaScript by Rick Waldron and Contributors is licensed under a Creative Commons Attribution 3.0 Unported License.
Based on a work at github.com/rwldrn/idiomatic.js. ================================================ FILE: translations/pt_BR/readme.md ================================================ # Princípios para Escrever JavaScript de forma Consistente e Idiomática ## Este é um documento vivo e novas ideias para melhorar os códigos correspondentes são sempre bem vindas. Contribua: faça fork, clone, branch, commit, push, pull request. * Rick Waldron [@rwaldron](http://twitter.com/rwaldron), [github](https://github.com/rwaldron) * Mathias Bynens [@mathias](http://twitter.com/mathias), [github](https://github.com/mathiasbynens) * Schalk Neethling [@ossreleasefeed](http://twitter.com/ossreleasefeed), [github](https://github.com/ossreleasefeed/) * Kit Cambridge [@kitcambridge](http://twitter.com/kitcambridge), [github](https://github.com/kitcambridge) * Raynos [github](https://github.com/Raynos) * Matias Arriola [@MatiasArriola](https://twitter.com/MatiasArriola), [github](https://github.com/MatiasArriola/) * John Fischer [@jfroffice](https://twitter.com/jfroffice), [github](https://github.com/jfroffice/) * Idan Gazit [@idangazit](http://twitter.com/idangazit), [github](https://github.com/idangazit) * Leo Balter [@leobalter](http://twitter.com/leobalter), [github](https://github.com/leobalter) * Breno Oliveira [@garu_rj](http://twitter.com/garu_rj), [github](https://github.com/garu) * Leo Beto Souza [@leobetosouza](http://twitter.com/leobetosouza), [github](https://github.com/leobetosouza) * Ryuichi Okumura [@okuryu](http://twitter.com/okuryu), [github](https://github.com/okuryu) * Pascal Precht [@PascalPrecht](http://twitter.com/PascalPrecht), [github](https://github.com/pascalprecht) * EngForDev [engfordev](http://www.opentutorials.org/course/167/1363) - Hwan Min Hong / MinTaek Kwon [@leoinsight](http://twitter.com/leoinsight) / Tw Shim [@marocchino](http://twitter.com/marocchino), [github](https://github.com/marocchino) / Nassol Kim [@nassol99](http://twitter.com/nassol99), [github](https://github.com/nassol) / Juntai Park [@rkJun](http://twitter.com/rkJun), [github](https://github.com/rkJun) / Minkyu Shim / Gangmin Won / Justin Yoo [@justinchronicle](http://twitter.com/justinchronicle) / Daeyup Lee * Marco Trulla [@marcotrulla](http://twitter.com/marcotrulla), [github](https://github.com/Ragnarokkr) * Alex Navasardyan [@alexnavasardyan](http://twitter.com/alexnavasardyan), [github](https://github.com/2k00l) * Mihai Paun [@mihaipaun](http://twitter.com/mihaipaun), [github](https://github.com/mihaipaun) * Evgeny Mandrikov [@\_godin\_](http://twitter.com/_godin_), [github](https://github.com/Godin) * Sofish Lin [@sofish](http://twitter.com/sofish), [github](https://github.com/sofish) * Дејан Димић [@dejan_dimic](http://twitter.com/dejan_dimic), [github](https://github.com/rubystream) * Miloš Gavrilović [@gavrisimo](http://twitter.com/gavrisimo), [github](https://github.com/gavrisimo) * Duc Nguyen [@ducntq](https://twitter.com/ducntq), [github](https://github.com/ducntq) * James Young [@jamsyoung](http://twitter.com/jamsyoung), [github](https://github.com/jamsyoung) * Stephane Moreau [github](https://github.com/stmoreau) * Boris Nekezov [github](https://github.com/boris-nekezov) * Akshat Joshi [@akshat_joshi](http://twitter.com/akshat_joshi), [github](https://https://github.com/akshatjoshii) ## Todo código em qualquer aplicação deve parecer como se tivesse sido escrito por uma única pessoa, independentemente de quantas pessoas tenham contribuído. ### A lista a seguir descreve as práticas que eu uso em todo código onde sou o autor original; contribuições em projetos que eu criei devem seguir essas mesmas orientações. ### Eu não tenho a intenção de impor minhas preferências por estilos nos códigos ou projetos de outras pessoas; se eles seguem um estilo em comum, isso deve ser respeitado. > ### "Argumentos além do estilo são inúteis. Deve haver um guia de estilo, e você deve segui-lo" >_Rebecca_ _Murphey_ > ### "Parte de ser um bom gestor de um projeto bem sucedido é perceber que escrever código para si mesmo é uma má ideia™. Se milhares de pessoas estão usando o seu código, escreva-o com máxima clareza, não sob a sua preferência pessoal de como ser esperto com a especificação." >_Idan_ _Gazit_ ## Traduções * [ORIGINAL](https://github.com/rwldrn/idiomatic.js/) * [Bulgarian](https://github.com/rwldrn/idiomatic.js/tree/master/translations/bg_BG) * [German](https://github.com/rwldrn/idiomatic.js/tree/master/translations/de_DE) * [French](https://github.com/rwldrn/idiomatic.js/tree/master/translations/fr_FR) * [Spanish](https://github.com/rwldrn/idiomatic.js/tree/master/translations/es_ES) * [Portuguese - Brazil](https://github.com/rwldrn/idiomatic.js/tree/master/translations/pt_BR) * [Korean](https://github.com/rwldrn/idiomatic.js/tree/master/translations/ko_KR) * [Japanese](https://github.com/rwldrn/idiomatic.js/tree/master/translations/ja_JP) * [Italian](https://github.com/rwldrn/idiomatic.js/tree/master/translations/it_IT) * [Russian](https://github.com/rwldrn/idiomatic.js/tree/master/translations/ru_RU) * [Romanian](https://github.com/rwldrn/idiomatic.js/tree/master/translations/ro_RO) * [简体中文](https://github.com/rwldrn/idiomatic.js/tree/master/translations/zh_CN) * [Serbian - cyrilic alphabet](https://github.com/rwldrn/idiomatic.js/tree/master/translations/ср_СР) * [Serbian - latin aplphabet](https://github.com/rwldrn/idiomatic.js/tree/master/translations/sr_SR) * [Greek](https://github.com/rwaldron/idiomatic.js/tree/master/translations/gr_GR) * [Hindi](https://github.com/rwaldron/idiomatic.js/tree/master/translations/hi_HI) ## Conteúdo importante e não idiomático: ### Qualidade de código: ferramentas, recursos e referências * [JavaScript Plugin](http://docs.codehaus.org/display/SONAR/JavaScript+Plugin) for [Sonar](http://www.sonarsource.org/) * [Plato](https://github.com/jsoverson/plato) * [jsPerf](http://jsperf.com/) * [jsFiddle](http://jsfiddle.net/) * [jsbin](http://jsbin.com/) * [JavaScript Lint (JSL)](http://javascriptlint.com/) * [jshint](http://jshint.com/) * [jslint](http://jslint.org/) * [Editorconfig](http://editorconfig.org/) ## Fique ligado ### [Annotated ECMAScript 5.1](http://es5.github.com/) ### [EcmaScript Language Specification, 5.1 Edition](http://ecma-international.org/ecma-262/5.1/) A lista a seguir deve ser considerada: 1) incompleta; e 2) *LEITURA OBRIGATÓRIA*. Eu não concordo sempre com os estilos escritos pelos autores abaixo, mas uma coisa é certa: eles são consistentes. Além disso, esses são autoridades na linguagem. * [Baseline For Front End Developers](http://rmurphey.com/blog/2012/04/12/a-baseline-for-front-end-developers/) * [Eloquent JavaScript](http://eloquentjavascript.net/) * [JavaScript, JavaScript](http://javascriptweblog.wordpress.com/) * [Adventures in JavaScript Development](http://rmurphey.com/) * [Perfection Kills](http://perfectionkills.com/) * [Douglas Crockford's Wrrrld Wide Web](http://www.crockford.com) * [JS Assessment](https://github.com/rmurphey/js-assessment) * [Leveraging Code Quality Tools (em pt_BR: Tirando Proveito de Ferramentas de Qualidade de Código) por Anton Kovalyov](http://anton.kovalyov.net/slides/gothamjs/) ### Processos de build e deploy Projetos devem sempre tentar incluir algumas formas genéricas nas quais o código podem ser checados com ferramentas de lint, testados e compactados no preparo para uso em produção. Para essa tarefa, o [grunt](https://github.com/cowboy/grunt) pelo Ben Alman é a melhor opção, além de ter substituído oficialmente o diretório "kits/" neste repositório. ### Ambiente de teste Projetos _devem_ incluir alguma forma de teste unitário, de referência, de implementação ou funcional. Demonstrações de casos de uso NÃO SE QUALIFICAM como "testes". A lista a seguir contém frameworks de testes, nenhuma delas é considerada melhor que as demais. * [QUnit](http://github.com/jquery/qunit) * [Jasmine](https://github.com/pivotal/jasmine) * [Vows](https://github.com/cloudhead/vows) * [Mocha](https://github.com/visionmedia/mocha) * [Hiro](http://hirojs.com/) * [JsTestDriver](https://code.google.com/p/js-test-driver/) * [Buster.js](http://busterjs.org/) * [Sinon.js](http://sinonjs.org/) ## Índice * [Espaço em branco](#whitespace) * [Sintaxe bonita](#spacing) * [Checagem de escrita (cortesia das Recomendações de Estilo do Núcleo do jQuery)](#type) * [Avaliação condicional](#cond) * [Estilo prático](#practical) * [Nomenclatura](#naming) * [Miscelâneas](#misc) * [Objetos nativos e hospedados](#native) * [Comentários](#comments) * [Código em apenas um idioma](#language) ------------------------------------------------ ## Prefácio As seções a seguir descrevem um guia de estilos razoável para desenvolvimento de JavaScript moderno e não pretendem ser obrigatórias. A conclusão mais importante é a **lei da consistência de estilo de código**. O que for escolhido como estilo para o seu projeto deverá ser considerado lei. Faça um link para este documento como uma regra do seu projeto sobre comprometimento de consistência, legibilidade e manutenção de estilo de código. ## Manifesto de estilo idiomático 1. Espaço em branco - Nunca misture espaços e tabs. - Quando começar um projeto, antes de escrever qualquer código, escolha entre indentação suave (espaços) ou tabulação real (tabs), considere isso como **lei**. - Pela legibilidade, eu sempre recomendo que configure o tamanho de indentação de seu editor para dois caracteres - isso significa dois espaços ou dois espaços representando um tab real. - Se o seu editor suportar, sempre trabalhe com a configuração de "mostrar caracteres invisíveis" ligada. Os benefícios desta prática são: - fortalecer a consistência; - eliminar espaço em branco ao final da linha; - eliminar espaços em uma linha em branco; - commits e diffs mais legíveis. 2. Sintaxe bonita A. Parênteses, chaves e quebras de linhas ```javascript // if/else/for/while/try sempre tem espaços, chaves e ocorrem em múltiplas linhas // isso facilita a legibilidade // 2.A.1.1 // Exemplos de código pouco claro/bagunçado if(condicao) facaAlgo(); while(condicao) iteracao++; for(var i=0;i<100;i++) algumaIteracao(); // 2.A.1.1 // Use espaço em branco para facilitar a leitura if ( condicao ) { // instruções } while ( condicao ) { // instruções } for ( var i = 0; i < 100; i++ ) { // instruções } // Melhor ainda: var i, length = 100; for ( i = 0; i < length; i++ ) { // instruções } // Ou... var i = 0, length = 100; for ( ; i < length; i++ ) { // instruções } var prop; for ( prop in object ) { // instruções } if ( true ) { // instruções } else { // instruções } ``` B. Atribuições, declarações, funções (nomenclatura, expressão, construtor) ```javascript // 2.B.1.1 // Variáveis var foo = "bar", num = 1, undef; // Notações literais: var array = [], object = {}; // 2.B.1.2 // Utilizando apenas um `var` por escopo (função) promove legibilidade // e mantém a sua lista de declaração livre de desordem (além de evitar algumas tecladas) // Ruim var foo = ""; var bar = ""; var qux; // Bom var foo = "", bar = "", quux; // ou.. var // comentário aqui foo = "", bar = "", quux; // 2.B.1.3 // declarações de variáveis devem sempre estar no início de seu respectivo escopo (função) // O mesmo deve acontecer para declarações de `const` e `let` do ECMAScript 6. // Ruim function foo() { // algumas instruções aqui var bar = "", qux; } // Bom function foo() { var bar = "", qux; // algumas instruções depois das declarações de variáveis } ``` ```javascript // 2.B.2.1 // Declaração de função nomeada function foo( arg1, argN ) { } // Utilização foo( arg1, argN ); // 2.B.2.2 // Declaração de função nomeada function square( number ) { return number * number; } // Utilização square( 10 ); // Estilo de passagem artificialmente contínua function square( number, callback ) { callback( number * number ); } square( 10, function( square ) { // instruções de callback }); // 2.B.2.3 // Expressão de função var square = function( number ) { // Retorna algo de valor e relevante return number * number; }; // Expressão de função com identificador // Esse formato preferencial tem o valor adicional de permitir // chamar a si mesmo e ter uma identidade na pilha de comandos: var factorial = function factorial( number ) { if ( number < 2 ) { return 1; } return number * factorial( number-1 ); }; // 2.B.2.4 // Declaração de construtor function FooBar( options ) { this.options = options; } // Utilização var fooBar = new FooBar({ a: "alpha" }); fooBar.options; // { a: "alpha" } ``` C. Exceções, pequenos desvios ```javascript // 2.C.1.1 // Funções com callbacks foo(function() { // Veja que não há espaço extra entre os parênteses // da chamada de função e a palavra "function" }); // Função recebendo uma array, sem espaço foo([ "alpha", "beta" ]); // 2.C.1.2 // Função recebendo um objeto, sem espaço foo({ a: "alpha", b: "beta" }); // String literal como argumento único, sem espaço foo("bar"); // Parênteses internos de agrupamento, sem espaço if ( !("foo" in obj) ) { } ``` D. Consistência sempre ganha Nas seções 2.A-2.C, as regras de espaço em branco são recomendadas sob um propósito simples e maior: consistência. É importante notar que preferências de formatação, tais como "espaço em branco interno" deve ser considerado opcional, mas apenas um estilo deve existir por toda a fonte de seu projeto. ```javascript // 2.D.1.1 if (condition) { // instruções } while (condition) { // instruções } for (var i = 0; i < 100; i++) { // instruções } if (true) { // instruções } else { // instruções } ``` E. Aspas Se você preferir usar simples ou dupla não importa, não há diferença em como o JavaScript analisa elas. O que **ABSOLUTAMENTE PRECISA** ser aplicado é consistência. **Nunca misture diferentes tipos de aspas em um mesmo projeto. Escolha um estilo e fique com ele.** F. Finais de linha e linhas vazias Espaços em branco podem arruinar diffs e fazer com que _changesets_ sejam impossíveis de se ler. Considere incorporar um gancho de pre-commit que remova espaços em branco ao final das linhas e espaços em branco em linhas vazias automaticamente. 3. Checagem de escrita (cortesia das Recomendações de Estilo do Núcleo do jQuery) A. Tipos existentes String: ```javascript typeof variavel === "string" ``` Number: ```javascript typeof variavel === "number" ``` Boolean: ```javascript typeof variavel === "boolean" ``` Object: ```javascript typeof variavel === "object" ``` Array: ```javascript Array.isArray( variavel ) // (quando possível) ``` null: ```javascript variavel === null ``` null ou undefined: ```javascript variavel == null ``` undefined: Variáveis Globais: ```javascript typeof variavel === "undefined" ``` Variáveis Locais: ```javascript variavel === undefined ``` Propriedades: ```javascript object.prop === undefined object.hasOwnProperty( prop ) "prop" in object ``` B. Tipos coagidos Considere as implicações do seguinte... Dado este HTML: ```html ``` ```javascript // 3.B.1.1 // `foo` foi declarado com o valor `0` e seu tipo é `number` var foo = 0; // typeof foo; // "number" ... // Algum momento depois no seu código, você precisa atualizar `foo` // com um novo valor derivado de um elemento `input` foo = document.getElementById("foo-input").value; // Se você testasse `typeof foo` agora, o resultado seria uma `string` // Isso significa que se tivesse uma lógica que testasse `foo` como: if ( foo === 1 ) { importantTask(); } // `importantTask()` nunca seria chamado, mesmo que `foo` tivesse um valor "1" // 3.B.1.2 // Você pode prevenir problemas utilizando uma coerção automática com os operadores + ou -: foo = +document.getElementById("foo-input").value; // ^ o operador + irá converter o operando do lado direito para um número // typeof foo; // "number" if ( foo === 1 ) { importantTask(); } // `importantTask()` será chamado ``` Aqui temos alguns casos comuns com coerções: ```javascript // 3.B.2.1 var number = 1, string = "1", bool = false; number; // 1 number + ""; // "1" string; // "1" +string; // 1 +string++; // 1 string; // 2 bool; // false +bool; // 0 bool + ""; // "false" ``` ```javascript // 3.B.2.2 var number = 1, string = "1", bool = true; string === number; // false string === number + ""; // true +string === number; // true bool === number; // false +bool === number; // true bool === string; // false bool === !!string; // true ``` ```javascript // 3.B.2.3 var array = [ "a", "b", "c" ]; !!~array.indexOf( "a" ); // true !!~array.indexOf( "b" ); // true !!~array.indexOf( "c" ); // true !!~array.indexOf( "d" ); // false // Note que o que está acima deve ser considerado // "desnecessariamente inteligente". // Prefira a aproximação óbvia de comparar o valor retornado do // indexOf, como por exemplo: if ( array.indexOf( "a" ) >= 0 ) { // ... } ``` ```javascript // 3.B.2.3 var num = 2.5; parseInt( num, 10 ); // é o mesmo que... ~~num; num >> 0; num >>> 0; // Todos resultam em 2 // De qualquer forma, lembre-se que números negativos são tratados // de forma diferente... var neg = -2.5; parseInt( neg, 10 ); // é o mesmo que... ~~neg; neg >> 0; // Resulta em -2 // Porém... neg >>> 0; // Vai resultar em 4294967294 ``` 4. Avaliação condicional ```javascript // 4.1.1 // Quando estiver apenas avaliando se um array tem tamanho, // ao invés disso: if ( array.length > 0 ) ... // ...avalie a verdade lógica, como isso: if ( array.length ) ... // 4.1.2 // Quando estiver apenas avaliando se um array está vazio, // ao invés disso: if ( array.length === 0 ) ... // ...avalie a verdade lógica, como isso: if ( !array.length ) ... // 4.1.3 // Quando estiver apenas avaliando se uma string não está vazia, // ao invés disso: if ( string !== "" ) ... // ...avalie a verdade lógica, como isso: if ( string ) ... // 4.1.4 // Quando estiver apenas avaliando se uma string está vazia, // ao invés disso: if ( string === "" ) ... // ...avalie se ela é logicamente falsa, como isso: if ( !string ) ... // 4.1.5 // Quando estiver avaliando se uma referência é verdadeira, // ao invés disso: if ( foo === true ) ... // ...avalie como se quisesse isso, use a vantagem de suas capacidades primitivas: if ( foo ) ... // 4.1.6 // Quando estiver avaliando se uma referência é falsa, // ao invés disso: if ( foo === false ) ... // ...use a negação para coagir para uma avaliação verdadeira if ( !foo ) ... // ...Seja cuidadoso, isso também irá funcionar com: 0, "", null, undefined, NaN // Se você _PRECISA_ testar um valor falso de tipo booleano, então use if ( foo === false ) ... // 4.1.7 // Quando apenas estiver avaliando uma referência que pode ser `null` ou `undefined`, mas NÃO `false`, "" ou 0, // ao invés disso: if ( foo === null || foo === undefined ) ... // ...aproveite a vantagem da coerção de tipo com ==, como isso: if ( foo == null ) ... // Lembre-se, utilizando == irá funcionar em um `null` TANTO para `null` quanto para `undefined` // mas não para `false`, "" ou 0 null == undefined ``` SEMPRE avalie para o melhor e mais preciso resultado - o que está acima é uma recomendação, não um dogma. ```javascript // 4.2.1 // Coerção de tipo e notas sobre avaliações Prefira `===` ao invés de `==` (ao menos em casos que necessitem avaliação de tipos flexíveis) === não faz coerção de tipo, o que significa que: "1" === 1; // false == faz coerção de tipo, o que significa que: "1" == 1; // true // 4.2.2 // Booleanos, verdades e negações // Booleanos: true, false // Verdades: "foo", 1 // Negações: "", 0, null, undefined, NaN, void 0 ``` 5. Estilo Prático ```javascript // 5.1.1 // Um módulo prático (function( global ) { var Module = (function() { var data = "segredo"; return { // Essa é uma propriedade booleana bool: true, // Algum valor de string string: "uma string", // Uma propriedade em array array: [ 1, 2, 3, 4 ], // Uma propriedade em objeto object: { lang: "pt-BR" }, getData: function() { // pega o valor atual de `data` return data; }, setData: function( value ) { // atribui o valor a data que é retornado return ( data = value ); } }; })(); // Outras coisas que também podem acontecer aqui // Expor seu módulo ao objeto global global.Module = Module; })( this ); ``` ```javascript // 5.2.1 // Um construtor prático (function( global ) { function Ctor( foo ) { this.foo = foo; return this; } Ctor.prototype.getFoo = function() { return this.foo; }; Ctor.prototype.setFoo = function( val ) { return ( this.foo = val ); }; // Para chamar um construtor sem o `new`, você pode fazer assim: var ctor = function( foo ) { return new Ctor( foo ); }; // exponha nosso construtor ao objeto global global.ctor = ctor; })( this ); ``` 6. Nomenclatura A. Se você não é um compilador humano ou compactador de código, não tente ser um. O código a seguir é um exemplo de nomenclatura ruim: ```javascript // 6.A.1.1 // Exemplo de código com nomenclaturas fracas function q(s) { return document.querySelectorAll(s); } var i,a=[],els=q("#foo"); for(i=0;iMiscelânea Esta seção deve servir para ilustrar idéias e conceitos sobre como não se considerar isso como um dogma, mas ao invés disso deve encorajar o questionamento de práticas na tentativa de encontrar formas melhores para executar tarefas comuns na programação em JavaScript. A. Evite utilizar `switch`, métodos modernos de verificação deverão adicionar funções com `switch` em suas listas negras Parecem haver melhorias drásticas à execução do comando `switch` nas últimas versões do Firefox e do Chrome: http://jsperf.com/switch-vs-object-literal-vs-module Melhorias notáveis podem ser observadas aqui também: https://github.com/rwldrn/idiomatic.js/issues/13 ```javascript // 7.A.1.1 // Um exemplo de uma instrução switch switch( foo ) { case "alpha": alpha(); break; case "beta": beta(); break; default: // algo para executar por padrão break; } // 7.A.1.2 // Uma maneira alternativa de dar suporte para facilidade de composição e // reutiilização é utilizar um objeto que guarde "cases" e uma função // para delegar: var cases, delegator; // Retornos de exemplo apenas para ilustração. cases = { alpha: function() { // instruções // um retorno return [ "Alpha", arguments.length ]; }, beta: function() { // instruções // um retorno return [ "Beta", arguments.length ]; }, _default: function() { // instruções // um retorno return [ "Default", arguments.length ]; } }; delegator = function() { var args, key, delegate; // Transforma a lista de argumentos em uma array args = [].slice.call( arguments ); // Retira a chave inicial dos argumentos key = args.shift(); // Atribui o manipulador de caso padrão delegate = cases._default; // Deriva o método para delegar a operação para if ( cases.hasOwnProperty( key ) ) { delegate = cases[ key ]; } // O argumento de escopo pode ser definido para algo específico // nesse caso, |null| será suficiente return delegate.apply( null, args ); }; // 7.A.1.3 // Coloque a API do 7.A.1.2 para funcionar: delegator( "alpha", 1, 2, 3, 4, 5 ); // [ "Alpha", 5 ] // Claro que a argumento de chave inicial pode ser facilmente baseada // em alguma outra condição arbitrária. var caseKey, someUserInput; // Possivelmente alguma maneira de entrada de formulário? someUserInput = 9; if ( someUserInput > 10 ) { caseKey = "alpha"; } else { caseKey = "beta"; } // ou... caseKey = someUserInput > 10 ? "alpha" : "beta"; // E assim... delegator( caseKey, someUserInput ); // [ "Beta", 1 ] // E claro... delegator(); // [ "Default", 0 ] ``` B. Retornos antecipados promovem legibilidade de código com mínima diferença de performance ```javascript // 7.B.1.1 // Ruim: function returnLate( foo ) { var ret; if ( foo ) { ret = "foo"; } else { ret = "quux"; } return ret; } // Bom: function returnEarly( foo ) { if ( foo ) { return "foo"; } return "quux"; } ``` 8. Objetos nativos e hospedados O princípio básico aqui é: ### Não faça coisas estúpidas e tudo vai ficar bem. Para reforçar esse conceito, por favor, assista essa apresentação: #### “Everything is Permitted: Extending Built-ins” por Andrew Dupont (JSConf2011, Portland, Oregon) https://www.youtube.com/watch?v=xL3xCO7CLNM 9. Comentários * Uma linha única acima do código que é comentado * Multiplas linhas é bom * Comentários ao final da linha são proibidos! * O estilo do JSDoc é bom, porém requer um investimento de tempo significante 10. Código em apenas um idioma Programas devem ser escritos em um único idioma, não importe o idioma que seja, a ser definido por quem o mantém. ## Apêndice ### Vírgula inicial. Qualquer projeto que cite este documento como seu guia base de estilo não aceitará formatação de código com vírgula inicial, a não ser que isso seja explicitamente especificado de outra forma pelo autor do projeto. ================================================ FILE: translations/ro_RO/readme.md ================================================ # Principii de codare consistentă și idiomatică în JavaScript ## Acesta este un document în continuă dezvoltare și noi idei pentru îmbunătățirea codului pe care-l scriem sunt întotdeauna binevenite. Contribuie și tu: fork, clone, branch, commit, push, pull request. * Rick Waldron [@rwaldron](http://twitter.com/rwaldron), [github](https://github.com/rwaldron) * Mathias Bynens [@mathias](http://twitter.com/mathias), [github](https://github.com/mathiasbynens) * Schalk Neethling [@ossreleasefeed](http://twitter.com/ossreleasefeed), [github](https://github.com/ossreleasefeed/) * Kit Cambridge [@kitcambridge](http://twitter.com/kitcambridge), [github](https://github.com/kitcambridge) * Raynos [github](https://github.com/Raynos) * Matias Arriola [@MatiasArriola](https://twitter.com/MatiasArriola), [github](https://github.com/MatiasArriola/) * John Fischer [@jfroffice](https://twitter.com/jfroffice), [github](https://github.com/jfroffice/) * Idan Gazit [@idangazit](http://twitter.com/idangazit), [github](https://github.com/idangazit) * Leo Balter [@leobalter](http://twitter.com/leobalter), [github](https://github.com/leobalter) * Breno Oliveira [@garu_rj](http://twitter.com/garu_rj), [github](https://github.com/garu) * Leo Beto Souza [@leobetosouza](http://twitter.com/leobetosouza), [github](https://github.com/leobetosouza) * Ryuichi Okumura [@okuryu](http://twitter.com/okuryu), [github](https://github.com/okuryu) * Pascal Precht [@PascalPrecht](http://twitter.com/PascalPrecht), [github](https://github.com/pascalprecht) * EngForDev [engfordev](http://www.opentutorials.org/course/167/1363) - Hwan Min Hong / MinTaek Kwon [@leoinsight](http://twitter.com/leoinsight) / Tw Shim [@marocchino](http://twitter.com/marocchino), [github](https://github.com/marocchino) / Nassol Kim [@nassol99](http://twitter.com/nassol99), [github](https://github.com/nassol) / Juntai Park [@rkJun](http://twitter.com/rkJun), [github](https://github.com/rkJun) / Minkyu Shim / Gangmin Won / Justin Yoo [@justinchronicle](http://twitter.com/justinchronicle) / Daeyup Lee * Marco Trulla [@marcotrulla](http://twitter.com/marcotrulla), [github](https://github.com/Ragnarokkr) * Alex Navasardyan [@alexnavasardyan](http://twitter.com/alexnavasardyan), [github](https://github.com/2k00l) * Mihai Paun [@mihaipaun](http://twitter.com/mihaipaun), [github](https://github.com/mihaipaun) * Evgeny Mandrikov [@\_godin\_](http://twitter.com/_godin_), [github](https://github.com/Godin) * Sofish Lin [@sofish](http://twitter.com/sofish), [github](https://github.com/sofish) * Дејан Димић [@dejan_dimic](http://twitter.com/dejan_dimic), [github](https://github.com/rubystream) * Miloš Gavrilović [@gavrisimo](http://twitter.com/gavrisimo), [github](https://github.com/gavrisimo) * Duc Nguyen [@ducntq](https://twitter.com/ducntq), [github](https://github.com/ducntq) * James Young [@jamsyoung](http://twitter.com/jamsyoung), [github](https://github.com/jamsyoung) * Stephane Moreau [github](https://github.com/stmoreau) * Boris Nekezov [github](https://github.com/boris-nekezov) * Akshat Joshi [@akshat_joshi](http://twitter.com/akshat_joshi), [github](https://https://github.com/akshatjoshii) ## Tot codul dintr-o aplicație trebuie să arate ca și cum ar fi fost scris de o singură persoană, indiferent de câți oameni au contribuit la scrierea lui. ### Următoarea listă subliniază practicile pe care le folosesc în aplicațiile al căror autor original sunt; contribuțiile la proiectele pe care le-am creat ar trebui să urmeze aceste indicații. ### Nu intenționez să impun preferințele mele de stilizare a codului altor oameni sau proiecte; în cazul în care un stil comun există, ar trebui respectat. > ### "Dezbaterile asupra stilizării sunt inutile. Ar trebui să existe un ghid de stilizare, şi ar trebui urmat" >_Rebecca_ _Murphey_   > ### "Una din condițiile pentru a fi un bun administrator al unui proiect de succes este realizarea faptului că a scrie cod pentru tine este o IDEE REA™. Dacă mii de oameni îți folosesc codul, atunci scrie cod pentru claritate maximă, nu după preferințele personale de a deveni expert în specificații." >_Idan_ _Gazit_ ## Traduceri * [ORIGINAL](https://github.com/rwldrn/idiomatic.js/) * [Bulgarian](https://github.com/rwldrn/idiomatic.js/tree/master/translations/bg_BG) * [German](https://github.com/rwldrn/idiomatic.js/tree/master/translations/de_DE) * [French](https://github.com/rwldrn/idiomatic.js/tree/master/translations/fr_FR) * [Spanish](https://github.com/rwldrn/idiomatic.js/tree/master/translations/es_ES) * [Portuguese - Brazil](https://github.com/rwldrn/idiomatic.js/tree/master/translations/pt_BR) * [Korean](https://github.com/rwldrn/idiomatic.js/tree/master/translations/ko_KR) * [Japanese](https://github.com/rwldrn/idiomatic.js/tree/master/translations/ja_JP) * [Italian](https://github.com/rwldrn/idiomatic.js/tree/master/translations/it_IT) * [Russian](https://github.com/rwldrn/idiomatic.js/tree/master/translations/ru_RU) * [Romanian](https://github.com/rwldrn/idiomatic.js/tree/master/translations/ro_RO) * [简体中文](https://github.com/rwldrn/idiomatic.js/tree/master/translations/zh_CN) * [Serbian - cyrilic alphabet](https://github.com/rwldrn/idiomatic.js/tree/master/translations/ср_СР) * [Serbian - latin aplphabet](https://github.com/rwldrn/idiomatic.js/tree/master/translations/sr_SR) * [Greek](https://github.com/rwaldron/idiomatic.js/tree/master/translations/gr_GR) * [Hindi](https://github.com/rwaldron/idiomatic.js/tree/master/translations/hi_HI) ## Conținut Important și Non-Idiomatic: ### Calitatea codului: Unelte, Resurse și Referințe * [JavaScript Plugin](http://docs.codehaus.org/display/SONAR/JavaScript+Plugin) for [Sonar](http://www.sonarsource.org/) * [jsPerf](http://jsperf.com/) * [jsFiddle](http://jsfiddle.net/) * [jsbin](http://jsbin.com/) * [JavaScript Lint (JSL)](http://javascriptlint.com/) * [jshint](http://jshint.com/) * [jslint](http://jslint.org/) * [Editorconfig](http://editorconfig.org/) ## Învață ### [ECMAScript 5.1 Adnotat](http://es5.github.com/) ### [Specificațiile EcmaScript, Ediția 5.1](http://ecma-international.org/ecma-262/5.1/) Următoarele ar trebui să fie considerate 1) incomplete, și 2) *LECTURĂ OBLIGATORIE*. Nu sunt întotdeauna de acord cu stilul promovat de următorii autori, dar un lucru este clar: Sunt consecvenți. Mai mult decât atât, ei reprezintă autorități ale limbajului. * [Baseline For Front End Developers](http://rmurphey.com/blog/2012/04/12/a-baseline-for-front-end-developers/) * [Eloquent JavaScript](http://eloquentjavascript.net/) * [JavaScript, JavaScript](http://javascriptweblog.wordpress.com/) * [Adventures in JavaScript Development](http://rmurphey.com/) * [Perfection Kills](http://perfectionkills.com/) * [Douglas Crockford's Wrrrld Wide Web](http://www.crockford.com) * [JS Assessment](https://github.com/rmurphey/js-assessment) * [Leveraging Code Quality Tools by Anton Kovalyov](http://anton.kovalyov.net/slides/gothamjs/) ### Procesul de Build & Deployment Proiectele ar trebui să încerce mereu să includă unele mijloace prin care sursele pot fi validate (linted), testate și comprimate în vederea pregătirii pentru producție. Pentru această activitate, [grunt](https://github.com/cowboy/grunt) de Ben Alman este principala opțiune și a înlocuit oficial directorul "kits/" al acestui repozitoriu. ### Procesul de Testare Proiectele _trebuie_ să includă o formă sau alta de testare unitară, de referință, de implementare sau funcțională. Studiile de caz NU SE CONSIDERĂ "teste". Lista următoare este o listă de framework-uri de testare, niciunul dintre ele nefiind mai avizat decât celălalt. * [QUnit](http://github.com/jquery/qunit) * [Jasmine](https://github.com/pivotal/jasmine) * [Vows](https://github.com/cloudhead/vows) * [Mocha](https://github.com/visionmedia/mocha) * [Hiro](http://hirojs.com/) * [JsTestDriver](https://code.google.com/p/js-test-driver/) * [Buster.js](http://busterjs.org/) ## Cuprins * [Spațiile albe](#whitespace) * [Sintaxă plăcută](#spacing) * [Verificarea tipului (Curtoazie a indicațiilor stilistice din jQuery Core)](#type) * [Evaluare condițională](#cond) * [Stil practic](#practical) * [Nomenclatura](#naming) * [Diverse](#misc) * [Obiecte native și gazdă](#native) * [Comentarii](#comments) * [Un cod, un limbaj](#language) ------------------------------------------------ ## Prefață Următoarele secțiuni subliniază un ghid de stilizare _rezonabil_ pentru dezvoltarea modernă de cod JavaScript și nu sunt menite să fie normative. Cea mai importantă de reținut este **legea coerenței stilului de cod**. Orice stil ai considera pentru proiectul tău trebuie considerat lege. Consideră acest document ca o declarație a consistenței, lizibilității și mentenabilității proiectului tău. ## Manifest de stil idiomatic 1. Spațierea - Nu se amestecă spațiile albe cu taburile. - La începutul unui proiect, înainte de a începe să scrii cod, alege între spațiere soft (spații) sau taburi - consideră aceasta **lege**. - Pentru lizibilitate, recomand configurarea setării de indentare a editorului la 2 caractere — asta înseamnă două spații sau două spații reprezentând un tab real. - Dacă editorul suportă, opțiunea "show invisibles" ar trebui să fie bifată. Beneficiile acestei practici sunt: - Consecvență aplicată - Eliminarea spațiilor albe de la sfîrșitul liniei - Eliminarea rândurilor libere - Commit-urile și diff-urile sunt mai ușor de citit 2. Sintaxă curată A. Parantezele, Acoladele, Liniile noi ```javascript // if/else/for/while/try au întotdeauna spații, acolade și se întind pe mai multe linii // asta încurajează lizibilitatea codului // 2.A.1.1 // Exemple de sintaxă foarte înghesuită if(condition) doSomething(); while(condition) iterating++; for(var i=0;i<100;i++) someIterativeFn(); // 2.A.1.1 // Folosește spațiere pentru a încuraja lizibilitatea codului if ( condition ) { // declarații } while ( condition ) { // declarații } for ( var i = 0; i < 100; i++ ) { // declarații } // De preferat: var i, length = 100; for ( i = 0; i < length; i++ ) { // declarații } // Sau... var i = 0, length = 100; for ( ; i < length; i++ ) { // declarații } var prop; for ( prop in object ) { // declarații } if ( true ) { // declarații } else { // declarații } ``` B. Atribuiri, Declarații, Funcții ( Nomenclatura, Expresie, Constructor ) ```javascript // 2.B.1.1 // Variabile var foo = "bar", num = 1, undef; // Notații literale: var array = [], object = {}; // 2.B.1.2 // Folosirea unei singure `var` per context (funcție) încurajează lizibilitatea codului // și păstrează lista declarațiilor în ordine (de asemenea te scutește de câteva tastări) // Incorect var foo = ""; var bar = ""; var qux; // Corect var foo = "", bar = "", quux; // sau.. var // Comentarii foo = "", bar = "", quux; // 2.B.1.3 // declarațiile de variable trebuie să fie la începutul contextului lor respectiv (funcției). // Același lucru se aplică pentru const și let din ECMAScript 6. // Incorect function foo() { // unele declarații aici var bar = "", qux; } // Corect function foo() { var bar = "", qux; // restul codului după declarațiile de variabile } ``` ```javascript // 2.B.2.1 // Declarație de funcție denumită function foo( arg1, argN ) { } // Utilizare foo( arg1, argN ); // 2.B.2.2 // Declarație de funcție denumită function square( number ) { return number * number; } // Utilizare square( 10 ); // Stil foarte artificial de transmitere a continuității function square( number, callback ) { callback( number * number ); } square( 10, function( square ) { // declarații callback }); // 2.B.2.3 // Exprimarea Funcției var square = function( number ) { // returnează ceva valoros și relevant return number * number; }; // Exprimarea Funcției și Identificator // Această formă preferată are valoarea adăugată de a fi // capabilă de a se invoca și de a avea o identitate în stiva de comenzi var factorial = function factorial( number ) { if ( number < 2 ) { return 1; } return number * factorial( number-1 ); }; // 2.B.2.4 // Declarația Constructor-ului function FooBar( options ) { this.options = options; } // Utilizare var fooBar = new FooBar({ a: "alpha" }); fooBar.options; // { a: "alpha" } ``` C. Excepții, Ușoare Abateri ```javascript // 2.C.1.1 // Funcții cu callbacks foo(function() { // De observat că nu există spațiu intre prima paranteză // a funcției în execuție și cuvântul "function" }); // Funcție care primește ca parametru un array, fără spații foo([ "alpha", "beta" ]); // 2.C.1.2 // Funcție care primește ca paremtru un obiect, fără spații foo({ a: "alpha", b: "beta" }); // Un singur argument literal de tip string, fără spații foo("bar"); // Paranteze interioare grupate, fără spații if ( !("foo" in obj) ) { } ``` D. Consecvența are câștig de cauză întotdeauna În secțiunile 2.A-2.C, normele de spațiere sunt stabilite drept o recomandare cu un scop simplu și precis: consecvența. E important de reținut că preferințele de formatare, precum "spațierea interioară" ar trebui să fie considerate opționale, dar un singur stil ar trebui să existe pe întreaga sursă a proiectului. ```javascript // 2.D.1.1 if (condition) { // declarații } while (condition) { // declarații } for (var i = 0; i < 100; i++) { // declarații } if (true) { // declarații } else { // declarații } ``` E. Ghilimele Fie că preferi ghilimele simple sau duble nu ar trebui să conteze, nu există o diferență în modul de parsare al JavaScript. Ce trebuie **NEAPĂRAT FĂCUT** este să primeze consecvența. **Nu amesteca tipul de ghilimele în același proiect. Alege un stil și ține-te de el.** F. Sfîrșitul de Linii și Liniile Goale Spațiile albe pot distruge diff-urile și pot randa modificările imposibil de citit. Ia în calcul incorporarea unui hook pre-commit care elimină automat spațiile albe de la sfîrșitul liniilor și spațiile goale de pe liniile libere. 3. Verificarea tipului (Curtoazie a indicațiilor stilistice din jQuery Core) A. Tipuri Existente String: typeof variable === "string" Number: typeof variable === "number" Boolean: typeof variable === "boolean" Object: typeof variable === "object" Array: Array.isArray( arrayLikeObject ) (ori de câte ori este posibil) Node: elem.nodeType === 1 null: variable === null null sau undefined: variable == null undefined: Variabile Globale: typeof variable === "undefined" Variabile Locale: variable === undefined Proprietăți: object.prop === undefined object.hasOwnProperty( prop ) "prop" in object B. Tipuri Constrânse Luați în considerare implicațiile următoarelor... Dat fiind codul HTML: ```html ``` ```javascript // 3.B.1.1 // `foo` a fost declarat cu valoarea `0` și este de tipul `number` var foo = 0; // typeof foo; // "number" ... // Ulterior, trebuie actualizată variabila `foo` // cu o nouă valoare derivată dintr-un element `input` foo = document.getElementById("foo-input").value; // Dacă ar fi să verificați `typeof foo` acum, rezultatul ar fi `string` // Asta înseamnă că dacă ați fi avut logică care să verifice `foo` în următoarea manieră: if ( foo === 1 ) { importantTask(); } // `importantTask()` nu s-ar evalua, chiar dacă `foo` are valoarea "1" // 3.B.1.2 // Se pot anticipa asftel de probleme prin folosirea operatorilor unari + sau -: foo = +document.getElementById("foo-input").value; // ^ operatorul unar + va converti operandul din dreapta într-un număr // typeof foo; // "number" if ( foo === 1 ) { importantTask(); } // `importantTask()` va fi apelat ``` Câteva cazuri comune, alături de constrângeri: ```javascript // 3.B.2.1 var number = 1, string = "1", bool = false; number; // 1 number + ""; // "1" string; // "1" +string; // 1 +string++; // 1 string; // 2 bool; // false +bool; // 0 bool + ""; // "false" ``` ```javascript // 3.B.2.2 var number = 1, string = "1", bool = true; string === number; // false string === number + ""; // true +string === number; // true bool === number; // false +bool === number; // true bool === string; // false bool === !!string; // true ``` ```javascript // 3.B.2.3 var array = [ "a", "b", "c" ]; !!~array.indexOf("a"); // true !!~array.indexOf("b"); // true !!~array.indexOf("c"); // true !!~array.indexOf("d"); // false // De remarcat că cele de mai sus trebuie considerate "inteligente inutil" // E de preferat abordarea evidentă a comparării valorii returnate de // indexOf, după cum urmează: if ( array.indexOf( "a" ) >= 0 ) { // ... } ``` ```javascript // 3.B.2.3 var num = 2.5; parseInt( num, 10 ); // e la fel ca... ~~num; num >> 0; num >>> 0; // Toate au ca rezultat 2 // De reținut totuși, numerele negative vor fi tratate diferit... var neg = -2.5; parseInt( neg, 10 ); // e la fel ca... ~~neg; neg >> 0; // Toate au ca rezultat -2 // Totuși... neg >>> 0; // Va avea ca rezultat 4294967294 ``` 4. Evaluare Condițională ```javascript // 4.1.1 // Când se evaluează dacă un array are dimensiune, // în loc de: if ( array.length > 0 ) ... // ...se evaluează valoarea de adevăr, după cum urmează: if ( array.length ) ... // 4.1.2 // Când se evaluează dacă un array este gol, // în loc de: if ( array.length === 0 ) ... // ...se evaluează valoarea de adevăr, după cum urmează: if ( !array.length ) ... // 4.1.3 // Când se evaluează dacă un string nu este gol, // în loc de: if ( string !== "" ) ... // ...se evaluează valoarea de adevăr, după cum urmează: if ( string ) ... // 4.1.4 // Când se evaluează dacă un string _este_ gol, // în loc de: if ( string === "" ) ... // ...se evaluează falsitatea, după cum urmează: if ( !string ) ... // 4.1.5 // Când se evaluează dacă o referință este adevarată, // în loc de: if ( foo === true ) ... // ...se evaluează așa cum are sens, profitând de capacitățile native ale limbajului: if ( foo ) ... // 4.1.6 // Când se evaluează dacă o referință este falsă, // în loc de: if ( foo === false ) ... // ...se folosește negarea pentru a constrânge o evaluare adevarată if ( !foo ) ... // ...Atenție, această declarație va funcționa și cu: 0, "", null, undefined, NaN // Dacă _TREBUIE_ verificată o valoare booleană falsă, se folosește if ( foo === false ) ... // 4.1.7 // Când se evaluează numai o referință care poate fi null sau undefined, dar NU și false, "" sau 0, // în loc de: if ( foo === null || foo === undefined ) ... // ...trebuie profitat de constrângerea tipului ==, după cum urmează: if ( foo == null ) ... // Reține, folosirea == va corespunde cu `null` atât pentru `null` cât și pentru `undefined` // dar nu și pentru `false`, "" sau 0 null == undefined ``` Se evaluează ÎNTOTDEAUNA pentru cel mai bun, cel mai precis rezultat - instrucțiunile de mai sus sunt o recomandare, nu o dogmă. ```javascript // 4.2.1 // Tipuri de constrângere și note de evaluare // Se preferă `===` în pofida `==` (cu excepția cazului care necesită evaluarea tipului declarat) // === nu constrânge tipul, ceea ce înseamnă că: "1" === 1; // false // == constrânge tipul, ceea ce înseamnă că: "1" == 1; // true // 4.2.2 // Valori Boolene, de Adevăr și Negative // Boolene: true, false // Valori de Adevăr: "foo", 1 // Valori Negative: "", 0, null, undefined, NaN, void 0 ``` 5. Stil practic ```javascript // 5.1.1 // Un modul practic (function( global ) { var Module = (function() { var data = "secret"; return { // Aceasta este o proprietate booleană bool: true, // O valoare string oarecare string: "a string", // O proprietare de tip array array: [ 1, 2, 3, 4 ], // O proprietate de tip obiect object: { lang: "en-Us" }, getData: function() { // returnează valoarea actuală a variabilei `data` return data; }, setData: function( value ) { // setează valoarea variabilei `data` și o returnează return ( data = value ); } }; })(); // Alte instrucțiuni pot urma aici // expune modulul obiectului global global.Module = Module; })( this ); ``` ```javascript // 5.2.1 // Un Constructor Practic (function( global ) { function Ctor( foo ) { this.foo = foo; return this; } Ctor.prototype.getFoo = function() { return this.foo; }; Ctor.prototype.setFoo = function( val ) { return ( this.foo = val ); }; // Pentru a apela constructorul fără `new`, se poate utiliza: var ctor = function( foo ) { return new Ctor( foo ); }; // expune modulul obiectului global global.ctor = ctor; })( this ); ``` 6. Nomenclatură A. Nu ești un compilator/compresor de cod uman, deci nu încerca să fii unul. Următorul cod este un exemplu de nomenclatură greșită: ```javascript // 6.A.1.1 // Exemplu de cod cu denumire slabă function q(s) { return document.querySelectorAll(s); } var i,a=[],els=q("#foo"); for(i=0;iDiverse Această secțiune ilustrează idei și concepte care nu ar trebui considerate dogmatice, ci există pentru a încuraja practicile de punere sub semnul întrebării într-o încercare de a găsi căi mai bune pentru a executa sarcini comune în programarea JavaScript. A. Utilizarea `switch` ar trebui evitată, metode moderne de tracing vor trece funcțiile cu declarații switch pe lista neagră Se pare că există îmbunătățiri drastice ale executării declarațiilor `switch` în ultimele versiuni Firefox și Chrome. http://jsperf.com/switch-vs-object-literal-vs-module îmbunătățiri notabile pot fi observate și aici: https://github.com/rwldrn/idiomatic.js/issues/13 ```javascript // 7.A.1.1 // Un exemplu de declarație switch switch( foo ) { case "alpha": alpha(); break; case "beta": beta(); break; default: // execută implicit break; } // 7.A.1.2 // O abordare mai bună ar fi folosirea un obiect literal sau chiar a unui modul: var switchObj = { alpha: function() { // declarații // return }, beta: function() { // declarații // return }, _default: function() { // declarații // return } }; var switchModule = (function () { return { alpha: function() { // declarații // return }, beta: function() { // declarații // return }, _default: function() { // declarații // return } }; })(); // 7.A.1.3 // Dacă `foo` este o proprietate a `switchObj` sau a `switchModule`, execută ca o metodă... ( Object.hasOwnProperty.call( switchObj, foo ) && switchObj[ foo ] || switchObj._default )( args ); ( Object.hasOwnProperty.call( switchObj, foo ) && switchModule[ foo ] || switchModule._default )( args ); // Dacă știți și aveți încredere în valoarea lui `foo`, ați putea chiar omite verificarea OR // păstrând doar execuția: switchObj[ foo ]( args ); switchModule[ foo ]( args ); // Acest șablon încurajează, de asemenea, reutilizarea codului. ``` B. "Return"-urile timpurii încurajează lizibilitatea codului cu diferențe de performanță neglijabile ```javascript // 7.B.1.1 // Incorect: function returnLate( foo ) { var ret; if ( foo ) { ret = "foo"; } else { ret = "quux"; } return ret; } // Corect: function returnEarly( foo ) { if ( foo ) { return "foo"; } return "quux"; } ``` 8. Obiecte native și gazdă Principiul de bază aici este: ### Nu fă nimic stupid și totul va fi în regulă. Pentru a consolida acest concept, vizionați următoarea prezentare: #### “Everything is Permitted: Extending Built-ins” de Andrew Dupont (JSConf2011, Portland, Oregon) https://www.youtube.com/watch?v=xL3xCO7CLNM 9. Comentarii * O singură linie deasupra codului la care se referă * Comentariile pe mai multe linii sunt bune * Comentariile la sfârșitul de linie sunt interzise! * Stilul din JSDoc este bun, dar necesită o investiție substanțială de timp 10. Un cod, un limbaj Programele ar trebui scrise într-un singur limbaj, oricare ar fi el, așa cum a fost dictat de administrator sau administratori. ## Anexă ### Prima virgulă (Comma First). Orice proiect care are ca referință acest document la baza ghidului de stilizare nu va accepta o formatare de tip prima virgulă (comma first), cu excepția cazului în care acest lucru a fost specificat diferit de autorul proiectului. ================================================ FILE: translations/ru_RU/readme.md ================================================ # Принципы написания консистентного, идиоматического кода на JavaScript *** ## Это "живой" документ и новые идеи по улучшению кода всегда приветствуются. Примите участие: fork, clone, branch, commit, push, pull request. *** * Rick Waldron [@rwaldron](http://twitter.com/rwaldron), [github](https://github.com/rwaldron) * Mathias Bynens [@mathias](http://twitter.com/mathias), [github](https://github.com/mathiasbynens) * Schalk Neethling [@ossreleasefeed](http://twitter.com/ossreleasefeed), [github](https://github.com/ossreleasefeed/) * Kit Cambridge [@kitcambridge](http://twitter.com/kitcambridge), [github](https://github.com/kitcambridge) * Raynos [github](https://github.com/Raynos) * Matias Arriola [@MatiasArriola](https://twitter.com/MatiasArriola), [github](https://github.com/MatiasArriola/) * John Fischer [@jfroffice](https://twitter.com/jfroffice), [github](https://github.com/jfroffice/) * Idan Gazit [@idangazit](http://twitter.com/idangazit), [github](https://github.com/idangazit) * Leo Balter [@leobalter](http://twitter.com/leobalter), [github](https://github.com/leobalter) * Breno Oliveira [@garu_rj](http://twitter.com/garu_rj), [github](https://github.com/garu) * Leo Beto Souza [@leobetosouza](http://twitter.com/leobetosouza), [github](https://github.com/leobetosouza) * Ryuichi Okumura [@okuryu](http://twitter.com/okuryu), [github](https://github.com/okuryu) * Pascal Precht [@PascalPrecht](http://twitter.com/PascalPrecht), [github](https://github.com/pascalprecht) * EngForDev [engfordev](http://www.opentutorials.org/course/167/1363) - Hwan Min Hong / MinTaek Kwon [@leoinsight](http://twitter.com/leoinsight) / Tw Shim [@marocchino](http://twitter.com/marocchino), [github](https://github.com/marocchino) / Nassol Kim [@nassol99](http://twitter.com/nassol99), [github](https://github.com/nassol) / Juntai Park [@rkJun](http://twitter.com/rkJun), [github](https://github.com/rkJun) / Minkyu Shim / Gangmin Won / Justin Yoo [@justinchronicle](http://twitter.com/justinchronicle) / Daeyup Lee * Marco Trulla [@marcotrulla](http://twitter.com/marcotrulla), [github](https://github.com/Ragnarokkr) * Alex Navasardyan [@alexnavasardyan](http://twitter.com/alexnavasardyan), [github](https://github.com/2k00l) * Mihai Paun [@mihaipaun](http://twitter.com/mihaipaun), [github](https://github.com/mihaipaun) * Evgeny Mandrikov [@\_godin\_](http://twitter.com/_godin_), [github](https://github.com/Godin) * Sofish Lin [@sofish](http://twitter.com/sofish), [github](https://github.com/sofish) * Дејан Димић [@dejan_dimic](http://twitter.com/dejan_dimic), [github](https://github.com/rubystream) * Miloš Gavrilović [@gavrisimo](http://twitter.com/gavrisimo), [github](https://github.com/gavrisimo) * Aleksandr Filatov [@greybax] (http://twitter.com/greybax), [github](https://github.com/greybax) * Duc Nguyen [@ducntq](https://twitter.com/ducntq), [github](https://github.com/ducntq) * James Young [@jamsyoung](http://twitter.com/jamsyoung), [github](https://github.com/jamsyoung) * Stephane Moreau [github](https://github.com/stmoreau) * Boris Nekezov [github](https://github.com/boris-nekezov) * Akshat Joshi [@akshat_joshi](http://twitter.com/akshat_joshi), [github](https://https://github.com/akshatjoshii) ## Код в любом проекте должен выглядеть так, будто его писал один человек, неважно как много людей работали над ним. *** ### Все последующее является списком норм, которыми я руководствуюсь при написании кода, чьим автором я являюсь; любой вклад в проекты, которые я создал, должен отвечать этим нормам. *** ### Я не намерен навязывать свои предпочтения в стиле другим людям или проектам; собственный стиль написания кода достоин уважения. > ### "Споры по поводу стилей бессмысленны. У вас должно быть руководство по стилю и вы должны следовать ему." >_Rebecca_ _Murphey_   > ### "Чтобы быть хорошим управляющим проекта, нужно понимать, что писать код для себя это Плохая Идея. Если тысячи людей используют ваш код, то пишите свой код максимально понятно, а не на собственное усмотрение." >_Idan_ _Gazit_ ## Переводы * [ORIGINAL](https://github.com/rwldrn/idiomatic.js/) * [Bulgarian](https://github.com/rwldrn/idiomatic.js/tree/master/translations/bg_BG) * [German](https://github.com/rwldrn/idiomatic.js/tree/master/translations/de_DE) * [French](https://github.com/rwldrn/idiomatic.js/tree/master/translations/fr_FR) * [Spanish](https://github.com/rwldrn/idiomatic.js/tree/master/translations/es_ES) * [Portuguese - Brazil](https://github.com/rwldrn/idiomatic.js/tree/master/translations/pt_BR) * [Korean](https://github.com/rwldrn/idiomatic.js/tree/master/translations/ko_KR) * [Japanese](https://github.com/rwldrn/idiomatic.js/tree/master/translations/ja_JP) * [Italian](https://github.com/rwldrn/idiomatic.js/tree/master/translations/it_IT) * [Russian](https://github.com/rwldrn/idiomatic.js/tree/master/translations/ru_RU) * [Romanian](https://github.com/rwldrn/idiomatic.js/tree/master/translations/ro_RO) * [简体中文](https://github.com/rwldrn/idiomatic.js/tree/master/translations/zh_CN) * [Serbian - cyrilic alphabet](https://github.com/rwldrn/idiomatic.js/tree/master/translations/ср_СР) * [Serbian - latin aplphabet](https://github.com/rwldrn/idiomatic.js/tree/master/translations/sr_SR) * [Greek](https://github.com/rwaldron/idiomatic.js/tree/master/translations/gr_GR) * [Hindi](https://github.com/rwaldron/idiomatic.js/tree/master/translations/hi_HI) ## Важное, не идиоматическое ### Качество кода: онлайн сервисы, ресурсы и ссылки * [JavaScript Plugin](http://docs.codehaus.org/display/SONAR/JavaScript+Plugin) for [Sonar](http://www.sonarsource.org/) * [Plato](https://github.com/es-analysis/plato) * [jsPerf](http://jsperf.com/) * [jsFiddle](http://jsfiddle.net/) * [Codepen](http://codepen.io/) * [jsbin](http://jsbin.com/) * [JavaScript Lint (JSL)](http://javascriptlint.com/) * [jshint](http://jshint.com/) * [jslint](http://jslint.org/) * [eslint](http://eslint.org/) * [jscs](https://www.npmjs.org/package/jscs) * [jscodesniffer](https://www.npmjs.org/package/jscodesniffer) * [Editorconfig](http://editorconfig.org/) * [Hound](https://houndci.com/) ### Становись умнее ### [ECMAScript 5.1 с комментариями](http://es5.github.com/) ### [Спецификация языка ECMAScript, издание 5.1](http://ecma-international.org/ecma-262/5.1/) Следующее должно считаться 1) незавершенным, и 2) *ТРЕБУЮЩИМ ЧТЕНИЯ*. Я не всегда согласен со стилями этих авторов, но одно точно: они консистентны. Более того, это каноны для языка. * [Baseline For Front End Developers](http://rmurphey.com/blog/2012/04/12/a-baseline-for-front-end-developers/) * [Eloquent JavaScript](http://eloquentjavascript.net/) * [JavaScript, JavaScript](http://javascriptweblog.wordpress.com/) * [Adventures in JavaScript Development](http://rmurphey.com/) * [Perfection Kills](http://perfectionkills.com/) * [Douglas Crockford's Wrrrld Wide Web](http://www.crockford.com) * [JS Assessment](https://github.com/rmurphey/js-assessment) ### Компиляция и Развертывание Проекты всегда должны стараться включать в себя какой-то инструментарий для контроля стиля, тестирования и сжатия кода. Для этого вы можете использовать [grunt](https://github.com/cowboy/grunt) от Ben Alman. ### Тестирование Проекты должны иметь юнит, ссылочные, "по реализации" или функуциональные тесты. Демонстрация сценариев использования НЕ ЯВЛЯЕТСЯ тестом. Ниже приведен список фреймворков для тестирования, ни один из которых не получил бОльшего одобрения, чем другие. * [QUnit](http://github.com/jquery/qunit) * [Jasmine](https://github.com/pivotal/jasmine) * [Vows](https://github.com/cloudhead/vows) * [Mocha](https://github.com/visionmedia/mocha) * [Hiro](http://hirojs.com/) * [JsTestDriver](https://code.google.com/p/js-test-driver/) * [Buster.js](http://busterjs.org/) ## Содержание * [Пробелы, табуляция и пустые строки](#whitespace) * [Красивый синтаксис](#spacing) * [Проверка типов (Руководство по стилю от команды jQuery Core)](#type) * [Условное Вычисление](#cond) * [Практичный стиль](#practical) * [Именование](#naming) * [Разное](#misc) * ["Родные" и "чужие" объекты](#native) * [Комментарии](#comments) * [Код одного языка](#language) ------------------------------------------------ ## Предисловие Следующие секции обрисовывают приемлемое руководство по стилю для современной разработки на языке JavaScript и не являются предписанием. Самое важное - это **закон написания консистентного кода**. Какой бы стиль вы ни выбрали для вашего проекта, он должен считаться законом. Сошлитесь на этот документ как заявление о приверженности вашего проекта к консистентности кода, читабельности и удобству сопровождения. ## Манифест идиоматического стиля 1. Пробелы, табуляция и пустые строки - Никогда не мешайте пробел и знак табуляции. - Перед тем как начать проект, перед тем, как писать код, выберите между "мягкими" отступами (пробелами) или настоящими знаками табуляции и считайте это **законом**. - Для лучшей читабельности кода, я всегда рекомендую выставлять размер отступа в вашем редакторе на 2 символа &mdash это либо два пробела, либо два пробела, которые представляют собой знак табуляции. - Всегда работайте со включенной опцией "показать скрытое", если ваш редактор поддерживает ее. Преимущества: - принужденная последовательность - удаление пробела в конце строки - удаление пустых строк - читабельные коммиты и диффы 2. Красивый Синтаксис A. Скобки, Фигурные скобки, Переносы строк ```javascript // if/else/for/while/try всегда разделяются пробелом, // это улучшает читабельность // 2.A.1.1 // Пример неразборчивого синтаксиса if(condition) doSomething(); while(condition) iterating++; for(var i=0;i<100;i++) someInterativeFn(); // 2.A.1.1 // Используйте пробелы для того, чтобы улучшить читабельность if ( condition ) { // выражения } while ( condition ) { // выражения } for ( var i = 0; i < 100; i++ ) { // выражения } // Еще лучше: var i, length = 100; for ( i = 0; i < length; i++ ) { // выражения } // Или... var i = 0, length = 100; for ( ; i < length; i++ ) { // выражения } var prop; for ( prop in object ) { // выражения } if ( true ) { // выражения } else { // выражения } ``` B. Присваивание, Объявление, Функции (Именованные, Функции-Выражения, Функции-Конструкторы) ```javascript // 2.B.1.1 // Переменные var foo = "bar", num = 1, undef; // Объявление литералов: var array = [], object = {}; // 2.B.1.2 // Использование только одного `var` на одну область видимости улучшает читабельность // и упорядочивает блок объявления переменных (также сохраняет вам несколько нажатий клавиш) // Неправильно var foo = ""; var bar = ""; var qux; // Правильно var foo = "", bar = "", quux; // или... var // комментарий для переменных foo = "", bar = "", quux; // 2.B.1.3 // Оператор var всегда должен быть в начале области видимости (функции). // То же самое верно для констант и оператора let из ECMAScript 6. // Неправильно function foo() { // выражения var bar = "", qux; } // Правильно function foo() { var bar = "", qux; // все выражения после объявления переменных. } ``` ```javascript // 2.B.2.1 // Объявление Именованных Функций function foo( arg1, argN ) { } // Использование foo( arg1, argN ); // 2.B.2.2 // Объявление Именованных Функций function square( number ) { return number * number; } // Использование square( 10 ); // Очень надуманный стиль передачи параметров function square( number, callback ) { callback( number * number ); } square( 10, function( square ) { // обратный вызов }); // 2.B.2.3 // Функция-Выражение var square = function( number ) { // вернуть что-то ценное и важное return number * number; }; // Функция-Выражение с Идентификатором // Такое объявление хорошо тем, что функция может вызвать сама себя // и ее имя будет видно в стеке вызова функций: var factorial = function factorial( number ) { if ( number < 2 ) { return 1; } return number * factorial( number-1 ); }; // 2.B.2.4 // Объявление Конструктора function FooBar( options ) { this.options = options; } // Использование var fooBar = new FooBar({ a: "alpha" }); fooBar.options; // { a: "alpha" } ``` C. Исключения, Незначительные Отклонения от правил ```javascript // 2.C.1.1 // Функции с обратным вызовом foo(function() { // Заметьте, что пробела между "function" и первой скобкой нет }); // Функция, которая принимает массив как параметр, тоже без пробела foo([ "alpha", "beta" ]); // 2.C.1.2 // Функция, которая принимает объект как параметр, тоже без пробела foo({ a: "alpha", b: "beta" }); // Одна строка, тоже без пробела foo("bar"); // Внутренние скобки, тоже без пробела if ( !("foo" in obj) ) { } ``` D. Консистентность всегда побеждает В секции 2.A-2.C, правила использования пробела и знака табуляции установлены с простой целью: консистентность. Очень важно отметить, что предпочтения в форматировании, такие как "внутренний пробел", должны считаться опциональными, но в вашем проекте должен использоваться только один стиль форматирования. ```javascript // 2.D.1.1 if (condition) { // выражения } while (condition) { // выражения } for (var i = 0; i < 100; i++) { // выражения } if (true) { // выражения } else { // выражения } ``` E. Кавычки Абсолютно неважно, какие кавычки вы используете (одинарные или двойные), нет никакой разницы в том, как JavaScript обрабатывает их. Что **действительно важно**, это сохранять консистентность. **Никогда не путайте кавычки в вашем проекте. Выберите один стиль и придерживайтесь его.** F. Конец строки и пустые строки Пробелы, знаки табуляции могут испортить диффы и сделать чэнджсеты непригодными для чтения. Подумайте о том, чтобы убирать пробелы в конце строк и пустые строки автоматически перед коммитом. 3. Проверка типов (Руководство по стилю от jQuery Core) A. Типы String: typeof variable === "string" Number: typeof variable === "number" Boolean: typeof variable === "boolean" Object: typeof variable === "object" Array: Array.isArray( arrayLikeObject ) (где возможно) Node: elem.nodeType === 1 null: variable === null null or undefined: variable == null undefined: Глобальные переменные: typeof variable === "undefined" Локальные переменные: variable === undefined Свойства: object.prop === undefined object.hasOwnProperty( prop ) "prop" in object B. Неявное приведение типов Представьте результат следующего... Пусть дан следующий HTML: ```html ``` ```js // 3.B.1.1 // `foo` была объявлена, ей был присвоен `0` и ее тип `number` var foo = 0; // typeof foo; // "number" ... // Далее в коде вам нужно обновить значение `foo` // новым значением из input элемента foo = document.getElementById("foo-input").value; // Если бы вы проверили тип переменной сейчас `typeof foo`, то получили бы `string` // Это значит, что если бы вы тестировали `foo` вот так: if ( foo === 1 ) { importantTask(); } // то `importantTask()` не была вызвана, даже если значение `foo` было бы "1" // 3.B.1.2 // Вы можете избежать ошибок, используя приведение типов с помощью унарных операторов "+" и "-": foo = +document.getElementById("foo-input").value; // ^ унарный оператор + приведет правую часть выражения к типу `number` // typeof foo; // "number" if ( foo === 1 ) { importantTask(); } // `importantTask()` будет вызвана ``` Вот несколько простых примеров приведения типов: ```javascript // 3.B.2.1 var number = 1, string = "1", bool = false; number; // 1 number + ""; // "1" string; // "1" +string; // 1 +string++; // 1 string; // 2 bool; // false +bool; // 0 bool + ""; // "false" ``` ```javascript // 3.B.2.2 var number = 1, string = "1", bool = true; string === number; // false string === number + ""; // true +string === number; // true bool === number; // false +bool === number; // true bool === string; // false bool === !!string; // true ``` ```javascript // 3.B.2.3 var array = [ "a", "b", "c" ]; !!~array.indexOf("a"); // true !!~array.indexOf("b"); // true !!~array.indexOf("c"); // true !!~array.indexOf("d"); // false // Заметьте, что вышеизложенное можно считать "черезчур умным" // Лучше делать так: if ( array.indexOf( "a" ) >= 0 ) { // ... } ``` ```javascript // 3.B.2.3 var num = 2.5; parseInt( num, 10 ); // то же самое, что и ... ~~num; num >> 0; num >>> 0; // Во всех случаях результат равен 2 // Помните, что отрицательные числа будут обработаны по-другому... var neg = -2.5; parseInt( neg, 10 ); // тоже самое что... ~~neg; neg >> 0; // Во всех случаях результат равен -2 // Хотя... neg >>> 0; // покажет 4294967294 ``` 4. Условное Вычисление/Обработка ```javascript // 4.1.1 // Проверяя, есть ли у массива длина, // вместо: if ( array.length > 0 ) ... // проверяйте значение выражения: if ( array.length ) ... // 4.1.2 // Проверяя, пустой ли массив: // вместо: if ( array.length === 0 ) ... // проверяйте значение выражения: if ( !array.length ) ... // 4.1.3 // Проверяя, не пуста ли строка: // вместо: if ( string !== "" ) ... // проверяйте значение выражения: if ( string ) ... // 4.1.4 // Проверяя, пустая ли строка: // вместо: if ( string === "" ) ... // проверяйте ложно ли выражение: if ( !string ) ... // 4.1.5 // Проверяя, является ли переменная истиной, // вместо: if ( foo === true ) ... // проверяйте следующим образом: if ( foo ) ... // 4.1.6 // Проверяя, является ли переменная ложью, // вместо: if ( foo === false ) ... // проверяйте, используя отрицание: if ( !foo ) ... // ...Будьте осторожны, потому что это выражение справедливо и для: 0, "", null, undefined, NaN // Для проверки значения заведомо ложных выражений, используйте: if ( foo === false ) ... // 4.1.7 // Проверяя, если переменная null или undefined, но НЕ ложь, "" или 0, // вместо: if ( foo === null || foo === undefined ) ... // ...воспользуйтесь оператором ==: if ( foo == null ) ... // Помните, что сравнение с помощью оператора == с `null` сработает для ОБОИХ `null` и `undefined` // но не для `false`, "" или 0 null == undefined ``` ВСЕГДА оценивайте самый лучший и точный результат - выше приведено руководство, а не догма. ```javascript // 4.2.1 // Приведение типов и оценка выражений // Отдавайте предпочтение `===`, а не `==` (только если конкретный случай не требует слабо типизированной оценки) // === не приводит типы принудительно, т.е.: "1" === 1; // false // == приводит типы принудительно, т.е.: "1" == 1; // true // 4.2.2 // Логические выражения, Истинные и Ложные // Логические выражения: true, false // Истинные: "foo", 1 // Ложные: "", 0, null, undefined, NaN, void 0 ``` 5. Стиль на практике ```javascript // 5.1.1 // Модуль (function( global ) { var Module = (function() { var data = "secret"; return { // Логическое свойство bool: true, // Свойство типа строка string: "a string", // Свойство - массив array: [ 1, 2, 3, 4 ], // Свойство - объект object: { lang: "ru-RU" }, getData: function() { // получить текущее значение переменной `data` return data; }, setData: function( value ) { // присвоить значение переменной `data` и вернуть его return ( data = value ); } }; })(); // Другие объявления // делаем наш модуль глобальным global.Module = Module; })( this ); ``` ```javascript // 5.2.1 // Конструктор (function( global ) { function Ctor( foo ) { this.foo = foo; return this; } Ctor.prototype.getFoo = function() { return this.foo; }; Ctor.prototype.setFoo = function( val ) { return ( this.foo = val ); }; // Чтобы вызывать конструктор без использования оператора `new`, можно объявить конструктор так: var ctor = function( foo ) { return new Ctor( foo ); }; // делаем наш конструктор глобальным global.ctor = ctor; })( this ); ``` 6. Именование A. Вы не компилятор или компрессор, так что не пытайтесь быть одним из них. Весь последующий код является примером плохого именования переменных: ```javascript // 6.A.1.1 // Пример кода с "бедными на описание" именами переменных function q(s) { return document.querySelectorAll(s); } var i,a=[],els=q("#foo"); for(i=0;iРазное Этот раздел описывает идеи и концепции, которые не должны рассматриваться как догма. Он существуют для того, чтобы посеять сомнения в общепринятых методах в попытке найти более эффективные способы для выполнения общих задач программирования на JavaScript. A. Использование `switch` следует избегать, потому что современный метод отладки будет скрывать вызовы функций, которые используют `switch`. В последних версиях браузеров Firefox и Chrome, кажется, есть значительные улучшения в исполнении функций, которые используют `switch`. http://jsperf.com/switch-vs-object-literal-vs-module На заметные улучшения также можно посмотреть тут: https://github.com/rwldrn/idiomatic.js/issues/13 ```javascript // 7.A.1.1 // Пример оператора switch switch( foo ) { case "alpha": alpha(); break; case "beta": beta(); break; default: // какое-то значение по умолчанию break; } // 7.A.1.2 // Лучшим подходом было бы использовать объект или даже модуль: var switchObj = { alpha: function() { // выражения // возвращаем результат }, beta: function() { // выражения // возвращаем результат }, _default: function() { // выражения // возвращаем результат } }; var switchModule = (function () { return { alpha: function() { // выражения // возвращаем результат }, beta: function() { // выражения // возвращаем результат }, _default: function() { // выражения // возвращаем результат } }; })(); // 7.A.1.3 // Если `foo` это свойство `switchObj` или `switchModule`, то выполнить метод... ( Object.hasOwnProperty.call( switchObj, foo ) && switchObj[ foo ] || switchObj._default )( args ); ( Object.hasOwnProperty.call( switchObj, foo ) && switchModule[ foo ] || switchModule._default )( args ); // Если вы знаете возможные значения `foo` и доверяете его источнику, вы можете опустить условие ИЛИ // оставив только выполнение switchObj[ foo ]( args ); switchModule[ foo ]( args ); // Эта модель также поддерживает повторное использование кода. ``` B. "Ранние возвраты" способствуют читабельности кода с незначительной разницей в производительности ```javascript // 7.B.1.1 // Неправильно: function returnLate( foo ) { var ret; if ( foo ) { ret = "foo"; } else { ret = "quux"; } return ret; } // Правильно: function returnEarly( foo ) { if ( foo ) { return "foo"; } return "quux"; } ``` 8. "Родные" и "чужие" объекты Основное правило: ### Не делайте тупых вещей и все будет хорошо. Для лучшего понимания этой концепции, посмотрите вот это видео: #### “Everything is Permitted: Extending Built-ins” by Andrew Dupont (JSConf2011, Portland, Oregon) https://www.youtube.com/watch?v=xL3xCO7CLNM 9. Комментарии * Однострочные комментарии на линию выше кода * Комментарии в несколько строк тоже приветствуются * Комментарии в конце строки запрещены! * Стиль JSDoc хорош, но в нем нужно долго разбираться 10. Код Одного Языка Программы должны быть написаны на одном языке (независимо от языка), как требуют того люди, которые сопровождают код. ## Приложение ### Первая Запятая. Любой проект, который ссылается на этот документ в качестве руководства по стилю, не примет форматирование кода "первой запятой", только если автор специально не указал этого. ================================================ FILE: translations/sr_SR/readme.md ================================================ # Principi pisanja konzistentnog, idiomatskog JavaScript-a ## Ovo je "živ" dokument i nove ideje za unapređenje koda oko nas su uvek dobrodošle. Doprinesite: fork, clone, branch, commit, push, pull request. * Rick Waldron [@rwaldron](http://twitter.com/rwaldron), [github](https://github.com/rwaldron) * Mathias Bynens [@mathias](http://twitter.com/mathias), [github](https://github.com/mathiasbynens) * Schalk Neethling [@ossreleasefeed](http://twitter.com/ossreleasefeed), [github](https://github.com/ossreleasefeed/) * Kit Cambridge [@kitcambridge](http://twitter.com/kitcambridge), [github](https://github.com/kitcambridge) * Raynos [github](https://github.com/Raynos) * Matias Arriola [@MatiasArriola](https://twitter.com/MatiasArriola), [github](https://github.com/MatiasArriola/) * John Fischer [@jfroffice](https://twitter.com/jfroffice), [github](https://github.com/jfroffice/) * Idan Gazit [@idangazit](http://twitter.com/idangazit), [github](https://github.com/idangazit) * Leo Balter [@leobalter](http://twitter.com/leobalter), [github](https://github.com/leobalter) * Breno Oliveira [@garu_rj](http://twitter.com/garu_rj), [github](https://github.com/garu) * Leo Beto Souza [@leobetosouza](http://twitter.com/leobetosouza), [github](https://github.com/leobetosouza) * Ryuichi Okumura [@okuryu](http://twitter.com/okuryu), [github](https://github.com/okuryu) * Pascal Precht [@PascalPrecht](http://twitter.com/PascalPrecht), [github](https://github.com/pascalprecht) * EngForDev [engfordev](http://www.opentutorials.org/course/167/1363) - Hwan Min Hong / MinTaek Kwon [@leoinsight](http://twitter.com/leoinsight) / Tw Shim [@marocchino](http://twitter.com/marocchino), [github](https://github.com/marocchino) / Nassol Kim [@nassol99](http://twitter.com/nassol99), [github](https://github.com/nassol) / Juntai Park [@rkJun](http://twitter.com/rkJun), [github](https://github.com/rkJun) / Minkyu Shim / Gangmin Won / Justin Yoo [@justinchronicle](http://twitter.com/justinchronicle) / Daeyup Lee * Marco Trulla [@marcotrulla](http://twitter.com/marcotrulla), [github](https://github.com/Ragnarokkr) * Alex Navasardyan [@alexnavasardyan](http://twitter.com/alexnavasardyan), [github](https://github.com/2k00l) * Mihai Paun [@mihaipaun](http://twitter.com/mihaipaun), [github](https://github.com/mihaipaun) * Evgeny Mandrikov [@\_godin\_](http://twitter.com/_godin_), [github](https://github.com/Godin) * Sofish Lin [@sofish](http://twitter.com/sofish), [github](https://github.com/sofish) * Дејан Димић [@dejan_dimic](http://twitter.com/dejan_dimic), [github](https://github.com/rubystream) * Miloš Gavrilović [@gavrisimo](http://twitter.com/gavrisimo), [github](https://github.com/gavrisimo) * Duc Nguyen [@ducntq](https://twitter.com/ducntq), [github](https://github.com/ducntq) * James Young [@jamsyoung](http://twitter.com/jamsyoung), [github](https://github.com/jamsyoung) * Stephane Moreau [github](https://github.com/stmoreau) * Boris Nekezov [github](https://github.com/boris-nekezov) * Akshat Joshi [@akshat_joshi](http://twitter.com/akshat_joshi), [github](https://https://github.com/akshatjoshii) ## Sav kod u bilo kojoj "bazi koda" trebalo bi da izgleda kao da ga je napisala jedna osoba, bez obzira koliko je ljudi doprinelo njegovom kreiranju. ### Lista koja sledi uokviruje praksu koju ja primenjujem u svom kodu, čiji sam ja originalni autor. Saradnici, na projektima koje sam ja kreirao, bi trebalo da se pridržavaju ovih uputstava. ### Ja nemam nameru da namećem svoje osobine stila na kod ili projekte drugih ljudi, ako već postoji zajednički stil, on mora biti poštovan. > ### "Argumenti oko stila nemaju smisla. Potrebno je da postoji uputstvo korišćenja stila, i ti bi trebalo da ga se pridržavaš." >_Rebecca_ _Murphey_   > ### "Deo uloge dobrog upravnika uspešnog projekta je i u razumevanju da pisanje koda po svojim merilima je loša ideja™. Ako hiljade ljudi koristi tvoj kod, onda piši najjasniji kod, a ne prema svojim ličnim preferencijama ili da sa željom da ispadneš pametan u okvirima specifikacije." >_Idan_ _Gazit_ ## Translations * [ORIGINAL](https://github.com/rwldrn/idiomatic.js/) * [Bulgarian](https://github.com/rwldrn/idiomatic.js/tree/master/translations/bg_BG) * [German](https://github.com/rwldrn/idiomatic.js/tree/master/translations/de_DE) * [French](https://github.com/rwldrn/idiomatic.js/tree/master/translations/fr_FR) * [Spanish](https://github.com/rwldrn/idiomatic.js/tree/master/translations/es_ES) * [Portuguese - Brazil](https://github.com/rwldrn/idiomatic.js/tree/master/translations/pt_BR) * [Korean](https://github.com/rwldrn/idiomatic.js/tree/master/translations/ko_KR) * [Japanese](https://github.com/rwldrn/idiomatic.js/tree/master/translations/ja_JP) * [Italian](https://github.com/rwldrn/idiomatic.js/tree/master/translations/it_IT) * [Russian](https://github.com/rwldrn/idiomatic.js/tree/master/translations/ru_RU) * [Romanian](https://github.com/rwldrn/idiomatic.js/tree/master/translations/ro_RO) * [简体中文](https://github.com/rwldrn/idiomatic.js/tree/master/translations/zh_CN) * [Serbian - cyrilic alphabet](https://github.com/rwldrn/idiomatic.js/tree/master/translations/ср_СР) * [Serbian - latin aplphabet](https://github.com/rwldrn/idiomatic.js/tree/master/translations/sr_SR) * [Greek](https://github.com/rwaldron/idiomatic.js/tree/master/translations/gr_GR) * [Hindi](https://github.com/rwaldron/idiomatic.js/tree/master/translations/hi_HI) ## Važne, ne idiomatske stvari: ### Alati za proveravanje kvaliteta koda, izvori i literatura * [JavaScript Plugin](http://docs.codehaus.org/display/SONAR/JavaScript+Plugin) for [Sonar](http://www.sonarsource.org/) * [Plato](https://github.com/jsoverson/plato) * [jsPerf](http://jsperf.com/) * [jsFiddle](http://jsfiddle.net/) * [jsbin](http://jsbin.com/) * [JavaScript Lint (JSL)](http://javascriptlint.com/) * [jshint](http://jshint.com/) * [jslint](http://jslint.org/) * [Editorconfig](http://editorconfig.org/) ## Budite pametniji ### [Annotated ECMAScript 5.1](http://es5.github.com/) ### [EcmaScript Language Specification, 5.1 Edition](http://ecma-international.org/ecma-262/5.1/) Sledeće treba smatrati za: 1) nepotpunu, i 2) *OBAVEZNA LEKTIRA*. Ja se ne slažem uvek sa stilom pisanog od strane autora u nastavku, ali jedna stvar je sigurna: Oni su dosledni. Osim toga, to su autoriteti u ovom jeziku. * [Baseline For Front End Developers](http://rmurphey.com/blog/2012/04/12/a-baseline-for-front-end-developers/) * [Eloquent JavaScript](http://eloquentjavascript.net/) * [JavaScript, JavaScript](http://javascriptweblog.wordpress.com/) * [Adventures in JavaScript Development](http://rmurphey.com/) * [Perfection Kills](http://perfectionkills.com/) * [Douglas Crockford's Wrrrld Wide Web](http://www.crockford.com) * [JS Assessment](https://github.com/rmurphey/js-assessment) * [Leveraging Code Quality Tools by Anton Kovalyov](http://anton.kovalyov.net/slides/gothamjs/) ### Build i deployment procesi Projekti bi trebalo da uvek sadrže neki vid generičkih alata pomoću kojih kod može biti pročišćen, testiran i komprimovan u procesu pripreme za produkcionu primenu. Za ovaj zadatak, [grunt](https://github.com/cowboy/grunt) od Ben Alman-a je odličan i zvanično je zamenio "kits/" direktorijum ovog repozitorijuma. ### Pogon za testiranje Projekti _moraju_ da uključe neku formu "unit", "reference", "implementation" ili "functional" testiranja. "Use case" demoi se NE KVALIFIKUJU kao "testovi". Sledi lista alata za testiranje, nijedan od njih nije prihvaćeniji od drugih. * [QUnit](http://github.com/jquery/qunit) * [Jasmine](https://github.com/pivotal/jasmine) * [Vows](https://github.com/cloudhead/vows) * [Mocha](https://github.com/visionmedia/mocha) * [Hiro](http://hirojs.com/) * [JsTestDriver](https://code.google.com/p/js-test-driver/) * [Buster.js](http://busterjs.org/) * [Sinon.js](http://sinonjs.org/) ## Sadržaj * [Beline (Whitespace)](#whitespace) * [Lepa sintaksa](#spacing) * [Provera tipa (Zahvalnica jQuery Core Style Guidelines)](#type) * [Uslovna evaluacija](#cond) * [Praktičan stil](#practical) * [Imenovanje](#naming) * [Razno](#misc) * [Native i Host objekti](#native) * [Komentari](#comments) * [Kod u jednom jeziku](#language) ------------------------------------------------ ## Predgovor Sledeće sekcije ocrtavaju _razuma_ vodič za stil modernog JavaScript razvoja i nije im namera da budu preopširne. Najznačajnija poruka je **zakon o koezistentnosti stila pisanja koda**. Šta god da izaberete kao stil za vaš projekat to treba smatrati zakonom. Povežite ovaj dokument kao izjavu vašeg projekta koezistentnosti stila pisanja koda, čitljivosti i lakoći održavanja istog. ## Idiomatski manifest stila 1. Beline (Whitespace) - Nikada ne mešajte razmake i tabulatore. - Kada započinjete projekat, pre nego što napišete i jednu liniju koda, izaberite između razmaka (spaces) i tabulatora i to tretirajte kao **zakon**. - Radi čitljivosti, ja uvek preporučujem da postavite uvlačenje vašeg editora na dva karaktera — ovo predstavlja dva razmaka ili tab veličine dva razmaka. - Ukoliko vaš editor podržava, uvek radite sa uključenom opcijom "show invisibles". Koristi od ove prakse su: - Nametnuta koezistentnost - Eliminisanje nepotrebnih razmaka na kraju reda - Eliminisanje nepotrebnih razmaka u praznim redovima - Commits i diffs komande koje se lakše čitaju 2. Lepa sintaksa A. Razmaci, zagrade, novi red ```javascript // if/else/for/while/try uvek imaju razmake, zagrade i prostiru se na više redova // ovo podstiče čitljivost // 2.A.1.1 // Primeri stvarno skučene sintakse if(condition) doSomething(); while(condition) iterating++; for(var i=0;i<100;i++) someIterativeFn(); // 2.A.1.1 // Koristite beline da bi promovisali čitljivost if ( condition ) { // statements } while ( condition ) { // statements } for ( var i = 0; i < 100; i++ ) { // statements } // Još bolje: var i, length = 100; for ( i = 0; i < length; i++ ) { // statements } // Ili... var i = 0, length = 100; for ( ; i < length; i++ ) { // statements } var prop; for ( prop in object ) { // statements } if ( true ) { // statements } else { // statements } ``` B. Dodela vrednosti, deklaracije, funkcije ( imenovane, izrazi, konstruktor ) ```javascript // 2.B.1.1 // Promenjive var foo = "bar", num = 1, undef; // Slovna notacija: var array = [], object = {}; // 2.B.1.2 // Korišćenje samo jedne `var` deklaracije po oblasti važenja (function) promoviše čitljivost // i održava vašu listu deklaracija čistu od nasumičnog (a štedi i nekoliko kucanja po taserima) // Loše var foo = ""; var bar = ""; var qux; // Dobro var foo = "", bar = "", quux; // Ili.. var // Komentar o ovima foo = "", bar = "", quux; // 2.B.1.3 // var deklaracije bi uvek trebalo da se nalaze na početku njihove oblasti važenja (function). // Ovo isto važi i za const i let iz ECMAScript 6. // Loše function foo() { // some statements here var bar = "", qux; } // Dobro function foo() { var bar = "", qux; // all statements after the variables declarations. } ``` ```javascript // 2.B.2.1 // Deklaracija imenovane funkcije function foo( arg1, argN ) { } // Korišćenje foo( arg1, argN ); // 2.B.2.2 // Deklaracija imenovane funkcije function square( number ) { return number * number; } // Usage square( 10 ); // Veoma izmišljen stil prenošenja parametara function square( number, callback ) { callback( number * number ); } square( 10, function( square ) { // callback statements }); // 2.B.2.3 // Funkcioni izraz var square = function( number ) { // Return something valuable and relevant return number * number; }; // Funkcioni izraz sa određivačem // Ovaj poželjni oblik ima dodatu vrednost da može // da pozove sebe i ima identitet u stack traces: var factorial = function factorial( number ) { if ( number < 2 ) { return 1; } return number * factorial( number-1 ); }; // 2.B.2.4 // Deklaracija konstruktora function FooBar( options ) { this.options = options; } // Korišćenje var fooBar = new FooBar({ a: "alpha" }); fooBar.options; // { a: "alpha" } ``` C. Izuzetci, mala odstupanja ```javascript // 2.C.1.1 // Funkcije sa povratnim pozivima (callbacks) foo(function() { // Zabeležite da nema dodatog razmaka između prve zagrade // poziva funkcije koja se izvršava i reči "function" }); // Funkcija koja prihvata niz, bez razmaka foo([ "alpha", "beta" ]); // 2.C.1.2 // Funkcija koja prihvata objekat, bez razmaka foo({ a: "alpha", b: "beta" }); // Jedan tekstualni argument, bez razmaka foo("bar"); // Unutrašnje grupisanje zagrada, bez razmaka if ( !("foo" in obj) ) { } ``` D. Konzistentnost uvek pobeđuje U sekcijama 2.A-2.C, pravila korišćenja belina su postavljena preporuka sa jednostavnijom, višom namenom: konzistentnost. Važno je da se naglasi da preference formatiranja, kao što su "unutrašnje beline", se mogu smatrati opcionim, ali samo jedan stil bi trebalo da se primenjuje kroz ceo kod vašeg projekta. ```javascript // 2.D.1.1 if (condition) { // statements } while (condition) { // statements } for (var i = 0; i < 100; i++) { // statements } if (true) { // statements } else { // statements } ``` E. Navodnici Sve jedno da li preferirate jednostruke ili dvostruke navodnike, ne postoji razlika kako ih JavaScript parsira. Ono što se **APSOLUTNO MORA** nametnuti je konzistentnost. **Nikada ne mešati različite navognike u istom projektu. Izaberite jedan stil i držite se njega.** F. Kraj reda i prazni redovi Beline mogu upropastiti diff komande i učiniti ih nečitljivim. Razmotrite uključivanje pre-commit hook koji automatski uklanja beline na kraju reda i beline u praznim redovima. 3. Provera tipa (Zahvalnica jQuery Core Style Guidelines) A. Stvarni tipovi String: typeof variable === "string" Number: typeof variable === "number" Boolean: typeof variable === "boolean" Object: typeof variable === "object" Array: Array.isArray( arrayLikeObject ) (wherever possible) Node: elem.nodeType === 1 null: variable === null null or undefined: variable == null undefined: Globalne promenjive: typeof variable === "undefined" Lokalne promenjive: variable === undefined Osobine: object.prop === undefined object.hasOwnProperty( prop ) "prop" in object B. Implicitna konverzija tipa Razmislite o implikacijama sledećeg... Za dati HTML: ```html ``` ```javascript // 3.B.1.1 // `foo` je deklarisana sa vrednošću `0` i njen tip je `number` var foo = 0; // typeof foo; // "number" ... // Negde kasnije u vašem kodu, želite da osvežite `foo` // sa novom vrednošću koja je došla iz ulaznog elementa foo = document.getElementById("foo-input").value; // Ako bi sada testirali `typeof foo`, rezultat bi bio `string` // Ovo znači da ako imate logiku koja proverava `foo` kao: if ( foo === 1 ) { importantTask(); } // `importantTask()` nikada ne bi bio izvršen, čak i kada `foo` ima vrednost "1" // 3.B.1.2 // Možete preduprediti probleme koristeći pametnu implicitnu konverziju tipa sa unarnim + i - operatorima: foo = +document.getElementById("foo-input").value; // ^ unarni + operator će konvertovati svoj desi operand u broj // typeof foo; // "number" if ( foo === 1 ) { importantTask(); } // `importantTask()` će biti pozvan ``` Evo nekoliko uobičajenih primera sa konverzijom tipa: ```javascript // 3.B.2.1 var number = 1, string = "1", bool = false; number; // 1 number + ""; // "1" string; // "1" +string; // 1 +string++; // 1 string; // 2 bool; // false +bool; // 0 bool + ""; // "false" ``` ```javascript // 3.B.2.2 var number = 1, string = "1", bool = true; string === number; // false string === number + ""; // true +string === number; // true bool === number; // false +bool === number; // true bool === string; // false bool === !!string; // true ``` ```javascript // 3.B.2.3 var array = [ "a", "b", "c" ]; !!~array.indexOf("a"); // true !!~array.indexOf("b"); // true !!~array.indexOf("c"); // true !!~array.indexOf("d"); // false // Zabeležite da prethodno treba smatrati "nepotrebno pametno" // Preferirajte očigledan pristup u upoređivanju povratne vrednosti // indexOf, kao: if ( array.indexOf( "a" ) >= 0 ) { // ... } ``` ```javascript // 3.B.2.4 var num = 2.5; parseInt( num, 10 ); // je isto kao... ~~num; num >> 0; num >>> 0; // Sve ima rezultat 2 // Zapamtite, negativni brojevi će biti drugačije tretirani... var neg = -2.5; parseInt( neg, 10 ); // je isto kao... ~~neg; neg >> 0; // Sve ima rezultat -2 // Međutim... neg >>> 0; // će imati rezultat 4294967294 ``` 4. Uslovna evaluacija ```javascript // 4.1.1 // Kada utvrđujete da niz ima svoju dužinu, // umesto ovoga: if ( array.length > 0 ) ... // ...ustanovite istinitost, ovako: if ( array.length ) ... // 4.1.2 // Kada utvrđujete da je niz prazan, // umesto ovoga: if ( array.length === 0 ) ... // ...ustanovite istinitost, ovako: if ( !array.length ) ... // 4.1.3 // Kada utvrđujete da string nije prazan, // umesto ovoga: if ( string !== "" ) ... // ...ustanovite istinitost, ovako: if ( string ) ... // 4.1.4 // Kada utvrđujete da string _jeste_ prazan: // umesto ovoga: if ( string === "" ) ... // ...ustanovite neistinitost, ovako: if ( !string ) ... // 4.1.5 // Kada utvrđujete da je referenca true, // umesto ovoga: if ( foo === true ) ... // ...ustanovite onako kako ste to i mislili like you mean it, iskoristite ugrađene mogućnosti: if ( foo ) ... // 4.1.6 // Kada utvrđujete da je referenca false, // umesto ovoga: if ( foo === false ) ... // ...koristite negaciju da prinudite istinitu evaluaciju if ( !foo ) ... // ...Budite oprezni, ovo će isto odgovarati i: 0, "", null, undefined, NaN // Ako _MORATE_ da testirate na logičko false, koristite if ( foo === false ) ... // 4.1.7 // Kada samo utvrđujete da referenca može biti null ili undefinded, ali NE i false, "" ili 0, // umesto ovoga: if ( foo === null || foo === undefined ) ... // ...iskoristite prednost == prinudne konverzije tipa, ovako: if ( foo == null ) ... // Upamtite, korišćenje == će odgovarati `null` za `null` _I_ `undefined` // ali ne i za `false`, "" ili 0 null == undefined ``` Uvek utvrđujte za najbolji, najtačniji rezultat - prethodno je smernica, a ne dogma. ```javascript // 4.2.1 // Zabeleške oko prinudne konverzije tipa i evaluacije // Preferišite `===` u odnosu na `==` (osim ako slučaj zahteva labavu proveru tipa) // === ne konvertuje tip, što znači da: "1" === 1; // false // == konvertuje tip, što znači da: "1" == 1; // true // 4.2.2 // Logičke promenjive, istinitost i neistinitost // Logičke promenjive: true, false // Istinito: "foo", 1 // Neistinito: "", 0, null, undefined, NaN, void 0 ``` 5. Praktičan stil ```javascript // 5.1.1 // Praktičan modul (function( global ) { var Module = (function() { var data = "secret"; return { // Ovo je nak logička osobina bool: true, // Neka tekstualna vrednost string: "a string", // Niz array: [ 1, 2, 3, 4 ], // Objekat object: { lang: "en-Us" }, getData: function() { // vraća tekuću vrednost promenjive `data` return data; }, setData: function( value ) { // postavlja vrednost promenjive `data` i vraća je return ( data = value ); } }; })(); // Ostale stvari koje se mogu ovde desiti // izložite naš modul kao globalni objekat global.Module = Module; })( this ); ``` ```javascript // 5.2.1 // Praktični konstruktor (function( global ) { function Ctor( foo ) { this.foo = foo; return this; } Ctor.prototype.getFoo = function() { return this.foo; }; Ctor.prototype.setFoo = function( val ) { return ( this.foo = val ); }; // da bi pozvali konstruktore bez korišćenja `new`, možete uraditi ovo: var ctor = function( foo ) { return new Ctor( foo ); }; // izložite naš konstruktor kao globalni objekat global.ctor = ctor; })( this ); ``` 6. Imenovanje A. Vi niste ljudski kompajler/kompresor koda, i ne pokušavajte to da budete. Sledeći kod je primer nečuvenog imenovanja: ```javascript // 6.A.1.1 // Primer koda sa lošim imenima function q(s) { return document.querySelectorAll(s); } var i,a=[],els=q("#foo"); for(i=0;iRazno Ova sekcija će služiti da ilustruje ideje i koncepte koje ne treba smatrati dogmama, već postoje da bi podstakle preispitivanje praksi kao pokušaj da se pronađe bolji način izvršavanja uobičajenih JavaScript programerski zadataka. A. Korišćenje `switch`-a treba izbegavati, moderne metode praćenja će staviti na crnu listu funkcije sa switch izrazima Izgleda da postoje drastična poboljšanja u izvršavanju `switch` izraza u poslednjim izdanjima Firefox i Chrome. http://jsperf.com/switch-vs-object-literal-vs-module Primetna poboljšanja se mogu uočiti takođe i ovde: https://github.com/rwldrn/idiomatic.js/issues/13 ```javascript // 7.A.1.1 // Primer switch izraza switch( foo ) { case "alpha": alpha(); break; case "beta": beta(); break; default: // podrazumevana vrednost break; } // 7.A.1.2 // Alternativni pristup koji podržava "composability" i "reusability" je da se // koristi objekat koji sadrži sve slučajeve i funkciju da delegira: var cases, delegator; // Example returns for illustration only. cases = { alpha: function() { // izrazi // povratna vrednost return [ "Alpha", arguments.length ]; }, beta: function() { // izrazi // povratna vrednost return [ "Beta", arguments.length ]; }, _default: function() { // izrazi // povratna vrednost return [ "Default", arguments.length ]; } }; delegator = function() { var args, key, delegate; // Transformiše listu argumenata u niz args = [].slice.call( arguments ); // uzmi vrednost prvog indeksa iz liste argumenata key = args.shift(); // Dodeli podrazumevani obrađivač slučajeva delegate = cases._default; // Izvedi metodu koja će da delegira operacije if ( cases.hasOwnProperty( key ) ) { delegate = cases[ key ]; } // Obim argumenta bi mogao biti podešen na nešto specifično, // u ovom slučaju, |null| je dovoljno return delegate.apply( null, args ); }; // 7.A.1.3 // Postavi API iz 7.A.1.2 da radi: delegator( "alpha", 1, 2, 3, 4, 5 ); // [ "Alpha", 5 ] // Naravno, `case` argument bi lako mogao da bude baziran // na nekom drugom arbitrarnom uslovu. var caseKey, someUserInput; // Možda neka vrsta form input-a? someUserInput = 9; if ( someUserInput > 10 ) { caseKey = "alpha"; } else { caseKey = "beta"; } // ili... caseKey = someUserInput > 10 ? "alpha" : "beta"; // i onda... delegator( caseKey, someUserInput ); // [ "Beta", 1 ] // i naravno... delegator(); // [ "Default", 0 ] ``` B. Rano vraćanje vrednosti funkcija promoviše čitljivost koda sa manjom razlikom u performansama koda ```javascript // 7.B.1.1 // Loše: function returnLate( foo ) { var ret; if ( foo ) { ret = "foo"; } else { ret = "quux"; } return ret; } // Dobro: function returnEarly( foo ) { if ( foo ) { return "foo"; } return "quux"; } ``` 8. Native & Host Objekti Osnovni princip ovde je: ### Ne pravite glupa sranja i sve će biti u redu. Da bi utvrdili ovaj koncept, molim vas da pogledate sledeću prezentaciju: #### “Everything is Permitted: Extending Built-ins” by Andrew Dupont (JSConf2011, Portland, Oregon) https://www.youtube.com/watch?v=xL3xCO7CLNM 9. Komentari #### Jedna linija iznad koda je naslov #### Više linija je dobro #### Komentari na kraju reda su zabranjeni! #### JSDoc stil je dobar, ali zahteva značajnu insvesticiju u vremenu 10. Kod u jednom jeziku Programi bi trebalo biti pisani u jednom jeziku, bez obzira koji je to jezik, diktirano od strane osobe ili osoba koje održavaju kod. ## Dodaci ### Zarez prvi. Svaki projekat koji citira ovaj dukument kao svoj osnovni stil neće prihvatiti "prvi zaret" formatiranje, osim ako nije eksplicitno naglašeno od strane autora projekta. ---------- Creative Commons License
Principles of Writing Consistent, Idiomatic JavaScript by Rick Waldron and Contributors is licensed under a Creative Commons Attribution 3.0 Unported License.
Based on a work at github.com/rwldrn/idiomatic.js. ================================================ FILE: translations/vi_VN/readme.md ================================================ # Nguyên tắc để Viết Javascript Nhất quán ## Đây là một tài liệu sống và những ý tưởng để nâng cao chất lượng code xung quanh chúng ta đều được chào mừng. Đóng góp: fork, clone, branch, commit, push, pull request. * Rick Waldron [@rwaldron](http://twitter.com/rwaldron), [github](https://github.com/rwaldron) * Mathias Bynens [@mathias](http://twitter.com/mathias), [github](https://github.com/mathiasbynens) * Schalk Neethling [@ossreleasefeed](http://twitter.com/ossreleasefeed), [github](https://github.com/ossreleasefeed/) * Kit Cambridge [@kitcambridge](http://twitter.com/kitcambridge), [github](https://github.com/kitcambridge) * Raynos [github](https://github.com/Raynos) * Matias Arriola [@MatiasArriola](https://twitter.com/MatiasArriola), [github](https://github.com/MatiasArriola/) * John Fischer [@jfroffice](https://twitter.com/jfroffice), [github](https://github.com/jfroffice/) * Idan Gazit [@idangazit](http://twitter.com/idangazit), [github](https://github.com/idan) * Leo Balter [@leobalter](http://twitter.com/leobalter), [github](https://github.com/leobalter) * Breno Oliveira [@garu_rj](http://twitter.com/garu_rj), [github](https://github.com/garu) * Leo Beto Souza [@leobetosouza](http://twitter.com/leobetosouza), [github](https://github.com/leobetosouza) * Ryuichi Okumura [@okuryu](http://twitter.com/okuryu), [github](https://github.com/okuryu) * Pascal Precht [@PascalPrecht](http://twitter.com/PascalPrecht), [github](https://github.com/pascalprecht) * EngForDev [engfordev](http://www.opentutorials.org/course/167/1363) - Hwan Min Hong / MinTaek Kwon [@leoinsight](http://twitter.com/leoinsight) / Tw Shim [@marocchino](http://twitter.com/marocchino), [github](https://github.com/marocchino) / Nassol Kim [@nassol99](http://twitter.com/nassol99), [github](https://github.com/nassol) / Juntai Park [@rkJun](http://twitter.com/rkJun), [github](https://github.com/rkJun) / Minkyu Shim / Gangmin Won / Justin Yoo [@justinchronicle](http://twitter.com/justinchronicle) / Daeyup Lee * Marco Trulla [@marcotrulla](http://twitter.com/marcotrulla), [github](https://github.com/Ragnarokkr) * Alex Navasardyan [@alexnavasardyan](http://twitter.com/alexnavasardyan), [github](https://github.com/2k00l) * Mihai Paun [@mihaipaun](http://twitter.com/mihaipaun), [github](https://github.com/mihaipaun) * Evgeny Mandrikov [@\_godin\_](http://twitter.com/_godin_), [github](https://github.com/Godin) * Sofish Lin [@sofish](http://twitter.com/sofish), [github](https://github.com/sofish) * Дејан Димић [@dejan_dimic](http://twitter.com/dejan_dimic), [github](https://github.com/rubystream) * Miloš Gavrilović [@gavrisimo](http://twitter.com/gavrisimo), [github](https://github.com/gavrisimo) * Firede [@firede](https://twitter.com/firede) [github](https://github.com/firede) * monkadd [github](https://github.com/monkadd) * Stephan Lindauer [@stephanlindauer](http://twitter.com/stephanlindauer), [github](https://github.com/stephanlindauer) * Thomas P [@dragon5689](https://twitter.com/dragon5689) [github](https://github.com/dragon5689) * Yotam Ofek [@yotamofek](https://twitter.com/yotamofek) [github](https://github.com/yotamofek) * Aleksandr Filatov [@greybax] (http://twitter.com/greybax), [github](https://github.com/greybax) * Duc Nguyen [@ducntq](https://twitter.com/ducntq), [github](https://github.com/ducntq) * James Young [@jamsyoung](http://twitter.com/jamsyoung), [github](https://github.com/jamsyoung) * Stephane Moreau [github](https://github.com/stmoreau) * Boris Nekezov [github](https://github.com/boris-nekezov) * Akshat Joshi [@akshat_joshi](http://twitter.com/akshat_joshi), [github](https://https://github.com/akshatjoshii) ## Tất cả code trong bộ mã nguồn nên nhìn giống như một người viết ra, cho dù có bao nhiêu người đóng góp. ### Danh sách dưới đây chỉ ra những thực hành mà tôi dùng trong tất cả các code mà tôi là tác giả ban đầu; những đóng góp tới các dự án mà tôi tạo ra nên đi theo các chỉ dẫn đó. ### Tôi không định ép người khác phải theo phong cách viết của tôi; nếu có một kiểu viết chung, kiểu viết đó nên được làm theo. > ### "Tranh cãi về phong cách là vô nghĩa. Nên có một hướng dẫn về phong cách, và bạn nên làm theo." >_Rebecca_ _Murphey_   > ### "Một phần của người quản lý dự án tốt là nhận ra rằng viết code cho bản thân anh ta là một Ý Tưởng Tồi™. Nếu có hàng ngàn người đang dùng code của bạn, thì bạn nên viết code cho rõ ràng tối đa, chứ không phải theo cách bạn thích rằng thế này là thông minh trong một khuôn khổ." >_Idan_ _Gazit_ ## Bản dịch * [ORIGINAL](https://github.com/rwldrn/idiomatic.js/) * [Bulgarian](https://github.com/rwldrn/idiomatic.js/tree/master/translations/bg_BG) * [German](https://github.com/rwldrn/idiomatic.js/tree/master/translations/de_DE) * [French](https://github.com/rwldrn/idiomatic.js/tree/master/translations/fr_FR) * [Spanish](https://github.com/rwldrn/idiomatic.js/tree/master/translations/es_ES) * [Portuguese - Brazil](https://github.com/rwldrn/idiomatic.js/tree/master/translations/pt_BR) * [Korean](https://github.com/rwldrn/idiomatic.js/tree/master/translations/ko_KR) * [Japanese](https://github.com/rwldrn/idiomatic.js/tree/master/translations/ja_JP) * [Italian](https://github.com/rwldrn/idiomatic.js/tree/master/translations/it_IT) * [Russian](https://github.com/rwldrn/idiomatic.js/tree/master/translations/ru_RU) * [Romanian](https://github.com/rwldrn/idiomatic.js/tree/master/translations/ro_RO) * [简体中文](https://github.com/rwldrn/idiomatic.js/tree/master/translations/zh_CN) * [Serbian - cyrilic alphabet](https://github.com/rwldrn/idiomatic.js/tree/master/translations/ср_СР) * [Serbian - latin aplphabet](https://github.com/rwldrn/idiomatic.js/tree/master/translations/sr_SR) * [Tiếng Việt](https://github.com/rwldrn/idiomatic.js/tree/master/translations/vi_VN) * [Greek](https://github.com/rwaldron/idiomatic.js/tree/master/translations/gr_GR) * [Hindi](https://github.com/rwaldron/idiomatic.js/tree/master/translations/hi_HI) ## Quan trọng, những thành phần không nhất quán ### Công cụ Chất lượng Code, Tài nguyên & Tham khảo * [JavaScript Plugin](http://docs.codehaus.org/display/SONAR/JavaScript+Plugin) dành cho [Sonar](http://www.sonarsource.org/) * [Plato](https://github.com/es-analysis/plato) * [jsPerf](http://jsperf.com/) * [jsFiddle](http://jsfiddle.net/) * [jsbin](http://jsbin.com/) * [JavaScript Lint (JSL)](http://javascriptlint.com/) * [jshint](http://jshint.com/) * [jslint](http://jslint.org/) * [eslint](http://eslint.org/) * [jscs](https://www.npmjs.org/package/jscs) * [Editorconfig](http://editorconfig.org/) ## Trở nên thông minh ### [Chú giải ECMAScript 5.1](http://es5.github.com/) ### [Đặc tả kỹ thuật của Ngôn Ngữ EcmaScript, Phiên bản 5.1](http://ecma-international.org/ecma-262/5.1/) Những thứ dưới đây nên coi là 1) không đầy đủ, and 2) *YÊU CẦU ĐỌC*. Tôi không phải lúc nào cũng đồng ý với phong cách của những tác giả dưới đây, nhưng có một điều là chắc chắc: Tất cả đều nhất quán. Thêm nữa, đây là những người có ảnh hưởng đến ngôn ngữ. * [Baseline For Front End Developers](http://rmurphey.com/blog/2012/04/12/a-baseline-for-front-end-developers/) * [Eloquent JavaScript](http://eloquentjavascript.net/) * [JavaScript, JavaScript](http://javascriptweblog.wordpress.com/) * [Hành trình Phát triển JavaScript](http://rmurphey.com/) * [Cú giết hoàn hảo](http://perfectionkills.com/) * [Douglas Crockford's Wrrrld Wide Web](http://www.crockford.com) * [JS Assessment](https://github.com/rmurphey/js-assessment) ### Quy trình Build & Deployment Dự án luôn luôn chuẩn bị các chức năng để mã nguồn có thể kiểm tra phong cách, kiểm tra lỗi và nén lại để chuẩn bị cho sử dụng trong môi trường sản xuất. Để làm những việc này, [grunt](https://github.com/gruntjs/grunt) viết bởi Ben Alman là công cụ tốt nhất và chính thức thay thế cho thư mục "kits/" của repo này. ### Kiểm tra lỗi Dự án _phải_ có một sô cách để unit, reference, implementation hoặc functional testing. Use case demos KHÔNG ĐỦ TIÊU CHUẨN là "tests". Dưới đây là danh sách test frameworks, không có sản phẩm nào hơn sản phẩm nào cả. * [QUnit](http://github.com/jquery/qunit) * [Jasmine](https://github.com/pivotal/jasmine) * [Vows](https://github.com/cloudhead/vows) * [Mocha](https://github.com/visionmedia/mocha) * [Hiro](http://hirojs.com/) * [JsTestDriver](https://code.google.com/p/js-test-driver/) * [Buster.js](http://busterjs.org/) * [Sinon.js](http://sinonjs.org/) ## Mục lục * [Khoảng trắng](#whitespace) * [Cú pháp đẹp](#spacing) * [Kiểm tra Type (Trích từ jQuery Core Style Guidelines)](#type) * [Kiểm tra tính điều kiện](#cond) * [Phong cách thực tế](#practical) * [Đặt tên](#naming) * [Khác](#misc) * [Đối tượng Native & Host](#native) * [Chú thích](#comments) * [Code Một Ngôn ngữ](#language) ------------------------------------------------ ## Mở đầu Các phần dưới đây chỉ ra một phong cách _hợp lý_ cho phát triển JavaScript hiện đại và không có nghĩa là quy tắc. Nguyên tắc quan trọng nhất là **luật nhất quán của phong cách code**. Bất kể phong cách nào bạn chọn cho dự án của bạn, hãy coi đó là luật. Làm theo tài liệu này để đảm bảo tính nhất quán trong phong cách, khả năng đọc và bảo trì của dự án của bạn. ## Hướng dẫn đến nhất quán trong phong cách 1. Khoảng trắng - Không bao giờ dùng cả khoảng trắng và tab. - Khi bắt đầu một dự án, trước khi viết bất cứ dòng code nào, hãy chọn giữa soft indents (khoảng trắng) hoặc là tab thật, coi đây là **luật**. - Để tăng tính đọc, tôi luôn luôn đề xuất thiết lập cho trình soạn thảo của bạn khoảng lùi là 2 ký tự — điều này có nghĩa là lùi vào 2 khoảng trắng hoặc 2 khoảng trắng đại diện cho một tab. - Nếu trình soạn thảo hỗ trợ, hãy luôn bật chế độ "hiển thị tàng hình". Lợi ích của việc này: - Đảm bảo tính nhất quán - Loại bỏ khoảng trắng thừa - Loại bỏ dòng chỉ chứa khoảng trắng - Commits và diffs dễ đọc hơn 2. Cú pháp đẹp A. Dấu nháy, ngoặc, và xuống dòng ```javascript // if/else/for/while/try luôn luôn có khoảng trắng, ngoặc nhọn và xuống nhiều dòng // điều này đảm bảo tính đọc // 2.A.1.1 // Ví dụ của một cú pháp chật chội if(condition) doSomething(); while(condition) iterating++; for(var i=0;i<100;i++) someIterativeFn(); // 2.A.1.1 // Sử dụng khoảng trắng để tăng khả năng đọc if ( condition ) { // statements } while ( condition ) { // statements } for ( var i = 0; i < 100; i++ ) { // statements } // Hoặc tốt hơn: var i, length = 100; for ( i = 0; i < length; i++ ) { // statements } // Hoặc... var i = 0, length = 100; for ( ; i < length; i++ ) { // statements } var prop; for ( prop in object ) { // statements } if ( true ) { // statements } else { // statements } ``` B. Khai báo, gán, function ( Tên biến, Expression, Constructor ) ```javascript // 2.B.1.1 // Biến var foo = "bar", num = 1, undef; // Ký hiệu: var array = [], object = {}; // 2.B.1.2 // Chỉ sử dụng một `var` trong một scope (function) để tăng tính đọc // và đảm bảo danh sách khai báo không bị lộn xộn (và cũng tiết kiệm được vài ký tự) // Không tốt var foo = ""; var bar = ""; var qux; // Tốt var foo = "", bar = "", quux; // hoặc.. var // Chú thích vào đây foo = "", bar = "", quux; // 2.B.1.3 // var nên luôn luôn đặt ở đầu một scope (function). // Không tốt function foo() { // statements var bar = "", qux; } // Tốt function foo() { var bar = "", qux; // statements sau khai báo. } // 2.B.1.4 // const và let, từ ECMAScript 6, cũng nên để ở đầu scope (một khối). // Không tốt function foo() { let foo, bar; if (condition) { bar = ""; // statements } } // Tốt function foo() { let foo; if (condition) { let bar = ""; // statements } } ``` ```javascript // 2.B.2.1 // Khai báo tên function function foo( arg1, argN ) { } // Sử dụng foo( arg1, argN ); // 2.B.2.2 // Khai báo tên function function square( number ) { return number * number; } // Sử dụng square( 10 ); // Đảm bảo sự liền mạch khi khai báo param function square( number, callback ) { callback( number * number ); } square( 10, function( square ) { // callback statements }); // 2.B.2.3 // Khai báo bên trong function var square = function( number ) { // Return một thứ gì đó có giá trị và quan trọng return number * number; }; // Khai báo trong function với Identifier // Cách này nên được sử dụng khi thêm giá trị vào chính bản thân nó // và khả năng tự gọi, tự xác định bên trong stack traces: var factorial = function factorial( number ) { if ( number < 2 ) { return 1; } return number * factorial( number - 1 ); }; // 2.B.2.4 // Khai báo Constructor function FooBar( options ) { this.options = options; } // Sử dụng var fooBar = new FooBar({ a: "alpha" }); fooBar.options; // { a: "alpha" } ``` C. Exceptions, Độ lệch nhẹ ```javascript // 2.C.1.1 // Functions với callbacks foo(function() { // Lưu ý là không có khoảng trắng bên trong param // của function và từ khóa "function" }); // Param của function là mảng, không có khoảng trắng foo([ "alpha", "beta" ]); // 2.C.1.2 // Param của function là đối tượng, không có khoảng trắng foo({ a: "alpha", b: "beta" }); // Một param là chuỗi, không có khoảng trắng foo("bar"); // Nhóm bên trong dấu nháy, không khoảng trắng if ( !("foo" in obj) ) { } ``` D. Tính nhất quán luôn luôn thắng Trong phần 2.A-2.C, quy tắc về khoảng trắng được nhắc đến như là đề nghị với mục đích đơn giản và cao hơn: tính nhất quán. Điều quan trọng là sự ưa thích, như là "khoảng trắng bên trong" nên được coi là không bắt buộc, nhưng nên áp dụng chỉ một phong cách duy nhất trong dự án của bạn. ```javascript // 2.D.1.1 if (condition) { // statements } while (condition) { // statements } for (var i = 0; i < 100; i++) { // statements } if (true) { // statements } else { // statements } ``` E. Dấu nháy Cho dù bạn thích nháy đơn hay nháy kép, điều đó không quan trọng, Javascript không đối xử khác nhau giữa 2 kiểu nháy này. Điều **CẦN PHẢI** làm là đảm bảo tính nhất quán. **Không bao giờ lẫn giữa các loại dấu nháy trong cùng một dự án. Chọn một kiểu và làm theo kiểu đó.** F. Hết dòng và dòng trắng Khoảng trắng có thể làm hỏng diffs và làm cho changesets không thể đọc được. Có thể sử dụng pre-commit hook để loại bỏ các khoảng trắng cuối dòng và khoảng trắng trên dòng rỗng tự động. 3. Kiểm tra Type (Trích từ jQuery Core Style Guidelines) A. Kiểm tra nghiêm ngặt String: typeof variable === "string" Number: typeof variable === "number" Boolean: typeof variable === "boolean" Object: typeof variable === "object" Array: Array.isArray( arrayLikeObject ) (wherever possible) Node: elem.nodeType === 1 null: variable === null null hoặc undefined: variable == null undefined: Biến Global: typeof variable === "undefined" Biến Local: variable === undefined Properties: object.prop === undefined object.hasOwnProperty( prop ) "prop" in object B. Kiểm tra cưỡng chế Cho một đoạn code như sau... Có một đoạn HTML: ```html ``` ```javascript // 3.B.1.1 // `foo` được khai báo với giá trị `0` và kiểu là `number` var foo = 0; // typeof foo; // "number" ... // Đâu đó trong code của bạn, bạn cập nhật giá trị của `foo` // với một giá trị mới lấy từ phần tử input foo = document.getElementById("foo-input").value; // Nếu bạn kiểm tra `typeof foo`, giá trị trả lại sẽ là `string` // Điều này có nghĩa là nếu bạn có kiểm tra logic với `foo` như sau: if ( foo === 1 ) { importantTask(); } // `importantTask()` sẽ không bao giờ được gọi, mặc dù `foo` có giá trị "1" // 3.B.1.2 // Bạn có thể sửa khắc phục điều này bằng cách sử dụng toán tử một ngôi (unary operator) + hoặc -: foo = +document.getElementById("foo-input").value; // ^ toán tử một ngôi + sẽ chuyển giá trị bên phải thành số // typeof foo; // "number" if ( foo === 1 ) { importantTask(); } // `importantTask()` sẽ được gọi ``` Một số tình huống thường gặp khác: ```javascript // 3.B.2.1 var number = 1, string = "1", bool = false; number; // 1 number + ""; // "1" string; // "1" +string; // 1 +string++; // 1 string; // 2 bool; // false +bool; // 0 bool + ""; // "false" ``` ```javascript // 3.B.2.2 var number = 1, string = "1", bool = true; string === number; // false string === number + ""; // true +string === number; // true bool === number; // false +bool === number; // true bool === string; // false bool === !!string; // true ``` ```javascript // 3.B.2.3 var array = [ "a", "b", "c" ]; !!~array.indexOf("a"); // true !!~array.indexOf("b"); // true !!~array.indexOf("c"); // true !!~array.indexOf("d"); // false // Lưu ý là những phương pháp trên được coi là "thông minh không cần thiết" // Sử dụng các phương pháp tiếp cận đảm bảo khác để so sánh giá trị như là // indexOf, như sau: if ( array.indexOf( "a" ) >= 0 ) { // ... } ``` ```javascript // 3.B.2.4 var num = 2.5; parseInt( num, 10 ); // bằng với... ~~num; num >> 0; num >>> 0; // Tất cả đều trả lại kết quả là 2 // Hãy lưu ý rằng, số âm sẽ được xử lý khác... var neg = -2.5; parseInt( neg, 10 ); // tương tự... ~~neg; neg >> 0; // Tất cả đều trả lại kết quả là -2 // Tuy nhiên... neg >>> 0; // Sẽ trả lại 4294967294 ``` 4. Kiểm tra tính điều kiện ```javascript // 4.1.1 // Khi kiểm tra array có độ dài (length), // thay vì: if ( array.length > 0 ) ... // ...hãy làm như sau: if ( array.length ) ... // 4.1.2 // Khi kiểm tra array rỗng, // thay vì: if ( array.length === 0 ) ... // ...hãy làm như sau: if ( !array.length ) ... // 4.1.3 // Khi kiểm tra string không rỗng, // thay vì: if ( string !== "" ) ... // ...hãy làm như sau: if ( string ) ... // 4.1.4 // Khi kiểm tra string _rỗng_, // thay vì: if ( string === "" ) ... // ...hãy kiểm tra độ sai, làm như sau: if ( !string ) ... // 4.1.5 // Khi kiểm tra tham chiếu (reference) có đúng hay không, // thay vì: if ( foo === true ) ... // ...hãy kiểm tra chính giá trị của đối tượng, tận dụng khả năng sẵn có: if ( foo ) ... // 4.1.6 // Khi kiểm tra tham chiếu có sai hay không, // thay vì: if ( foo === false ) ... // ...hãy kiểm tra độ sai if ( !foo ) ... // ...Cẩn thận, đoạn code trên cũng đúng với: 0, "", null, undefined, NaN // Nếu bạn _PHẢI_ kiểm tra giá trị boolean false, hãy dùng: if ( foo === false ) ... // 4.1.7 // Khi kiểm tra tham chiếu có thể là null hoặc undefined, nhưng không phải là false, "" hoặc 0, // thay vì: if ( foo === null || foo === undefined ) ... // ...tận dụng độ lệch nhẹ == khi so sánh, như sau: if ( foo == null ) ... // Hãy nhớ, sử dụng == để so sánh với `null` sẽ BẰNG với `null` và `undefined` // chứ không phải là `false`, "" hoặc 0 null == undefined ``` LUÔN LUÔN kiểm tra theo phương thức cho kết quả chính xác nhất - phương thức ở trên chỉ là hướng dẫn, không phải là giáo lý. ```javascript // 4.2.1 // Ghi chú về biểu thức ép buộc kiểu // Luôn dùng `===` thay vì `==` (ngoại trừ trường hợp yêu cầu biểu thức kiểu lỏng lẻo - loose type) // === không ép buộc kiểu, vì vậy: "1" === 1; // false // == ép buộc kiểu, vì vậy: "1" == 1; // true // 4.2.2 // Booleans, Đúng và Sai // Booleans: true, false // Đúng: "foo", 1 // Sai: "", 0, null, undefined, NaN, void 0 ``` 5. Phong cách thực tế ```javascript // 5.1.1 // Module thực tế (function( global ) { var Module = (function() { var data = "secret"; return { // Đây là một property kiểu boolean bool: true, // Giá trị string string: "a string", // Property là array array: [ 1, 2, 3, 4 ], // Property là Object object: { lang: "en-Us" }, getData: function() { // lấy giá trị hiện tại của biến `data` return data; }, setData: function( value ) { // đặt giá trị cho `data` và trả lại giá trị đó return ( data = value ); } }; })(); // Một vài việc khác có thể xảy ra ở đây // biến module thành một Object Global global.Module = Module; })( this ); ``` ```javascript // 5.2.1 // Constructor trong thực tế (function( global ) { function Ctor( foo ) { this.foo = foo; return this; } Ctor.prototype.getFoo = function() { return this.foo; }; Ctor.prototype.setFoo = function( val ) { return ( this.foo = val ); }; // Để gọi constructor không cần `new`, bạn có thể làm như sau: var ctor = function( foo ) { return new Ctor( foo ); }; // biến constructor thành Object Global global.ctor = ctor; })( this ); ``` 6. Đặt tên A. Bạn không phải là một bộ compiler mã máy, vì vậy đừng cố tả ra như vậy. Ví dụ sau đây là một sai lầm nghiêm trọng trong việc đặt tên: ```javascript // 6.A.1.1 // Ví dụ về code với cách đặt tên nghèo nàn function q(s) { return document.querySelectorAll(s); } var i,a=[],els=q("#foo"); for(i=0;iKhác Phần này sẽ được dùng để mô tả ý tưởng và khái niệm không nên được coi là bắt buộc, nhưng được khuyến khích sử dụng trong thực tế để tìm ra cách tốt hơn để thực hiện các tác vụ trong lập trình Javascript. A. Nên tránh sử dụng`switch` Đã có những thay đổi lớn đến hiệu suất của `switch` trong các phiên bản mới nhất của Firefox và Chrome. http://jsperf.com/switch-vs-object-literal-vs-module Những cải tiến đó cũng có thể xem ở đây: https://github.com/rwldrn/idiomatic.js/issues/13 ```javascript // 7.A.1.1 // Ví dụ khi sử dụng `switch` switch( foo ) { case "alpha": alpha(); break; case "beta": beta(); break; default: // làm cái gì khác break; } // 7.A.1.2 // Một cách khác để xử lý các trường hợp điều kiện // là sử dụng một object lưu trữ các "trường hợp" và một function để xử lý: var cases, delegator; // Ví dụ chỉ có tính minh họa. cases = { alpha: function() { // code xử lý // trả lại dữ liệu return [ "Alpha", arguments.length ]; }, beta: function() { // code xử lý // trả lại dữ liệu return [ "Beta", arguments.length ]; }, _default: function() { // code xử lý // trả lại dữ liệu return [ "Default", arguments.length ]; } }; delegator = function() { var args, key, delegate; // Chuyển danh sách param thành một mảng args = [].slice.call( arguments ); // Lấy key là trường hợp đúng key = args.shift(); // Gán trường hợp mặc định delegate = cases._default; // Chuyển đến trường hợp được chọn if ( cases.hasOwnProperty( key ) ) { delegate = cases[ key ]; } // Param đầu tiên có thể là dữ liệu được sử dụng, // trong trường hợp này, |null| sẽ được dùng return delegate.apply( null, args ); }; // 7.A.1.3 // Sử dụng API từ 7.A.1.2: delegator( "alpha", 1, 2, 3, 4, 5 ); // [ "Alpha", 5 ] // Tất nhiên, key của `trường hợp` có thể dựa trên // các điều kiện phức tạp hơn var caseKey, someUserInput; // Có thể là lấy từ đầu vào (input)? someUserInput = 9; if ( someUserInput > 10 ) { caseKey = "alpha"; } else { caseKey = "beta"; } // hoặc là... caseKey = someUserInput > 10 ? "alpha" : "beta"; // Sau đó... delegator( caseKey, someUserInput ); // [ "Beta", 1 ] // và tất nhiên là... delegator(); // [ "Default", 0 ] ``` B. Return sớm tăng khả năng đọc của code với tăng hiệu năng nhỏ ```javascript // 7.B.1.1 // Không tốt: function returnLate( foo ) { var ret; if ( foo ) { ret = "foo"; } else { ret = "quux"; } return ret; } // Tốt: function returnEarly( foo ) { if ( foo ) { return "foo"; } return "quux"; } ``` 8. Đối tượng Native & Host Nguyên tắc cơ bản: ### Đừng làm điều ngu ngốc và mọi thứ sẽ không sao cả. Để đảm bảo nguyên tắc trên, hãy đọc phần bên dưới: #### “Everything is Permitted: Extending Built-ins” (Tất cả đều cho phép: Mở rộng thành phần dựng sẵn) viết bởi Andrew Dupont (JSConf2011, Portland, Oregon) https://www.youtube.com/watch?v=xL3xCO7CLNM 9. Chú thích #### Dòng đầu tiên trên code là tiêu đề #### Nhiều dòng cũng tốt #### Chú thích cuối dùng là không được phép! #### Chú thích theo JSDoc cũng hay, nhưng cần thời gian để nghiên cứu 10. Code Một Ngôn Ngữ Chương trình chỉ nên viết bằng một ngôn ngữ, cho dù đó là ngôn ngữ nào, quyết định bởi một hay nhiều người duy trì dự án. ## Phụ lục ### Dấu phẩy đầu tiên. Bất kỳ dự án nào trích dẫn tài liệu này như là một hướng dẫn về phong cách code sẽ không chấp nhận phong cách dấu phẩy đầu tiên, trừ khi là được quy định bởi tác giả của dự án. ---------- Creative Commons License
Nguyên tắc để Viết Javascript Nhất quán viết bởi Rick Waldron và Những người đóng góp được cấp phép Creative Commons Attribution 3.0 Unported License.
Dựa trên tài liệu ở github.com/rwldrn/idiomatic.js. ================================================ FILE: translations/zh_CN/readme.md ================================================ # 书写具备一致风格、通俗易懂 JavaScript 的原则 ## 这是一份用来改进我们代码,以让其总是让人喜爱的持续更新的文档(living document)和新思想。参与构建:(请)fork、clone、branch、commit、push、pull、pull request。 * Rick Waldron [@rwaldron](http://twitter.com/rwaldron), [github](https://github.com/rwaldron) * Mathias Bynens [@mathias](http://twitter.com/mathias), [github](https://github.com/mathiasbynens) * Schalk Neethling [@ossreleasefeed](http://twitter.com/ossreleasefeed), [github](https://github.com/ossreleasefeed/) * Kit Cambridge [@kitcambridge](http://twitter.com/kitcambridge), [github](https://github.com/kitcambridge) * Raynos [github](https://github.com/Raynos) * Matias Arriola [@MatiasArriola](https://twitter.com/MatiasArriola), [github](https://github.com/MatiasArriola/) * John Fischer [@jfroffice](https://twitter.com/jfroffice), [github](https://github.com/jfroffice/) * Idan Gazit [@idangazit](http://twitter.com/idangazit), [github](https://github.com/idangazit) * Leo Balter [@leobalter](http://twitter.com/leobalter), [github](https://github.com/leobalter) * Breno Oliveira [@garu_rj](http://twitter.com/garu_rj), [github](https://github.com/garu) * Leo Beto Souza [@leobetosouza](http://twitter.com/leobetosouza), [github](https://github.com/leobetosouza) * Ryuichi Okumura [@okuryu](http://twitter.com/okuryu), [github](https://github.com/okuryu) * Pascal Precht [@PascalPrecht](http://twitter.com/PascalPrecht), [github](https://github.com/pascalprecht) * EngForDev [engfordev](http://www.opentutorials.org/course/167/1363) - Hwan Min Hong / MinTaek Kwon [@leoinsight](http://twitter.com/leoinsight) / Tw Shim [@marocchino](http://twitter.com/marocchino), [github](https://github.com/marocchino) / Nassol Kim [@nassol99](http://twitter.com/nassol99), [github](https://github.com/nassol) / Juntai Park [@rkJun](http://twitter.com/rkJun), [github](https://github.com/rkJun) / Minkyu Shim / Gangmin Won / Justin Yoo [@justinchronicle](http://twitter.com/justinchronicle) / Daeyup Lee * Marco Trulla [@marcotrulla](http://twitter.com/marcotrulla), [github](https://github.com/Ragnarokkr) * Alex Navasardyan [@alexnavasardyan](http://twitter.com/alexnavasardyan), [github](https://github.com/2k00l) * Mihai Paun [@mihaipaun](http://twitter.com/mihaipaun), [github](https://github.com/mihaipaun) * Evgeny Mandrikov [@\_godin\_](http://twitter.com/_godin_), [github](https://github.com/Godin) * Sofish Lin [@sofish](http://twitter.com/sofish), [github](https://github.com/sofish) * Дејан Димић [@dejan_dimic](http://twitter.com/dejan_dimic), [github](https://github.com/rubystream) * Miloš Gavrilović [@gavrisimo](http://twitter.com/gavrisimo), [github](https://github.com/gavrisimo) * Duc Nguyen [@ducntq](https://twitter.com/ducntq), [github](https://github.com/ducntq) * James Young [@jamsyoung](http://twitter.com/jamsyoung), [github](https://github.com/jamsyoung) * Stephane Moreau [github](https://github.com/stmoreau) * Boris Nekezov [github](https://github.com/boris-nekezov) * Akshat Joshi [@akshat_joshi](http://twitter.com/akshat_joshi), [github](https://https://github.com/akshatjoshii) ## 无论有多少人在维护,所有在代码仓库中的代码理应看起来像同一个人写的。 ### 下面的清单概括了我作为原作者的所有代码中使用的实践。在我创建的项目中的所有构建代码都必须遵循这些规则。 ### 我并不想强制别人在其代码或项目中使用我个人所偏好的代码风格;如果已经存在一个通用编码规范,它必须受到尊崇。 > ### "对风格的挑刺毫无意义可言。它们必须是指导原则,且你必须遵循。" >_Rebecca_ _Murphey_   > ### "成为一个优秀的成功项目管理者的一个条件是,明白按自己的偏好风格写代码是非常不好的做法。如果成千上万的人都在使用你的代码,那么请尽可能通俗易懂地写出你的代码,而非在规范之下自作聪明地使用自己偏好的风格。" >_Idan_ _Gazit_ ## 翻译版本 * [ORIGINAL](https://github.com/rwldrn/idiomatic.js/) * [Bulgarian](https://github.com/rwldrn/idiomatic.js/tree/master/translations/bg_BG) * [German](https://github.com/rwldrn/idiomatic.js/tree/master/translations/de_DE) * [French](https://github.com/rwldrn/idiomatic.js/tree/master/translations/fr_FR) * [Spanish](https://github.com/rwldrn/idiomatic.js/tree/master/translations/es_ES) * [Portuguese - Brazil](https://github.com/rwldrn/idiomatic.js/tree/master/translations/pt_BR) * [Korean](https://github.com/rwldrn/idiomatic.js/tree/master/translations/ko_KR) * [Japanese](https://github.com/rwldrn/idiomatic.js/tree/master/translations/ja_JP) * [Italian](https://github.com/rwldrn/idiomatic.js/tree/master/translations/it_IT) * [Russian](https://github.com/rwldrn/idiomatic.js/tree/master/translations/ru_RU) * [Romanian](https://github.com/rwldrn/idiomatic.js/tree/master/translations/ro_RO) * [简体中文](https://github.com/rwldrn/idiomatic.js/tree/master/translations/zh_CN) * [Serbian - cyrilic alphabet](https://github.com/rwldrn/idiomatic.js/tree/master/translations/ср_СР) * [Serbian - latin aplphabet](https://github.com/rwldrn/idiomatic.js/tree/master/translations/sr_SR) * [Greek](https://github.com/rwaldron/idiomatic.js/tree/master/translations/gr_GR) * [Hindi](https://github.com/rwaldron/idiomatic.js/tree/master/translations/hi_HI) ## 重要,非常通用资源: ### 代码质量工具、资源和文献 * [JavaScript Plugin](http://docs.codehaus.org/display/SONAR/JavaScript+Plugin) for [Sonar](http://www.sonarsource.org/) * [jsPerf](http://jsperf.com/) * [jsFiddle](http://jsfiddle.net/) * [jsbin](http://jsbin.com/) * [JavaScript Lint (JSL)](http://javascriptlint.com/) * [jshint](http://jshint.com/) * [jslint](http://jslint.org/) * [Editorconfig](http://editorconfig.org/) ## 变聪明点 ### [ECMAScript 5.1 注解版](http://es5.github.com/) ### [EcmaScript 语言规范, 5.1 版](http://ecma-international.org/ecma-262/5.1/) 下列文档的现实是:1)不完全版,2)*必读*。我并不全(不总是,always agree)赞同下列所有作者所写的风格,但有一点可以确定的是:他们具备一致性。除此之外,他们还都是这门语言的权威人士。 * [Baseline For Front End Developers](http://rmurphey.com/blog/2012/04/12/a-baseline-for-front-end-developers/) * [Eloquent JavaScript](http://eloquentjavascript.net/) * [JavaScript, JavaScript](http://javascriptweblog.wordpress.com/) * [Adventures in JavaScript Development](http://rmurphey.com/) * [Perfection Kills](http://perfectionkills.com/) * [Douglas Crockford's Wrrrld Wide Web](http://www.crockford.com) * [JS Assessment](https://github.com/rmurphey/js-assessment) * [Leveraging Code Quality Tools by Anton Kovalyov](http://anton.kovalyov.net/slides/gothamjs/) ### 编译和部署 项目必须总是提供一些通用的方法来检验(can be linted)、测试和压缩源码以为产品阶段使用做准备。对于此类工作 Ben Alman 所写的 [grunt](https://github.com/cowboy/grunt) 可谓首屈一指,并已替代这个仓库的 “kits/” 目录作官方工具。 ### 测试工具 项目 _必须_ 包括某此类型的单元、引用、实现或者功能性测试。使用代码示例并不足以称为“测试”。下面是一系列测试框架,他们只代表自己(谁都不是谁的更好替代品,which are endorsed more than the other)。 * [QUnit](http://github.com/jquery/qunit) * [Jasmine](https://github.com/pivotal/jasmine) * [Vows](https://github.com/cloudhead/vows) * [Mocha](https://github.com/visionmedia/mocha) * [Hiro](http://hirojs.com/) * [JsTestDriver](https://code.google.com/p/js-test-driver/) * [Buster.js](http://busterjs.org/) * [Sinon.js](http://sinonjs.org/) ## 目录 * [Whitespace](#whitespace) * [Beautiful Syntax](#spacing) * [Type Checking (Courtesy jQuery Core Style Guidelines)](#type) * [Conditional Evaluation](#cond) * [Practical Style](#practical) * [Naming](#naming) * [Misc](#misc) * [Native & Host Objects](#native) * [Comments](#comments) * [One Language Code](#language) ------------------------------------------------ ## 前言 下面的章节描述的是一个 _合理_ 的现代 JavaScript 开发风格指南,并非硬性规定。其想送出的核心理念是*高度统一的代码风格*(the law of code style consistency)。你为项目所择风格都应为最高准则。作为一个描述放置于你的项目中,并链接到这个文档作为代码风格一致性、可读性和可维护性的保证。 ## Idiomatic 风格宣言 1. 空白 - 永远都不要混用空格和Tab。 - 开始一个项目,在写代码之前,选择软缩进(空格)或者 Tab(作为缩进方式),并将其作为**最高准则**。 - 为了可读, 我总是推荐在你的编辑中设计2个字母宽度的缩进 — 这等同于两个空格或者两个空格替代一个 Tab。 - 如果你的编辑器支持,请总是打开 “显示不可见字符” 这个设置。好处是: - 保证一致性 - 去掉行末的空格 - 去掉空行的空格 - 提交和对比更具可读性 2. 美化语法 A. 小括号, 花括号, 换行 ```javascript // if/else/for/while/try 通常都有小括号、花括号和多行 // 这有助于可读 // 2.A.1.1 // 难辨语法(cramped syntax)的例子 if(condition) doSomething(); while(condition) iterating++; for(var i=0;i<100;i++) someIterativeFn(); // 2.A.1.1 // 使用空格来提升可读性 if ( condition ) { // 语句 } while ( condition ) { // 语句 } for ( var i = 0; i < 100; i++ ) { // 语句 } // 更好的做法: var i, length = 100; for ( i = 0; i < length; i++ ) { // 语句 } // 或者... var i = 0, length = 100; for ( ; i < length; i++ ) { // 语句 } var prop; for ( prop in object ) { // 语句 } if ( true ) { // 语句 } else { // 语句 } ``` B. 赋值, 声明, 函数 ( 命名函数, 函数表达式, 构建函数 ) ```javascript // 2.B.1.1 // 变量 var foo = "bar", num = 1, undef; // 字面量标识: var array = [], object = {}; // 2.B.1.2 // 在一个作用域(函数)内只使用一个 `var` 有助于提升可读性 // 并且让你的声明列表变得有条不紊 (还帮你省了几次键盘敲击) // 不好 var foo = ""; var bar = ""; var qux; // 好 var foo = "", bar = "", quux; // 或者.. var // 对这些变量的注释 foo = "", bar = "", quux; // 2.B.1.3 // `var` 语句必须总是在各自作用域(函数)顶部 // 同样适应于来自 ECMAScript 6 的常量 // 不好 function foo() { // 在变量前有语句 var bar = "", qux; } // 好 function foo() { var bar = "", qux; // 所有语句都在变量之后 } ``` ```javascript // 2.B.2.1 // 命名函数声明 function foo( arg1, argN ) { } // 使用方法 foo( arg1, argN ); // 2.B.2.2 // 命名函数声明 function square( number ) { return number * number; } // 使用方法 square( 10 ); // 非常不自然的连带传参(continuation passing)风格 function square( number, callback ) { callback( number * number ); } square( 10, function( square ) { // 回调内容 }); // 2.B.2.3 // 函数表达式 var square = function( number ) { // 返回有价值的、相关的内容 return number * number; }; // 带标识符的函数表达式 // 这种首选形式有附加的功能让其可以调用自身 // 并且在堆栈中有标识符 var factorial = function factorial( number ) { if ( number < 2 ) { return 1; } return number * factorial( number-1 ); }; // 2.B.2.4 // 构造函数声明 function FooBar( options ) { this.options = options; } // 使用方法 var fooBar = new FooBar({ a: "alpha" }); fooBar.options; // { a: "alpha" } ``` C. 异常, 细节 ```javascript // 2.C.1.1 // 带回调的函数 foo(function() { // 注意:在第一函数调用的小括号和 `function` 处并没有空格 }); // 函数接受 `array` 作为参数,没有空格 foo([ "alpha", "beta" ]); // 2.C.1.2 // 函数接受 `object` 作为参数,没有空格 foo({ a: "alpha", b: "beta" }); // 函数接受 `string` 字面量作为参数,没有空格 foo("bar"); // 分组用的小括号内部,没有空格 if ( !("foo" in obj) ) { } ``` D. 一致性(统一)总是笑到最后的(Consistency Always Wins) 在 2.A-2.C 节,留白作为一个推荐方式被提出,基于单纯的、更高的目的:统一。值得注意的是格式化偏好,像“内部留白”必须是可选的,但在整个项目的源码中必须只存在着一种。 ```javascript // 2.D.1.1 if (condition) { // 语句 } while (condition) { // 语句 } for (var i = 0; i < 100; i++) { // 语句 } if (true) { // 语句 } else { // 语句 } ``` E. 引号 无论你选择单引号还是双引号都无所谓,在 JavaScript 中它们在解析上没有区别。而**绝对需要**强制的是一致性。 **永远不要在同一个项目中混用两种引号,选择一种,并保持一致**。 F. 行末和空行 留白会破坏区别并使用变更不可读。考虑包括一个预提交的 hook 自动删除行末和空行中的空格。 3. 类型检测 (来源于 jQuery Core Style Guidelines) A. 直接类型(实际类型,Actual Types) String: typeof variable === "string" Number: typeof variable === "number" Boolean: typeof variable === "boolean" Object: typeof variable === "object" Array: Array.isArray( arrayLikeObject ) (如果可能的话) Node: elem.nodeType === 1 null: variable === null null or undefined: variable == null undefined: 全局变量: typeof variable === "undefined" 局部变量: variable === undefined 属性: object.prop === undefined object.hasOwnProperty( prop ) "prop" in object B. 转换类型(强制类型,Coerced Types) 考虑下面这个的含义... 给定的 HTML: ```html ``` ```javascript // 3.B.1.1 // `foo` 已经被赋予值 `0`,类型为 `number` var foo = 0; // typeof foo; // "number" ... // 在后续的代码中,你需要更新 `foo`,赋予在 input 元素中得到的新值 foo = document.getElementById("foo-input").value; // 如果你现在测试 `typeof foo`, 结果将是 `string` // 这意味着你在 if 语句检测 `foo` 有类似于此的逻辑: if ( foo === 1 ) { importantTask(); } // `importantTask()` 将永远不会被执行,即使 `foo` 有一个值 "1" // 3.B.1.2 // 你可以巧妙地使用 + / - 一元运算符强制转换类型以解决问题: foo = +document.getElementById("foo-input").value; // ^ + 一元运算符将它右边的运算对象转换为 `number` // typeof foo; // "number" if ( foo === 1 ) { importantTask(); } // `importantTask()` 将被调用 ``` 对于强制类型转换这里有几个例子: ```javascript // 3.B.2.1 var number = 1, string = "1", bool = false; number; // 1 number + ""; // "1" string; // "1" +string; // 1 +string++; // 1 string; // 2 bool; // false +bool; // 0 bool + ""; // "false" ``` ```javascript // 3.B.2.2 var number = 1, string = "1", bool = true; string === number; // false string === number + ""; // true +string === number; // true bool === number; // false +bool === number; // true bool === string; // false bool === !!string; // true ``` ```javascript // 3.B.2.3 var array = [ "a", "b", "c" ]; !!~array.indexOf("a"); // true !!~array.indexOf("b"); // true !!~array.indexOf("c"); // true !!~array.indexOf("d"); // false // 值得注意的是上述都是 "不必要的聪明" // 采用明确的方案来比较返回的值 // 如 indexOf: if ( array.indexOf( "a" ) >= 0 ) { // ... } ``` ```javascript // 3.B.2.3 var num = 2.5; parseInt( num, 10 ); // 等价于... ~~num; num >> 0; num >>> 0; // 结果都是 2 // 时刻牢记心底, 负值将被区别对待... var neg = -2.5; parseInt( neg, 10 ); // 等价于... ~~neg; neg >> 0; // 结果都是 -2 // 但是... neg >>> 0; // 结果即是 4294967294 ``` 4. 对比运算 ```javascript // 4.1.1 // 当只是判断一个 array 是否有长度,相对于使用这个: if ( array.length > 0 ) ... // ...判断真伪, 请使用这种: if ( array.length ) ... // 4.1.2 // 当只是判断一个 array 是否为空,相对于使用这个: if ( array.length === 0 ) ... // ...判断真伪, 请使用这种: if ( !array.length ) ... // 4.1.3 // 当只是判断一个 string 是否为空,相对于使用这个: if ( string !== "" ) ... // ...判断真伪, 请使用这种: if ( string ) ... // 4.1.4 // 当只是判断一个 string 是为空,相对于使用这个: if ( string === "" ) ... // ...判断真伪, 请使用这种: if ( !string ) ... // 4.1.5 // 当只是判断一个引用是为真,相对于使用这个: if ( foo === true ) ... // ...判断只需像你所想,享受内置功能的好处: if ( foo ) ... // 4.1.6 // 当只是判断一个引用是为假,相对于使用这个: if ( foo === false ) ... // ...使用叹号将其转换为真 if ( !foo ) ... // ...需要注意的是:这个将会匹配 0, "", null, undefined, NaN // 如果你 _必须_ 是布尔类型的 false,请这样用: if ( foo === false ) ... // 4.1.7 // 如果想计算一个引用可能是 null 或者 undefined,但并不是 false, "" 或者 0, // 相对于使用这个: if ( foo === null || foo === undefined ) ... // ...享受 == 类型强制转换的好处,像这样: if ( foo == null ) ... // 谨记,使用 == 将会令 `null` 匹配 `null` 和 `undefined` // 但不是 `false`,"" 或者 0 null == undefined ``` 总是判断最好、最精确的值,上述是指南而非教条。 ```javascript // 4.2.1 // 类型转换和对比运算说明 // 首次 `===`,`==` 次之 (除非需要松散类型的对比) // `===` 总不做类型转换,这意味着: "1" === 1; // false // `==` 会转换类型,这意味着: "1" == 1; // true // 4.2.2 // 布尔, 真 & 伪 // 布尔: true, false // 真: "foo", 1 // 伪: "", 0, null, undefined, NaN, void 0 ``` 5. 实用风格 ```javascript // 5.1.1 // 一个实用的模块 (function( global ) { var Module = (function() { var data = "secret"; return { // 这是一个布尔值 bool: true, // 一个字符串 string: "a string", // 一个数组 array: [ 1, 2, 3, 4 ], // 一个对象 object: { lang: "en-Us" }, getData: function() { // 得到 `data` 的值 return data; }, setData: function( value ) { // 返回赋值过的 `data` 的值 return ( data = value ); } }; })(); // 其他一些将会出现在这里 // 把你的模块变成全局对象 global.Module = Module; })( this ); ``` ```javascript // 5.2.1 // 一个实用的构建函数 (function( global ) { function Ctor( foo ) { this.foo = foo; return this; } Ctor.prototype.getFoo = function() { return this.foo; }; Ctor.prototype.setFoo = function( val ) { return ( this.foo = val ); }; // 不使用 `new` 来调用构建函数,你可能会这样做: var ctor = function( foo ) { return new Ctor( foo ); }; // 把我们的构建函数变成全局对象 global.ctor = ctor; })( this ); ``` 6. 命名 A. 你并不是一个人肉 编译器/压缩器,所以尝试去变身为其一。 下面的代码是一个极糟命名的典范: ```javascript // 6.A.1.1 // 糟糕命名的示例代码 function q(s) { return document.querySelectorAll(s); } var i,a=[],els=q("#foo"); for(i=0;iMisc 这个部分将要说明的想法和理念都并非教条。相反更鼓励对现存实践保持好奇,以尝试提供完成一般 JavaScript 编程任务的更好方案。 A. 避免使用 `switch`,现代方法跟踪(method tracing)将会把带有 switch 表达式的函数列为黑名单。 似乎在最新版本的 Firefox 和 Chrome 都对 `switch` 语句有重大改进。http://jsperf.com/switch-vs-object-literal-vs-module 值得注意的是,改进可以这里看到: https://github.com/rwldrn/idiomatic.js/issues/13 ```javascript // 7.A.1.1 // switch 语句示例 switch( foo ) { case "alpha": alpha(); break; case "beta": beta(); break; default: // 默认分支 break; } // 7.A.1.2 // 一个可支持组合、重用的方法是使用一个对象来存储 “cases”, // 使用一个 function 来做委派: var cases, delegator; // 返回值仅作说明用 cases = { alpha: function() { // 语句 // 一个返回值 return [ "Alpha", arguments.length ]; }, beta: function() { // 语句 // 一个返回值 return [ "Beta", arguments.length ]; }, _default: function() { // 语句 // 一个返回值 return [ "Default", arguments.length ]; } }; delegator = function() { var args, key, delegate; // 把 `argument` 转换成数组 args = [].slice.call( arguments ); // 从 `argument` 中抽出最前一个值 key = args.shift(); // 调用默认分支 delegate = cases._default; // 从对象中对方法进行委派操作 if ( cases.hasOwnProperty( key ) ) { delegate = cases[ key ]; } // arg 的作用域可以设置成特定值, // 这种情况下,|null| 就可以了 return delegate.apply( null, args ); }; // 7.A.1.3 // 使用 7.A.1.2 中的 API: delegator( "alpha", 1, 2, 3, 4, 5 ); // [ "Alpha", 5 ] // 当然 `case` key 的值可以轻松地换成任意值 var caseKey, someUserInput; // 有没有可能是某种形式的输入? someUserInput = 9; if ( someUserInput > 10 ) { caseKey = "alpha"; } else { caseKey = "beta"; } // 或者... caseKey = someUserInput > 10 ? "alpha" : "beta"; // 然后... delegator( caseKey, someUserInput ); // [ "Beta", 1 ] // 当然还可以这样搞... delegator(); // [ "Default", 0 ] ``` B. 提前返回值提升代码的可读性并且没有太多性能上的差别 ```javascript // 7.B.1.1 // 不好: function returnLate( foo ) { var ret; if ( foo ) { ret = "foo"; } else { ret = "quux"; } return ret; } // 好: function returnEarly( foo ) { if ( foo ) { return "foo"; } return "quux"; } ``` 8. 原生 & 宿主对象(注:其实一直觉得 Host Objects 真不应该翻译过来,这是就按一般书的写法翻出来吧) 最基本的原则是: ### 不要干任何蠢事,事情总会变好的。 为了加强这个观念,请观看这个演示: #### “一切都被允许: 原生扩展” by Andrew Dupont (JSConf2011, Portland, Oregon) http://www.everytalk.tv/talks/441-JSConf-Everything-is-Permitted-Extending-Built-ins 9. 注释 * 单行注释放于代码上方为首选 * 多行也可以 * 行末注释应被避免! * JSDoc 的方式也不错,但需要比较多的时间 10. 单用一门语言 无论是什么语言程序维护者(或团队)规定使用何种语言,程序都应只用同一种语言书写。 ## 附录 ### 前置逗号(Comma First) 所有使用这个文档作为基本风格指南的项目都不允许前置逗号的代码格式,除非明确指定或者作者要求。 ================================================ FILE: translations/zh_TW/readme.md ================================================ # 撰寫一致風格且通順易懂的 JavaScript 之原則 ## 這是一份持續更新的文件,歡迎任何對於增進本文件內程式碼的想法。參與貢獻:fork、clone、branch、commit、push、pull、pull request。 * Rick Waldron [@rwaldron](http://twitter.com/rwaldron), [github](https://github.com/rwldrn) * Mathias Bynens [@mathias](http://twitter.com/mathias), [github](https://github.com/mathiasbynens) * Schalk Neethling [@ossreleasefeed](http://twitter.com/ossreleasefeed), [github](https://github.com/ossreleasefeed/) * Kit Cambridge [@kitcambridge](http://twitter.com/kitcambridge), [github](https://github.com/kitcambridge) * Raynos [github](https://github.com/Raynos) * Matias Arriola [@MatiasArriola](https://twitter.com/MatiasArriola), [github](https://github.com/MatiasArriola/) * John Fischer [@jfroffice](https://twitter.com/jfroffice), [github](https://github.com/jfroffice/) * Idan Gazit [@idangazit](http://twitter.com/idangazit), [github](https://github.com/idangazit) * Leo Balter [@leobalter](http://twitter.com/leobalter), [github](https://github.com/leobalter) * Breno Oliveira [@garu_rj](http://twitter.com/garu_rj), [github](https://github.com/garu) * Leo Beto Souza [@leobetosouza](http://twitter.com/leobetosouza), [github](https://github.com/leobetosouza) * Ryuichi Okumura [@okuryu](http://twitter.com/okuryu), [github](https://github.com/okuryu) * Pascal Precht [@PascalPrecht](http://twitter.com/PascalPrecht), [github](https://github.com/pascalprecht) * EngForDev [engfordev](http://www.opentutorials.org/course/167/1363) - Hwan Min Hong / MinTaek Kwon [@leoinsight](http://twitter.com/leoinsight) / Tw Shim [@marocchino](http://twitter.com/marocchino), [github](https://github.com/marocchino) / Nassol Kim [@nassol99](http://twitter.com/nassol99), [github](https://github.com/nassol) / Juntai Park [@rkJun](http://twitter.com/rkJun), [github](https://github.com/rkJun) / Minkyu Shim / Gangmin Won / Justin Yoo [@justinchronicle](http://twitter.com/justinchronicle) / Daeyup Lee * Marco Trulla [@marcotrulla](http://twitter.com/marcotrulla), [github](https://github.com/Ragnarokkr) * Alex Navasardyan [@alexnavasardyan](http://twitter.com/alexnavasardyan), [github](https://github.com/2k00l) * Mihai Paun [@mihaipaun](http://twitter.com/mihaipaun), [github](https://github.com/mihaipaun) * Evgeny Mandrikov [@\_godin\_](http://twitter.com/_godin_), [github](https://github.com/Godin) * Sofish Lin [@sofish](http://twitter.com/sofish), [github](https://github.com/sofish) * Дејан Димић [@dejan_dimic](http://twitter.com/dejan_dimic), [github](https://github.com/rubystream) * Miloš Gavrilović [@gavrisimo](http://twitter.com/gavrisimo), [github](https://github.com/gavrisimo) * Duc Nguyen [@ducntq](https://twitter.com/ducntq), [github](https://github.com/ducntq) * James Young [@jamsyoung](http://twitter.com/jamsyoung), [github](https://github.com/jamsyoung) * Hao-Wei Jeng [@l0ckys](http://twitter.com/l0ckys), [github](https://github.com/lockys) * Stephane Moreau [github](https://github.com/stmoreau) * Boris Nekezov [github](https://github.com/boris-nekezov) * Akshat Joshi [@akshat_joshi](http://twitter.com/akshat_joshi), [github](https://https://github.com/akshatjoshii) ## 不論有多少人在撰寫同一個程式庫,所有在此程式庫的程式看起來都是由一個人寫的。 ### 在下面清單中列出了應用在作者是我的程式之一些撰寫規則。任何對於我建立的建案的貢獻都必須遵守這些規則。 ### 我並不是強制別人使用我的程式撰寫風格在別人的專案中或程式中;如果某專案已經存在一個一致的程式撰寫風格,它應該要被遵從與尊重。 > ### "對於風格的爭論是沒有意義的。它們應該是一種風格的指南,且你也應該要遵守。" >_Rebecca_ _Murphey_   > ### "要成為一個成功專案的好管理者,有一個因素是你必須要了解到總是以自己的風格寫程式碼是一個不好的做法。 如果有成千上萬的人在使用你的程式碼,那請用通俗易懂的方式來寫你的程式碼,而不是自作聰明地用自己的撰寫風格。" >_Idan_ _Gazit_ ## 多語言翻譯 * [ORIGINAL](https://github.com/rwldrn/idiomatic.js/) * [Bulgarian](https://github.com/rwldrn/idiomatic.js/tree/master/translations/bg_BG) * [German](https://github.com/rwldrn/idiomatic.js/tree/master/translations/de_DE) * [French](https://github.com/rwldrn/idiomatic.js/tree/master/translations/fr_FR) * [Spanish](https://github.com/rwldrn/idiomatic.js/tree/master/translations/es_ES) * [Portuguese - Brazil](https://github.com/rwldrn/idiomatic.js/tree/master/translations/pt_BR) * [Korean](https://github.com/rwldrn/idiomatic.js/tree/master/translations/ko_KR) * [Japanese](https://github.com/rwldrn/idiomatic.js/tree/master/translations/ja_JP) * [Italian](https://github.com/rwldrn/idiomatic.js/tree/master/translations/it_IT) * [Russian](https://github.com/rwldrn/idiomatic.js/tree/master/translations/ru_RU) * [Romanian](https://github.com/rwldrn/idiomatic.js/tree/master/translations/ro_RO) * [简体中文](https://github.com/rwldrn/idiomatic.js/tree/master/translations/zh_CN) * [Serbian - cyrilic alphabet](https://github.com/rwldrn/idiomatic.js/tree/master/translations/ср_СР) * [Serbian - latin aplphabet](https://github.com/rwldrn/idiomatic.js/tree/master/translations/sr_SR) * [繁體中文](https://github.com/rwldrn/idiomatic.js/tree/master/translations/zh_TW) * [Greek](https://github.com/rwaldron/idiomatic.js/tree/master/translations/gr_GR) * [Hindi](https://github.com/rwaldron/idiomatic.js/tree/master/translations/hi_HI) ## 重要的、通用的資源: > 建議搭配英文版一同閱讀,有些程式專有名詞翻譯成中文或許無法很好地表達出原意。 ### 程式品質工具、資源與參考文獻 * [JavaScript Plugin](http://docs.codehaus.org/display/SONAR/JavaScript+Plugin) for [Sonar](http://www.sonarsource.org/) * [jsPerf](http://jsperf.com/) * [jsFiddle](http://jsfiddle.net/) * [jsbin](http://jsbin.com/) * [JavaScript Lint (JSL)](http://javascriptlint.com/) * [jshint](http://jshint.com/) * [jslint](http://jslint.org/) * [Editorconfig](http://editorconfig.org/) ## 變得更聰明! ### [ECMAScript 5.1 註解版](http://es5.github.com/) ### [EcmaScript 語言規範, 5.1 版](http://ecma-international.org/ecma-262/5.1/) 下列文件應該被視為:1)不完全版的,2)*必讀的*。我並不全然贊同下列作者們所撰寫的風格,但是可以確定的一點是:它們有一致性。此外,他們也都是這個語言界的權威專家。 * [Baseline For Front End Developers](http://rmurphey.com/blog/2012/04/12/a-baseline-for-front-end-developers/) * [Eloquent JavaScript](http://eloquentjavascript.net/) * [JavaScript, JavaScript](http://javascriptweblog.wordpress.com/) * [Adventures in JavaScript Development](http://rmurphey.com/) * [Perfection Kills](http://perfectionkills.com/) * [Douglas Crockford's Wrrrld Wide Web](http://www.crockford.com) * [JS Assessment](https://github.com/rmurphey/js-assessment) * [Leveraging Code Quality Tools by Anton Kovalyov](http://anton.kovalyov.net/slides/gothamjs/) ### 建置與部署的過程 專案應該總是要包含一些通用的方法,使得程式能夠被檢驗、測試或壓縮以為產品正式上線做準備。針對此類的工作,由 Ben Alman 所開發的 [grunt](https://github.com/cowboy/grunt) 是一個非常棒的工具,並且已經正式地取代這個程式庫下的 "kits/" 目錄。 ### 測試工具 專案 _必須_ 包含某種單元、基準、執行與功能性的測試。使用案例(use case)的展示並不能被視為 "測試"。 下面列出一些測試用的框架,誰都不是誰更好的替代品(None of which are endorsed more than the other)。 * [QUnit](http://github.com/jquery/qunit) * [Jasmine](https://github.com/pivotal/jasmine) * [Vows](https://github.com/cloudhead/vows) * [Mocha](https://github.com/visionmedia/mocha) * [Hiro](http://hirojs.com/) * [JsTestDriver](https://code.google.com/p/js-test-driver/) * [Buster.js](http://busterjs.org/) * [Sinon.js](http://sinonjs.org/) ## 目錄 * [空格 (Whitespace)](#whitespace) * [漂亮的語法 (Beautiful Syntax)](#spacing) * [型別檢測 (Courtesy jQuery Core Style Guidelines)](#type) * [條件語句之評估 (Conditional Evaluation)](#cond) * [實用的撰寫風格 (Practical Style)](#practical) * [命名](#naming) * [其他雜項的規定、風格 Misc](#misc) * [原生與宿主物件 Native & Host Object](#native) * [註解 (Comments)](#comments) * [使用單一語言 (One Language Code)](#language) ------------------------------------------------ ## 前言 下面章節所講的是一個 _合理_ 的現代 JavaScript 開發風格指南,目的並不是要做硬性規範。最重要的目的是要傳達*高度一致性的程式撰寫風格法則*(the law of code style consistency)。你為你的專案所選擇的撰寫風格都應該被視為最高準則。在你的專案中連結此份文件作為程式撰寫風格之一致性、可讀性以及可維護性的保證。 ## 慣例風格宣言 1. 空格 - 永遠不要混用空格與 Tab - 在開始一個專案,還沒寫程式碼之前,選擇一種縮排方式,空格或 real Tab,並將它視為**最高準則**。 - 為了程式的可讀性, 我總推薦設定你的編輯器的縮排為兩個字元的寬度 — 這代表兩個空白或以兩個空白代表 Tab。 - 如果你的編輯器有支援的話,請一定要打開 "顯示不可見字元" 的設定。這個慣例的好處是: - 保證一致性 - 去掉行尾的空格 - 去掉空行的空格 - 提交與差異對比更具有可讀性 2. 漂亮的語法 A. 小括號、大括號、換行 ```javascript // if/else/for/while/try 總是有要有小括號、大括號與換行 // 這對於可讀性有幫助 // 2.A.1.1 // 不好辨認的語法(cramped syntax)範例 if(condition) doSomething(); while(condition) iterating++; for(var i=0;i<100;i++) someIterativeFn(); // 2.A.1.1 // 善用空格來提升可讀性 if ( condition ) { // 敘述、程式邏輯 } while ( condition ) { // 敘述、程式邏輯 } for ( var i = 0; i < 100; i++ ) { // 敘述、程式邏輯 } // 更好的作法: var i, length = 100; for ( i = 0; i < length; i++ ) { // 敘述、程式邏輯 } // 或者是... var i = 0, length = 100; for ( ; i < length; i++ ) { // 敘述、程式邏輯 } var prop; for ( prop in object ) { // 敘述、程式邏輯 } if ( true ) { // 敘述、程式邏輯 } else { // 敘述、程式邏輯 } ``` B. 賦予值, 宣告, 函式 ( 命名函式, 函式表達式 (Expression), 建構函式 (constructor) ) ```javascript // 2.B.1.1 // 變數 var foo = "bar", num = 1, undef; // 實字表示 (Literal notations): var array = [], object = {}; // 2.B.1.2 // 在一個函式内只使用一個 `var` 有助於提升可讀性 // 並且讓你的宣告列表更加的整齊 (還幫你少敲了幾次鍵盤) // 不好的做法 var foo = ""; var bar = ""; var qux; // 好的做法 var foo = "", bar = "", quux; // 或者是.. var // 對這些變數下註解 foo = "", bar = "", quux; // 2.B.1.3 // `var` 描述應該總要在函式作用域的頂端 // 不好的做法 function foo() { // 在變數前有些程式邏輯、敘述 var bar = "", qux; } // 好的做法 function foo() { var bar = "", qux; // 所有程式邏輯或敘述要在變數之後 } // 2.B.1.4 // ECMAScript 6 的 const 和 let , 也應該要在作用域的頂端 (區塊). // 不好的做法 function foo() { let foo, bar; if ( condition ) { bar = ""; // 程式邏輯、敘述 } } // 好的做法 function foo() { let foo; if ( condition ) { let bar = ""; // 程式邏輯、敘述 } } ``` ```javascript // 2.B.2.1 // 命名函式的宣告 function foo( arg1, argN ) { } // 使用方法 foo( arg1, argN ); // 2.B.2.2 // 命名函式的宣告 function square( number ) { return number * number; } // 使用方法 square( 10 ); // 2.B.2.3 // 函式表達式 var square = function( number ) { // 回傳相關數值 return number * number; }; // 具有名字的函式表達式 // 這種宣告形式的好處是它可以呼叫自己 // 並在程式出錯時的 stack trace 具有名字 var factorial = function factorial( number ) { if ( number < 2 ) { return 1; } return number * factorial( number-1 ); }; // 2.B.2.4 // 建構函式 function FooBar( options ) { this.options = options; } // 使用方法 var fooBar = new FooBar({ a: "alpha" }); fooBar.options; // { a: "alpha" } ``` C. 例外, 一些細節 ```javascript // 2.C.1.1 // 具有回呼 (callback) 的函式 foo(function() { // 注意在呼叫之函式的第一個小括號與 `function` 之間沒有空格 }); // 函式可傳入 `array` 作為參數,沒有空格 foo([ "alpha", "beta" ]); // 2.C.1.2 // 函式可傳入 `object` 作為參數,沒有空格 foo({ a: "alpha", b: "beta" }); // 函式可傳入 `string` 實字作為參數,沒有空格 foo("bar"); // 在外部的小括號內部包住條件式 (condition) 的小括號,没有空格 if ( !("foo" in obj) ) { } ``` D. 保持一致性是無庸置疑的(Consistency Always Wins) 在 2.A-2.C 章節中,我們建議以空格(留白)規則來撰寫程式,為了是一個更簡單的、更高的目標:一致性。值得注意的是對於程式排版的偏好,譬如"在內部的空格"是可選擇的,但是在整個專案中的程式碼中必須只遵守一種風格。 ```javascript // 2.D.1.1 if (condition) { // 程式邏輯、敘述 } while (condition) { // 程式邏輯、敘述 } for (var i = 0; i < 100; i++) { // 程式邏輯、敘述 } if (true) { // 程式邏輯、敘述 } else { // 程式邏輯、敘述 } ``` E. 引號 (Quote) 無論你選擇單引號或雙引號都沒關係,在 JavaScript 解析中並沒有差別。但**絕對需要**強制的還是一致性。 **永遠不要在你的專案中混用兩種引號,選擇一種,並保持一致**。 F. 行尾與空行 在行尾或空行空格(留白)會破壞變更紀錄 [changesets](https://en.wikipedia.org/wiki/Changeset) 的可讀性。請考慮加入在提交前 (pre-commit) 會自動刪除行尾以及空行空格的工具。 3. 型別檢測 (來自於 jQuery Core Style Guidelines) A. 直接型別(Actual Types) String: typeof variable === "string" Number: typeof variable === "number" Boolean: typeof variable === "boolean" Object: typeof variable === "object" Array: Array.isArray( arrayLikeObject ) (如果可能的話) Node: elem.nodeType === 1 null: variable === null null or undefined: variable == null undefined: 全域變數: typeof variable === "undefined" 區域變數: variable === undefined 屬性: object.prop === undefined object.hasOwnProperty( prop ) "prop" in object B. 轉換類型(強制型別,Coerced Types) 想想下面的含義... 给定下列的 HTML: ```html ``` ```javascript // 3.B.1.1 // `foo` 被賦予 `0`,型別是 `number` var foo = 0; // typeof foo; // "number" ... // 在之後的程式碼中,你需要更新 `foo`,賦予在 input 元素中得到的新值 foo = document.getElementById("foo-input").value; // 如果你現在測試 `typeof foo`, 結果會是 `string` // 這代表著你在 if 判斷式檢測 `foo` 時,會有以下邏輯: if ( foo === 1 ) { importantTask(); } // `importantTask()` 將永遠不會被執行到,即使 `foo` 的值是 "1" // 3.B.1.2 // 你可以巧妙地使用 + / - 一元運算符以強制轉換型別來解決此問題: foo = +document.getElementById("foo-input").value; // ^ + 一元運算符將他的右邊的運算對象轉換成 `number` // typeof foo; // "number" if ( foo === 1 ) { importantTask(); } // `importantTask()` 將會被執行到 ``` 下面是幾個強制轉換型別的範例: ```javascript // 3.B.2.1 var number = 1, string = "1", bool = false; number; // 1 number + ""; // "1" string; // "1" +string; // 1 +string++; // 1 string; // 2 bool; // false +bool; // 0 bool + ""; // "false" ``` ```javascript // 3.B.2.2 var number = 1, string = "1", bool = true; string === number; // false string === number + ""; // true +string === number; // true bool === number; // false +bool === number; // true bool === string; // false bool === !!string; // true ``` ```javascript // 3.B.2.3 var array = [ "a", "b", "c" ]; !!~array.indexOf("a"); // true !!~array.indexOf("b"); // true !!~array.indexOf("c"); // true !!~array.indexOf("d"); // false // 值得注意的是上面例子都有點 "不必要的聰明" // 請使用較明確的方法來比較 indexOf 回傳的值 if ( array.indexOf( "a" ) >= 0 ) { // ... } ``` ```javascript // 3.B.2.3 var num = 2.5; parseInt( num, 10 ); // 等於... ~~num; num >> 0; num >>> 0; // 结果都是 2 // 請時時刻刻牢記在心裡, 負數將被特別對待... var neg = -2.5; parseInt( neg, 10 ); // 等於... ~~neg; neg >> 0; // 结果都是 -2 // 但是... neg >>> 0; // 结果就是 4294967294 ``` 4. 條件語句之評估 ```javascript // 4.1.1 // 當判斷 array 內是否有東西時,建議不要使用以下方法: if ( array.length > 0 ) ... // ... 請使用以下方式: if ( array.length ) ... // 4.1.2 // 當判斷一個 array 是否為空,建議不要使用以下方法: if ( array.length === 0 ) ... // ... 請使用以下方式: if ( !array.length ) ... // 4.1.3 // 當判斷一個 string 是否不等於空字串,建議不要使用以下方法: if ( string !== "" ) ... // ... 請使用以下方式: if ( string ) ... // 4.1.4 // 當判斷一個 string 是否等於空字串,建議不要使用以下方法: if ( string === "" ) ... // ... 請使用以下方式: if ( !string ) ... // 4.1.5 // 當判斷一個變數值是否為真,建議不要使用以下方法: if ( foo === true ) ... // ...只需這樣,享受內建功能的好處: if ( foo ) ... // 4.1.6 // 當判斷一個變數值是否為假,建議不要使用以下方法: if ( foo === false ) ... // ...使用驚嘆號 (negation) 將判斷式整體轉為真值 if ( !foo ) ... // ...需要注意的是:這幾個數值也會符合這情況 0, "", null, undefined, NaN // 如果你 _必須_ 是布林型別的 false,請這樣使用: if ( foo === false ) ... // 4.1.7 // 當想判斷一個變數為 null 或者 undefined,但不是 false, "" 或者 0, // 請不要使用: if ( foo === null || foo === undefined ) ... // ...享受 == 型別轉換的好處,像是這樣: if ( foo == null ) ... // 請記住,使用 == 將會使 `null` 等於 `null` 和 `undefined` // 但不是 `false`,"" 或者 0 null == undefined // true ``` 總是判斷最好、最精確的數值,上述是指南而非教條。 ```javascript // 4.2.1 // 型別轉換和比較運算符说明 // 首重 `===`,`==` 次之 (除非需要鬆散型別的比較) // `===` 不會做型別轉換,這代表著: "1" === 1; // false // `==` 會先轉換型別,這代表著: "1" == 1; // true // 4.2.2 // 布林, 真 & 假 // 布林: true, false // 真: "foo", 1 // 假: "", 0, null, undefined, NaN, void 0 ``` 5. 實用的撰寫風格 ```javascript // 5.1.1 // 一個實用的模組 (function( global ) { var Module = (function() { var data = "secret"; return { // 這是一個布林值 bool: true, // 一個字串 string: "a string", // 一個數字陣列 array: [ 1, 2, 3, 4 ], // 一個物件 object: { lang: "en-Us" }, getData: function() { // 取得 `data` 的值 return data; }, setData: function( value ) { // 回傳賦予值過的 `data` 值 return ( data = value ); } }; })(); // 其他一些程式邏輯敘述將會在這... // 把你的模組變成全域物件 global.Module = Module; })( this ); ``` ```javascript // 5.2.1 // 一個實用的建構函式 (function( global ) { function Ctor( foo ) { this.foo = foo; return this; } Ctor.prototype.getFoo = function() { return this.foo; }; Ctor.prototype.setFoo = function( val ) { return ( this.foo = val ); }; // 不使用 `new` 來呼叫建構函式的話,你可能會這樣做: var ctor = function( foo ) { return new Ctor( foo ); }; // 把我們的建構函式變成全域物件 global.ctor = ctor; })( this ); ``` 6. 命名 A. 你不是一個人體編譯器/壓縮器,所以不要嘗試去做編譯器/壓縮器該做的事。 下面是一個極為糟糕的命名範例: ```javascript // 6.A.1.1 // 糟糕的命名範例 function q(s) { return document.querySelectorAll(s); } var i,a=[],els=q("#foo"); for(i=0;i其他雜項的規定、風格 Misc(miscellaneous) 這一章節主要會描述一些想法與概念,而非教條。相反地,我們更鼓勵對於現有的慣例保持好奇心,進而嘗試找到更好的撰寫 JavaScript 程式的方法。 A. 避免使用 `switch`,現代方法追蹤(method tracing)將會把含有 switch 敘述的函式列為黑名單。 似乎在最新版本的 Firefox 和 Chrome 都對於 `switch` 敘述有重大的改進。http://jsperf.com/switch-vs-object-literal-vs-module 值得注意的是,改進可以在此連結看到: https://github.com/rwldrn/idiomatic.js/issues/13 ```javascript // 7.A.1.1 // switch 敘述範例 switch( foo ) { case "alpha": alpha(); break; case "beta": beta(); break; default: // 預設的邏輯敘述 break; } // 7.A.1.2 // 一個具有組合性與重複使用性的替代方法是使用物件來儲存 "cases" // 並使用一個 function 来做委派: var cases, delegator; // 回傳值僅作說明用的範例 cases = { alpha: function() { // 邏輯敘述 // 一個回傳值 return [ "Alpha", arguments.length ]; }, beta: function() { // 邏輯敘述 // 一個回傳值 return [ "Beta", arguments.length ]; }, _default: function() { // 邏輯敘述 // 一個回傳值 return [ "Default", arguments.length ]; } }; delegator = function() { var args, key, delegate; // 把 `argument` 轉換為陣列 args = [].slice.call( arguments ); // 從 `argument` 中拿出第一個值 key = args.shift(); // 使用預設的 case (Default) delegate = cases._default; // 從物件中取得方法並委派執行方法 if ( cases.hasOwnProperty( key ) ) { delegate = cases[ key ]; } // arg 的作用域可以設成特定值, // 在這種情況下,設成 |null| 就可以了 return delegate.apply( null, args ); }; // 7.A.1.3 // 使用 7.A.1.2 中的 API: delegator( "alpha", 1, 2, 3, 4, 5 ); // [ "Alpha", 5 ] // 當然 `case` key 的值可以輕鬆地根據一些其他不同的情況而做設定。 var caseKey, someUserInput; // 有可能是某表單的輸入? someUserInput = 9; if ( someUserInput > 10 ) { caseKey = "alpha"; } else { caseKey = "beta"; } // 或者... caseKey = someUserInput > 10 ? "alpha" : "beta"; // 然後... delegator( caseKey, someUserInput ); // [ "Beta", 1 ] // 當然你還可以這樣做... delegator(); // [ "Default", 0 ] ``` B. 提前回傳值可提升可讀性,且對於性能不怎麼有影響 ```javascript // 7.B.1.1 // 不好的做法: function returnLate( foo ) { var ret; if ( foo ) { ret = "foo"; } else { ret = "quux"; } return ret; } // 好的做法: function returnEarly( foo ) { if ( foo ) { return "foo"; } return "quux"; } ``` 8. 原生 & 宿主物件 (Host Objects) 基本的原則是: ### 不要做蠢事,Everything will be ok! 為了加深這個概念,請看看以下的演講: #### “一切都被允许: 擴展內建的方法或物件..等” by Andrew Dupont (JSConf2011, Portland, Oregon) https://www.youtube.com/watch?v=xL3xCO7CLNM 9. 註解 * 單行的註解放在程式碼上面是首選 * 多行也可以 * 避免行尾的註解! * JSDoc 的註解方式也不錯,但就需要花比較多時間。 10. 使用單一語言 無論是什麼語言的維護者(或者團隊)規定使用什麼語言,程式應該都使用同一種語言撰寫。 ## 附錄 ### 逗號前置(Comma First) 所有使用本文件作為風格指南的專案都不允許逗號優先的撰寫風格,除非專案作者有明確的指定或者要求。 ---------- Creative Commons License
Principles of Writing Consistent, Idiomatic JavaScript by Rick Waldron and Contributors is licensed under a Creative Commons Attribution 3.0 Unported License.
Based on a work at github.com/rwldrn/idiomatic.js. ================================================ FILE: translations/ср_СР/readme.md ================================================ # Принципи писања Конзистентног, Идиоматског JavaScript-а ## Ово је "жив" документ и нове идеје за унапређење кода око нас су увек добродошле. Допринесите: fork, clone, branch, commit, push, pull request. * Rick Waldron [@rwaldron](http://twitter.com/rwaldron), [github](https://github.com/rwaldron) * Mathias Bynens [@mathias](http://twitter.com/mathias), [github](https://github.com/mathiasbynens) * Schalk Neethling [@ossreleasefeed](http://twitter.com/ossreleasefeed), [github](https://github.com/ossreleasefeed/) * Kit Cambridge [@kitcambridge](http://twitter.com/kitcambridge), [github](https://github.com/kitcambridge) * Raynos [github](https://github.com/Raynos) * Matias Arriola [@MatiasArriola](https://twitter.com/MatiasArriola), [github](https://github.com/MatiasArriola/) * John Fischer [@jfroffice](https://twitter.com/jfroffice), [github](https://github.com/jfroffice/) * Idan Gazit [@idangazit](http://twitter.com/idangazit), [github](https://github.com/idangazit) * Leo Balter [@leobalter](http://twitter.com/leobalter), [github](https://github.com/leobalter) * Breno Oliveira [@garu_rj](http://twitter.com/garu_rj), [github](https://github.com/garu) * Leo Beto Souza [@leobetosouza](http://twitter.com/leobetosouza), [github](https://github.com/leobetosouza) * Ryuichi Okumura [@okuryu](http://twitter.com/okuryu), [github](https://github.com/okuryu) * Pascal Precht [@PascalPrecht](http://twitter.com/PascalPrecht), [github](https://github.com/pascalprecht) * EngForDev [engfordev](http://www.opentutorials.org/course/167/1363) - Hwan Min Hong / MinTaek Kwon [@leoinsight](http://twitter.com/leoinsight) / Tw Shim [@marocchino](http://twitter.com/marocchino), [github](https://github.com/marocchino) / Nassol Kim [@nassol99](http://twitter.com/nassol99), [github](https://github.com/nassol) / Juntai Park [@rkJun](http://twitter.com/rkJun), [github](https://github.com/rkJun) / Minkyu Shim / Gangmin Won / Justin Yoo [@justinchronicle](http://twitter.com/justinchronicle) / Daeyup Lee * Marco Trulla [@marcotrulla](http://twitter.com/marcotrulla), [github](https://github.com/Ragnarokkr) * Alex Navasardyan [@alexnavasardyan](http://twitter.com/alexnavasardyan), [github](https://github.com/2k00l) * Mihai Paun [@mihaipaun](http://twitter.com/mihaipaun), [github](https://github.com/mihaipaun) * Дејан Димић [@dejan_dimic](http://twitter.com/dejan_dimic), [github](https://github.com/rubystream) * Duc Nguyen [@ducntq](https://twitter.com/ducntq), [github](https://github.com/ducntq) * James Young [@jamsyoung](http://twitter.com/jamsyoung), [github](https://github.com/jamsyoung) * Hao-Wei Jeng [@l0ckys](http://twitter.com/l0ckys), [github](https://github.com/lockys) * Stephane Moreau [github](https://github.com/stmoreau) * Boris Nekezov [github](https://github.com/boris-nekezov) ## Сав код у било којој "бази кода" требало би да изгледа као да га је написала једна особа, без обзира колико је људи допринело његовом креирању. ### Листа која следи уоквирује праксу коју ја примењујем у свом коду, чији сам ја оригинални аутор. Сарадници, на пројектима које сам ја креирао, би требало да се придржавају ових упутстава. ### Ја немам намеру да намећем своје особине стила на код или пројекте других људи, ако већ постоји заједнички стил, он мора бити поштован. > ### "Аргументи око стила немају смисла. Потребно је да постоји упутство коришћења стила, и ти би требало да га се придржаваш." >_Rebecca_ _Murphey_   > ### "Део улоге доброг управника успешног пројекта је и у разумевању да писање кода по својим мерилима је Лоша Идеја™. Ако хиљаде људи користи твој код, онда пиши најјаснији код, а не према својим личним преференцијама или да са жељом да испаднеш паметан у оквирима спецификације." >_Idan_ _Gazit_ ## Преводи * [ORIGINAL](https://github.com/rwldrn/idiomatic.js/) * [Bulgarian](https://github.com/rwldrn/idiomatic.js/tree/master/translations/bg_BG) * [German](https://github.com/rwldrn/idiomatic.js/tree/master/translations/de_DE) * [French](https://github.com/rwldrn/idiomatic.js/tree/master/translations/fr_FR) * [Spanish](https://github.com/rwldrn/idiomatic.js/tree/master/translations/es_ES) * [Portuguese - Brazil](https://github.com/rwldrn/idiomatic.js/tree/master/translations/pt_BR) * [Korean](https://github.com/rwldrn/idiomatic.js/tree/master/translations/ko_KR) * [Japanese](https://github.com/rwldrn/idiomatic.js/tree/master/translations/ja_JP) * [Italian](https://github.com/rwldrn/idiomatic.js/tree/master/translations/it_IT) * [Russian](https://github.com/rwldrn/idiomatic.js/tree/master/translations/ru_RU) * [Romanian](https://github.com/rwldrn/idiomatic.js/tree/master/translations/ro_RO) * [简体中文](https://github.com/rwldrn/idiomatic.js/tree/master/translations/zh_CN) * [Serbian - cyrilic alphabet](https://github.com/rwldrn/idiomatic.js/tree/master/translations/ср_СР) * [Serbian - latin aplphabet](https://github.com/rwldrn/idiomatic.js/tree/master/translations/sr_SR) * [繁體中文](https://github.com/rwldrn/idiomatic.js/tree/master/translations/zh_TW) * [Greek](https://github.com/rwaldron/idiomatic.js/tree/master/translations/gr_GR) ## Важне, Не-Идиоматске ствари: ### Алати за проверавање квалитета кода, Извори и Литература * [JavaScript Plugin](http://docs.codehaus.org/display/SONAR/JavaScript+Plugin) for [Sonar](http://www.sonarsource.org/) * [Plato](https://github.com/jsoverson/plato) * [jsPerf](http://jsperf.com/) * [jsFiddle](http://jsfiddle.net/) * [jsbin](http://jsbin.com/) * [JavaScript Lint (JSL)](http://javascriptlint.com/) * [jshint](http://jshint.com/) * [jslint](http://jslint.org/) * [Editorconfig](http://editorconfig.org/) ## Будите паметнији ### [Annotated ECMAScript 5.1](http://es5.github.com/) ### [EcmaScript Language Specification, 5.1 Edition](http://ecma-international.org/ecma-262/5.1/) Следеће треба сматрати за 1) непотпуну, и 2) *ОБАВЕЗНА ЛЕКТИРА*. Ја се не слажем увек са стилом писаног од стране аутора у наставку, али једна ствар је сигурна: Они су доследни. Осим тога, то су ауторитети у овом језику. * [Baseline For Front End Developers](http://rmurphey.com/blog/2012/04/12/a-baseline-for-front-end-developers/) * [Eloquent JavaScript](http://eloquentjavascript.net/) * [JavaScript, JavaScript](http://javascriptweblog.wordpress.com/) * [Adventures in JavaScript Development](http://rmurphey.com/) * [Perfection Kills](http://perfectionkills.com/) * [Douglas Crockford's Wrrrld Wide Web](http://www.crockford.com) * [JS Assessment](https://github.com/rmurphey/js-assessment) * [Leveraging Code Quality Tools by Anton Kovalyov](http://anton.kovalyov.net/slides/gothamjs/) ### Build & Deployment Процес Пројекти би требало да увек садрже неки вид генеричких алата помоћу којих код може бити прочишћен, тестиран и компримован у процесу примпреме за продукциону примену. За овај задатак, [grunt](https://github.com/cowboy/grunt) од Ben Alman-а је одличан и званично је заменио "kits/" директоријум овог репозиторијума. ### Погон за тестирање Пројекти _морају_ да укључе неку форму 'unit', 'reference', 'implementation' или 'functional' тестирања. 'Use case' демои се НЕ КВАЛИФИКУЈУ као "тестови". Следи листа алата за тестирање, ниједан од њих није прихваћенији од других. * [QUnit](http://github.com/jquery/qunit) * [Jasmine](https://github.com/pivotal/jasmine) * [Vows](https://github.com/cloudhead/vows) * [Mocha](https://github.com/visionmedia/mocha) * [Hiro](http://hirojs.com/) * [JsTestDriver](https://code.google.com/p/js-test-driver/) * [Buster.js](http://busterjs.org/) * [Sinon.js](http://sinonjs.org/) ## Садржај * [Белине (Whitespace)](#whitespace) * [Лепа Синтакса](#spacing) * [Провера типа (Захвалница jQuery Core Style Guidelines)](#type) * [Условна евалуација](#cond) * [Практичан Стил](#practical) * [Именовање](#naming) * [Разно](#misc) * [Native и Host Објекти](#native) * [Коментари](#comments) * [Код у једном језику](#language) ------------------------------------------------ ## Предговор Следеће секције оцртавају _разуман_ водич за стил модерног JavaScript развоја и није им намера да буду преопширне. Најзначајнија порука је **закон о коезистентности стила писања кода**. Шта год да изаберете као стил за ваш пројекат то треба сматрати законом. Повежите овај документ као изјаву вашег пројекта коезистентности стила писања кода, читљивости и лакоћи одржавања истог. ## Идиоматски Манифест Стила 1. Белине (Whitespace) - Никада не мешајте размаке и табулаторе. - Када започињете пројекат, пре него што напишете и једну линију кода, изаберите између размака (spaces) и табулатора и ово третирајте као **закон**. - Ради читљивости, ја увек препоручујем да поставите увлачење вашег едитора на два карактера — ово представља два размака или таб величине два размака. - Уколико ваш едитор подржава, увек радите са укљученом опцијом "show invisibles". Користи од ове праксе су: - Наметнута коезистентност - Елиминисање непотребних размака на крају реда - Елиминисање непотребних размака у празним редовима - Commits и diffs команде које се лакше читају 2. Лепа Синтакса A. Размаци, Заграде, Нови Ред ```javascript // if/else/for/while/try увек имају размаке, заграде и простиру се на више редова // ово подстиче читљивост // 2.A.1.1 // Примери стварно скучене синтаксе if(condition) doSomething(); while(condition) iterating++; for(var i=0;i<100;i++) someIterativeFn(); // 2.A.1.1 // Користите белине да би промовисали читљивост if ( condition ) { // statements } while ( condition ) { // statements } for ( var i = 0; i < 100; i++ ) { // statements } // Још боље: var i, length = 100; for ( i = 0; i < length; i++ ) { // statements } // Или... var i = 0, length = 100; for ( ; i < length; i++ ) { // statements } var prop; for ( prop in object ) { // statements } if ( true ) { // statements } else { // statements } ``` B. Додела вредности, Декларације, Функције ( Именоване, Изрази, Конструктор ) ```javascript // 2.B.1.1 // Промењиве var foo = "bar", num = 1, undef; // Словна нотација: var array = [], object = {}; // 2.B.1.2 // Коришћење само једне `var` декларације по области важења (function) промовише читљивост // и одржава вашу листу декларација чисту од насумичног (а штеди и неколико куцања по тастерима) // Лоше var foo = ""; var bar = ""; var qux; // Добро var foo = "", bar = "", quux; // Или.. var // Коментар о овима foo = "", bar = "", quux; // 2.B.1.3 // var декларације би увек требало да се налазе на почетку њихове области важења (function). // Ово исто важи и за const и let из ECMAScript 6. // Лоше function foo() { // some statements here var bar = "", qux; } // Добро function foo() { var bar = "", qux; // all statements after the variables declarations. } ``` ```javascript // 2.B.2.1 // Декларација Именоване Функције function foo( arg1, argN ) { } // Коришћење foo( arg1, argN ); // 2.B.2.2 // Декларација Именоване Функције function square( number ) { return number * number; } // Коришћење square( 10 ); // Веома измишљен стил преношења параметара function square( number, callback ) { callback( number * number ); } square( 10, function( square ) { // callback statements }); // 2.B.2.3 // Функциони израз var square = function( number ) { // Return something valuable and relevant return number * number; }; // Функциони израз са одређивачем // Овај пожељни облик има додату вредност да може // да позове себе и има идентитет у stack traces: var factorial = function factorial( number ) { if ( number < 2 ) { return 1; } return number * factorial( number-1 ); }; // 2.B.2.4 // Декларација Конструктора function FooBar( options ) { this.options = options; } // Коришћење var fooBar = new FooBar({ a: "alpha" }); fooBar.options; // { a: "alpha" } ``` C. Изузетци, Мала одступања ```javascript // 2.C.1.1 // Функције са повратним позивима (callbacks) foo(function() { // Забележите да нема додатог размака између прве заграде // позива функције која се извршава и речи "function" }); // Функција која прихвата низ, без размака foo([ "alpha", "beta" ]); // 2.C.1.2 // Функција која прихвата објекат, без размака foo({ a: "alpha", b: "beta" }); // Један текстуални аргумент, без размака foo("bar"); // Унутрашње груписање заграда, без размака if ( !("foo" in obj) ) { } ``` D. Козистентност увек побеђује У секцијама 2.A-2.C, правила коришћења белина су постављена као препорука са једноставнијом, вишом наменом: конзсистентност. Важно је да се нагласи да преференце форматирања, као што су "унутрашње белине", се могу сматрати опционим, али само један стил би требало да се примењује кроз цео код вашег пројекта. ```javascript // 2.D.1.1 if (condition) { // statements } while (condition) { // statements } for (var i = 0; i < 100; i++) { // statements } if (true) { // statements } else { // statements } ``` E. Наводници Све једно да ли преферирате једноструке или двоструке наводнике, не постоји разлика како их JavaScript парсира. Оно што се **АПСОЛУТНО МОРА** наметнути је конзистентност. **Никада не мешати различите наводнике у истом пројекту. Изаберите један стил и држите се њега.** F. Крај Реда и Празни редови Белине могу упропастити diff команде и учинити их нечитљивим. Размотрите укључивање pre-commit hook који аутоматски уклања белине на крају реда и белине у празним редовима. 3. Провера типа (Захвалница jQuery Core Style Guidelines) A. Стварни типови String: typeof variable === "string" Number: typeof variable === "number" Boolean: typeof variable === "boolean" Object: typeof variable === "object" Array: Array.isArray( arrayLikeObject ) (wherever possible) Node: elem.nodeType === 1 null: variable === null null or undefined: variable == null undefined: Глобалне промењиве: typeof variable === "undefined" Локалне промењиве: variable === undefined Особине: object.prop === undefined object.hasOwnProperty( prop ) "prop" in object B. Имплицитна конверзија типа Размислите о импликацијама следећег... За дати HTML: ```html ``` ```javascript // 3.B.1.1 // `foo` је декларисана са вредношћу `0` и њен тип је `number` var foo = 0; // typeof foo; // "number" ... // Негде касније у вашем коду, желите да освежите `foo` // са новом вредношћу која је дошла из улазног елемента foo = document.getElementById("foo-input").value; // Ако би сада тестирали `typeof foo`, резултат би био `string` // Ово значи да ако имате логику које проверава `foo` као: if ( foo === 1 ) { importantTask(); } // `importantTask()` никада не би био извршен, чак и када `foo` има вредност "1" // 3.B.1.2 // Можете предупредити проблеме користећи паметну имплицитну конверзију типа са унарним + or - операторима: foo = +document.getElementById("foo-input").value; // ^ унарни + оператор ће конвертовати свој десни операнд у број // typeof foo; // "number" if ( foo === 1 ) { importantTask(); } // `importantTask()` ће бити позван ``` Ово неколико уобичајених примера са konverzijom типа: ```javascript // 3.B.2.1 var number = 1, string = "1", bool = false; number; // 1 number + ""; // "1" string; // "1" +string; // 1 +string++; // 1 string; // 2 bool; // false +bool; // 0 bool + ""; // "false" ``` ```javascript // 3.B.2.2 var number = 1, string = "1", bool = true; string === number; // false string === number + ""; // true +string === number; // true bool === number; // false +bool === number; // true bool === string; // false bool === !!string; // true ``` ```javascript // 3.B.2.3 var array = [ "a", "b", "c" ]; !!~array.indexOf("a"); // true !!~array.indexOf("b"); // true !!~array.indexOf("c"); // true !!~array.indexOf("d"); // false // Забележите да предходно треба сматрати "непотребно паметно" // Преферирајте очигледан приступ упоређивању повратне вредности // indexOf, као: if ( array.indexOf( "a" ) >= 0 ) { // ... } ``` ```javascript // 3.B.2.3 var num = 2.5; parseInt( num, 10 ); // је исто као... ~~num; num >> 0; num >>> 0; // Све има резултат 2 // Запамптите, негативни бројеви ће бити другачије третирани... var neg = -2.5; parseInt( neg, 10 ); // је исто као... ~~neg; neg >> 0; // Све има резултат -2 // Међутим... neg >>> 0; // ће имати резултат 4294967294 ``` 4. Условна евалуација ```javascript // 4.1.1 // Када утврђујете да низ има своју дужину, // уместо овога: if ( array.length > 0 ) ... // ...установите истинитост, овако: if ( array.length ) ... // 4.1.2 // Када утврђујете да је низ празан, // уместо овога: if ( array.length === 0 ) ... // ...установите истинитост, овако: if ( !array.length ) ... // 4.1.3 // Када утврђујете да string није празан, // уместо овога: if ( string !== "" ) ... // ...установите истинитост, овако: if ( string ) ... // 4.1.4 // када утврђујете да string _јеste_ празан, // уместо овога: if ( string === "" ) ... // ...установите неистинитост, овако: if ( !string ) ... // 4.1.5 // Када утврђујете да је референца true, // уместо овога: if ( foo === true ) ... // ...установите онако како сте то и мислили, искористите уграђене могућности: if ( foo ) ... // 4.1.6 // Када утврђујете да је референца false, // уместо овога: if ( foo === false ) ... // ...користите негацију да принудите истиниту евалуацију if ( !foo ) ... // ...Будите опрезни, ово ће исто одговарати и: 0, "", null, undefined, NaN // Ако _МОРАТЕ_ да тестирате на логичко false, користите if ( foo === false ) ... // 4.1.7 // Када само утврђујете да референца може бити null или undefined, али НЕ и false, "" или 0, // уместо овога: if ( foo === null || foo === undefined ) ... // ...искористите предност == принудне конверзије типа, овако: if ( foo == null ) ... // Упамтите, коришћење == ће одговарати `null` за `null` _I_ `undefined` // али не и за `false`, "" или 0 null == undefined ``` УВЕК утврђујте за најбољи, најтачнији резултат - предходно је смерница, а не догма. ```javascript // 4.2.1 // Забелешке око принудне конверзије типа и евалуације // Преферишите `===` у односу на `==` (осим ако случај захтева лабаву проверу типа) // === не конвертује тип, што значи да: "1" === 1; // false // == конвертује тип, што значи да: "1" == 1; // true // 4.2.2 // Логичке промењиве, Истинитост & Неистинитост // Логичке промењиве: true, false // Истинито: "foo", 1 // Неистинито: "", 0, null, undefined, NaN, void 0 ``` 5. Практичан Стил ```javascript // 5.1.1 // Практичан Модул (function( global ) { var Module = (function() { var data = "secret"; return { // Ово је нека логичка особина bool: true, // Нека текстуална вредност string: "a string", // Низ array: [ 1, 2, 3, 4 ], // Објекат object: { lang: "en-Us" }, getData: function() { // враћа текућу вредност промењиве `data` return data; }, setData: function( value ) { // поставља вредност промењиве `data` и враћа је return ( data = value ); } }; })(); // Остале ствари које се могу овде десити // изложите наш модул као глобални објекат global.Module = Module; })( this ); ``` ```javascript // 5.2.1 // Практични конструктор (function( global ) { function Ctor( foo ) { this.foo = foo; return this; } Ctor.prototype.getFoo = function() { return this.foo; }; Ctor.prototype.setFoo = function( val ) { return ( this.foo = val ); }; // да би позвали конструкторе без коришћења `new`, можете урадити ово: var ctor = function( foo ) { return new Ctor( foo ); }; // изложите наш конструктор као глобални објекат global.ctor = ctor; })( this ); ``` 6. Именовање A. Ви нисте људски компајлер/компресор кода, и не покушавајте то да будете. Следећи код је пример нечувеног именовања: ```javascript // 6.A.1.1 // Пример кода са лошим именима function q(s) { return document.querySelectorAll(s); } var i,a=[],els=q("#foo"); for(i=0;iРазно Ова секција ће служити да илуструје идеје и концепте које не треба сматрати за догмама, већ постоје да би подстакле преиспитивање пракси као покушај да се пронађе бољи начин извршавања уобичајених JavaScript програмерских задатака. A. коришћење `switch`-а треба избегавати, модерне методе праћења ће ставити на црну листу функције са switch изразима Изгледа да постоје драстична побољшања у извршавању `switch` израза у последњим издањима Firefox и Chrome. http://jsperf.com/switch-vs-object-literal-vs-module Приметна побољшања се могу уочити такође и овде: https://github.com/rwldrn/idiomatic.js/issues/13 ```javascript // 7.A.1.1 // Пример switch израза switch( foo ) { case "alpha": alpha(); break; case "beta": beta(); break; default: // подразумевана вредност break; } // 7.A.1.2 // Бољи пример би било коришћење објекта или чак модула: var switchObj = { alpha: function() { // statements // a return }, beta: function() { // statements // a return }, _default: function() { // statements // a return } }; var switchModule = (function () { return { alpha: function() { // statements // a return }, beta: function() { // statements // a return }, _default: function() { // statements // a return } }; })(); // 7.A.1.3 // Ако `foo` је особина `switchObj` или `switchModule`, извршите као метод... ( Object.hasOwnProperty.call( switchObj, foo ) && switchObj[ foo ] || switchObj._default )( args ); ( Object.hasOwnProperty.call( switchObj, foo ) && switchModule[ foo ] || switchModule._default )( args ); // Ако познајете и верујете вредности `foo`, можете изоставити и OR проверу // leaving only the execution: switchObj[ foo ]( args ); switchModule[ foo ]( args ); // Овај шаблон промовише и поновно коришћење кода. ``` B. Рано враћање вредности функција промовише читљивост кода са мањом разликом у перформансама кода ```javascript // 7.B.1.1 // Лоше: function returnLate( foo ) { var ret; if ( foo ) { ret = "foo"; } else { ret = "quux"; } return ret; } // Добро: function returnEarly( foo ) { if ( foo ) { return "foo"; } return "quux"; } ``` 8. Native & Host Објекти Основни принцип овде је: ### Не правите глупости и све ће бити у реду. Да би утврдили овај концепт, молим вас погледајте следећу презентацију: #### “Everything is Permitted: Extending Built-ins” by Andrew Dupont (JSConf2011, Portland, Oregon) https://www.youtube.com/watch?v=xL3xCO7CLNM 9. Коментари * Једна линија изнад кода који је тема * Више линија је добро * Коментари на крају реда су забрањени! * JSDoc стил је добар, али захтева значајну инвестицију у времену 10. Код у једном језику Програми би требало бити писани у једном језику, без обзира који је то језик, диктирано од стране особе или особа које одржавају код. ## Додатци ### Зарез Први. Сваки пројекат који цитира овај документ као свој основни стил неће прихватити "прво зарез" форматирање, осим ако није експлицитно наглашено од стране аутора пројекта. ---------- Creative Commons License
Principles of Writing Consistent, Idiomatic JavaScript by Rick Waldron and Contributors is licensed under a Creative Commons Attribution 3.0 Unported License.
Based on a work at github.com/rwldrn/idiomatic.js.