From 513e84a7dd9c55fe2bf23fcce42c7bec4dc44fea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ang=C3=A9llica=20Cardozo?= Date: Tue, 16 Dec 2014 19:21:30 -0200 Subject: [PATCH 001/105] Portuguese (Brazil) version Portuguese (Brazil) version --- doc/language.json | 2 +- doc/pt/array/constructor.md | 29 ++++ doc/pt/array/general.md | 59 +++++++++ doc/pt/core/delete.md | 85 ++++++++++++ doc/pt/core/eval.md | 45 +++++++ doc/pt/core/semicolon.md | 106 +++++++++++++++ doc/pt/core/undefined.md | 68 ++++++++++ doc/pt/function/arguments.md | 113 ++++++++++++++++ doc/pt/function/closures.md | 83 ++++++++++++ doc/pt/function/constructors.md | 115 ++++++++++++++++ doc/pt/function/general.md | 46 +++++++ doc/pt/function/scopes.md | 225 ++++++++++++++++++++++++++++++++ doc/pt/function/this.md | 108 +++++++++++++++ doc/pt/index.json | 69 ++++++++++ doc/pt/intro/index.md | 38 ++++++ doc/pt/object/forinloop.md | 41 ++++++ doc/pt/object/general.md | 83 ++++++++++++ doc/pt/object/hasownproperty.md | 56 ++++++++ doc/pt/object/prototype.md | 109 ++++++++++++++++ doc/pt/other/timeouts.md | 161 +++++++++++++++++++++++ doc/pt/types/casting.md | 67 ++++++++++ doc/pt/types/equality.md | 70 ++++++++++ doc/pt/types/instanceof.md | 38 ++++++ doc/pt/types/typeof.md | 83 ++++++++++++ 24 files changed, 1898 insertions(+), 1 deletion(-) create mode 100644 doc/pt/array/constructor.md create mode 100644 doc/pt/array/general.md create mode 100644 doc/pt/core/delete.md create mode 100644 doc/pt/core/eval.md create mode 100644 doc/pt/core/semicolon.md create mode 100644 doc/pt/core/undefined.md create mode 100644 doc/pt/function/arguments.md create mode 100644 doc/pt/function/closures.md create mode 100644 doc/pt/function/constructors.md create mode 100644 doc/pt/function/general.md create mode 100644 doc/pt/function/scopes.md create mode 100644 doc/pt/function/this.md create mode 100644 doc/pt/index.json create mode 100644 doc/pt/intro/index.md create mode 100644 doc/pt/object/forinloop.md create mode 100644 doc/pt/object/general.md create mode 100644 doc/pt/object/hasownproperty.md create mode 100644 doc/pt/object/prototype.md create mode 100644 doc/pt/other/timeouts.md create mode 100644 doc/pt/types/casting.md create mode 100644 doc/pt/types/equality.md create mode 100644 doc/pt/types/instanceof.md create mode 100644 doc/pt/types/typeof.md diff --git a/doc/language.json b/doc/language.json index dc45c11f..dbf7c885 100644 --- a/doc/language.json +++ b/doc/language.json @@ -1,5 +1,5 @@ { "default": "en", - "listed": ["en", "fi", "ru", "zhtw", "zh", "tr", "pl", "ko", "ja", "es", "it", "hu"] + "listed": ["en", "fi", "ru", "zhtw", "zh", "tr", "pl", "ko", "ja", "es", "it", "hu","pt"] } diff --git a/doc/pt/array/constructor.md b/doc/pt/array/constructor.md new file mode 100644 index 00000000..eaaf1c20 --- /dev/null +++ b/doc/pt/array/constructor.md @@ -0,0 +1,29 @@ +## O construtor `Array` + +Uma vez que o construtor `Array` é ambíguo na forma como ele lida com seus parâmetros, +o uso da notação `[]` é fortemente recomendado ao criar novo arrays. + + [1, 2, 3]; // Resultado: [1, 2, 3] + new Array(1, 2, 3); // Resultado: [1, 2, 3] + + [3]; // Resultado: [3] + new Array(3); // Resultado: [] + new Array('3') // Resultado: ['3'] + +Nos casos onde somente um argumento é passado para o construtor `Array` e quando o argumento é +um `Number`, o construtor retornará um novo array *sem elementos* com a propriedade `length` configurada de acordo com o valor do argumento. +É importante perceber que **somente** a propriedade `length` do novo array será configurada desta maneira; os índices do array não serão inicializados. + + var arr = new Array(3); + arr[1]; // undefined + 1 in arr; // false, o índice não foi definida + +Ser capaz de definir o comprimento de um array antecipadamente é útil em poucos casos, +como ao replicar uma string, em que se evita o uso de um loop. + + new Array(count + 1).join(stringToRepeat); + +### Conclusão + +O uso de literais é preferencial na inicialição de Arrays. São curtos, possuem uma sintaxe limpa, e contribuem para a legibilidade do código. + diff --git a/doc/pt/array/general.md b/doc/pt/array/general.md new file mode 100644 index 00000000..10543a84 --- /dev/null +++ b/doc/pt/array/general.md @@ -0,0 +1,59 @@ +## Iteração com Arrays e propriedades + +Embora arrays em JavaScript sejam objetos, não existem boas razões para utilizar +o [`for in`](#object.forinloop) loop. De fato, existem muitas boas razões para +**evitar** o uso de `for in` com arrays. + +> **Nota:** JavaScript arrays **não** são *arrays associativos*. JavaScript utiliza +> [objects](#object.general) apenas para mapear chaves com valores. Enquanto arrays associativos +> **preservam** a ordem, objetos **não preservam**. + +Uma vez que o `for in` loop enumera todas as propriedades que estão na cadeia +prototype e visto que o único modo de excluir tais propriedades é por meio do uso +do [`hasOwnProperty`](#object.hasownproperty), ele chega a ser **vinte vezes** +mais custoso que o uso normal do `for` loop. + +### Iteração + +A fim de atingir a melhor performance ao interagir sobre arrays, +a melhor opção é utilizar o clássico `for` loop. + + var list = [1, 2, 3, 4, 5, ...... 100000000]; + for(var i = 0, l = list.length; i < l; i++) { + console.log(list[i]); + } + +Existe um detalhe importante no exemplo acima , que é o caching +do comprimento do array via `l = list.length`. + +Embora a propriedade `length` esteja definida no próprio array, ainda existe +um trabalho extra ao executar a busca em cada iteração do array. +Enquanto que recentes engines JavaScript **talvez** implementem um otimização +para este caso, não existe uma maneira de saber quando o código será executado em uma +dessas novas engines. + +De fato, deixando de lado o armazenamento em caching pode resultar em um loop **duas vezes mais rápido** +do que com o armazenamento em caching. + +### A propriedade `length` + +Enquanto que o *getter* da propriedade `length` retorna o total de elementos +que estão contidos no array, o *setter* pode ser usado para **truncar** o array. + + var foo = [1, 2, 3, 4, 5, 6]; + foo.length = 3; + foo; // [1, 2, 3] + + foo.length = 6; + foo.push(4); + foo; // [1, 2, 3, undefined, undefined, undefined, 4] + +Atribuir um valor de menor para length trunca o array. Por outro lado, incrementando +o valor de length cria um array esparso. + +### Conclusão + +Para melhor performance, é recomendado o uso do `for` loop e o cache da propriedade +`length`. O uso do `for in` loop na iteração com array é um sinal de código mal escrito +e tendencioso a apresentar defeitos, além de ter performance ruim. + diff --git a/doc/pt/core/delete.md b/doc/pt/core/delete.md new file mode 100644 index 00000000..949c24d8 --- /dev/null +++ b/doc/pt/core/delete.md @@ -0,0 +1,85 @@ +## O operador `delete` + +Em resumo, é *impossível* remover variáveis globais, funções e outras coisas em JavaScript +que tenham o atributo `DontDelete` definido. + +### Código global e código de função + +Quando uma variável ou função é definida no escopo global ou em +um [escopo de função](#function.scopes) ela passa a ser uma propriedade de ambos +objeto Activation e do objeto Global. Tais propriedades possuem um conjunto de atributos, um dos quais é o `DontDelete`. +Declarações de funções e variáveis em código global e em código de função +sempre criam propriedades com `DontDelete`, e portanto não podem ser removidas. + + // variável global: + var a = 1; // DontDelete está definido + delete a; // false + a; // 1 + + // função comum: + function f() {} // DontDelete está definido + delete f; // false + typeof f; // "function" + + // mudar o valor do atributo não ajuda: + f = 1; + delete f; // false + f; // 1 + +### Propriedades explícitas + +Propriedades definidas explicitamente podem ser apagadas normalmente. + + // definição explícita de propriedade: + var obj = {x: 1}; + obj.y = 2; + delete obj.x; // true + delete obj.y; // true + obj.x; // undefined + obj.y; // undefined + +No exemplo acima, `obj.x` e `obj.y` podem ser removidos por que eles não possuem o +atributo `DontDelete`. Este é o motivo pelo qual o exemplo abaixo também funciona. + + // Desconsiderando o IE, isto funciona bem: + var GLOBAL_OBJECT = this; + GLOBAL_OBJECT.a = 1; + a === GLOBAL_OBJECT.a; // true - apenas uma variável global + delete GLOBAL_OBJECT.a; // true + GLOBAL_OBJECT.a; // undefined + +Aqui nós utilizamos um truque para remover `a`. Aqui o [`this`](#function.this) +faz referência ao objeto Global e declara explicitamente a variável `a` como +sua propriedade a qual nos permite removê-la. + +O IE (pelo menos 6-8) possui defeitos, então o código acima não funciona. + +### Argumentos de função e propriedades nativas + +Argumentos de função, [objetos `arguments`](#function.arguments) e +propriedades nativas tambêm possuem o `DontDelete` definido. + + // argumentos de funções e propriedades: + (function (x) { + + delete arguments; // false + typeof arguments; // "object" + + delete x; // false + x; // 1 + + function f(){} + delete f.length; // false + typeof f.length; // "number" + + })(1); + +### Objetos hosts + +O comportamento do operador `delete` pode ser imprevisível para objetos hosts. +Devido a especificação, objetos hosts têm permissão para implementar qualquer tipo de comportamento. + +### Conclusão + +O operador `delete` freqüentemente apresenta um comportamento inesperado e só +pode ser usado com segurança para remover propriedades definidas explicitamente em objetos normais. diff --git a/doc/pt/core/eval.md b/doc/pt/core/eval.md new file mode 100644 index 00000000..0579953d --- /dev/null +++ b/doc/pt/core/eval.md @@ -0,0 +1,45 @@ +## Por que não utilizar `eval` + +A função `eval` executará uma string de código JavaScript no escopo local. + + var foo = 1; + function test() { + var foo = 2; + eval('foo = 3'); + return foo; + } + test(); // 3 + foo; // 1 + +Entreranto, `eval` somente é executado no escopo local quando é chamado diretamente +*e* quanto o nome da função chamada é `eval`. + + var foo = 1; + function test() { + var foo = 2; + var bar = eval; + bar('foo = 3'); + return foo; + } + test(); // 2 + foo; // 3 + +O uso de `eval` deve ser evitado. 99.9% de seu "uso" pode ser alcançado **sem** ele. + +### `eval` dissimulado + +As [funções timeout](#other.timeouts) `setTimeout` e `setInterval` podem ambas receberem uma string +como primeiro argumento. Tais strings **sempre** serão executadas no escopo global uma vez que +`eval` não é chamado diretamente, naquele caso. + +### Problemas de segurança + +`eval` também é considerado um problema de segurança, por que executa **qualquer** código dado. +Ele **nunca** deve ser utilizado com strings de origens duvidosas ou desconhecidas. + +### Conclusão + +`eval` nunca deve ser utilizado. Qualquer código que faça uso de `eval` seve ser questionado +em sua utilizade, performance e segurança. Se algo necessita de `eval` para funcionar, então **não** deve ser utilizado. +Um *design melhor* deve ser utilizado, um que não faça uso de `eval`. + diff --git a/doc/pt/core/semicolon.md b/doc/pt/core/semicolon.md new file mode 100644 index 00000000..38375017 --- /dev/null +++ b/doc/pt/core/semicolon.md @@ -0,0 +1,106 @@ +## Inserção automática do ponto e vírgula + +Apesar do JavaScript possuir uma sintaxe no estilo C, o uso do ponto e vírgula **não** é obrigatório. + +JavaScript não é uma linguagem 'semicolon-less'. De fato, o ponto e vírgula é necessário para o interpretação do código. Entretanto, o parser do JavaScript insere o **automaticamente** ponto e vírgula sempre que ocorrer um error de parser, decorrente da falta do ponto e vírgula. + + var foo = function() { + } // parse error, semicolon expected + test() + +A inserção acontece e o parser realiza uma nova tentativa. + + var foo = function() { + }; // no error, parser continues + test() + +A inseção automática de ponto e vírgula é considerada um dos **maiores** equívocos no design da linguagem pois pode influenciar no comportamento do código. + +### Como funciona + +O código abaixo não possui ponto e vírgula, então fica à cargo do parser inserir o ponto e vírgula onde julgar necessário. + + (function(window, undefined) { + function test(options) { + log('testing!') + + (options.list || []).forEach(function(i) { + + }) + + options.value.test( + 'long string to pass here', + 'and another long string to pass' + ) + + return + { + foo: function() {} + } + } + window.test = test + + })(window) + + (function(window) { + window.someLibrary = {} + + })(window) + +Abaixo está o resultado do processamento do parser. + + (function(window, undefined) { + function test(options) { + + // Not inserted, lines got merged + log('testing!')(options.list || []).forEach(function(i) { + + }); // <- inserted + + options.value.test( + 'long string to pass here', + 'and another long string to pass' + ); // <- inserted + + return; // <- inserted, breaks the return statement + { // treated as a block + + // a label and a single expression statement + foo: function() {} + }; // <- inserted + } + window.test = test; // <- inserted + + // The lines got merged again + })(window)(function(window) { + window.someLibrary = {}; // <- inserted + + })(window); //<- inserted + +> **Nota:** O parser do JavaScript não manipula corretamente 'return statements' que são seguidos de uma nova linha. Apesar de não ser necessariamente uma > > > falha da inserção automática do ponto e vírgula, ainda pode gerar efeitos colaterais não-esperados. + +O parser mudou o comportamento do código acima drásticamente. Em determinados casos, o parser **não procede** como o esperado. + +### Parênteses + +No caso de parênteses, o parser **não** insere o ponto e vírgula. + + log('testing!') + (options.list || []).forEach(function(i) {}) + +Este código é interpretado em uma só linha. + + log('testing!')(options.list || []).forEach(function(i) {}) + +As chances de `log` não retornar uma função são **muito** altas; portanto, o código acima irá produzir um `TypeError` informando que `undefined is not a function`. + +### Conclusão + +It is highly recommended to **never** omit semicolons. It is also recommended +that braces be kept on the same line as their corresponding statements and to +never omit them for single-line `if` / `else` statements. These measures will +not only improve the consistency of the code, but they will also prevent the +JavaScript parser from changing code behavior. + +É **fortemente** recomendado que nunca se omita o ponto e vírgula. Também é recomendado que chaves sejam mantidas na mesma linha que seus statements e que nunca sejam omitadas em declações de uma só linha como `if` / `else` statements. Tais medidas não somente melhorarão a consistência do código, como também irão previnir alteração no comportamento do código por má interpretação do parser do JavaScript. + diff --git a/doc/pt/core/undefined.md b/doc/pt/core/undefined.md new file mode 100644 index 00000000..463a9618 --- /dev/null +++ b/doc/pt/core/undefined.md @@ -0,0 +1,68 @@ +## `undefined` e `null` + +JavaScript tem duas formas distintas para representar o nada, `null` e `undefined`, com +o último sendo o mais útil. + +### O valor `undefined` + +`undefined` é um tipo com um valor exato : `undefined`. + +A linguagem também define uma variável global que tem como valor `undefined`; +esta variável também é chamada `undefined`. Entretanto tal variável *não é nem* uma constante +*muito menos* uma palavra-chave da linguagem. Isto significa que seu *valor* pode ser facilmente +sobrescrito. + +> **Nota ES5:** `undefined` em ECMAScript 5 **não dispõe** mais de permissão para escrita no modo estrito, porém +> sua denominação ainda pode ser confundida com, por exemplo, uma função com o nome `undefined`. + +Aqui estão alguns exemplos de quando o valor `undefined` é retornado: + + - Acessando uma variável global (não-modificada) `undefined`. + - Acessando uma variável declarada *mas não* ainda inicializada. + - Retornos implícitos de funções devido ao esquecimento do `return` statement. + - `return` statements que explicimente retornam o nada. + - Busca por propriedades não-existentes. + - Parâmetros de funções que não têm um valor explícito definido. + - Qualquer coisa que tenha sido definida como `undefined`. + - Qualquer expressão no formato `void(expressão)` + +### Manipulando mudanças no valor de `undefined` + +Uma que a variável global `undefined` apenas mantém uma cópia do valor *atual* de `undefined`, atribuir-lhe +um novo valor **não** muda o valor do tipo `undefined`. + +Ainda, a fim de comparar alguma coisa com o valor de `undefined`, é ncessário que +primeiro se retorne o `undefined`. + +A fim de proteger o código contra uma possível sobrescrtia da variável `undefined`, uma +técnica comum utilizada é a de adicionar um parâmetro adicional em um [wrapper anônimo](#function.scopes) + que não recebe argumentos. + + var undefined = 123; + (function(something, foo, undefined) { + // undefined no escopo local agora + // refer-se ao valor `undefined` + + })('Hello World', 42); + +Outra maneira de atingir o mesmo efeito seria utilizar uma declaração dentro do wrapper. + + var undefined = 123; + (function(something, foo) { + var undefined; + ... + + })('Hello World', 42); + +A única diferença aqui é a que a última versão resulta na redução de 4 bytes, e nã existe +outro `var` statement dentro do wrapper anônimo. + +### Usos do `null` + +Enquanto que `undefined` no contexto da linguagem JavaScript é normalmente utilizado +como um *null*, o atual `null` (ambos o tipo e o literal) é mais ou menos um outro tipo de dado. + +Ele é utilizado internamente pelo JavaScript (como na declaração no fim da cadeia prototype +ao definir `Foo.prototype = null`), porém na maioria dos casos, pode ser substituido por `undefined`. + + diff --git a/doc/pt/function/arguments.md b/doc/pt/function/arguments.md new file mode 100644 index 00000000..099ecf02 --- /dev/null +++ b/doc/pt/function/arguments.md @@ -0,0 +1,113 @@ +## O objeto `arguments` + +Todo escopo de uma função em JavaScript em acesso à variável especial `arguments`. +Esta variável armazena uma lista de todos os argumentos que foram passados para a função. + +> **Nota:** No caso em que `arguments` tenha sido definido dentro do escopo da função por meio +> de `var` statement ou que este seja o nome de um parâmetro formal, o objeto `arguments` não será criado. + +O objeto `arguments` **não** é um `Array`. Enquanto que ele possui uma semântica +parecida com a de um array - a saber a propriedade `length` - ele não herda de `Array.prototype` +e é de fato um `Object`. + +Devido a isto, **não** é possível usar os métodos padrões de array como `push`, +`pop` ou `slice` no `arguments`. Enquanto que a iteração com um simples `for` loop funciona bem, +é necessário convertê-lo para um `Array` a fim de usar os métodos padrões de `Array`. + +### Convertendo em um Array + +O código abaixo irá retornar um novo `Array` contendo todos os elementos do +objeto `arguments`. + + Array.prototype.slice.call(arguments); + +Por este tipo de conversão ser **lenta**, seu uso em porções de código que apresentam performance crítica **não é recomendado**. + +### Passando argumentos + +O código abaixo é a maneira recomendada de se passar argumentos de uma função para outra. + + function foo() { + bar.apply(null, arguments); + } + function bar(a, b, c) { + // do stuff here + } + +Outro truque é o de usar ambos `call` e `apply` juntos para criar wrappers. + + function Foo() {} + + Foo.prototype.method = function(a, b, c) { + console.log(this, a, b, c); + }; + + // Create an unbound version of "method" + // It takes the parameters: this, arg1, arg2...argN + Foo.method = function() { + + // Result: Foo.prototype.method.call(this, arg1, arg2... argN) + Function.call.apply(Foo.prototype.method, arguments); + }; + + +### Parâmetros formais Formal Parameters and Arguments Indices + +O objeto `arguments` cria funções *getter* e *setter* para suas propriedades, +bem como os parâmetros formais da função. + +Como resultado, alterando o valor de um parâmetro formal também mudará o valor +da propriedade correspondente no objeto `arguments`, e vice versa. + + function foo(a, b, c) { + arguments[0] = 2; + a; // 2 + + b = 4; + arguments[1]; // 4 + + var d = c; + d = 9; + c; // 3 + } + foo(1, 2, 3); + +### Mitos e verdades sobre performance + +A única vez em que o objeto `arguments` não é criado é quando é declarado como um nome dentro de uma função +ou declarado como um de seus parâmetros formais. Não importa se ele é usado ou não. + +Ambos *getters* e *setters* são *sempre* criados; desta maneira, usá-los não causa impacto +de performance, especialmente não em código do mundo real, onde existe mais de um simples +acesso às propriedades do objeto `arguments`. + +> **Nota ES5:** Estes *getters* e *setters* não são criados no strict mode. + +Entretando, existe um caso em que a performance é drasticamente reduzida +em engines modernas de JavaScript. Este caso é o uso de `arguments.callee` + + function foo() { + arguments.callee; // Faça alguma coisa com os objeto deta função + arguments.callee.caller; // e o calling do objeto da função + } + + function bigLoop() { + for(var i = 0; i < 100000; i++) { + foo(); // Would normally be inlined... + } + } + +No código acima, `foo` +In the above code, `foo` can no longer be a subject to [inlining][1] since it +needs to know about both itself and its caller. +Isto não somente acaba com possíveis ganhos de performance que resultariam de inlining, +mas também quebram o encapsulamento pois a função agora depende de uma chamada específica de contexto. + +O uso de `arguments.callee` é **fortemente desencorajado**. + +> **Nota ES5:** No strict mode, `arguments.callee` lança `TypeError` uma vez que +> se tornou obsoleto. + +[1]: http://en.wikipedia.org/wiki/Inlining + + diff --git a/doc/pt/function/closures.md b/doc/pt/function/closures.md new file mode 100644 index 00000000..cdf8fd30 --- /dev/null +++ b/doc/pt/function/closures.md @@ -0,0 +1,83 @@ +## Closures e Referências + +Uma das caracterísricas mais poderosas do JavaScript é a possibilidade de usar *closures*. Quando usamos closures, definimos que um escopo **sempre** poderá acessar o escopo externo no qual foi definido. Uma vez que a única concepção de escopo em JavaScripe é [function scope](#function.scopes), todas as funções, por default, agem como closures. + +### Emulando variáveis privadas + + function Counter(start) { + var count = start; + return { + increment: function() { + count++; + }, + + get: function() { + return count; + } + } + } + + var foo = Counter(4); + foo.increment(); + foo.get(); // 5 + +Aqui, `Counter` retorna **duas** closures: a função 'increment' bem como a função 'get'. Ambas as funções mantêm uma **referência** ao escopo de 'Counter' e, portanto, sempre mantêm o acesso à variável 'count' definida naquele escopo. + +### Por que variáveis privadas funcionam + +Uma vez que não é possível referenciar ou atribuir escopos em JavaScript, **não** existe uma maneira de acessar a variável 'count' por fora. A única maneira de interagir com a variável é através das duas closures. + + var foo = new Counter(4); + foo.hack = function() { + count = 1337; + }; + +O código acima **não** irá mudar a variável 'count' no escopo de 'Counter', uma vez que 'foo.hack' não foi definido **naquele** escopo. Neste caso, uma variável 'global' 'count' será criada ou substituida. + +### Closures dentro de laços + +Um erro comum é utilizar closures dentro de laços, como se elas copiassem o valor da variável de indexação do laço. + + for(var i = 0; i < 10; i++) { + setTimeout(function() { + console.log(i); + }, 1000); + } + +O exemplo acima **não** retornará os números '0' até '9', mas os número '10' dez vezes. + +A função *anônima* mantêm uma **referência** para 'i'. No momento em que 'console.log' é chamado, 'o laço for' já encerrou a execução, e o valor '10' está atrbuído em 'i'. + +Com a finalidade de se obter o comportamento esperado, é necessário criar uma **cópia** do valor de 'i'. + +### Evitando problemas de referência + +Com a finalidade de copiar o valor da variável de indexação do laço, a melhor opção é utilizar um [wrapper anônimo](#function.scopes). + + for(var i = 0; i < 10; i++) { + (function(e) { + setTimeout(function() { + console.log(e); + }, 1000); + })(i); + } + +A função anônima será chamada imediatamente com 'i' como seu primeiro argumento e receberá uma cópia do **valor** de 'i' como parâmetro de 'e'. + +A função anônima que é passada para o 'setTimeout' agora possui uma referência a 'e', cujo os valores **não** são modificados pelo laço. + +Não existe outra maneira de se obter este resultado, que não seja retornando uma função do wrapper anônimo que terá, então, o mesmo comportamento que o código acima. + + for(var i = 0; i < 10; i++) { + setTimeout((function(e) { + return function() { + console.log(e); + } + })(i), 1000) + } + +Há ainda uma outra maneira, usando .bind, que pode ligar argumentos e um contexto'this' a uma função. Isto se comporta como o código acima + + for(var i = 0; i < 10; i++) { + setTimeout(console.log.bind(console, i), 1000); + } diff --git a/doc/pt/function/constructors.md b/doc/pt/function/constructors.md new file mode 100644 index 00000000..26abfedf --- /dev/null +++ b/doc/pt/function/constructors.md @@ -0,0 +1,115 @@ +## Construtores + +Construtores em JavaScript ainda são diferentes de muitas outras linguagens. +Qualquer chamada a uma função que seja precedida pela palavra-chave `new` age como um cosntrutor. + +Dentro do construtor - a função chamada - o valor de `this` se refere ao objeto recém criado. +O [prototype](#object.prototype) deste **novo** objeto é definido como o `prototype` do objeto da função que foi +invocada como construtor. + +Se a função chamada não possui um `return` statement explícito, então implicitamente +retornará o valor de `this` - o novo objeto. + + function Foo() { + this.bla = 1; + } + + Foo.prototype.test = function() { + console.log(this.bla); + }; + + var test = new Foo(); + +O código acima chama `Foo` como construtor e define o `prototype` do objeto recém criado +como `Foo.prototype`. + +No caso de um `return` statement explícito, a função retorna o valor +especificado pelo statement, mas **somente** se o valor de retorno for um `Object`. + + function Bar() { + return 2; + } + new Bar(); // um novo objeto + + function Test() { + this.value = 2; + + return { + foo: 1 + }; + } + new Test(); // o objeto retornado + +Quando a palavra-chave `new` é omitida, a função **não** retornará o novo objeto. + + function Foo() { + this.bla = 1; // esta definida no escopo global do objeto + } + Foo(); // undefined + +Enquanto que o exemplo acima pareça funcionar em alguns casos, devido +a maneira como [`this`](#function.this) funciona em JavaScript, o *objeto global* +será usado como valor do `this`. + +### Fábricas + +A fim de omitir a palavra-chave `new`, o construtor da função deve retornar um valor explicitamente. + + function Bar() { + var value = 1; + return { + method: function() { + return value; + } + } + } + Bar.prototype = { + foo: function() {} + }; + + new Bar(); + Bar(); + +Ambas as chamadas a `Bar` retornam a mesma coisa, um objeto recém criado +que tem a propriedade chamada `method`, que é uma [Closure](#function.closures). + +Deve-se perceber que a chamada `new Bar()` **não** afeta o prototype do objeto retornado. +Enquanto o prototype é definido no objeto recém criado, `Bar` nunca retornará um novo objeto. + +No exemplo acima, não existe diferença funcional entre o uso ou não de `new`. + +### Criando novos objetos por fábricas + +É recomendado **não** usar `new` pois eventual o esquecimento de seu uso +pode levar à defeitos. + +A fim de criar um novo objeto, deve-se utilizar uma fábrica e construir o novo objeto dentro desta fábrica. + + function Foo() { + var obj = {}; + obj.value = 'blub'; + + var private = 2; + obj.someMethod = function(value) { + this.value = value; + } + + obj.getPrivate = function() { + return private; + } + return obj; + } + +Enquanto que o código acima previne defeitos decorrentes do esquecimnto da palavra-chave `new` +e certamente utiliza-se de [private variables](#function.closures) de forma mais fácil, este apresenta algumas desvantagens: + + 1. Utiliza mais memória desde que os objetos criados **não** compartilham métodos em um prototype. + 2. A fim de implementar herença, a fábrica precisa copiar todos os métodos de um outro objeto ou colocar o outro objeto no prototype do novo objeto. + 3. Quebrar a cadeia prototype somente por causa de esquecer eventualmente o `new` vai contra o que é proposto pela linguagem. + +### Conclusão + +Enquanto que a omissão do `new` origine defeitos, **não** é certamente uma razão para +quebrar a estrura prototype como um todo. No final, a melhor solução é sempre a que se adequa às necessidades de cada projeto. +O importante é utilizar de forma **consistente** o modelo de criação de objetos escolhido. + diff --git a/doc/pt/function/general.md b/doc/pt/function/general.md new file mode 100644 index 00000000..dc002e8f --- /dev/null +++ b/doc/pt/function/general.md @@ -0,0 +1,46 @@ +## Declaração de funções e expressões + +Funções em JavaScript são objetos de primeira classe. Isto significa que elas +podem ser tratadas como qualquer outro tipo. Um uso muito comum desta característica é +o de passar uma *função anônima* como uma callback para outra, talvez uma função assíncrona. + +### A declaração `function` + + function foo() {} + +A função acima sofrerá [hoisting](#function.scopes) antes que a execução do programa se inicie; assim, +ela estará disponível em *todo* o escopo em que foi *definida*, até mesmo se for chamada antes de ter +sido definida no código. + + foo(); // Funciona pois foo foi elevada para o topo do escopo + function foo() {} + +### A expressão `function` + + var foo = function() {}; + +Este exemplo atribui uma função sem nome e *anônima* à variável `foo`. + + foo; // 'undefined' + foo(); // dispara TypeError + var foo = function() {}; + +Devido ao fato de que `var` é uma declaração que eleva a definição da variável `foo` ao topo do escopo, esta sofrerá hoist e `foo` estará declarado logo que o script for executado. + +Como atribuições só ocorrem em tempo de execução, o valor default de `foo` +será [undefined](#core.undefined) antes que o código seja executado. + +### Expressão de uma função nomeada + +Outro caso especial é a atribuição de funções nomeadas. + + var foo = function bar() { + bar(); // Funciona + } + bar(); // ReferenceError + +Aqui, `bar` não está disponível fora do escopo, uma vez que a função se encontra atribuída +em `foo`; no entanto, dentro de `bar`, ela esta disponível. Isto ocorre devido ao fato de +como o [name resolution](#function.scopes) funciona em JavaScript, o nome da função está *sempre* +disponível no escopo local da própria função. + diff --git a/doc/pt/function/scopes.md b/doc/pt/function/scopes.md new file mode 100644 index 00000000..0bcd99d6 --- /dev/null +++ b/doc/pt/function/scopes.md @@ -0,0 +1,225 @@ +## Escopos e Namespaces + +Embora o JavaScript lide bem com a sintaxe de duas chaves para definir blocos, ele **não** oferece suporte a escopos em blocos; por isso, +todo o restante da linguagem é definido em *escopo de função*. + + function test() { // define escopo + for(var i = 0; i < 10; i++) { // não define escopo + // count + } + console.log(i); // 10 + } + +> **Nota:** Quando não usado em um assignment, em um statement return ou como um argumento de função, +> a notação `{...}` será interpretada como um block statement e **não** como um objeto literal. +> Isto, em conjunto com a [inserção automática de ponto-e-vírgula](#core.semicolon), pode levar à erros sutis. + +Também não existem namespaces distintos em JavaScript, o que significa que tudo é +automaticamente definido em um namespace *globalmente compartilhado*. + +Cada vez que uma variável é referenciada, o JavaScript vai percorrer toda a hierarquia +de escopos até encontrá-la. Caso ele alcance o escopo global e ainda não tenha encontrado +a variável, ele lançará um `ReferenceError`. + +### A queda das variáveis globais + + // script A + foo = '42'; + + // script B + var foo = '42' + +O dois scripts acima **não** têm o mesmo efeito. O Script A define uma +variável chamada `foo` no escopo *global*, e o Script B define `foo` no +escopo *atual*. + +Novamente, isto **não** é *mesma coisa*: emitir o uso de `var` tem várias implicações. + + // escopo global + var foo = 42; + function test() { + // escopo local + foo = 21; + } + test(); + foo; // 21 + +Deixando o statement `var` de fora da função `test` faz com que o valor de `test` seja sobrescrito. +Enquanto que à primeira vista isto não pareça um problema, um script com milhares de linhas de código +que não utiliza `var` apresenta erros horríveis e bugs difíceis de serem detectados. + + // escopo global + var items = [/* uma lista qualquer */]; + for(var i = 0; i < 10; i++) { + subLoop(); + } + + function subLoop() { + // escopo de subLoop + for(i = 0; i < 10; i++) { // esquecendo do var statement + // faça algo incrível! + } + } + +O loop externo terminará depois da primeira chamada para `subLoop`, uma vez que `subLoop` +sobrescreve o valor global `i`. Utilizar `var` no segundo `for` loop evitaria facilmente este problema. +O `var` statement **nunca** pode ser esquecido a não ser que o *efeito desejado* seja afetar o escopo externo. + +### Variáveis locais + +A única fonte de variáveis locais em JavaScript são parâmetros de [função](#function.general) +e variáveis declaradas via `var` statement. + + // escopo global + var foo = 1; + var bar = 2; + var i = 2; + + function test(i) { + // escopo local da função test + i = 5; + + var foo = 3; + bar = 4; + } + test(10); + +Enquanto que `foo` e `i` são variáveis locais dentro do escopo da função `test`, +a atribuição de `bar` irá substituir a variável global com o mesmo nome. + +### Hoisting + +Javascript **eleva** declarações. Isto quer dizer que ambas declarações `var` +e `function` serão movidas para o topo do escopo ao qual pertencem. + + bar(); + var bar = function() {}; + var someValue = 42; + + test(); + function test(data) { + if (false) { + goo = 1; + + } else { + var goo = 2; + } + for(var i = 0; i < 100; i++) { + var e = data[i]; + } + } + +O código acima é modificado antes mesmo que seja executado. O JavaScript move + todos as declarações `var` assim como as de `function`, para o topo +do escopo mais próximo. + + // declarações var são movidas aqui + var bar, someValue; // default para 'undefined' + + // as declarações de função também são movidas + function test(data) { + var goo, i, e; // escopo de bloco ausente move essas variáveis p/ cá + if (false) { + goo = 1; + + } else { + goo = 2; + } + for(i = 0; i < 100; i++) { + e = data[i]; + } + } + + bar(); // falha com um TypeError uma vez que bar continua 'undefined' + someValue = 42; // atribuições não são afetadas pelo hoisting + bar = function() {}; + + test(); + +A falta de delimitação de um escopo não somente moverá `var` statements para fora de loops + e seus blocos, isto também fará com que os testes de determinados `if` se tornem não-intuitivos. + + No código original, embora o `if` statement pareça modificar a *variável global* + `goo`, ele modifica a *variável local* - depois que hoisting foi aplicado. + +Por desconhecer o *hoisting*, pode-se suspeitar que o código abaixo lançaria um +`ReferenceError`. + + // verifique se SomeImportantThing já foi inicializado + if (!SomeImportantThing) { + var SomeImportantThing = {}; + } + +Mas é claro, isto funciona devido ao fato de que `var` statement é movido para o topo +do *escopo global*. + + var SomeImportantThing; + + // outro código pode inicializar SomeImportantThing aqui, ou não + + // tenha certeza de que isto foi inicializado + if (!SomeImportantThing) { + SomeImportantThing = {}; + } + +### Ordem da Resolução de Nomes + +Todos os escopos em JavaScript, incluindo o *escopo global*, possuem o [`this`](#function.this) + o qual faz referência ao *objeto atual*. + +Escopos de funções também possuem o [`arguments`](#function.arguments), o qual contêm +os argumentos que foram passados para a função. + +Por exemplo, ao tentar acessar a variável denominada `foo` dentro do escopo de uma função, JavaScript irá +procurar pela variável na seguinte ordem: + + 1. No caso de haver `var foo` statement no escopo atual, use-a. + 2. Se um dos parâmetros é denominado `foo`, use-o. + 3. Se a própria função é denominada `foo`, use-a. + 4. Vá para o escopo externo mais próximo e inicie do **#1**. + +> **Nota:** Dispor de um parâmetro denominado `arguments` irá **previnir** a criação +> do objeto default `arguments`. + +### Namespaces + +Um problema comum relacionado ao fato de dispor de apenas um namespace global é +a probabilidade de esbarrar com problemas onde nomes de variáveis coincidem. Em JavaScript, +este problema pode ser facilmente evitado com a ajuda de *wrappers anônimos*. + + (function() { + // um "namespace" autocontido + + window.foo = function() { + // closure exposta + }; + + })(); // execute a função imediatamente + + +Funções sem nome são consideradas [expressões](#function.general); a fim de ser referênciável, +elas devem ser avaliadas. + + ( // avalie a função dentro dos parênteses + function() {} + ) // e retorne o objeto de função + () // chama o resultado da avaliação + +Existem outras maneiras para avaliar e chamar diretamente a expressão da função a qual, +enquanto que diferentes em sintaxe, comportam-se da mesma maneira. + + // Alguns outros estilos para invocar diretamente ... + !function(){}() + +function(){}() + (function(){}()); + // e assim por diante... + +### Conclusão + +É recomendado sempre utilizar um *wrapper anônimo* para encapsular código em seu +próprio namespace. Isto não é somente uma maneira de se proteger contra conflitos de nomes, +como também contribui para melhor modularização de programas. + +Adicionalmente, o uso de variáveis globais é considerado **uma prática ruim**. **Qualquer** +uso delas indica código mal escrito que tende à apresentar erros e apresenta manutenção complexa. + diff --git a/doc/pt/function/this.md b/doc/pt/function/this.md new file mode 100644 index 00000000..6f8c45d9 --- /dev/null +++ b/doc/pt/function/this.md @@ -0,0 +1,108 @@ +## Como funciona o `this` + +JavaScript tem uma concepção diferente sobre a que a palavra reservada `this` se refere da maioria das outras linguagens de programação. Existem exatamente **cinco** diferentes maneiras as quais os valores de `this` podem ser referenciados na linguagem. + +### O escopo Global + + this; + +Quando usando `this` no escopo global, ele simplesmente estará apontando para o objeto *global*. + + +### Chamando uma função + + foo(); + +Aqui, `this` irá referenciar novamente o objeto *global*. + +> **Nota ES5:** No strict mode, global **não existe**. +> neste caso, `this` receberá como valor `undefined`. + +### Chamando um método + + test.foo(); + +Neste exemplo, `this` irá referenciar `test`. + +### Chamando um construtor + + new foo(); + +Uma chamada de função que é precedida pela palavra chave `new` age como +um [construtor](#function.constructors). Dentro da função, `this` irá se referir +a um objeto *recém criado*. + +### Referência explícita do `this` + + function foo(a, b, c) {} + + var bar = {}; + foo.apply(bar, [1, 2, 3]); // array will expand to the below + foo.call(bar, 1, 2, 3); // results in a = 1, b = 2, c = 3 + +Quando utiliza-se os métodos `call` ou `apply` de `Function.prototype`, o valor de +`this` dentro da função chamada irá referenciar **explicitamente** o primeiro argumento +correspondente na chamada da função. + +Como resultado, no exemplo anterior o *escopo original do método* **não** é aplicado, e `this` +dentro de `foo` irá referenciar `bar`. + +> **Nota:** `this` **não** pode ser utilizado para referenciar o objeto dentro de um `Object` lietral. +> Logo `var obj = {me: this}` **não** irá resultar em `me` apontando para +> `obj`, uma vez que `this` só pode ser referenciado em dos cinco casos aqui apresentados. + +### Erros comuns + +Embora a maioria destes casos façam sentido, o primeiro pode ser considerado +como um engano de concepção da linguagem, já que **nunca** se mostrou útil. + + Foo.method = function() { + function test() { + // this referencia o objeto global + } + test(); + } + +Um erro comum é achar que `this` dentro de `test` referencia `Foo`; enquanto que, na realidade + **não é isto que acontece**. + +Com a finalidade de acessar `Foo` de dentro de `test`, é necessário instanciar +uma variável global dentro do método para se referir à `Foo`. + + Foo.method = function() { + var that = this; + function test() { + // Utilize that no lugar de this aqui + } + test(); + } + +`that` trata-se de uma variável normal, porém é normalmente utilizada para referências externas de `this`. +Quando combinadas com [closures](#function.closures), também podem ser utilizadas para repassar `this` como valor. + +### Atribuindo métodos + +Outra coisa que **não** funciona em JavaScript é function aliasing, ou seja, +**atribuir** um método a uma variável. + + var test = someObject.methodTest; + test(); + +Devido ao primeiro caso, `test` se comportará como uma chamada de função; como consequencia, +o `this` dentro do método não apontará para `someObject`. + +Enquanto que realizar binding do `this` pareça uma idéia ruim, no fundo, é o que faz a +[herança prototypal](#object.prototype) funcionar. + + function Foo() {} + Foo.prototype.method = function() {}; + + function Bar() {} + Bar.prototype = Foo.prototype; + + new Bar().method(); + +Quando os métodos da instância de `Bar` são chamados, o `this` faz referência +àquela mesma instância. + + diff --git a/doc/pt/index.json b/doc/pt/index.json new file mode 100644 index 00000000..e7b22d3f --- /dev/null +++ b/doc/pt/index.json @@ -0,0 +1,69 @@ +{ + "title": "JavaScript Garden", + "langTitle": "JavaScript Garden em Português", + "description": "Um guia pelas vantagens e desvantagens do JavaScript.", + "sections": [ + { + "title": "Introdução", + "dir": "intro", + "articles": ["index"] + }, + { + "title": "Objetos", + "dir": "object", + "articles": [ + "general", + "prototype", + "hasownproperty", + "forinloop" + ] + }, + { + "title": "Funções", + "dir": "function", + "articles": [ + "general", + "this", + "closures", + "arguments", + "constructors", + "scopes" + ] + }, + { + "title": "Arrays", + "dir": "array", + "articles": [ + "general", + "constructor" + ] + }, + { + "title": "Tipos", + "dir": "types", + "articles": [ + "equality", + "typeof", + "instanceof", + "casting" + ] + }, + { + "title": "Core", + "dir": "core", + "articles": [ + "eval", + "undefined", + "semicolon", + "delete" + ] + }, + { + "title": "Outros assuntos", + "dir": "other", + "articles": [ + "timeouts" + ] + } + ] +} diff --git a/doc/pt/intro/index.md b/doc/pt/intro/index.md new file mode 100644 index 00000000..ecba225b --- /dev/null +++ b/doc/pt/intro/index.md @@ -0,0 +1,38 @@ +## Introdução + +**JavaScript Garden** é uma coletânea crescente que documenta as peculiaridades da linguagem de programação JavaScript. Nela você encontra recomendações para escapar dos erros comuns aos mais sutís, bem como de problemas de desempenho e práticas ruins, que programadores novatos podem acabar encontrando enquanto se aprofundam na linguagem. + +JavaScript Garden **não** tem como propósito te ensinar à programar em JavaScript. Conhecimento prévio da linguagem é fortemente recomendado para que você entenda o conteúdo dos tópicos abordados neste guia. A fim de aprender as noções básicas da linguagem, por favor, consulte o excelente [guia][1] disponível na Mozilla Developer Network. + +## Os autores + +Este guia é fruto do trabalho de dois excelentes usuários do [Stack Overflow][2], [Ivo Wetzel][3] +(Conteúdo) e [Zhang Yi Jiang][4] (Design). + +É mantido atualmente por [Tim Ruffles](http://truffles.me.uk). + +## Contribuidores + +- São muitos para serem listados, [veja a lista completa clicando aqui](https://github.com/BonsaiDen/JavaScript-Garden/graphs/contributors). + + +## Hospedagem + +JavaScript Garden está hospedado no GitHub, porém [Cramer Development][7] nos apoia com um espelho em [JavaScriptGarden.info][8]. + +## Licença + +JavaScript Garden está publicado sob a [licença MIT][9] e hospedado no [GitHub][10]. Caso você encontre defeitos ou erros de digitação, por favor [registre o problema][11] ou realize um pull request no repositório. Você também pode nos encontrar na [sala de JavaScript][12] no chat do Stack Overflow. + +[1]: https://developer.mozilla.org/en/JavaScript/Guide +[2]: http://stackoverflow.com/ +[3]: http://stackoverflow.com/users/170224/ivo-wetzel +[4]: http://stackoverflow.com/users/313758/yi-jiang +[5]: https://github.com/caio +[6]: https://github.com/blixt +[7]: http://cramerdev.com/ +[8]: http://javascriptgarden.info/ +[9]: https://github.com/BonsaiDen/JavaScript-Garden/blob/next/LICENSE +[10]: https://github.com/BonsaiDen/JavaScript-Garden +[11]: https://github.com/BonsaiDen/JavaScript-Garden/issues +[12]: http://chat.stackoverflow.com/rooms/17/javascript diff --git a/doc/pt/object/forinloop.md b/doc/pt/object/forinloop.md new file mode 100644 index 00000000..fc35f5b2 --- /dev/null +++ b/doc/pt/object/forinloop.md @@ -0,0 +1,41 @@ +## O laço `for in` + +Assim como o operador `in`, o laço `for in` percorre a cadeia prototype quando interage sobre as propriedades de um objeto. + +> **Nota:** O laço `for in` **não** interage sobre propriedades que +> que tenham o atributo `enumerable` configurado como `false`; por exemplo, a propriedade `length` de um array. + + // Poluindo o Object.prototype + Object.prototype.bar = 1; + + var foo = {moo: 2}; + for(var i in foo) { + console.log(i); // retorna ambos bar e moo + } + +Uma vez que não é possível alterar o comportamento do laço `for in` por si só, faz-se necessário filtrar as propriedades do objeto durante o ciclo de repetição do laço; isso é feito usando o método [`hasOwnProperty`](#object.hasownproperty) do `Object.prototype`. + +> **Nota:** Uma vez que o `for in` percorre toda a cadeia prototype, +> cada camada a mais na herança do objeto deixa a execução do laço mais lenta. + +### Utilizando `hasOwnProperty` como filtro + + // o mesmo foo utilizado anteriormente + for(var i in foo) { + if (foo.hasOwnProperty(i)) { + console.log(i); + } + } + +Esta é única forma correta de usar. Devido ao uso de `hasOwnProperty`, o exemplo **só** irá retornar `moo`. Quando `hasOwnProperty` é deixado de lado, o código fica propenso a erros nos casos em que o prototype - por exemplo `Object.prototype`- tenha sido estendido. + +Um framework largamente utilizado que estende o `Object.prototype` é [Prototype][1]. +Quando este framework é utilizado, laços `for in` que não utilizam +`hasOwnProperty` ficam protegidos contra erros. + +### Conclusão + +Recomenda-se utilizar `hasOwnProperty` **sempre**. Nunca faça pressuposições sobre o ambiente em que o código está sendo executado, ou se os prototypes nativos foram estendidos ou não. + +[1]: http://www.prototypejs.org/ + diff --git a/doc/pt/object/general.md b/doc/pt/object/general.md new file mode 100644 index 00000000..a5e88626 --- /dev/null +++ b/doc/pt/object/general.md @@ -0,0 +1,83 @@ +## Propriedades e manipulação de objetos + +Tudo em JavaScript se comporta como um objeto, com apenas duas exceções que são +[`null`](#core.undefined) e [`undefined`](#core.undefined). + + false.toString(); // 'false' + [1, 2, 3].toString(); // '1,2,3' + + function Foo(){} + Foo.bar = 1; + Foo.bar; // 1 + +Um equívoco muito comum é a idéia de que números não podem ser manipulados como objetos. O parser do JavaScript analisa a *notação de ponto* como ponto flutuante de um número. + + 2.toString(); // raises SyntaxError + +Existem duas soluções para contornar este problema e permtir que números se comportem como objetos. + + 2..toString(); // o segundo ponto é reconhecido corretamente + 2 .toString(); // perceba o espaço deixado à esquerda do ponto + (2).toString(); // 2 é interpretado primeiro + +### Objetos como tipo de dados + +Em JavaScript, Objetos podem também ser utilizados como [*Hashmaps*][1]; eles consistem principalmente de propriedades nomeadas, que apontam para valores. + +Usando um objeto literal - notação do tipo `{}`- é possível criar um objeto simples. Este novo objeto [herda](#object.prototype) de `Object.prototype` e não possui [propriedades próprias](#object.hasownproperty) definidas. + + var foo = {}; // um novo objeto vazio + + // um novo objeto com uma propriedade 'test' populada com o valor 12 + var bar = {test: 12}; + +### Acessando propriedades + +As propriedades de um objeto podem ser acessadas de duas maneiras, através da notação de ponto ou da notação de colchete. + + var foo = {name: 'kitten'} + foo.name; // kitten + foo['name']; // kitten + + var get = 'name'; + foo[get]; // kitten + + foo.1234; // Erro de sintaxe + foo['1234']; // funciona + +Ambas as notações trabalham de forma quase idêntica, com a única diferença de que o colchete permite configuração dinâmica de propriedades e uso de propriedades nomeadas que de outra maneira levaria à erros de sintaxe. + +### Removendo propriedades + +A única maneira de remover uma propriedade de um objeto é através do operador `delete`; definir uma propriedade como `undefined` ou `null` somente apaga o valor associado com tal propriedade, mas não remove a *key*. + + var obj = { + bar: 1, + foo: 2, + baz: 3 + }; + obj.bar = undefined; + obj.foo = null; + delete obj.baz; + + for(var i in obj) { + if (obj.hasOwnProperty(i)) { + console.log(i, '' + obj[i]); + } + } + +O código acima retorna tanto `bar undefined` quanto`foo null` - somente `baz` foi removido e, portanto, não saiu no output. + +### Notações de Keys + + var test = { + 'case': 'I am a keyword, so I must be notated as a string', + delete: 'I am a keyword, so me too' // dispara SyntaxError + }; + +Propriedades de objetos podem ser tanto representadas como caracteres simples bem como strings. Devido a outro engano do parser do JavaScript, o exemplo acima irá retornar `SyntaxError` remetendo ao ECMAScript 5. + +Este erro decorre do fato de que 'apagar' é uma *palavra reservada*; por consequencia, deve ser representada como uma *string literal* a fim de garantir a interpretação correta pelas antigas engines de JavaScript. + +[1]: http://en.wikipedia.org/wiki/Hashmap + diff --git a/doc/pt/object/hasownproperty.md b/doc/pt/object/hasownproperty.md new file mode 100644 index 00000000..2ff0589f --- /dev/null +++ b/doc/pt/object/hasownproperty.md @@ -0,0 +1,56 @@ +## `hasOwnProperty` + +Para verificar se uma propriedade está definida no **próprio** objeto e não em outro lugar +da sua [cadeia prototype](#object.prototype), é necessário utilizar o método +`hasOwnProperty` o qual todos os objetos herdam de `Object.prototype`. + +> **Nota:** **Não** é sufuciente verificar se uma propriedade é `undefined`. +> A propriedade pode muito bem existir, porém acontece de seu valor só ser +> `undefined`. + +`hasOwnProperty` é a única coisa em JavaScript a qual lida com propriedades e **não** percorre a cadeia prototype. + + // Poluindo Object.prototype + Object.prototype.bar = 1; + var foo = {goo: undefined}; + + foo.bar; // 1 + 'bar' in foo; // true + + foo.hasOwnProperty('bar'); // false + foo.hasOwnProperty('goo'); // true + +Somente `hasOwnProperty` irá retornar o resultado correto e esperado; isto é +essencial quando se interage sobre propriedades de qualquer objeto. **Não** existe +outra maneira de verificar propriedades que não estejam definidas no próprio objeto, mas +em outro lugar na cadeia prototype. + +### `hasOwnProperty` como propriedade + +JavaScript não protege o nome do propriedade `hasOwnProperty`; assim, se +existe a possibilidade de algum objeto possuir uma propriedade com este mesmo nome, +torna-se necessário utilizar um `hasOwnProperty` **externo** a fim de obter resultados corretos. + + var foo = { + hasOwnProperty: function() { + return false; + }, + bar: 'Here be dragons' + }; + + foo.hasOwnProperty('bar'); // sempre retorna false + + // Utiliza hasOwnProperty de outro objeto e o instancia com 'this' apontado para foo + ({}).hasOwnProperty.call(foo, 'bar'); // true + + // Também é possível utilizar hasOwnProperty do Object + // prototype para este fim + Object.prototype.hasOwnProperty.call(foo, 'bar'); // true + + +### Conclusão + +O método é a **única** maneira confiável `hasOwnProperty` para verificar a existência da propriedade em um objeto. +É recomendado que `hasOwnProperty` seja utilizado em **cada** interação de um [laço `for in`](#object.forinloop) +a fim de evitar erros de extensão do [prototype](#object.prototype). + diff --git a/doc/pt/object/prototype.md b/doc/pt/object/prototype.md new file mode 100644 index 00000000..a44bb25e --- /dev/null +++ b/doc/pt/object/prototype.md @@ -0,0 +1,109 @@ +## Prototype + +JavaScript não dispõe de nenhum modelo clássico de herança; em vez disso, ele +faz uso do modelo *prototypal*. + +Enquanto isto é considerado muitas vezes como sendo um dos pontos fracos do JavaScript, o modelo de herança prototypal é de fato muito mais poderoso do que o modelo clássico. +Por exemplo, isto torna relativamente trivial construir um modelo clássico +com base no modelo prototypal, enquanto que o contrário se verifica como uma tarefa mais difícil. + +JavaScript é a única linguagem amplamente utilizada que apresenta um modelo de herança do tipo prototypal, +por isso pode levar algum tempo até que você se ajuste às diferenças entre os dois modelos. + +A primeira grande diferença é que herança em JavaScript utiliza o conceito de *cadeias prototype*. + +> **Nota:** Usando simplesmente `Bar.prototype = Foo.prototype` resultará em ambos os objetos +> compartilhando **o mesmo** prototype. Portanto, as alterações no prototype de um dos objetos +> também irá afetar o prototype do outro, o que na maioria dos casos não é o esperado. + + function Foo() { + this.value = 42; + } + Foo.prototype = { + method: function() {} + }; + + function Bar() {} + + // Apontar Bar's prototype para uma nava instância de Foo + Bar.prototype = new Foo(); + Bar.prototype.foo = 'Hello World'; + + // Tenha certeza de que Bar é o construtor atual + Bar.prototype.constructor = Bar; + + var test = new Bar(); // criar uma nova instância de bar + + // A cadeia prototype resultante + test [instance of Bar] + Bar.prototype [instance of Foo] + { foo: 'Hello World' } + Foo.prototype + { method: ... } + Object.prototype + { toString: ... /* etc. */ } + +No código acima, o objeto `test` irá herdar de ambos `Bar.prototype` e +`Foo.prototype`; portanto, ele terá acesso à função `method` que foi definida em Foo. +Ele também terá acesso à propriedade `value` da **única** instância de Foo que é seu próprio prototype. +É importante perceber que `new Bar()` não cria uma nova instância de `Foo`, mas +reutiliza aquela associada ao prototype; assim, todas as intâncias `Bar` dividirão a +**mesma** propriedade `value`. + +> **Nota:** **Não** utilize `Bar.prototype = Foo`, uma vez que isto não aponta para o prototype de `Foo`, mas sim para o objeto função `Foo`. +> Assim a cadeia prototype irá percorrer `Function.prototype` e não `Foo.prototype`; +> desse modo, `method` não estará na cadeia prototype. + +### Buscando propriedades + +Ao acessar as propriedades de um objeto, JavaScript irá percorre a cadeia prototype +**até o topo** para encontrar a propriedade solicitada. + +Caso atinja o topo da cadeia - denominada `Object.prototype` - e não encontre +a propriedade especificada, o valor [undefined](#core.undefined) será retornado. + +### A propriedade Prototype + +Enquanto a propriedade prototype é utilizada pela linguagem na contrução de cadeia de prototype, +ainda é possível associar **qualquer** valor dado a ele. No entanto, tipos primitivos serão +ignorados quando associados como prototype. + + function Foo() {} + Foo.prototype = 1; // sem efeito + +Atribuindo objetos, como demonstrado no exemplo anterior, irá funcionar, e permite +a criação dinâmica de cadeias prototype. + +### Performance + +O tempo de pesquisa por propriedades que estão no topo da cadeia prototype +pode ter um impacto negativo na performance, principalmente em código +onde a performance é um fator crítico. Além disso, a busca por propriedades que não existem +também atravessa a cadeia prototype. + +Além disso, ao [interagir](#object.forinloop) com propriedades de um objeto +**cada** propriedade na cadeia prototype será enumerada. + +### Estendendo Prototypes nativos + +Uma prática ruim que é normalmente utilizada é a de estender `Object.prototype` ou qualquer outro prototype construído. + +Esta técnica é denominada [monkey patching][1] e quebra o *encapsulamento*. +Mesmo utilizada por frameworks populars como [Prototype][2], não existe mais razão +para poluir tipos built-in com funcionalidades adicionais *fora de padrão*. + +A **única** boa razão existente para continuar estendendo um built-in prototype +é a de assegurar as novas funcionalidade de engines JavaScript modernas; por exemplo, [`Array.forEach`][3]. + +### Conclusão + +É **essencial** entender o modelo de herança prototypal antes de escrever código complexo +que faço uso do mesmo. Além disso, tome cuidado com o tamanho da cadeia prototype em seu código +e a refatore caso necessário a fim de evitar futuros problemas de performance. A respeito do prototypes nativos, +estes **nunca** devem ser estendidos ao menos que seja para manter a compatibilidade com novas +características do JavaScript. + +[1]: http://en.wikipedia.org/wiki/Monkey_patch +[2]: http://prototypejs.org/ +[3]: https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/forEach + diff --git a/doc/pt/other/timeouts.md b/doc/pt/other/timeouts.md new file mode 100644 index 00000000..8d522c4e --- /dev/null +++ b/doc/pt/other/timeouts.md @@ -0,0 +1,161 @@ +### `setTimeout` e `setInterval` + +Uma vez que JavaScript é assíncrono, é possível agendar a execução de uma função +usando as funções `setTimeout` e `setInterval`. + +> **Nota:** Timeouts **não** fazem parte do Padrão ECMAScript. Eles são +> implementados como parte do [DOM][1]. + + function foo() {} + var id = setTimeout(foo, 1000); // retorna um Number > 0 + +Quando `setTimeout` é chamado, ele retorna o ID do timeout e agenda a execução de `foo` +para **aproximadamente** mil milissegundos no futuro. +`foo` será executado uma **única** vez. + +Dependendo de como a enine JavaScript que está rodando o código resolve o timer, bem como +o fato de que o JavaScript é single threaded e outro código que é executado pode bloquear a +thread, **não há como** garantir a precisão dos intervalos especificados nas chamadas `setTimeout`. + +A função que foi passada como primeiro parâmetro será chamada pelo *objeto global*, o que +significa que o [`this`](#function.this) dentro da função chamada se refere ao objeto global. + + function Foo() { + this.value = 42; + this.method = function() { + // this faz referência ao objeto global + console.log(this.value); // log undefined + }; + setTimeout(this.method, 500); + } + new Foo(); + + +> **Nota:** Como o `setTimeout` espera um **objeto de função** para primeiro parâmetro, um +> erro comum é usar `setTimeout(foo(), 1000)`, que irá usar o +> **o valor retornado** por `foo` e **não** `foo`. Isto é, na maioria das vezes, +> um erro silencioso, visto que neste caso a função retorna `undefined`, logo `setTimeout` **não** +> lançará erro algum. + +### Acumulando chamadas com o `setInterval` + +Enquanto que `setTimeout` somente executa a função uma vez, `setInterval` - como +o nome sugere - irá executar a função a **cada** `X` milisegundos, porém seu uso é +desencorajado. + +Quando um código em execução bloqueia a chamada do timeout, `setInterval` continuará +emitindo chamads para a função em questão. Isto pode, especialmente com intervalos curtos, +resultar em uma pilha de chamadas de função. + + function foo(){ + // algo que bloqueie por 1 segundo + } + setInterval(foo, 1000); + +No código acima, `foo` será chamada uma vez e irá então bloquear a execução por um segundo. + +Enquanto `foo` bloqueia a execução, `setInterval` irá programar mais chamadas para ela. +Em seguida, quando `foo` completar sua execução, existirão **dez** chamadas programadas +para ela aguardando por execução. + +### Lidando com possíveis bloqueios de código + +A solução mais fácil, bem como a mais controlável, é usar `setTimeout` dentro da +própria função. + + function foo(){ + // Algo que bloqueia por um segundo + setTimeout(foo, 1000); + } + foo(); + +Isto não somente encapsula a chamada para `setTimeout`, mas também previne +o acumulo de chamadas e dá controle adicional. `foo` por si só pode decidir +quando rodar novamente ou não. + +### Limpando Timeouts manualmente + +A limpeza de intervalos e timeouts funciona passando o respectivo ID +para `clearTimeout` ou `clearInterval`, dependendo onde a função `set` foi usada primeiro. + + var id = setTimeout(foo, 1000); + clearTimeout(id); + +### Limpando todos os Timeouts + +Como não existe métodos próprios para limpar todos os timeouts e/ou intervalos, +é necessário usar a força bruta para chegar a esta funcionalidade. + + // limpe "todos" os timeouts + for(var i = 1; i < 1000; i++) { + clearTimeout(i); + } + +Mas ainda podem haver timeouts que não serão afetados por este número arbitrário. +Uma outra maneira de fazer isto é considerar que o ID dado a um timeout é +incrementado um a um cada vez que você chama `setTimeout`. + + // limpe "todos" os timeouts + var biggestTimeoutId = window.setTimeout(function(){}, 1), + i; + for(i = 1; i <= biggestTimeoutId; i++) { + clearTimeout(i); + } + +Apesar desta maneira funcionar nos principais navegadores hoje em dia, não está especificado +que os IDs respeitem uma ordem como este, logo esta ordem pode ser variada. Por este motivo, em vez disso +é recomendade manter o controle de todos os IDs de timeouts, de forma que possam ser apagados precisamente. + +### O uso oculto do `eval` + +`setTimeout` e `setInterval` aceitam uma string como primeiro argumento. +Esta funcionalidade **nunca** deve ser utilizada pois internamente faz uso de `eval`. + +> **Nota:** Uma vez que funções timeout **não** são especificadas pelo padrão ECMAScript, a maneira como +> eles interpretam uma string passada pode variar de acordo com a implementação do JavaScript. Por exemplo, JScript +> da Microsoft faz uso do construtor `Function` no lugar do `eval`. + + function foo() { + // será chamada + } + + function bar() { + function foo() { + // nunca será chamada + } + setTimeout('foo()', 1000); + } + bar(); + +Uma vez que `eval` não é chamado [diretamente](#core.eval) neste caso, a string +passada como argumento para `setTimeout` será executada no *escopo global*; assim, ela +não usará a variávle local `foo` do escopo de `bar`. + +Também é recomendado **não** usar uma string para passar argumentos +para a função que será chamada por qualquer uma das funções de timeout. + + function foo(a, b, c) {} + + // NUNCA use isto + setTimeout('foo(1, 2, 3)', 1000) + + // Utilize uma função anônima do lugar + setTimeout(function() { + foo(a, b, c); + }, 1000) + +> **Nota:** Enquanto que é possivel utilizar a sintaxe +> `setTimeout(foo, 1000, a, b, c)`, não é recomendada, pois sua utilização pode levar +> a erros sútis quando utilizadas com [métodos](#function.this). + +### Conclusão + +Uma string **nunca** deve ser usada como parâmetro `setTimeout` ou +`setInterval`. Esta prática é um sinal **claro** de código ruim, quando argumentos precisam ser fornecido para a função que é chamada. +Uma *função anônima* é que deve ser passada para que, em seguida, cuide da chamada. + +Além disso, o uso de `setInterval` deve ser evitado pois seu scheduler não é +bloqueado pela execução do JavaScript. + +[1]: http://en.wikipedia.org/wiki/Document_Object_Model "Document Object Model" + diff --git a/doc/pt/types/casting.md b/doc/pt/types/casting.md new file mode 100644 index 00000000..d7dc9b3f --- /dev/null +++ b/doc/pt/types/casting.md @@ -0,0 +1,67 @@ +## Conversão de tipos + +JavaScript é *fracamente tipado*, logo ele aplica a *coerção de tipos* +**sempre** que possível. + + // Estes retornam true + new Number(10) == 10; // Number.toString() é convertido + // de volta a um número + + 10 == '10'; // Strings são convertidas em Number + 10 == '+10 '; // Mais loucuras com strings + 10 == '010'; // E mais + isNaN(null) == false; // null é convertido em 0 + // que claro não é NaN + + // Estes retornam false + 10 == 010; + 10 == '-10'; + +> **Nota ES5:** Literais Number que começam com um `0` são interpretados como octais +> (Base 8). Suporte à octais para estes literais foi **removido** no modo estrito do ECMAScript. + +A fim de evitar os problemas acima, o uso do [operador de igualdade estrito](#types.equality) +é **fortemente** recomendado. Embora ele evite uma série de problemas comuns, +existem ainda muitas outras questões que surgem do fraco sistema de tipagem do JavaScript. + +### Construtores de tipos nativos + +Os construtores de tipos nativos como `Number` e `String` comportam-se +diferentemente quando utilizados com ou sem a palavra-chave `new`. + + new Number(10) === 10; // False, Object e Number + Number(10) === 10; // True, Number e Number + new Number(10) + 0 === 10; // True, devido à conversão implícita + +Utilizar um tipo nativo como `Number` como construtor iré criar um novo objeto `Number`, +porém omitir a palavra-chave `new` fará com que a função `Number` se comporte como +um conversor. + +Além, passando valores literais ou não-objetos irá resultar em mais coerções +de tipos. + +A melhor opção é converter para um dos três possíveis tipos **de forma explícita**. + +### Convertendo para String + + '' + 10 === '10'; // true + +Prefixando uma string vazia, qualquer valor pode ser facilmente convertido em uma string. + +### Convertendo para Number + + +'10' === 10; // true + +Ao utilizar o operador de soma **unário**, é possível converter um valor para Number. + +### Convertendo para Boolean + +Ao utilizar duas vezes o operador **not**, é possível converter um valor para Boolean. + + !!'foo'; // true + !!''; // false + !!'0'; // true + !!'1'; // true + !!'-1' // true + !!{}; // true + !!true; // true \ No newline at end of file diff --git a/doc/pt/types/equality.md b/doc/pt/types/equality.md new file mode 100644 index 00000000..709b1186 --- /dev/null +++ b/doc/pt/types/equality.md @@ -0,0 +1,70 @@ +## Igualdades e comparações + +JavaScript tem duas maneiras diferentes de comparar a igualdades entre valores de objetos. + +### O operador de igualdade + +O operador de igualdade consiste de dois sinais de igual : `==` + +JavaScript é *fracamente tipado*. Isto que dizer que o operador de igualdade +**induz** tipos ao invés de compará-los. + + "" == "0" // false + 0 == "" // true + 0 == "0" // true + false == "false" // false + false == "0" // true + false == undefined // false + false == null // false + null == undefined // true + " \t\r\n" == 0 // true + +A tabela acima mostra o resultado da coerção de tipos, e isto é principal razão +para que o uso `==` seja amplamente considerado uma má prática. Seu uso introduz defeitos +difíceis de serem rastreados devido às suas complicadas regras de conversão. + +Adicionalmente, também existe um impacto em performance quando a coerção acontece; +por exemplo, é necessário que uma string seja convertida em um número antes que seja comparada +com outro número. + +### O operador de igualdade estrito + +O operador de igualdade estrito consiste de **três** sinais de igual : `===`. + +Ele funciona como o operador de igualdade normal, salvo que o operador de igualdade estrito +**não** realiza coerção de tipos entre seus operandos. + + "" === "0" // false + 0 === "" // false + 0 === "0" // false + false === "false" // false + false === "0" // false + false === undefined // false + false === null // false + null === undefined // false + " \t\r\n" === 0 // false + +Os resultados acima são bastante claros e permitem uma análise objetiva do código. Pode parecer complicar o código até um certo ponto + mas também traz ganhos de performance em casos em que os operandos são de tipos diferentes. + +### Comparando Objetos + +Enquanto que ambos `==` e `===` são denominados operadores de **igualdade**, eles se comportam de +formas diferentes quando pelo menos um de seus operandos é um `Object`. + + {} === {}; // false + new String('foo') === 'foo'; // false + new Number(10) === 10; // false + var foo = {}; + foo === foo; // true + +Aqui, ambos os operadores comparam em função da **identidade** e **não** da igualdade; isto é, +eles vão comparar em função da mesma **instância** do objeto, muito parecido com o `is` do Python +e a comparação de ponteiros em C. + +### Conclusão + +E fortemente recomendado que só se use o operador de ** igualdade estrito**. +Em casos onde a coerção de tipos seja necessária, isto deve ser feito [explicitamente](#types.casting) +e não deve ser deixado para as complicadas regras de coerção da linguagem. + diff --git a/doc/pt/types/instanceof.md b/doc/pt/types/instanceof.md new file mode 100644 index 00000000..9cbd7561 --- /dev/null +++ b/doc/pt/types/instanceof.md @@ -0,0 +1,38 @@ +## O operador `instanceof` + +O operador `instanceof` compara os construtores de seus dois operandos. +Ele é útil somente quando estamos comparando objetos personalizados. Quando utilizado em tipos nativos, +ele é tão inútil quanto [o operador typeof](#types.typeof). + +### Comparando objetos personalizados + + function Foo() {} + function Bar() {} + Bar.prototype = new Foo(); + + new Bar() instanceof Bar; // true + new Bar() instanceof Foo; // true + + // Isto somente define Bar.prototype ao objeto de função Foo, + // mas não à instância atual de Foo + Bar.prototype = Foo; + new Bar() instanceof Foo; // false + +### Utilizando `instanceof` com tipos nativos + + new String('foo') instanceof String; // true + new String('foo') instanceof Object; // true + + 'foo' instanceof String; // false + 'foo' instanceof Object; // false + +Uma coisa importante para perceber aqui é que `instanceof` não funciona em objetos +originados de diferentes contextos de JavaScript (isto é, de diferentes documentos em um +navegador web), uma vez que seus construtores não irão representar exatamente o mesmo objeto. + +### Conclusão + +O operador `instanceof` deve **somente** ser utilizado quando estive lidando +com objetos customizados originados de um mesmo contexto JavaScript. Bem como o operador +[`typeof`](#types.typeof), qualquer outro uso de `instanceof` deve ser **evitado**. + diff --git a/doc/pt/types/typeof.md b/doc/pt/types/typeof.md new file mode 100644 index 00000000..3f499ee5 --- /dev/null +++ b/doc/pt/types/typeof.md @@ -0,0 +1,83 @@ +## O operador `typeof` + +O operador `typeof`(em conjunto com +[`instanceof`](#types.instanceof) é provavelmente a maior falha de design do JavaScript, +por estar **complemente mal implementado**. + +Embora `instanceof` ainda tenha seu uso limitado, `typeof` realmente só possui uma utilidade, +a qual **não** acaba por ser a de verificar o tipo de um objeto. + +> **Nota:** Enquanto que `typeof` possa também ser invocado com uma sintaxe parecida com a de chamada de função, i.e. +> `typeof(obj)`, não se trata de uma chamada de função. Os parênteses se comportam normalmente +> e o valor retornado será usado como o operando do operador `typeof`. +> **Não** existe a função `typeof`. + +### A tabela de tipos em JavaScript + + Value Class Type + ------------------------------------- + "foo" String string + new String("foo") String object + 1.2 Number number + new Number(1.2) Number object + true Boolean boolean + new Boolean(true) Boolean object + new Date() Date object + new Error() Error object + [1,2,3] Array object + new Array(1, 2, 3) Array object + new Function("") Function function + /abc/g RegExp object (function in Nitro/V8) + new RegExp("meow") RegExp object (function in Nitro/V8) + {} Object object + new Object() Object object + +Na tabela acima, *Type* se refere ao valor de retorno do operador `typeof`. +Como pode ser facilmente observado, este valor não é nada consistente. + +O *Class* se refere ao valor interno da propriedade `[[Class]]` de um objeto. + +> **Da especificação:** O valor de `[[Class]]` pode ser +> das seguintes strings. `Arguments`, `Array`, `Boolean`, `Date`, `Error`, +> `Function`, `JSON`, `Math`, `Number`, `Object`, `RegExp`, `String`. + +A fim de se obeter o valor de `[[Class]]`, deve-se utilizar o método +`toString` de `Object.prototype`. + +### A classe de um objeto + +A especificação fornece exatamente uma maneira de acessar o valor de `[[Class]]`, +com o uso de `Object.prototype.toString`. + + function is(type, obj) { + var clas = Object.prototype.toString.call(obj).slice(8, -1); + return obj !== undefined && obj !== null && clas === type; + } + + is('String', 'test'); // true + is('String', new String('test')); // true + +No exemplo acima, `Object.prototype.toString` é chamado enquanto que o valor de [this](#function.this) +é definido como o objeto o qual o valor `[[Class]]` deva ser retornado. + +> **Nota ES5:** Por conveniência o retorno do valor de `Object.prototype.toString` +> para ambos `null` e `undefined` foi **modificado** de `Object` para `Null` e +> `Undefined` no ECMAScript 5. + +### Teste para variáveis não-definidas + + typeof foo !== 'undefined' + +O exemplo acima irá verificar se `foo` foi declarado ou não; apenas +o fato de referênciá-lo poderia resultar em `ReferenceError`. Esta é a única utilidade +real de `typeof`. + +### Conclusão + +A fim de verificar o tipo de um objeto, é fortemente recomendade o uso de +`Object.prototype.toString` pelo motivo de que esta é a única maneira confiável de ser feita. +Como demonstrado na tabela anterior, alguns valores retornados de `typeof` não estão definidos na +especificação; assim, eles podem variar entre implementações. +O uso de `typeof` deve ser evitado, a menos que não se esteja testando se uma variável está ou não definida. + + From 82f528b968e72a36c793856f7fe678e8357147cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ang=C3=A9llica=20Cardozo?= Date: Sat, 20 Dec 2014 13:43:30 -0200 Subject: [PATCH 002/105] Add ptbr folder Remove pt and add ptbr --- doc/language.json | 5 ++--- doc/{pt => ptbr}/array/constructor.md | 0 doc/{pt => ptbr}/array/general.md | 0 doc/{pt => ptbr}/core/delete.md | 0 doc/{pt => ptbr}/core/eval.md | 0 doc/{pt => ptbr}/core/semicolon.md | 0 doc/{pt => ptbr}/core/undefined.md | 0 doc/{pt => ptbr}/function/arguments.md | 0 doc/{pt => ptbr}/function/closures.md | 0 doc/{pt => ptbr}/function/constructors.md | 0 doc/{pt => ptbr}/function/general.md | 0 doc/{pt => ptbr}/function/scopes.md | 0 doc/{pt => ptbr}/function/this.md | 0 doc/{pt => ptbr}/index.json | 0 doc/{pt => ptbr}/intro/index.md | 0 doc/{pt => ptbr}/object/forinloop.md | 0 doc/{pt => ptbr}/object/general.md | 0 doc/{pt => ptbr}/object/hasownproperty.md | 0 doc/{pt => ptbr}/object/prototype.md | 0 doc/{pt => ptbr}/other/timeouts.md | 0 doc/{pt => ptbr}/types/casting.md | 0 doc/{pt => ptbr}/types/equality.md | 0 doc/{pt => ptbr}/types/instanceof.md | 0 doc/{pt => ptbr}/types/typeof.md | 0 24 files changed, 2 insertions(+), 3 deletions(-) rename doc/{pt => ptbr}/array/constructor.md (100%) rename doc/{pt => ptbr}/array/general.md (100%) rename doc/{pt => ptbr}/core/delete.md (100%) rename doc/{pt => ptbr}/core/eval.md (100%) rename doc/{pt => ptbr}/core/semicolon.md (100%) rename doc/{pt => ptbr}/core/undefined.md (100%) rename doc/{pt => ptbr}/function/arguments.md (100%) rename doc/{pt => ptbr}/function/closures.md (100%) rename doc/{pt => ptbr}/function/constructors.md (100%) rename doc/{pt => ptbr}/function/general.md (100%) rename doc/{pt => ptbr}/function/scopes.md (100%) rename doc/{pt => ptbr}/function/this.md (100%) rename doc/{pt => ptbr}/index.json (100%) rename doc/{pt => ptbr}/intro/index.md (100%) rename doc/{pt => ptbr}/object/forinloop.md (100%) rename doc/{pt => ptbr}/object/general.md (100%) rename doc/{pt => ptbr}/object/hasownproperty.md (100%) rename doc/{pt => ptbr}/object/prototype.md (100%) rename doc/{pt => ptbr}/other/timeouts.md (100%) rename doc/{pt => ptbr}/types/casting.md (100%) rename doc/{pt => ptbr}/types/equality.md (100%) rename doc/{pt => ptbr}/types/instanceof.md (100%) rename doc/{pt => ptbr}/types/typeof.md (100%) diff --git a/doc/language.json b/doc/language.json index dbf7c885..e862f82a 100644 --- a/doc/language.json +++ b/doc/language.json @@ -1,5 +1,4 @@ { "default": "en", - "listed": ["en", "fi", "ru", "zhtw", "zh", "tr", "pl", "ko", "ja", "es", "it", "hu","pt"] -} - + "listed": ["en","es","fi","hu","it","ja","ko","pl","ptbr","ru","tr","zh","zhtw"] +} diff --git a/doc/pt/array/constructor.md b/doc/ptbr/array/constructor.md similarity index 100% rename from doc/pt/array/constructor.md rename to doc/ptbr/array/constructor.md diff --git a/doc/pt/array/general.md b/doc/ptbr/array/general.md similarity index 100% rename from doc/pt/array/general.md rename to doc/ptbr/array/general.md diff --git a/doc/pt/core/delete.md b/doc/ptbr/core/delete.md similarity index 100% rename from doc/pt/core/delete.md rename to doc/ptbr/core/delete.md diff --git a/doc/pt/core/eval.md b/doc/ptbr/core/eval.md similarity index 100% rename from doc/pt/core/eval.md rename to doc/ptbr/core/eval.md diff --git a/doc/pt/core/semicolon.md b/doc/ptbr/core/semicolon.md similarity index 100% rename from doc/pt/core/semicolon.md rename to doc/ptbr/core/semicolon.md diff --git a/doc/pt/core/undefined.md b/doc/ptbr/core/undefined.md similarity index 100% rename from doc/pt/core/undefined.md rename to doc/ptbr/core/undefined.md diff --git a/doc/pt/function/arguments.md b/doc/ptbr/function/arguments.md similarity index 100% rename from doc/pt/function/arguments.md rename to doc/ptbr/function/arguments.md diff --git a/doc/pt/function/closures.md b/doc/ptbr/function/closures.md similarity index 100% rename from doc/pt/function/closures.md rename to doc/ptbr/function/closures.md diff --git a/doc/pt/function/constructors.md b/doc/ptbr/function/constructors.md similarity index 100% rename from doc/pt/function/constructors.md rename to doc/ptbr/function/constructors.md diff --git a/doc/pt/function/general.md b/doc/ptbr/function/general.md similarity index 100% rename from doc/pt/function/general.md rename to doc/ptbr/function/general.md diff --git a/doc/pt/function/scopes.md b/doc/ptbr/function/scopes.md similarity index 100% rename from doc/pt/function/scopes.md rename to doc/ptbr/function/scopes.md diff --git a/doc/pt/function/this.md b/doc/ptbr/function/this.md similarity index 100% rename from doc/pt/function/this.md rename to doc/ptbr/function/this.md diff --git a/doc/pt/index.json b/doc/ptbr/index.json similarity index 100% rename from doc/pt/index.json rename to doc/ptbr/index.json diff --git a/doc/pt/intro/index.md b/doc/ptbr/intro/index.md similarity index 100% rename from doc/pt/intro/index.md rename to doc/ptbr/intro/index.md diff --git a/doc/pt/object/forinloop.md b/doc/ptbr/object/forinloop.md similarity index 100% rename from doc/pt/object/forinloop.md rename to doc/ptbr/object/forinloop.md diff --git a/doc/pt/object/general.md b/doc/ptbr/object/general.md similarity index 100% rename from doc/pt/object/general.md rename to doc/ptbr/object/general.md diff --git a/doc/pt/object/hasownproperty.md b/doc/ptbr/object/hasownproperty.md similarity index 100% rename from doc/pt/object/hasownproperty.md rename to doc/ptbr/object/hasownproperty.md diff --git a/doc/pt/object/prototype.md b/doc/ptbr/object/prototype.md similarity index 100% rename from doc/pt/object/prototype.md rename to doc/ptbr/object/prototype.md diff --git a/doc/pt/other/timeouts.md b/doc/ptbr/other/timeouts.md similarity index 100% rename from doc/pt/other/timeouts.md rename to doc/ptbr/other/timeouts.md diff --git a/doc/pt/types/casting.md b/doc/ptbr/types/casting.md similarity index 100% rename from doc/pt/types/casting.md rename to doc/ptbr/types/casting.md diff --git a/doc/pt/types/equality.md b/doc/ptbr/types/equality.md similarity index 100% rename from doc/pt/types/equality.md rename to doc/ptbr/types/equality.md diff --git a/doc/pt/types/instanceof.md b/doc/ptbr/types/instanceof.md similarity index 100% rename from doc/pt/types/instanceof.md rename to doc/ptbr/types/instanceof.md diff --git a/doc/pt/types/typeof.md b/doc/ptbr/types/typeof.md similarity index 100% rename from doc/pt/types/typeof.md rename to doc/ptbr/types/typeof.md From 20f073a3ab6db280c269d1fae277097a8fd2c316 Mon Sep 17 00:00:00 2001 From: PoziWorld Date: Sun, 21 Dec 2014 17:41:14 -0800 Subject: [PATCH 003/105] can be converted a boolean => converted to --- doc/en/types/casting.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/en/types/casting.md b/doc/en/types/casting.md index d5ed0944..f12aa811 100644 --- a/doc/en/types/casting.md +++ b/doc/en/types/casting.md @@ -58,7 +58,7 @@ Using the **unary** plus operator, it is possible to cast to a number. ### Casting to a Boolean -By using the **not** operator twice, a value can be converted a boolean. +By using the **not** operator twice, a value can be converted to a boolean. !!'foo'; // true !!''; // false From 2ee1a341ca17ea65baf4247ac845bb5f7b79784f Mon Sep 17 00:00:00 2001 From: Sam Morrow Date: Wed, 14 Jan 2015 10:49:22 +0000 Subject: [PATCH 004/105] Add Closures setTimeout example --- doc/en/function/closures.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/doc/en/function/closures.md b/doc/en/function/closures.md index f8061712..06207121 100644 --- a/doc/en/function/closures.md +++ b/doc/en/function/closures.md @@ -96,6 +96,18 @@ above. })(i), 1000) } +The other popular way to acheive this is to add an additional argument to +the setTimeout function, which behaves as a closure. + + + for(var i = 0; i < 10; i++) { + setTimeout(function(e) { + console.log(e); + }, 1000, i); + } + +Some legacy JS environments do not support this, however. + There's yet another way to accomplish this by using `.bind`, which can bind a `this` context and arguments to function. It behaves identically to the code above From 2dd022166fb9745d4c9076298f938ddd8d7c7020 Mon Sep 17 00:00:00 2001 From: Sam Morrow Date: Wed, 14 Jan 2015 10:49:35 +0000 Subject: [PATCH 005/105] Add Closures setTimeout example --- doc/en/function/closures.md | 1 - 1 file changed, 1 deletion(-) diff --git a/doc/en/function/closures.md b/doc/en/function/closures.md index 06207121..f1d1b07a 100644 --- a/doc/en/function/closures.md +++ b/doc/en/function/closures.md @@ -99,7 +99,6 @@ above. The other popular way to acheive this is to add an additional argument to the setTimeout function, which behaves as a closure. - for(var i = 0; i < 10; i++) { setTimeout(function(e) { console.log(e); From 0cbdf51ba05838b5cd70d49ab66052ea3e01ae99 Mon Sep 17 00:00:00 2001 From: Sam Morrow Date: Wed, 14 Jan 2015 11:12:29 +0000 Subject: [PATCH 006/105] Fix terminology in PR --- doc/en/function/closures.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/en/function/closures.md b/doc/en/function/closures.md index f1d1b07a..7112f77c 100644 --- a/doc/en/function/closures.md +++ b/doc/en/function/closures.md @@ -97,7 +97,7 @@ above. } The other popular way to acheive this is to add an additional argument to -the setTimeout function, which behaves as a closure. +the setTimeout function, which passes these arguments to the callback. for(var i = 0; i < 10; i++) { setTimeout(function(e) { From 5f3bc277acfe4cae5f28c615f1cc37094d2b4984 Mon Sep 17 00:00:00 2001 From: Sam Morrow Date: Wed, 14 Jan 2015 12:00:25 +0000 Subject: [PATCH 007/105] Explain Legacy IE incompatability --- doc/en/function/closures.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/en/function/closures.md b/doc/en/function/closures.md index 7112f77c..a0085a5c 100644 --- a/doc/en/function/closures.md +++ b/doc/en/function/closures.md @@ -105,7 +105,7 @@ the setTimeout function, which passes these arguments to the callback. }, 1000, i); } -Some legacy JS environments do not support this, however. +Some legacy JS environments (Internet Explorer 9 & below) do not support this. There's yet another way to accomplish this by using `.bind`, which can bind a `this` context and arguments to function. It behaves identically to the code From 26a4afaaf97c094d4d44149578ccf4bb803ce45c Mon Sep 17 00:00:00 2001 From: KwanEsq Date: Wed, 14 Jan 2015 16:31:24 +0000 Subject: [PATCH 008/105] Remove style attribute from mainNav after slide up, fixes #99 After showing/hiding the menu in mobile mode, switching to fullscreen leaves the mainNav hidden because jquery set style="display: none;" at the end of the slideUp() animation. This clears the style so it displays again. --- site/javascript/garden.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site/javascript/garden.js b/site/javascript/garden.js index cdaa174f..954674d0 100644 --- a/site/javascript/garden.js +++ b/site/javascript/garden.js @@ -184,7 +184,7 @@ Page.prototype = { $('#nav_main').click(function(){ if(that.window.width() < 1000) - mainNav.slideUp(300); + mainNav.slideUp(300, function() {this.removeAttr('style');}); }); }, From 6d2eaf9d524bf7be013bcc996e4200243f1601cc Mon Sep 17 00:00:00 2001 From: KwanEsq Date: Wed, 14 Jan 2015 19:33:55 +0000 Subject: [PATCH 009/105] Allow scrolling the nav menu when javascript is off --- site/style/garden.css | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/site/style/garden.css b/site/style/garden.css index 8b1896fb..d8100fa1 100644 --- a/site/style/garden.css +++ b/site/style/garden.css @@ -117,6 +117,11 @@ nav > div li.active a { width: 200px; } +#nav_main > ul { + height: calc(100% - 4em); + overflow-y: auto; +} + nav li { font-size: 16px; margin: 0px; From bc70cd394fd254b0076540cf24050078cabcd933 Mon Sep 17 00:00:00 2001 From: Oleg Fedotkin Date: Thu, 29 Jan 2015 11:54:51 +0300 Subject: [PATCH 010/105] ru/core/delete translation added --- doc/ru/core/delete.md | 88 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 88 insertions(+) create mode 100644 doc/ru/core/delete.md diff --git a/doc/ru/core/delete.md b/doc/ru/core/delete.md new file mode 100644 index 00000000..7db3010b --- /dev/null +++ b/doc/ru/core/delete.md @@ -0,0 +1,88 @@ +## Оператор `delete` + +Если говорить коротко, то JavaScript *невозможно* удалить глобальную переменную, функцию или любой другой объект, которому задан атрибут `DontDelete` . + +### Глобальный код и код функции + +Если переменная или функция определена в глобальной области видимости (scope) или в +[области видимости функции](#function.scopes), это значит что она является +свойством (property) глобального или же Activation объекта. +Подобные свойства имеют набор атрибутов, одним из которых и является +упомянутый ранее `DontDelete`. Объявление переменных и функций в коде +функции или глобально всегда создает свойство с атрибутом `DontDelete`, и поэтому +не может быть удалено. + + // глобальная переменная: + var a = 1; // задается DontDelete + delete a; // false + a; // 1 + + // обычная функция: + function f() {} // задается DontDelete + delete f; // false + typeof f; // "function" + + // переназначение не поможет: + f = 1; + delete f; // false + f; // 1 + +### Явные свойства + +Явно заданные свойство могут быть удалены обычным способом. + + // явно заданные свойства: + var obj = {x: 1}; + obj.y = 2; + delete obj.x; // true + delete obj.y; // true + obj.x; // undefined + obj.y; // undefined + +В примере выше, `obj.x` и `obj.y` могут быть удалены потому что у них не задан +атрибут `DontDelete`. Именно поэтому следующий пример тоже сработает. + + // работает хорошо везде, кроме IE: + var GLOBAL_OBJECT = this; + GLOBAL_OBJECT.a = 1; + a === GLOBAL_OBJECT.a; // true - просто глобальная переменная + delete GLOBAL_OBJECT.a; // true + GLOBAL_OBJECT.a; // undefined + +Здесь мы используем небольшой трюк, чтобы удалить `a`. [`this`](#function.this) здесь +относится к глобальному объекту и мы явно указали удаление переменной `a` как свойства +глобального объекта, что и позволи нам ее удалить. + +Из-за нескольких багов в IE (как минимум 6-8) предыдущий код работать в нем не будет. + +### Аргументы функций и встроенные модули (built-ins) + +Обычным аргументам функций [`arguments` objects](#function.arguments) и +встроенным свойствам также задан атрибут `DontDelete`. + + // аргументы функции и свойства: + (function (x) { + + delete arguments; // false + typeof arguments; // "object" + + delete x; // false + x; // 1 + + function f(){} + delete f.length; // false + typeof f.length; // "number" + + })(1); + +### Host объекты + +Host объект - это объект, предоставляемый окружением. К таким объектам относятся `window`, +`document`, `location` и так далее. +Для host объектов поведение оператора `delete` может быть непредсказуемым. +Согласно спецификации, таким объектам позволено реализовывать любой вид поведения. + +### Заключение + +Оператор `delete` часто обладает непредсказуемым поведением и безопасно использовать +его можно лишь для удаления явно заданных свойств обычных объектов. \ No newline at end of file From 9dfe710c9ee9fdfed390d511f57a11376528c0dd Mon Sep 17 00:00:00 2001 From: Chris Anderson Date: Sat, 7 Feb 2015 16:23:54 -0700 Subject: [PATCH 011/105] change 'that' to 'self' --- doc/en/function/this.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/en/function/this.md b/doc/en/function/this.md index 9a20d71b..0f299f91 100644 --- a/doc/en/function/this.md +++ b/doc/en/function/this.md @@ -72,14 +72,14 @@ In order to gain access to `Foo` from within `test`, it is necessary to create a local variable inside of `method` that refers to `Foo`. Foo.method = function() { - var that = this; + var self = this; function test() { - // Use that instead of this here + // Use self instead of this here } test(); } -`that` is just a normal variable name, but it is commonly used for the reference to an +`self` is just a normal variable name, but it is commonly used for the reference to an outer `this`. In combination with [closures](#function.closures), it can also be used to pass `this` values around. From 43152844b30a954d4431a8f8a3f01c186eabf845 Mon Sep 17 00:00:00 2001 From: Chris Anderson Date: Sat, 7 Feb 2015 17:22:02 -0700 Subject: [PATCH 012/105] rename foo and bar in a few examples. it isn't necessary to use var self, but it is an option. --- doc/en/array/general.md | 12 +++---- doc/en/core/eval.md | 22 ++++++------ doc/en/function/constructors.md | 60 ++++++++++++++++----------------- doc/en/function/this.md | 2 +- 4 files changed, 48 insertions(+), 48 deletions(-) diff --git a/doc/en/array/general.md b/doc/en/array/general.md index 2e38b670..a78091d3 100644 --- a/doc/en/array/general.md +++ b/doc/en/array/general.md @@ -40,13 +40,13 @@ While the *getter* of the `length` property simply returns the number of elements that are contained in the array, the *setter* can be used to **truncate** the array. - var foo = [1, 2, 3, 4, 5, 6]; - foo.length = 3; - foo; // [1, 2, 3] + var arr = [1, 2, 3, 4, 5, 6]; + arr.length = 3; + arr; // [1, 2, 3] - foo.length = 6; - foo.push(4); - foo; // [1, 2, 3, undefined, undefined, undefined, 4] + arr.length = 6; + arr.push(4); + arr; // [1, 2, 3, undefined, undefined, undefined, 4] Assigning a smaller length truncates the array. Increasing it creates a sparse array. diff --git a/doc/en/core/eval.md b/doc/en/core/eval.md index 2d929902..6fa000f9 100644 --- a/doc/en/core/eval.md +++ b/doc/en/core/eval.md @@ -2,27 +2,27 @@ The `eval` function will execute a string of JavaScript code in the local scope. - var foo = 1; + var number = 1; function test() { - var foo = 2; - eval('foo = 3'); - return foo; + var number = 2; + eval('number = 3'); + return number; } test(); // 3 - foo; // 1 + number; // 1 However, `eval` only executes in the local scope when it is being called directly *and* when the name of the called function is actually `eval`. - var foo = 1; + var number = 1; function test() { - var foo = 2; - var bar = eval; - bar('foo = 3'); - return foo; + var number = 2; + var copyOfEval = eval; + copyOfEval('number = 3'); + return number; } test(); // 2 - foo; // 3 + number; // 3 The use of `eval` should be avoided. 99.9% of its "uses" can be achieved **without** it. diff --git a/doc/en/function/constructors.md b/doc/en/function/constructors.md index 1a44c154..8973b791 100644 --- a/doc/en/function/constructors.md +++ b/doc/en/function/constructors.md @@ -11,45 +11,45 @@ constructor. If the function that was called has no explicit `return` statement, then it implicitly returns the value of `this` - the new object. - function Foo() { - this.bla = 1; + function Person(name) { + this.name = name; } - Foo.prototype.test = function() { - console.log(this.bla); + Person.prototype.logName = function() { + console.log(this.name); }; - var test = new Foo(); + var sean = new Person(); -The above calls `Foo` as constructor and sets the `prototype` of the newly -created object to `Foo.prototype`. +The above calls `Person` as constructor and sets the `prototype` of the newly +created object to `Person.prototype`. In case of an explicit `return` statement, the function returns the value specified by that statement, but **only** if the return value is an `Object`. - function Bar() { - return 2; + function Car() { + return 'ford'; } - new Bar(); // a new object + new Car(); // a new object, not 'ford' - function Test() { - this.value = 2; + function Person() { + this.someValue = 2; return { - foo: 1 + name: 'Charles' }; } - new Test(); // the returned object + new Test(); // the returned object ({name:'Charles'}), not including someValue When the `new` keyword is omitted, the function will **not** return a new object. - function Foo() { - this.bla = 1; // gets set on the global object + function Pirate() { + this.hasEyePatch = true; // gets set on the global object! } - Foo(); // undefined + var somePirate = Pirate(); // somePirate is undefined -While the above example might still appear to work in some cases, due to the -workings of [`this`](#function.this) in JavaScript, it will use the +While the above example might still appear to work in some cases, due to the +workings of [`this`](#function.this) in JavaScript, it will use the *global object* as the value of `this`. ### Factories @@ -57,28 +57,28 @@ workings of [`this`](#function.this) in JavaScript, it will use the In order to be able to omit the `new` keyword, the constructor function has to explicitly return a value. - function Bar() { - var value = 1; + function Robot() { + var color = 'gray'; return { - method: function() { - return value; + getColor: function() { + return color; } } } - Bar.prototype = { - foo: function() {} + Robot.prototype = { + someFunction: function() {} }; - new Bar(); - Bar(); + new Robot(); + Robot(); -Both calls to `Bar` return the same thing, a newly created object that +Both calls to `Robot` return the same thing, a newly created object that has a property called `method`, which is a [Closure](#function.closures). -It should also be noted that the call `new Bar()` does **not** affect the +It should also be noted that the call `new Robot()` does **not** affect the prototype of the returned object. While the prototype will be set on the newly -created object, `Bar` never returns that new object. +created object, `Robot` never returns that new object. In the above example, there is no functional difference between using and not using the `new` keyword. diff --git a/doc/en/function/this.md b/doc/en/function/this.md index 0f299f91..f123f336 100644 --- a/doc/en/function/this.md +++ b/doc/en/function/this.md @@ -68,7 +68,7 @@ mis-design of the language because it **never** has any practical use. A common misconception is that `this` inside of `test` refers to `Foo`; while in fact, it **does not**. -In order to gain access to `Foo` from within `test`, it is necessary to create a +In order to gain access to `Foo` from within `test`, you can create a local variable inside of `method` that refers to `Foo`. Foo.method = function() { From f5bd48b8be24d0b9a779eabf0024aa3458b8d337 Mon Sep 17 00:00:00 2001 From: Chris Anderson Date: Sat, 7 Feb 2015 19:59:44 -0700 Subject: [PATCH 013/105] change factory example to use cars instead of obj --- doc/en/function/constructors.md | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/doc/en/function/constructors.md b/doc/en/function/constructors.md index 8973b791..f8a3d9c7 100644 --- a/doc/en/function/constructors.md +++ b/doc/en/function/constructors.md @@ -92,19 +92,21 @@ lead to bugs. In order to create a new object, one should rather use a factory and construct a new object inside of that factory. - function Foo() { - var obj = {}; - obj.value = 'blub'; + function CarFactory() { + var car = {}; + car.owner = 'nobody'; - var private = 2; - obj.someMethod = function(value) { - this.value = value; + var milesPerGallon = 2; + + car.setOwner = function(newOwner) { + this.owner = newOwner; } - obj.getPrivate = function() { - return private; + car.getMPG = function() { + return milesPerGallon; } - return obj; + + return car; } While the above is robust against a missing `new` keyword and certainly makes From 04156c77507e146dda0d2c2608bc525fdb315d84 Mon Sep 17 00:00:00 2001 From: fediev Date: Tue, 17 Feb 2015 16:36:56 +0900 Subject: [PATCH 014/105] convert space indentation to tab and remove tabs in empty lines --- site/style/garden.css | 74 +++++++++++++++++++++---------------------- 1 file changed, 37 insertions(+), 37 deletions(-) diff --git a/site/style/garden.css b/site/style/garden.css index 8b1896fb..bb850e2c 100644 --- a/site/style/garden.css +++ b/site/style/garden.css @@ -74,16 +74,16 @@ nav { position: fixed; margin-left: 750px; top: 0; - padding-bottom: 20px; + padding-bottom: 20px; height: 100%; - + text-shadow: none; width: 240px; } nav > div li { - float: left; - margin-right: 1px; + float: left; + margin-right: 1px; } nav > div li a, #top, #hide_menu { @@ -96,7 +96,7 @@ nav > div li a, #top, #hide_menu { nav > div li.active a { border-top: 4px solid #0D2E4C; padding-top: 4px; - color: #FFC76D; + color: #FFC76D; } #hide_menu { @@ -119,8 +119,8 @@ nav > div li.active a { nav li { font-size: 16px; - margin: 0px; - list-style: none; + margin: 0px; + list-style: none; } nav > ul li:last-child a { @@ -182,10 +182,10 @@ nav li a.active:hover { nav a:hover, nav ul.active a:hover, nav a, nav li { -moz-transition-property: background-color, color; -moz-transition-duration: 0.3s; - + -webkit-transition-property: background-color, color; -webkit-transition-duration: 0.3s; - + -o-transition-property: background-color, color; -o-transition-duration: 0.3s; @@ -243,9 +243,9 @@ code { section pre code { font-size: 0.8125em; line-height: 1.4em; - padding: 0px; - margin-top: 3px; - margin-bottom: 1px; + padding: 0px; + margin-top: 3px; + margin-bottom: 1px; background: #0F192A; } @@ -267,7 +267,7 @@ section h1 { } section header + section h1 { - + } /* Adding 'icon' to the side of sections */ @@ -336,7 +336,7 @@ aside { width: 180px; right: -190px; opacity: 0.7; - + -moz-transition: opacity 0.3s; -webkit-transition: opacity 0.3s; -o-transition: opacity 0.3s; @@ -369,7 +369,7 @@ aside.es5:after { font-style: italic; top: -18px; right: -3px; - + -ms-filter: “progid:DXImageTransform.Microsoft.Alpha(Opacity=25)”; /* Just kill me already... */ opacity: 0.25; } @@ -377,7 +377,7 @@ aside.es5:after { /* Article elements */ section ol { - margin-bottom: 2em; + margin-bottom: 2em; list-style: decimal; } @@ -463,7 +463,7 @@ a abbr { nav > div li.active a { padding-top: 8px; } - + #nav_main { display: none; height: auto; @@ -471,29 +471,29 @@ a abbr { width: 100%; z-index: 100; padding: 0; - + -moz-box-shadow: 0 3px 3px rgba(0, 0, 0, 0.3); -webkit-box-shadow: 0 3px 3px rgba(0, 0, 0, 0.3); box-shadow: 0 3px 3px rgba(0, 0, 0, 0.3); } - + #nav_main ul ul { display: none !important; } - + #nav_main > ul > li { float: left; text-align: center; width: 14.28%; border-bottom: 0; } - + #nav_main li h1 a { background-image: none; height: 5em; padding: 1.5em 0 2em; } - + #nav_main li h1 a:after { display: block; font-family: Georgia; @@ -501,21 +501,21 @@ a abbr { font-weight: normal; margin-top: 10px; } - + #nav_main > div ul { height: auto; } - + nav a:hover, nav li.active, nav li.active a { background-color: #0D2E4C; } - + #hide_menu { display: block; } - + #nav_mobile { position: fixed; width: 24%; @@ -524,7 +524,7 @@ a abbr { display: block; z-index: 50; } - + #nav_mobile a { display: block; background-color: #556C81; @@ -532,12 +532,12 @@ a abbr { margin-bottom: 1px; text-align: right; } - + #nav_next_section, #nav_prev_section { font-size: 0.55em; text-transform: uppercase; } - + #nav_next_section .nav_section_name, #nav_prev_section .nav_section_name { display: block; @@ -547,12 +547,12 @@ a abbr { line-height: 1.3em; text-transform: none; } - + #show_menu { font-weight: bold; cursor: pointer; } - + pre { border-left: 0; padding-left: 12px; @@ -567,7 +567,7 @@ a abbr { right: -33%; width: 30%; } - + section:after { display: none; } @@ -580,12 +580,12 @@ screen and (-webkit-min-device-pixel-ratio: 2) { body { max-width: 600px; } - + section { margin-right: 30px; width: auto; } - + section:after { right: 0; font-size: 60px; @@ -599,15 +599,15 @@ screen and (-webkit-min-device-pixel-ratio: 2) { border-top: 1px solid #9eabb7; opacity: 0.85; } - + #nav_main > ul > li { width: 100%; } - + #nav_mobile { width: 160px; } - + aside.es5:after { display: none; } From e57fb6d670a613d381a663b6a48d1bf2e8f48025 Mon Sep 17 00:00:00 2001 From: fediev Date: Tue, 17 Feb 2015 16:57:20 +0900 Subject: [PATCH 015/105] fix to show menu properly in retina & width > 600px devices --- site/style/garden.css | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/site/style/garden.css b/site/style/garden.css index bb850e2c..b5e2a048 100644 --- a/site/style/garden.css +++ b/site/style/garden.css @@ -575,8 +575,7 @@ a abbr { /* "Smartphone" styles */ -@media screen and (max-width: 600px), -screen and (-webkit-min-device-pixel-ratio: 2) { +@media screen and (max-width: 600px) { body { max-width: 600px; } From b07ae6398e3d2f6207e04070cd76f5ef48146435 Mon Sep 17 00:00:00 2001 From: fediev Date: Tue, 17 Feb 2015 16:58:24 +0900 Subject: [PATCH 016/105] improve to show all menus in one screen on small screen smartphones --- site/style/garden.css | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/site/style/garden.css b/site/style/garden.css index b5e2a048..a8fa8115 100644 --- a/site/style/garden.css +++ b/site/style/garden.css @@ -600,7 +600,10 @@ a abbr { } #nav_main > ul > li { - width: 100%; + float: left; + text-align: center; + width: 25%; + border-bottom: 0; } #nav_mobile { @@ -611,3 +614,14 @@ a abbr { display: none; } } + +/* Small Screen "Smarphone" Vertical Mode */ + +@media screen and (max-width: 360px) { + #nav_main > ul > li { + float: left; + text-align: center; + width: 33.33%; + border-bottom: 0; + } +} From 55dad76d5c169e9150a405589aaa0126fbded7b1 Mon Sep 17 00:00:00 2001 From: Marco Trulla Date: Wed, 18 Feb 2015 18:04:40 +0100 Subject: [PATCH 017/105] Fix typos and update translation --- doc/it/array/general.md | 13 +++--- doc/it/core/eval.md | 23 +++++----- doc/it/function/constructors.md | 76 ++++++++++++++++----------------- doc/it/function/this.md | 19 ++++++--- doc/it/object/forinloop.md | 38 ++++++++++++----- doc/it/object/hasownproperty.md | 14 +++--- doc/it/other/timeouts.md | 23 ++++++---- doc/it/types/casting.md | 7 ++- 8 files changed, 120 insertions(+), 93 deletions(-) diff --git a/doc/it/array/general.md b/doc/it/array/general.md index 0b3e0c9c..453dc088 100644 --- a/doc/it/array/general.md +++ b/doc/it/array/general.md @@ -42,13 +42,13 @@ Mentre il *getter* della proprietà `length` ritorna semplicemente il numero di elementi che sono contenuti nell'array, il *setter* può essere usato per **troncare** l'array. - var foo = [1, 2, 3, 4, 5, 6]; - foo.length = 3; - foo; // [1, 2, 3] + var arr = [1, 2, 3, 4, 5, 6]; + arr.length = 3; + arr; // [1, 2, 3] - foo.length = 6; - foo.push(4); - foo; // [1, 2, 3, undefined, undefined, undefined, 4] + arr.length = 6; + arr.push(4); + arr; // [1, 2, 3, undefined, undefined, undefined, 4] Assegnando una lunghezza più piccola si tronca l'array. Incrementandola si crea un array frammentato. @@ -59,4 +59,3 @@ Per la miglior performance, si raccomanda di usare sempre il ciclo `for` classico e fare il caching della proprietà `length`. L'uso di `for in` su di un array è segno di un codice scritto male che è suscettibile a bug e pessima performance. - diff --git a/doc/it/core/eval.md b/doc/it/core/eval.md index 03af4c01..54cf4566 100644 --- a/doc/it/core/eval.md +++ b/doc/it/core/eval.md @@ -2,27 +2,27 @@ La funzione `eval` eseguirà una stringa di codice JavaScript nello scope locale. - var foo = 1; + var number = 1; function test() { - var foo = 2; - eval('foo = 3'); - return foo; + var number = 2; + eval('number = 3'); + return number; } test(); // 3 - foo; // 1 + number; // 1 Comunque, `eval` esegue solo nello scope locale quando viene chiamata direttamente *e* quando il nome della funzione chiamata è `eval`. - var foo = 1; + var number = 1; function test() { - var foo = 2; - var bar = eval; - bar('foo = 3'); - return foo; + var number = 2; + var copyOfEval = eval; + copyOfEval('number = 3'); + return number; } test(); // 2 - foo; // 3 + number; // 3 L'uso di `eval` dovrebbe essere evitato. Il 99.9% dei suoi "utilizzi" può essere ottenuto **senza** di essa. @@ -47,4 +47,3 @@ essere messo in discussione sotto l'aspetto della funzionalità, della performan e della sicurezza. Se qualcosa richiede `eval` per poter funzionare, allora **non** dovrebbe essere usato in primo luogo, ma si dovrebbe prevedere una *miglior progettazione* che non richieda l'uso di `eval`. - diff --git a/doc/it/function/constructors.md b/doc/it/function/constructors.md index a6f730c4..45983b2c 100644 --- a/doc/it/function/constructors.md +++ b/doc/it/function/constructors.md @@ -12,44 +12,44 @@ come costruttore. Se la funzione che è stata chiamata non ha un'istruzione `return` esplicita, allora essa ritorna implicitamente il valore di `this` (il nuovo oggetto). - function Foo() { - this.bla = 1; + function Person(name) { + this.name = name; } - Foo.prototype.test = function() { - console.log(this.bla); + Person.prototype.logName = function() { + console.log(this.name); }; - var test = new Foo(); + var sean = new Person(); -Questo esempio chiama `Foo` come costruttore ed imposta il `prototype` del -nuovo oggetto creato a `Foo.prototype`. +Questo esempio chiama `Person` come costruttore ed imposta il `prototype` del +nuovo oggetto creato a `Person.prototype`. In caso di istruzione `return` esplicita, la funzione ritorna il valore specificato da quell'istruzione, ma **solo** se il valore di ritorno è un `Object`. - function Bar() { - return 2; + function Car() { + return 'ford'; } - new Bar(); // un nuovo oggetto + new Car(); // un nuovo oggetto, non 'ford' - function Test() { - this.value = 2; + function Person() { + this.someValue = 2; return { - foo: 1 + name: 'Charles' }; } - new Test(); // l'oggetto ritornato + new Test(); // l'oggetto ritornato ({name: 'Charles'}), escluso someValue Quando la parola chiave `new` viene omessa, la funzione **non** ritornerà un nuovo oggetto. - function Foo() { - this.bla = 1; // imposta la proprietà dell'oggetto globale + function Pirate() { + this.hasEyePatch = true; // imposta la proprietà nell'oggetto globale! } - Foo(); // undefined + var somePirate = Pirate(); // somePirate è undefined Mentre l'esempio precedente potrebbe sembrare essere funzionante in alcuni casi, a causa del modo in cui lavora [`this`](#function.this) in JavaScript, @@ -60,27 +60,27 @@ esso userà l'*oggetto globale* come valore di `this`. Per poter omettere la parola chiave `new`, la funzione costruttore deve esplicitamente ritornare un valore. - function Bar() { - var value = 1; + function Robot() { + var color = 'gray'; return { - method: function() { - return value; + getColor: function() { + return color; } } } - Bar.prototype = { - foo: function() {} + Robot.prototype = { + someFunction: function() {} }; - new Bar(); - Bar(); + new Robot(); + Robot(); -Entrambe le chiamate a `Bar` ritornano lo stesso risultato, un nuovo oggetto +Entrambe le chiamate a `Robot` ritornano lo stesso risultato, un nuovo oggetto creato con una proprietà chiamata `method`, che è una [Closure](#function.closures). -Bisogna anche notare che la chiamata `new Bar()` **non** influisce sul prototipo +Bisogna anche notare che la chiamata `new Robot()` **non** influisce sul prototipo dell'oggetto ritornato. Mentre il prototipo sarà impostato con il nuovo oggetto -creato, `Bar` non ritornerà mai quel nuovo oggetto. +creato, `Robot` non ritornerà mai quel nuovo oggetto. Nell'esempio sopra, non c'è differenza funzionale nell'usare o meno la parola chiave `new`. @@ -93,19 +93,20 @@ può portare a bug potenzialmente insidiosi da risolvere. Per poter creare un nuovo oggetto, si dovrebbe invece usare una factory e costruire un nuovo oggetto all'interno di quella factory. - function Foo() { - var obj = {}; - obj.value = 'blub'; + function CarFactory() { + var car = {}; + car.owner = 'nobody'; - var private = 2; - obj.someMethod = function(value) { - this.value = value; + var milesPerGallon = 2; + + car.setOwner = function(newOwner) { + this.owner = newOwner; } - obj.getPrivate = function() { - return private; + car.getMPG = function() { + return milesPerGallon; } - return obj; + return car; } Sebbene questo esempio sia a prova di omissione della parola chiave `new` e @@ -126,4 +127,3 @@ bug, **non** è certo un motivo per privarsi completamente dell'uso dei prototip Alla fine si tratta di decidere quale sia la soluzione più adatta per l'applicazione. È specialmente importante scegliere uno specifico stile di creazione degli oggetti ed usarlo in maniera **consistente**. - diff --git a/doc/it/function/this.md b/doc/it/function/this.md index 8f405d09..5bee4398 100644 --- a/doc/it/function/this.md +++ b/doc/it/function/this.md @@ -71,21 +71,31 @@ uso pratico. Una comune credenza è che `this` all'interno di `test` faccia riferimento a `Foo` mentre, invece, **non** è così. -Per poter ottenere l'accesso a `Foo` dall'interno di `test`, è necessario creare +Per poter ottenere l'accesso a `Foo` dall'interno di `test`, si può creare una variabile locale all'interno di `method` che faccia riferimento a `Foo`. Foo.method = function() { - var that = this; + var self = this; function test() { - // Qui viene usato that invece di this + // Qui viene usato self invece di this } test(); } -`that` è solo un normale nome di variabile, ma viene comunemente usato come +`self` è solo un normale nome di variabile, ma viene comunemente usato come riferimento ad un `this` più esterno. Abbinato alle [closures](#function.closures) può anche essere usato per passare il valore di `this`. +Con l'introduzione di ECMAScript 5 è possibile usare il metodo `bind` combinato +con una funziona anonima + + Foo.method = function() { + var test = function() { + // this ora fa riferimento a Foo + }.bind(this); + test(); + } + ### Metodi di asseganzione Un'altra cosa che **non** funziona in JavaScript è la creazione di un alias ad @@ -112,4 +122,3 @@ l'[ereditarietà prototipale](#object.prototype). Quando `method` viene chiamato da un'istanza di `Bar`, `this` farà riferimento a quell'istanza. - diff --git a/doc/it/object/forinloop.md b/doc/it/object/forinloop.md index b77ab1ce..96fc2d24 100644 --- a/doc/it/object/forinloop.md +++ b/doc/it/object/forinloop.md @@ -17,8 +17,19 @@ prototipi quando itera tra le proprietà di un oggetto. Dato che non è possibile modificare il comportamento del ciclo `for in`, è necessario filtrare le proprietà indesiderate all'interno del ciclo stesso. -Questo può essere fatto usando il metodo [`hasOwnProperty`](#object.hasownproperty) -di `Object.prototype`. +In ECMAScript 3 o precedente, questo può essere fatto usando il metodo +[`hasOwnProperty`](#object.hasownproperty) di `Object.prototype`. + +A partire da ECMAScript 5, `Object.defineProperty` può essere utilizzato con +`enumerbale` impostato a `false` per aggiungere proprietà agli oggetti (incluso +`Object`) senza che queste proprietà vengano enumerate. In questo caso è +ragionevole assumere che, nel codice di un'applicazione, ogni proprietà +enumerabile sia stata aggiunta per un motivo, ed quindi omettere `hasOwnProperty` +in quanto rende il codice più prolisso e meno leggibile. Nel codice delle +librerie `hasOwnProperty` dovrebbe essere ancora utilizzato, dato che non è +possibile presumere quali proprietà enumerabili siano presenti nella catena dei +prototipi. + > **Nota:** dato che `for in` attraversa sempre tutta la catena di prototipi, > esso rallenterà per ogni strato aggiuntivo di ereditarietà aggiunto ad un @@ -33,20 +44,25 @@ di `Object.prototype`. } } -Questa è la sola versione corretta da usare. Proprio a causa dell'utilizzo di -`hasOwnProperty`, **soltanto** `moo` verrà stampato; mentre omettendone l'uso, -il codice sarà soggetto ad errori nei casi dove i prototipi nativi (ad esempio -`Object.prototype`) sono stati estesi. +Questa è la sola versione corretta da usare con le vecchie versioni di ECMAScript. +Proprio a causa dell'utilizzo di `hasOwnProperty`, **soltanto** `moo` verrà +stampato; mentre omettendone l'uso, il codice sarà soggetto ad errori nei casi +dove i prototipi nativi (ad esempio `Object.prototype`) sono stati estesi. -Un framework ampiamente usato che estende `Object.prototype` è [Prototype][1]. +Nelle nuove versioni di ECMAScript, le proprietà non enumerabili possono essere +definite con `Object.defineProperty`, riducendo il rischio di iterare sulle +proprietà non usando `hasOwnProperty`. È altresì importante stare attenti +quando si usano librerie come [Prototype][1], che ancora non sfruttano le nuove +funzionalità di ECMAScript. Quando questo framework viene incluso, è sicuro che i cicli `for in` che non utilizzano `hasOwnProperty` non funzioneranno. ### In conclusione -Si raccomanda di usare **sempre** `hasOwnProperty`. Non si dovrebbe mai dare -per scontato l'ambiente in cui il codice sta girando, o se i prototipi -nativi sono stati estesi o meno. +Si raccomanda di usare **sempre** `hasOwnProperty` in ECMAScript 3 o precedenti, +e nel codice delle librerie. Non si dovrebbe mai dare per scontato nell'ambiente +in cui il codice sta girando, se i prototipi nativi sono stati estesi o meno. A +partire da ECMAScript 5 `Object.defineProperty` rende possibile definire proprietà +non enumerabili ed omettere `hasOwnProperty` nel codice dell'applicazione. [1]: http://www.prototypejs.org/ - diff --git a/doc/it/object/hasownproperty.md b/doc/it/object/hasownproperty.md index a0ffa052..71226c10 100644 --- a/doc/it/object/hasownproperty.md +++ b/doc/it/object/hasownproperty.md @@ -22,10 +22,9 @@ Per verificare se un oggetto ha (possiede) una proprietà definita dentro foo.hasOwnProperty('bar'); // false foo.hasOwnProperty('goo'); // true -Solo `hasOwnProperty` darà il risultato atteso e corretto. Questo è essenziale -quando si itera tra le proprietà di un qualsiasi oggetto. **Non** c'è altro -modo per escludere proprietà che non sono definite all'interno dell'oggetto -stesso, ma da qualche altra parte nella sua catena di prototipi. +Solo `hasOwnProperty` darà il risultato atteso e corretto. Guarda la sezione +[cicli `for in`][#object.forinloop] per maggiori dettagli riguardo a quando +usare `hasOwnProperty` per iterare le proprietà di un oggetto. ### `hasOwnProperty` come proprietà @@ -54,7 +53,6 @@ risultato corretto. ### In conclusione Usare `hasOwnProperty` è l'**unico** metodo affidabile per verificare -l'esistenza di una proprietà in un oggetto. È raccomandabile usare -`hasOwnProperty` in **ogni** [ciclo `for in`](#object.forinloop) per -evitare errori con i [prototipi](#object.prototype) nativi estesi. - +l'esistenza di una proprietà in un oggetto. È raccomandabile che +`hasOwnProperty` venga usata in molti casi in cui è necessario iterare le +proprietà di un oggetto, come descritto nella sezione [cicli `for in`](#object.forinloop). diff --git a/doc/it/other/timeouts.md b/doc/it/other/timeouts.md index 4bf1757e..da216d54 100644 --- a/doc/it/other/timeouts.md +++ b/doc/it/other/timeouts.md @@ -3,8 +3,12 @@ Dato che JavaScript è asincrono, è possibile programmare l'esecuzione di una funzione usando le funzioni `setTimeout` e `setInterval`. -> **Nota:** i timeout **non** sono parte dello standard ECMAScript. Essi -> vengono implementati come parte del [DOM][1]. +> **Nota:** i timeout **non** sono parte dello standard ECMAScript. Erano stati +> implementati in [BOM, o DOM Level 0][1], i quali non sono mai stati definiti +> o documentati formalmente. Nessuna specifica raccomandazione è mai stata +> pubblicata, tuttavia, la loro standardizzazione è in via di ultimazione con +> [HTML5][2]. Per loro stessa natura, quindi, l'implementazione può essere +> differente nei vari browser e motori di rendering. function foo() {} var id = setTimeout(foo, 1000); // ritorna un Number > 0 @@ -52,7 +56,7 @@ con intervalli molto brevi, tradursi in chiamate a funzione che si sovrappongono function foo(){ // qualcosa che blocca per 1 secondo } - setInterval(foo, 100); + setInterval(foo, 1000); Nel codice precedente, `foo` verrà chiamato una volta e quindi bloccherà per un secondo. @@ -68,7 +72,7 @@ La soluzione più semplice, come anche la più controllabile, è quella di usare function foo(){ // qualcosa che blocca per 1 secondo - setTimeout(foo, 100); + setTimeout(foo, 1000); } foo(); @@ -119,8 +123,7 @@ gli ID dei timeout, così che possano essere puliti in modo specifico. primo parametro. Questa caratteristica non dovrebbe essere **mai** usata perché internamente fa uso di `eval`. -> **Nota:** dato che le funzioni di timeout **non** sono specificate dallo -> standard ECMAScript, l'esatto funzionamento quando viene passata una stringa +> **Nota:** L'esatto funzionamento quando viene passata una stringa > potrebbe differire nelle varie implementazioni di JavaScript. Per esempio, > JScript di Microsoft usa il costruttore `Function` al posto di `eval`. @@ -157,6 +160,9 @@ funzione che verrà chiamata da una delle funzioni di timeout. > `setTimeout(foo, 1000, 1, 2, 3)`, non la si raccomanda, dato che il suo > utilizzo potrebbe portare ad errori subdoli quando usata con i > [metodi](#function.this). +> Inoltre, la sintassi potrebbe non funzionare in alcune implementazioni di +> JavaScript. +> Ad esempio, Internet Explorer di Microsoft [**non** passa direttamente gli argomenti al callback](3). ### In conclusione @@ -169,5 +175,6 @@ di gestire l'effettiva chiamata. Inoltre, l'uso di `setInterval` dovrebbe essere evitato perché il suo schedulatore non viene bloccato dall'esecuzione di JavaScript. -[1]: http://en.wikipedia.org/wiki/Document_Object_Model "Document Object Model" - +[1]: http://www.nczonline.net/blog/2009/09/29/web-definitions-dom-ajax-and-more/ "Web definitions: DOM, Ajax, and more" +[2]: http://www.w3.org/TR/2014/WD-html5-20140617/webappapis.html#timers "6 Web application APIs - HTML5" +[3]: http://msdn.microsoft.com/en-us/library/ie/ms536753(v=vs.85).aspx "setTimeout method (Internet Explorer)" diff --git a/doc/it/types/casting.md b/doc/it/types/casting.md index 7c9f4a60..743ee317 100644 --- a/doc/it/types/casting.md +++ b/doc/it/types/casting.md @@ -4,8 +4,9 @@ JavaScript è un linguaggio **debolmente tipizzato**, perciò esso applicherà una *conversione di tipo* **ovunque** sia possibile. // Queste sono vere - new Number(10) == 10; // Number.toString() viene convertito - // nuovamente in un numero + new Number(10) == 10; // l'oggetto Number viene convertito + // in una primitiva numero tramite chiamata implicita + // al metodo Number.prototype.valueOf 10 == '10'; // String viene convertita in Number 10 == '+10 '; // Stringa più assurda @@ -72,5 +73,3 @@ booleano. !!'-1' // true !!{}; // true !!true; // true - - From 0d44519e9bab8221eee93f1633831d8680efdc5a Mon Sep 17 00:00:00 2001 From: Adam Kucharczyk <108adams@gmail.com> Date: Wed, 25 Feb 2015 17:24:11 +0100 Subject: [PATCH 018/105] Interpunction, grammar clean up --- doc/pl/array/general.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/doc/pl/array/general.md b/doc/pl/array/general.md index 6bd89bae..ecac9ca3 100644 --- a/doc/pl/array/general.md +++ b/doc/pl/array/general.md @@ -1,6 +1,6 @@ ## Iterowanie po tablicach oraz właściwościach tablic -Mimo że tablice w JavaScript są obiektami, nie ma dobrych powodów aby używać +Mimo, że tablice w JavaScript są obiektami, nie ma dobrych powodów, aby używać [`pętli for in`](#object.forinloop) do iteracji po nich. W rzeczywstości istnieje wiele dobrych powodów **przeciwko** wykorzystaniu `for in` na tablicach. @@ -9,9 +9,9 @@ wiele dobrych powodów **przeciwko** wykorzystaniu `for in` na tablicach. > tablice asocjacyjne **zachowują** porządek, natomiast obiekty **nie zachowują**. Ponieważ pętla `for in` wylicza wszystkie właściwości, które są wewnątrz -łańcucha prototypów i jedynym sposobem aby wykluczyć te właściwości jest użycie -[`hasOwnProperty`](#object.hasownproperty), ale wówczas pętla staje się -**dwadzieście razy** wolniejsza od normalnej pętli `for`. +łańcucha prototypów, jedynym sposobem, aby wykluczyć te właściwości, jest użycie +[`hasOwnProperty`](#object.hasownproperty). Wówczas pętla staje się jednak +**dwadzieścia razy** wolniejsza od normalnej pętli `for`. ### Iteracja From 6c201da582fe61caf968e9412d1e8c966b4f41a7 Mon Sep 17 00:00:00 2001 From: Adam Kucharczyk <108adams@gmail.com> Date: Wed, 25 Feb 2015 17:40:07 +0100 Subject: [PATCH 019/105] Grammar polished Cleaning up some obvious English calques. Added note about English term: Immediately-Invoked Function Expression - IIFE --- doc/pl/function/scopes.md | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/doc/pl/function/scopes.md b/doc/pl/function/scopes.md index bd36d03e..88f82c16 100644 --- a/doc/pl/function/scopes.md +++ b/doc/pl/function/scopes.md @@ -21,7 +21,7 @@ definiowane w jednej *globalnie współdzielonej* przestrzeni nazw. Z każdym odwołaniem do zmiennej, JavaScript przeszukuje w górę wszystkie zasięgi dopóki nie znajdzie tej zmiennej. W przypadku, gdy przeszukiwanie dotrze do globalnego -zasięgu i nadal nie znajdzie żądanej nazwy, to wyrzuca błąd `ReferenceError`. +zasięgu i nadal nie znajdzie żądanej nazwy, wyrzuca błąd `ReferenceError`. ### Zmora globalnych zmiennych @@ -35,7 +35,7 @@ Powyższe dwa skrypty **nie** dają tego samego efektu. Skrypt A definiuje zmien nazwaną `foo` w *globalnym* zasięgu, natomiast skrypt B definiuje `foo` w *aktualnym* zasięgu. -Jeszcze raz, to wcale nie daje *tego samego efektu*. Nie użycie `var` może mieć +Jeszcze raz, to wcale nie daje *tego samego efektu*. Brak użycia `var` może mieć poważne konsekwencje. // globalny zasięg @@ -48,8 +48,8 @@ poważne konsekwencje. foo; // 21 Pominięcie słowa `var` w deklaracji wewnątrz funkcji `test` nadpisze wartość -zmiennej globalnej `foo`. Mimo że nie wygląda to na początku na duży problem, -posiadanie wielu tysięcy linii kodu w JavaScript i nie korzystanie z `var` +zmiennej globalnej `foo`. Mimo, że nie wygląda to na początku na duży problem, +w przypadku kodu, który posiada wielu tysięcy linii, brak `var` wprowadzi straszne i trudne do wyśledzenia błędy. // globalny zasięg @@ -68,8 +68,8 @@ wprowadzi straszne i trudne do wyśledzenia błędy. Zewnętrzna pętla zakończy działanie po pierwszym wywołaniu `subLoop`, ponieważ `subLoop` nadpisuje wartość globalnej zmiennej `i`. Użycie `var` w drugiej pętli `for` pozwoliłoby łatwo uniknąć problemu. Słowo kluczowe `var` nie powinno być -**nigdy** pominięte w deklaracji, chyba że *pożądanym skutkiem* jest wpłynięcie na -zewnętrzny zasięg. +**nigdy** pominięte w deklaracji, chyba że *pożądanym skutkiem* jest modyfikacja +zewnętrznego zasięgu. ### Lokalne zmienne @@ -150,7 +150,7 @@ W oryginalnym kodzie instrukcja warunkowa `if` zdaje się modyfikować *zmienną globalną* `goo`, podczas gdy faktycznie modyfikuje ona *zmienną lokalną* - po tym jak zostało zastosowane windowanie (hoisting). -Bez wiedzy na temat podnoszenia (hoistingu), poniższy kod może sprawiać wrażenie, +Analizując poniższy kod bez wiedzy na temat hoistingu możemy odnieść wrażenie, że zobaczymy błąd `ReferenceError`. // sprawdz czy SomeImportantThing zostało zainicjalizowane @@ -182,19 +182,21 @@ funkcji. Na przykład, kiedy próbujemy odczytać zmienną `foo` wewnątrz zasięgu funkcji, JavaScript będzie szukać nazwy w określonej kolejności: - 1. Jeżeli wewnątrz aktualnego zasięgu znajduje się deklaracja `var foo` skorzystaj z niej. - 2. Jeżeli jeden z parametrów fukcji został nazwany `foo` użyj go. - 3. Jeżeli fukcja została nazwana `foo` skorzystaj z tego. - 4. Przejdz do zewnętrznego zasięgu i przejdz do kroku **#1**. -> **Uwaga:** Jeżeli jeden z parametrów fukcji został nazwany `arguments`, zapobiegnie -> to utworzeniu domyślnego obiektu `arguments`. + 1. Jeżeli wewnątrz aktualnego zasięgu znajduje się deklaracja `var foo`, skorzystaj z niej. + 2. Jeżeli jeden z parametrów fukcji został nazwany `foo`, użyj go. + 3. Jeżeli funkcja została nazwana `foo`, skorzystaj z tego. + 4. Przejdź do zewnętrznego zasięgu i przejdź do kroku **#1**. + +> **Uwaga:** Jeżeli jeden z parametrów fukcji został nazwany `arguments`, +> nie zostanie utworzony domyślny obiekt `arguments`. ### Przestrzenie nazw Powszechnym problemem posiadania tylko jednej globalnej przestrzeni nazw jest prawdopodobieństwo wystąpienia kolizji nazw. W JavaScripcie, można łatwo uniknąć -tego problemu korzystając z *anonimowych wrapperów*. +tego problemu korzystając z *anonimowych wrapperów* (inaczej: Immediately-Invoked +Function Expression - IIFE). (function() { // autonomiczna "przestrzeń nazw" From 660b48d32b850addb1415e960f83c307af9ad214 Mon Sep 17 00:00:00 2001 From: Adam Kucharczyk <108adams@gmail.com> Date: Wed, 25 Feb 2015 17:43:48 +0100 Subject: [PATCH 020/105] more grammar cleanups --- doc/pl/function/scopes.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/pl/function/scopes.md b/doc/pl/function/scopes.md index 88f82c16..bb43387b 100644 --- a/doc/pl/function/scopes.md +++ b/doc/pl/function/scopes.md @@ -153,7 +153,7 @@ jak zostało zastosowane windowanie (hoisting). Analizując poniższy kod bez wiedzy na temat hoistingu możemy odnieść wrażenie, że zobaczymy błąd `ReferenceError`. - // sprawdz czy SomeImportantThing zostało zainicjalizowane + // sprawdź, czy SomeImportantThing zostało zainicjalizowane if (!SomeImportantThing) { var SomeImportantThing = {}; } @@ -163,9 +163,9 @@ przeniesiona na początek *globalnego zasięgu*. var SomeImportantThing; - // inny kod który może ale nie musi zainicjalizować SomeImportantThing + // inny kod, który może, ale nie musi zainicjalizować SomeImportantThing - // upewnienie się, że SomeImportantThing zostało zainicjalizowane + // upewnij się, że SomeImportantThing zostało zainicjalizowane if (!SomeImportantThing) { SomeImportantThing = {}; } From 9e80aefefc96d202b485b2d2aeda2b905d2e513f Mon Sep 17 00:00:00 2001 From: Adam Kucharczyk <108adams@gmail.com> Date: Wed, 25 Feb 2015 17:48:27 +0100 Subject: [PATCH 021/105] Grammar polished --- doc/pl/array/constructor.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/pl/array/constructor.md b/doc/pl/array/constructor.md index 7df61c1d..e715c840 100644 --- a/doc/pl/array/constructor.md +++ b/doc/pl/array/constructor.md @@ -11,9 +11,9 @@ przekazane do niego parametry. new Array(3); // Rezultat: [] new Array('3') // Rezultat: ['3'] -W przypadku gdy tylko jeden argument zostanie przekazany do kostruktora `Array` i +W przypadku, gdy tylko jeden argument zostanie przekazany do kostruktora `Array` i ten argument jest typu `Number`, konstruktor zwróci nową *dziwną* tablicę -z ustawioną właściwością `length` na wartość przekazaną jako argument. Należy +z właściwością `length` ustawioną na wartość przekazaną jako argument. Należy zauważyć, że **tylko** właściwość `length` zostanie ustawiona w ten sposób. Rzeczywiste indeksy w tej tablicy nie zostaną zainicjalizowane. From 6a6d1d29bc7faa69fa4fefc0995671cd1ef6d1d1 Mon Sep 17 00:00:00 2001 From: Adam Kucharczyk <108adams@gmail.com> Date: Wed, 25 Feb 2015 17:50:49 +0100 Subject: [PATCH 022/105] Interpunction, grammar clean up --- doc/pl/array/general.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/doc/pl/array/general.md b/doc/pl/array/general.md index ecac9ca3..499e0d62 100644 --- a/doc/pl/array/general.md +++ b/doc/pl/array/general.md @@ -26,10 +26,10 @@ użyć klasycznej pętli `for`. W powyższym przykładzie jest jeszcze jeden dodatkowy haczyk. Jest to zbuforowanie długości tablicy poprzez `l = list.length`. -Mimo że właściwość `length` jest zdefiniowana wewnątrz tablicy, istnieje nadal -dodatkowy koszt na wyszukiwanie tej właściwości przy każdej iteracji w pętli. -Chociaż najnowsze silniki JavaScript **mogą** zastosować w tym -przypadku optymalizację. Nie ma jednak możliwość ustalenia czy kod będzie wykonywany w jednym +Mimo, że właściwość `length` jest zdefiniowana wewnątrz tablicy, istnieje nadal +dodatkowy koszt wyszukiwania tej właściwości przy każdej iteracji w pętli. +Najnowsze silniki JavaScript **mogą** zastosować w tym +przypadku optymalizację. Nie ma jednak możliwości ustalenia, czy kod będzie wykonywany w jednym z tych nowych silników, czy też nie. W rzeczywistości pominięcie buforowania długości tablicy może spowodować, że pętla From cc5984d765b7e385ca93bef3b4a205e4c1ffd65e Mon Sep 17 00:00:00 2001 From: fediev Date: Wed, 11 Mar 2015 03:37:45 +0900 Subject: [PATCH 023/105] fix css media query limit for mobile --- site/style/garden.css | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/site/style/garden.css b/site/style/garden.css index 2689343f..9c95ff95 100644 --- a/site/style/garden.css +++ b/site/style/garden.css @@ -443,10 +443,10 @@ a abbr { /* "Tablet" Styles */ -@media screen and (max-width: 1000px) { +@media screen and (max-width: 999px) { body { width: 100%; - max-width: 1000px; + max-width: 999px; overflow-x: hidden; } From 44994e601ce449a175513d603c705dc4f71fdc12 Mon Sep 17 00:00:00 2001 From: fediev Date: Wed, 11 Mar 2015 03:57:32 +0900 Subject: [PATCH 024/105] fix #nav_main click handler's wrong behavior on mobile In the event handler, 'this' is not a jquery object, but a DOM object. Instead of using $(this) to fix this problem, $mainNav is used because it is already created and no need to be re-wrapped as jquery object. $varname style is used for preventing this type of problem. --- site/javascript/garden.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/site/javascript/garden.js b/site/javascript/garden.js index 954674d0..0b69aaa5 100644 --- a/site/javascript/garden.js +++ b/site/javascript/garden.js @@ -143,7 +143,7 @@ function Page() { Page.prototype = { init: function() { var that = this, - mainNav = $('#nav_main'); + $mainNav = $('#nav_main'); $.extend(this, { scrollLast: 0, @@ -177,14 +177,14 @@ Page.prototype = { // Show menu for tablets $('#show_menu').click(function (){ var scrollTop = $.mobile ? that.window.scrollTop() : 0; - - mainNav.slideDown(300).css('top', scrollTop); + + $mainNav.slideDown(300).css('top', scrollTop); return false; }); - - $('#nav_main').click(function(){ + + $mainNav.click(function(){ if(that.window.width() < 1000) - mainNav.slideUp(300, function() {this.removeAttr('style');}); + $mainNav.slideUp(300, function() { $mainNav.removeAttr('style'); }); }); }, From 6967b77d2c8852fcf81d1e65de12c9068de87cfd Mon Sep 17 00:00:00 2001 From: fediev Date: Wed, 11 Mar 2015 04:06:53 +0900 Subject: [PATCH 025/105] revise unnecessary 'that' use for 'this' in this code, 'this' in the scope is correct this. no need to use 'that' --- site/javascript/garden.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site/javascript/garden.js b/site/javascript/garden.js index 0b69aaa5..d5ba4419 100644 --- a/site/javascript/garden.js +++ b/site/javascript/garden.js @@ -158,7 +158,7 @@ Page.prototype = { that.onResize(); }); - that.sections.map(); + this.sections.map(); setTimeout(function() { that.sections.highlight(); }, 10); From b31ab5c983d00e02c58408717da747df40fa3143 Mon Sep 17 00:00:00 2001 From: fediev Date: Wed, 11 Mar 2015 04:12:49 +0900 Subject: [PATCH 026/105] remove unnecessary js codes that handles css css handling is done by css media query --- site/javascript/garden.js | 17 ++--------------- 1 file changed, 2 insertions(+), 15 deletions(-) diff --git a/site/javascript/garden.js b/site/javascript/garden.js index d5ba4419..f90c8f60 100644 --- a/site/javascript/garden.js +++ b/site/javascript/garden.js @@ -163,22 +163,9 @@ Page.prototype = { that.sections.highlight(); }, 10); - // Mobile, for position: fixed - if ($.mobile) { - var navs = $('#nav_mobile, #nav_main'); - navs.css('position', 'absolute'); - this.window.scroll(function(){ - navs.offset({ - top: that.window.scrollTop() - }); - }); - } - - // Show menu for tablets + // Show menu for tablets and smart phones $('#show_menu').click(function (){ - var scrollTop = $.mobile ? that.window.scrollTop() : 0; - - $mainNav.slideDown(300).css('top', scrollTop); + $mainNav.slideDown(300); return false; }); From 31fbff733ec96ed65d980f01d3dd752bb909168a Mon Sep 17 00:00:00 2001 From: fediev Date: Wed, 11 Mar 2015 04:20:15 +0900 Subject: [PATCH 027/105] remove jQuery.browser.mobile plugin file Mobile device checking is done by css media query. jQuery.browser.mobile plugin is not needed any more. --- garden.jade | 2 -- site/javascript/plugin.js | 12 ------------ 2 files changed, 14 deletions(-) delete mode 100644 site/javascript/plugin.js diff --git a/garden.jade b/garden.jade index 63ce447b..f3006ec9 100644 --- a/garden.jade +++ b/garden.jade @@ -88,11 +88,9 @@ html(lang=language) - if (language === baseLanguage) script(src='http://github.com/javascript/prettify.js') - script(src='http://github.com/javascript/plugin.js') script(src='http://github.com/javascript/garden.js') - else script(src='http://github.com/javascript/prettify.js') - script(src='http://github.com/javascript/plugin.js') script(src='http://github.com/javascript/garden.js') diff --git a/site/javascript/plugin.js b/site/javascript/plugin.js deleted file mode 100644 index 9461358a..00000000 --- a/site/javascript/plugin.js +++ /dev/null @@ -1,12 +0,0 @@ -/** - * jQuery.browser.mobile (http://detectmobilebrowser.com/) - * - * Copyright (c) 2010 Chad Smith (http://twitter.com/chadsmith) - * Dual licensed under the MIT and GPL licenses. - * http://www.opensource.org/licenses/mit-license.php - * http://www.opensource.org/licenses/gpl-license.php - * - * jQuery.browser.mobile will be true if the browser is a mobile device - * - **/ -(function(a){jQuery.browser.mobile=/android|avantgo|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|symbian|treo|up\.(browser|link)|vodafone|wap|windows (ce|phone)|xda|xiino/i.test(a)||/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|e\-|e\/|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(di|rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|xda(\-|2|g)|yas\-|your|zeto|zte\-/i.test(a.substr(0,4))})(navigator.userAgent||navigator.vendor||window.opera); \ No newline at end of file From a275c8ceb2c8e6908d0b09e4c66f51c125751ef6 Mon Sep 17 00:00:00 2001 From: fediev Date: Wed, 11 Mar 2015 04:27:17 +0900 Subject: [PATCH 028/105] revise misc indentation and coding style in garden.js and garden.jade --- garden.jade | 19 +++++++++---------- site/javascript/garden.js | 20 ++++++++++---------- 2 files changed, 19 insertions(+), 20 deletions(-) diff --git a/garden.jade b/garden.jade index f3006ec9..df3b3e33 100644 --- a/garden.jade +++ b/garden.jade @@ -24,7 +24,7 @@ html(lang=language) // Navigation nav(id='nav_main') div - ul + ul - each lang in languages li(class=lang.id === language ? 'active' : '') - if (lang.id === baseLanguage) @@ -54,7 +54,7 @@ html(lang=language) a(id='nav_next_section', href='#') next section span(class='nav_section_name') section name - + a(id='show_menu') show menu // Sections @@ -78,19 +78,18 @@ html(lang=language) // Footer footer p Copyright ©. Built with - | - a(href='http://nodejs.org/') Node.js - | using a - a(href='https://github.com/visionmedia/jade/') jade - | template. + | + a(href='http://nodejs.org/') Node.js + | using a + a(href='https://github.com/visionmedia/jade/') jade + | template. script(src='http://ajax.googleapis.com/ajax/libs/jquery/1.5.1/jquery.min.js') - + - if (language === baseLanguage) script(src='http://github.com/javascript/prettify.js') script(src='http://github.com/javascript/garden.js') - + - else script(src='http://github.com/javascript/prettify.js') script(src='http://github.com/javascript/garden.js') - diff --git a/site/javascript/garden.js b/site/javascript/garden.js index f90c8f60..3939a2c7 100644 --- a/site/javascript/garden.js +++ b/site/javascript/garden.js @@ -60,18 +60,18 @@ Sections.prototype = { } }, - expand: function (sectionName) { + expand: function(sectionName) { var nav = this.page.nav, index = nav.find('a[href=#' + sectionName + ']') .closest('nav > ul > li').index(); var height = this.page.window.height() - $('nav > div').height() - - (33 * this.heights.length), + - (33 * this.heights.length); - sections = [], - currentHeight = 0, - distance = 0; + var sections = [], + currentHeight = 0, + distance = 0; while ((currentHeight + this.heights[index]) < height) { sections.push(index); @@ -135,7 +135,7 @@ function Page() { section: null, articule: null }); - + this.sections = new Sections(this); this.init(); } @@ -149,11 +149,11 @@ Page.prototype = { scrollLast: 0, resizeTimeout: null }); - + this.window.scroll(function() { that.onScroll(); }); - + this.window.resize(function() { that.onResize(); }); @@ -164,12 +164,12 @@ Page.prototype = { }, 10); // Show menu for tablets and smart phones - $('#show_menu').click(function (){ + $('#show_menu').click(function() { $mainNav.slideDown(300); return false; }); - $mainNav.click(function(){ + $mainNav.click(function() { if(that.window.width() < 1000) $mainNav.slideUp(300, function() { $mainNav.removeAttr('style'); }); }); From 8b458977d92cc14010041c24ab516ceb73f9ae98 Mon Sep 17 00:00:00 2001 From: Sebastien Nicoud Date: Thu, 19 Mar 2015 11:37:36 -0600 Subject: [PATCH 029/105] fr translation --- doc/fr/array/constructor.md | 27 +++++ doc/fr/array/general.md | 46 +++++++ doc/fr/core/delete.md | 76 ++++++++++++ doc/fr/core/eval.md | 42 +++++++ doc/fr/core/semicolon.md | 100 ++++++++++++++++ doc/fr/core/undefined.md | 55 +++++++++ doc/fr/function/arguments.md | 118 ++++++++++++++++++ doc/fr/function/closures.md | 97 +++++++++++++++ doc/fr/function/constructors.md | 109 +++++++++++++++++ doc/fr/function/general.md | 38 ++++++ doc/fr/function/scopes.md | 204 ++++++++++++++++++++++++++++++++ doc/fr/function/this.md | 100 ++++++++++++++++ doc/fr/index.json | 69 +++++++++++ doc/fr/intro/index.md | 36 ++++++ doc/fr/object/forinloop.md | 44 +++++++ doc/fr/object/general.md | 85 +++++++++++++ doc/fr/object/hasownproperty.md | 46 +++++++ doc/fr/object/prototype.md | 85 +++++++++++++ doc/fr/other/timeouts.md | 130 ++++++++++++++++++++ doc/fr/types/casting.md | 62 ++++++++++ doc/fr/types/equality.md | 58 +++++++++ doc/fr/types/instanceof.md | 35 ++++++ doc/fr/types/typeof.md | 66 +++++++++++ doc/language.json | 2 +- garden.jade | 2 +- 25 files changed, 1730 insertions(+), 2 deletions(-) create mode 100644 doc/fr/array/constructor.md create mode 100644 doc/fr/array/general.md create mode 100644 doc/fr/core/delete.md create mode 100644 doc/fr/core/eval.md create mode 100644 doc/fr/core/semicolon.md create mode 100644 doc/fr/core/undefined.md create mode 100644 doc/fr/function/arguments.md create mode 100644 doc/fr/function/closures.md create mode 100644 doc/fr/function/constructors.md create mode 100644 doc/fr/function/general.md create mode 100644 doc/fr/function/scopes.md create mode 100644 doc/fr/function/this.md create mode 100644 doc/fr/index.json create mode 100644 doc/fr/intro/index.md create mode 100644 doc/fr/object/forinloop.md create mode 100644 doc/fr/object/general.md create mode 100644 doc/fr/object/hasownproperty.md create mode 100644 doc/fr/object/prototype.md create mode 100644 doc/fr/other/timeouts.md create mode 100644 doc/fr/types/casting.md create mode 100644 doc/fr/types/equality.md create mode 100644 doc/fr/types/instanceof.md create mode 100644 doc/fr/types/typeof.md diff --git a/doc/fr/array/constructor.md b/doc/fr/array/constructor.md new file mode 100644 index 00000000..76f9eda0 --- /dev/null +++ b/doc/fr/array/constructor.md @@ -0,0 +1,27 @@ +## Le constructeur `Array` + +Le constructeur `Array` traite ses paramètres de façon ambigu. +Il est fortement recommandé d'utiliser le littéral de tableau - notation `[]` - pour créer de nouveaux tableaux. + + [1, 2, 3]; // Résultat: [1, 2, 3] + new Array(1, 2, 3); // Résultat: [1, 2, 3] + + [3]; // Résultat: [3] + new Array(3); // Résultat: [] + new Array('3') // Résultat: ['3'] + +Dans les cas où il n'y a qu'un seul argument passé au constructeur `Array`, et quand cet argument est un nombre `Number`, le constructeur va retourner un nouveau tableau *clairsemé* avec la propriété `length` (longueur) fixée à la valeur de l'argument. +Il faut noter que de cette façon, **seulement** la propriété `length` du nouveau tableau sera mise en place, les indices réels du tableau ne seront pas initialisés. + + var arr = new Array(3); + arr[1]; // undefined + 1 in arr; // faux, l'indice n'existe pas + +Être en mesure de régler la longueur du tableau à l'avance n'est utile que dans quelques cas, comme la répétition d'une chaîne de caractères, dans lequel on évite l'utilisation d'une boucle. + + new Array(count + 1).join(chaineARepeter); + +### En conclusion + +Les littéraux sont préférés au constructeur `Array`. Ils sont plus courts, ont une syntaxe plus claire, et augmente la lisibilité du code. + diff --git a/doc/fr/array/general.md b/doc/fr/array/general.md new file mode 100644 index 00000000..ab9183a0 --- /dev/null +++ b/doc/fr/array/general.md @@ -0,0 +1,46 @@ +## Tableaux: iteration et propriétés + +Bien que les tableaux soient des objets en JavaScript, il n'y a pas de bonnes raisons d'utiliser la boucle [`for in`](#object.forinloop). +En fait, il un certain nombre de bonnes raisons **contre** l'utilisation de `for in` sur les tableaux. + +**Remarque:** Les tableaux JavaScript ne sont **pas** *associatifs*. JavaScript n'offre que les [objets](#object.general) pour associer des clés à des valeurs. Contrairement aux tableaux associatifs, les objets ne préservent **pas** l'ordre. + +La boucle `for in` énumère toutes les propriétés qui sont sur la chaîne de prototypes, et le seul moyen d'exclure ces propriétés consiste à utiliser +[`hasOwnProperty`](#object.hasownproperty), par conséquent la boucle `for in ` est **vingt fois** plus lente qu'une boucle `for` classique. + +### Itération + +Pour itérer sur les tableaux de façon performante, il est préférable d'utiliser la boucle `for` classique. + + var list = [1, 2, 3, 4, 5, ...... 100000000]; + for(var i = 0, l = list.length; i < l; i++) { + console.log(list[i]); + } + +Notez l'optimization supplémentaire dans l'exemple ci-dessus: la longueur du tableau est mise en mémoire "cached" via `l = list.length`. + +La propriété `length` est définie sur le tableau lui-même, mais la rechercher à chaque itération de la boucle à un coût. +Bien que les moteurs JavaScript récents **peuvent** appliquer l'optimisation, il n'y a aucun moyen de savoir si le code s'exécutera sur un de ces nouveaux moteurs. + +En effet, mettre la longueur du tableau en mémoire cache peut **doubler** la vitesse d'execution de la boucle. + +### La propriété `length` + +Le *getter* de la propriété `length` (longueur) renvoie simplement le nombre d'éléments contenus dans le tableau, mais le *setter* peut être utilisé pour +tronquer le tableau. + + var arr = [1, 2, 3, 4, 5, 6]; + arr.length = 3; + arr; // [1, 2, 3] + + arr.length = 6; + arr.push(4); + arr; // [1, 2, 3, undefined, undefined, undefined, 4] + +Attribuer une longueur inférieure tronque le tableau. Accroître la longueur crée un tableau clairsemé. + +### En conclusion + +Pour de meilleures performances, il est recommandé de toujours utiliser la boucle `for` classique et de mettre en mémoire la propriété `length`. +L'utilisation de la boucle `for in` sur un tableau est un signe de code mal écrit, de mauvaise performance, et sujet à des bogues. + diff --git a/doc/fr/core/delete.md b/doc/fr/core/delete.md new file mode 100644 index 00000000..5ef0b16b --- /dev/null +++ b/doc/fr/core/delete.md @@ -0,0 +1,76 @@ +## L'opérateur `delete` + +Il est *impossible* de supprimer les variables globales, fonctions et autres choses qui ont l'attribut `DontDelete` en JavaScript. + +### Le code global et le code de fonction + +Quand une variable ou une fonction est définie dans la portée globale ou une [portée de fonction](#function.scopes), c'est une propriété soit de l'objet d'activation, soit de l'objet global. +Ces propriétés ont un ensemble d'attributs, dont l'un est `DontDelete`. Les déclarations de variables et de fonctions dans le code global et le code de fonction vont toujours créer des propriétés avec `DontDelete`, elle ne peuvent donc pas être supprimées. + + // global variable: + var a = 1; // DontDelete est mis + delete a; // faux + a; // 1 + + // normal function: + function f() {} // DontDelete is mis + delete f; // faux + typeof f; // "function" + + // reassigner n'aide pas: + f = 1; + delete f; // faux + f; // 1 + +### Propriétés explicites + +Les propriétés crées explicitement peuvent être supprimées normalement. + + // propriété crée explicitement: + var obj = {x: 1}; + obj.y = 2; + delete obj.x; // vrai + delete obj.y; // vrai + obj.x; // undefined + obj.y; // undefined + +Dans l'exemple ci-dessus, les propriétés `obj.x` et `obj.y` peuvent être supprimées parce qu'elles n'ont pas l'attribut `DontDelete`. C'est aussi pourquoi l'exemple ci-dessous fonctionne également. + + // ceci fonctionne, sauf sur IE: + var GLOBAL_OBJECT = this; + GLOBAL_OBJECT.a = 1; + a === GLOBAL_OBJECT.a; // vrai - juste une var globale + delete GLOBAL_OBJECT.a; // vrai + GLOBAL_OBJECT.a; // undefined + +Ici, nous utilisons une astuce pour supprimer `a`. [`this`](#function.this) se réfère ici à l'objet global et nous déclarons explicitement la variable `a` comme sa propriété, ce qui nous permet de la supprimer. + +IE (au moins 6-8) a quelques bogues, le code ci-dessus n'y fonctionne pas. + +### Les arguments de fonction et built-ins + +Les arguments normaux de fonctions, [objets `arguments`](#Function.arguments) et les propriétés intégrées "built-in" ont aussi l'attribut `DontDelete`. + + // les arguments de fonction et les propriétés: + (function (x) { + + delete arguments; // faux + typeof arguments; // "object" + + delete x; // faux + x; // 1 + + function f(){} + delete f.length; // faux + typeof f.length; // "number" + + })(1); + +### Objets hôtes + +Le comportement de l'opérateur `delete` peut être imprévisible pour les objets hébergés "hosted". Dû à la spécification, les objets hôte sont autorisés à mettre en œuvre tout type de comportement. + +### En conclusion + +L'opérateur `delete` a souvent un comportement inattendu et ne peut être utilisé que pour supprimer les propriétés explicitement définies sur des objets normaux. + diff --git a/doc/fr/core/eval.md b/doc/fr/core/eval.md new file mode 100644 index 00000000..5b2cdcd1 --- /dev/null +++ b/doc/fr/core/eval.md @@ -0,0 +1,42 @@ +## Il ne faut pas utiliser `eval` + +La fonction `eval` exécute une chaîne de caractères représentant du code JavaScript dans la portée locale. + + var number = 1; + function test() { + var number = 2; + eval('number = 3'); + return number; + } + test(); // 3 + number; // 1 + +Cependant, `eval` n'exécute dans la portée locale que quand il est appelé directement *et* quand le nom de la fonction appelée est en fait `eval`. + + var number = 1; + function test() { + var number = 2; + var copyOfEval = eval; + copyOfEval('number = 3'); + return number; + } + test(); // 2 + number; // 3 + +L'utilisation de la fonction `eval` doit être évitée. 99,9% de ses "cas d'utilisation" peuvent être obtenues **sans** elle. + +### `eval` déguisé + +Les [fonctions timeout](#other.timeouts) `setTimeout` et `setInterval` acceptent une chaîne comme premier argument. +Cette chaîne sera **toujours** exécutée dans la portée globale car dans ce cas, `eval` n'est pas appelé directement. + +### Problèmes de sécurité + +`eval` est aussi un problème de sécurité, car il exécute **n'importe quel** code qu'on lui donne. +Il devrait **jamais** être utilisé avec des chaînes d'origines inconnues ou douteuses. + +### En conclusion + +`eval` ne devrait jamais être utilisé. Sa presence met en doute le fonctionnement, la performance, et la sécurité du code qui l'utilise. +Si quelque chose a besoin d'`eval` pour pouvoir fonctionner, il ne doit **pas** être utilisé en premier lieu. Un *meilleur design* qui n'utilise pas `eval` doit être trouvé et implementé. + diff --git a/doc/fr/core/semicolon.md b/doc/fr/core/semicolon.md new file mode 100644 index 00000000..75e4ac11 --- /dev/null +++ b/doc/fr/core/semicolon.md @@ -0,0 +1,100 @@ +## Insertion automatique du point-virgule + +Bien que JavaScript a une syntaxe de style C, il n'impose **pas** les points-virgules dans le code source. Il est donc possible de les omettre. + +JavaScript n'est pas un langage sans points-virgules. En fait, les points-virgules sont necessaires pour comprendre le code source. Par conséquent, l'analyseur JavaScript les insère **automatiquement** chaque fois qu'il rencontre une erreur d'analyse due à un point-virgule manquant. + + var foo = function() { + } // erreur d'analyse, point-virgule attendu + test() + +L'analyseur insère un point-virgule, puis tente à nouveau. + + var foo = function() { + }; // plus d'error, l'analyse continue + test() + +L'insertion automatique du point-virgule est considérée comme l'un des **plus gros** défauts de conception dans le langage parce que cela *peut* changer le comportement du code. + +### Comment cela marche + +Le code ci-dessous n'a pas de points-virgules, l'analyseur va donc décider où les insérer. + + (function(window, undefined) { + function test(options) { + log('testing!') + + (options.list || []).forEach(function(i) { + + }) + + options.value.test( + 'long string to pass here', + 'and another long string to pass' + ) + + return + { + foo: function() {} + } + } + window.test = test + + })(window) + + (function(window) { + window.someLibrary = {} + + })(window) + +Voici le résultat du jeu de devinette de l'analyseur. + + (function(window, undefined) { + function test(options) { + + // pas inséré, les lignes ont fusionné + log('testing!')(options.list || []).forEach(function(i) { + + }); // <- inséré + + options.value.test( + 'long string to pass here', + 'and another long string to pass' + ); // <- inséré + + return; // <- inséré, casse la déclaration return + { // traité comme un bloc + + // un label et une déclaration d'expression + foo: function() {} + }; // <- inséré + } + window.test = test; // <- inséré + + // les lignes ont fusionné ici encore + })(window)(function(window) { + window.someLibrary = {}; // <- inséré + + })(window); //<- inséré + +> **Remarque:** L'analyseur JavaScript ne manipule pas "correctement" les déclarations return suivies par une nouvelle ligne. + +L'analyseur a radicalement changé le comportement du code ci-dessus. Dans certains cas, il fait la **mauvaise chose**. + +### Parenthèse en tête + +En cas de parenthèse en tête, l'analyseur ne va **pas** insérer de point-virgule. + + log('testing!') + (options.list || []).forEach(function(i) {}) + +Ce code fusionne en une ligne. + + log('testing!')(options.list || []).forEach(function(i) {}) + +Il y a de **très** fortes chances que `log` ne retourne **pas** de fonction; par conséquent, le programme ci-dessus va produire une erreur de type `TypeError` indiquant que undefined n'est pas un function `undefined is not a function`. + +### En conclusion + +Il est fortement recommandé de ne **jamais** omettre les points-virgules. Il est également recommandé de garder les accolades sur la même ligne que leurs déclarations correspondantes et de ne jamais les omettre pour les déclaration en une ligne `if` / `else`. Ces mesures vont non seulement améliorer la cohérence du code, mais elles empêcheront également l'analyseur JavaScript de changer le comportement du code. + diff --git a/doc/fr/core/undefined.md b/doc/fr/core/undefined.md new file mode 100644 index 00000000..4736b5dc --- /dev/null +++ b/doc/fr/core/undefined.md @@ -0,0 +1,55 @@ +## `undefined` et `null` + +JavaScript a deux valeurs distinctes pour "rien": `null` et `undefined`, `undefined` étant la plus utile. + +### La valeur `undefined` + +`undefined` est un type avec exactement une valeur:` undefined`. + +Le langage définit également une variable globale qui a la valeur `undefined`. Cette variable est aussi appelée `undefined`. Cependant, cette variable n'est ni une constante, ni un mot clé du langage, ce que signifie que sa *valeur* peut être facilement écrasée. + +> **Remarque ES5:** `undefined` dans ECMAScript 5 n'est **plus** inscriptible dans le mode stricte, mais son nom peut toujours être outrepassé, par example par une fonction avec le nom `undefined`. + +Voici quelques exemples de cas où la valeur `undefined` est retournée: + + - Accès à la variable globale (non modifié) `undefined`. + - Accès à une variable déclarée, mais *pas encore* initialisée. + - Retours implicites de fonctions sans déclaration `return`. + - Déclarations `return` vides, qui ne renvoient rien. + - Recherches de propriétés inexistantes. + - Paramètres de fonction qui ne ont pas de valeur explicite passée. + - Tout ce qui a été mis à la valeur de `undefined`. + - Toute expression sous forme de `void(expression)`. + +### Changements à la valeur de `undefined` + +Puisque la variable globale `undefined` contient uniquement une copie de la *valeur* réelle `undefined`, l'attribution d'une nouvelle valeur à la variable ne modifie **pas** la valeur du *type* `undefined`. + +Pourtant, pour pouvoir comparer quelque chose contre la valeur de `undefined`, il est d'abord nécessaire pour récupérer la valeur de `undefined`. + +Afin de protéger le code contre une éventuelle variable `undefined` écrasée, une technique commune utilisée consiste à ajouter un paramètre supplémentaire à une [enveloppe anonyme](#function.scopes) et de lui passer aucun argument. + + var undefined = 123; + (function(something, foo, undefined) { + // undefined dans la portée locale + // réfère bien à la valeur `undefined` + + })('Hello World', 42); + +Une autre façon d'obtenir le même effet est d'utiliser une déclaration à l'intérieur de l'enveloppe. + + var undefined = 123; + (function(something, foo) { + var undefined; + ... + + })('Hello World', 42); + +La seule différence étant quelques caractères de plus pour écrire "var". + +### Utilisation de `null` + +Alors que `undefined` dans le contexte du langage JavaScript est utilisé dans la plupart des cas dans le d'un *null* traditionnel, le `null` réel (un littéral et un type) est juste un autre type de données. + +`null` est utilisé par JavaScript (comme signaler la fin de la chaîne de prototypes avec `Foo.prototype = null`), mais dans presque tous les cas, il peut être remplacé par `undefined`. + diff --git a/doc/fr/function/arguments.md b/doc/fr/function/arguments.md new file mode 100644 index 00000000..84a09ea1 --- /dev/null +++ b/doc/fr/function/arguments.md @@ -0,0 +1,118 @@ +## L'objet `arguments` + +Chaque portée "scope" de fonction en JavaScript peut accéder à la variable spéciale `arguments`. +Cette variable contient une liste de tous les arguments qui ont été passés à la fonction. + +> **Remarque:** Si `arguments` a déjà été définie soit par une déclaration `var` +> à l'intérieur de la fonction ou par un paramètre de fonction, l'objet `arguments` ne sera pas créé. + +L'objet `arguments` n'est **pas** un tableau `Array`. Même s'il a la sémantique d'un tableau - à savoir la propriété `length` (longueur) - il n'hérite pas de +`Array.prototype` mais est en fait un `Object`. + +Pour cette raison, il n'est **pas** possible d'utiliser les méthodes de tableau standards comme `push`, `pop` ou `slice` sur `arguments`. +Bien qu'itérer avec une boucle `for` fonctionne, il est nécessaire de convertir la variable `arguments` en un véritable `Array` pour pouvoir lui appliquer les fonctions de tableau `Array` standards. + +### Conversion à Array + +Le code ci-dessous va retourner un nouveau tableau `Array` contenant tous les éléments de l'objet `arguments`. + + Array.prototype.slice.call(arguments); + +Cette conversion est **lente**, il n'est donc **pas** recommandé de l'utiliser dans des sections de code où la performance est critique. + +### Passage d'arguments + +Voici la méthode recommandée pour passer des arguments d'une fonction à une autre. + + function foo() { + bar.apply(null, arguments); + } + function bar(a, b, c) { + // faire qqch ici + } + +Une autre astuce consiste à utiliser à la fois `call` et `apply` pour transformer des méthodes - fonctions qui utilisent la +valeur de `this` ainsi que leurs arguments - en des fonctions normales qui n'utilisent que leurs arguments. + + function Person(first, last) { + this.first = first; + this.last = last; + } + + Person.prototype.fullname = function(joiner, options) { + options = options || { order: "western" }; + var first = options.order === "western" ? this.first : this.last; + var last = options.order === "western" ? this.last : this.first; + return first + (joiner || " ") + last; + }; + + // Créer une version non liée de "fullname", utilisable sur n'importe quel + // objet avec les propriétés 'first' et 'last' passées comme premier + // argument. Cette enveloppe n'aura pas besoin de changer si fullname + // change le nombre ou l'ordre des ses arguments. + Person.fullname = function() { + // résultat: Person.prototype.fullname.call(this, joiner, ..., argN); + return Function.call.apply(Person.prototype.fullname, arguments); + }; + + var grace = new Person("Grace", "Hopper"); + + // 'Grace Hopper' + grace.fullname(); + + // 'Turing, Alan' + Person.fullname({ first: "Alan", last: "Turing" }, ", ", { order: "eastern" }); + + +### Paramètres formels et arguments indexés + +L'objet `arguments` crée des fonctions *getter* et *setter* à la fois pour ses propriétés et les paramètres formels de la fonction. + +Par conséquent, changer la valeur d'un paramètre formel va également modifier la valeur de la propriété correspondante sur l'objet `arguments`, et vice-versa. + + function foo(a, b, c) { + arguments[0] = 2; + a; // 2 + + b = 4; + arguments[1]; // 4 + + var d = c; + d = 9; + c; // 3 + } + foo(1, 2, 3); + +### Mythes et faits sur la performance + +Le seul moment où l'objet `arguments` n'est pas créé est quand il est déclaré comme un nom à l'intérieur d'une fonction ou l'un de ses paramètres formels. Le fait qu'il soit utilisé ou non n'est pas important. + +Les deux *getter* et *setter* sont toujours créé; et donc l'utilisation d'`arguments` n'a aucune incidence sur la performance. + +> **Remarque ES5:** Ces *getters* et *setters* ne sont pas créés en mode strict. + +Cependant, un cas va considérablement réduire la performance des moteurs JavaScript modernes. +C'est le cas de l'utilisation de `arguments.callee`. + + function foo() { + arguments.callee; // faire quelque chose avec cet objet de fonction + arguments.callee.caller; // et la fonction appelante + } + + function bigLoop() { + for(var i = 0; i < 100000; i++) { + foo(); // Seraient normalement inline... + } + } + +Dans le code ci-dessus, `foo` ne peut plus être [inline][1] car il a besoin de se connaitre lui-même et connaitre son appelant. +Cela défait les gains possibles de performance qui découleraient d'inline, mais cela casse également l'encapsulation +car la fonction peut maintenant être dépendante d'un contexte d'appel spécifique. + +Utiliser `arguments.callee` ou l'une de ses propriétés est **fortement déconseillé**. + +> **Remarque ES5:** En mode strict, `arguments.callee` jettera une erreur de type `TypeError` +> car son utilisation est marquée comme obsolète "deprecated". + +[1]: http://en.wikipedia.org/wiki/Inlining + diff --git a/doc/fr/function/closures.md b/doc/fr/function/closures.md new file mode 100644 index 00000000..50983db3 --- /dev/null +++ b/doc/fr/function/closures.md @@ -0,0 +1,97 @@ +## Fermetures et réferences + +Les *fermetures* "closures" sont une des fonctionnalités les plus puissantes de JavaScript. +Avec les fermetures, les portées gardent **toujours** l'accès à la portée externe, dans laquelle elles ont été définies. +Puisque la seule portée que JavaScript a est la [portée de fonction](#function.scopes), toutes les fonctions, par défaut, agissent comme des fermetures. + +### Simuler les variables privées + + function Counter(start) { // compteur + var count = start; // compte + return { + increment: function() { + count++; + }, + + get: function() { + return count; + } + } + } + + var foo = Counter(4); + foo.increment(); + foo.get(); // 5 + +Ici, `Counter` retourne **deux** fermetures: la fonction` increment` ainsi que la fonction `get`. Ces deux fonctions conservent une **référence** à la portée de `Counter` et, par conséquent, gardent toujours l'accès à la variable `count` qui a été définie dans cette portée. + +### Comment marchent les variables privées + +Comme il ne est pas possible de référencer ou assigner des portées en JavaScript, il n'y a **aucun** moyen d'accéder à la variable `count` de l'extérieur. +La seule façon d'interagir avec elle est par l'intermédiaire des deux fermetures. + + var foo = new Counter(4); + foo.hack = function() { + count = 1337; + }; + +Le code ci-dessus ne va **pas** changer la variable `count` dans la portée de `Counter`, car `foo.hack` n'a pas été défini dans cette portée. En fait, une nouvelle variable va etre crée - ou va remplacer - la variable *globale* `count`. + +### Fermetures dans les boucles + +Une erreur souvent commise est d'utiliser les fermetures à l'intérieur de boucles comme si elles copiaient la valeur de la variable d'indice de la boucle. + + for(var i = 0; i < 10; i++) { + setTimeout(function() { + console.log(i); + }, 1000); + } + +La programme ci-dessus ne vas **pas** produire les numéros `0` à `9`, il imprimera `10` dix fois. + +La fonction *anonyme* garde une **référence** à `i`. Au moment où `console.log` est appelée, la `boucle for` est déjà achevée, et donc la valeur de `i` est à `10`. + +Afin d'obtenir le comportement souhaité, il est nécessaire de créer une **copie** de la valeur de `i`. + +### Eviter le problème de référence + +Pour copier la valeur de la variable d'index de la boucle, il est préférable d'utiliser une [enveloppe anonyme](#function.scopes) "wrapper". + + for(var i = 0; i < 10; i++) { + (function(e) { + setTimeout(function() { + console.log(e); + }, 1000); + })(i); + } + +La fonction externe anonyme est appelée immédiatement avec `i` en tant que premier argument, et donc le paramètre `e` recevra une copie de la **valeur** de `i`. + +La fonction anonyme qui est passé à `setTimeout` a maintenant une référence à `e`, dont la valeur ne peut **pas** être changée par la boucle. + +Une autre façon de faire est de retourner une fonction de l'enveloppe anonyme qui aura alors le même comportement que le code ci-dessus. + + for(var i = 0; i < 10; i++) { + setTimeout((function(e) { + return function() { + console.log(e); + } + })(i), 1000) + } + +Une autre façon populaire d'achever le même comportement est d'ajouter un argument supplémentaire à la fonction `setTimeout`. La fonction passera ces arguments à la fonction de rappel "callback". + + for(var i = 0; i < 10; i++) { + setTimeout(function(e) { + console.log(e); + }, 1000, i); + } + +Sachez que certains environnements JS (Internet Explorer 9 et avant) ne supportent pas cette dernière approche. + +Enfin, une dernière façon de faire et d'utiliser `bind`, qui peut lier le contexte `this` et les arguments pour la fonction. + + for(var i = 0; i < 10; i++) { + setTimeout(console.log.bind(console, i), 1000); + } + diff --git a/doc/fr/function/constructors.md b/doc/fr/function/constructors.md new file mode 100644 index 00000000..e92dea93 --- /dev/null +++ b/doc/fr/function/constructors.md @@ -0,0 +1,109 @@ +## Constructeurs + +Les constructeurs en JavaScript diffèrent de beaucoup d'autres langages. +Tout appel de fonction précédé par le mot clé `new` agit comme un constructeur. + +Dans le constructeur - la fonction appelée - la valeur de `this` se réfère à un objet nouvellement créé. +Le [prototype](#Object.prototype) de ce **nouvel** objet pointe sur le `prototype` de l'objet de fonction qui a été invoqué comme constructeur. + +Si la fonction qui a été appelée n'a pas de déclaration `return` explicite, elle renvoira implicitement la valeur de `this` - le nouvel objet. + + function Person(name) { + this.name = name; + } + + Person.prototype.logName = function() { + console.log(this.name); + }; + + var sean = new Person(); + +Le code ci-dessus appelle `Person` en tant que constructeur et définit le `prototype` du nouvel objet créé à `Person.prototype`. + +En cas d'une déclaration `return` explicite, la fonction renvoie la valeur spécifiée par cette déclaration, mais **seulement** si cette valeur est un objet `Object`. + + function Car() { + return 'ford'; + } + new Car(); // un nouvel objet, pas 'ford' + + function Person() { + this.someValue = 2; + + return { + name: 'Charles' + }; + } + new Test(); // l'objet retourné ({name:'Charles'}) n'inclue pas someValue + +Lorsque le mot clé `new` est omis, la fonction ne retournera **pas** un nouvel objet. + + function Pirate() { + this.hasEyePatch = true; // this est l'object global! + } + var somePirate = Pirate(); // somePirate est undefined + +Bien que l'exemple ci-dessus a l'air de marcher, il utilisera l'*objet global* pour la valeur de `this`, en raison du fonctionnement particulier de [`this`](#function.this) en JavaScript. + +### Fabriques + +Pour pouvoir omettre le mot clé `new`, la fonction constructeur doit retourner explicitement une valeur. + + function Robot() { + var color = 'gray'; + return { + getColor: function() { + return color; + } + } + } + Robot.prototype = { + someFunction: function() {} + }; + + new Robot(); + Robot(); + +Les deux appels à `Robot` retournent la même chose, un objet nouvellement créé qui possède une propriété appelée `getColor`, qui est une [fermeture](#function.closures) "closure". + +Il convient également de noter que l'appel `new Robot()` n'affecte **pas** le prototype de l'objet retourné. +Bien que le prototype sera mis sur le nouvel objet créé, `Robot` ne retourne jamais cet objet. + +Dans l'exemple ci-dessus, il n'y a pas de différence fonctionnelle entre l'utilisation et la non-utilisation du mot clé `new`. + +### Creation de nouvels objects via fabriques + +Il est souvent recommandé de ne **pas** utiliser `new` car l'oublier peut conduire à des bugs. + +Pour créer un nouvel objet, il faut plutôt utiliser une fabrique qui va construire un nouvel objet. + + function CarFactory() { + var car = {}; + car.owner = 'nobody'; + + var milesPerGallon = 2; + + car.setOwner = function(newOwner) { + this.owner = newOwner; + } + + car.getMPG = function() { + return milesPerGallon; + } + + return car; + } + +Bien que le code qui précède est robuste contre un mot clé `new` manquant et rend certainement +l'utilisation de [variables privées](#function.closures) plus facile, il y a des inconvénients. + + 1. Il utilise plus de mémoire car les objets créés ne partagent **pas** leurs méthodes avec un prototype. + 2. Pour hériter, la fabrique a besoin de copier toutes les méthodes de l'autre objet ou mettre l'autre objet sur le prototype du nouvel objet. + 3. Abandonner la chaîne de prototype à cause d'un mot clé `new` laissé de côté est contraire à l'esprit du langage. + +### En Conclusion + +Omettre le mot clé `new` peut conduire à des bugs, mais ce n'est certainement **pas** une raison d'abandonner l'utilisation des prototypes. +En fin de compte il s'agit de savoir quelle solution est la mieux adaptée pour les besoins de l'application. +Il est particulièrement important de choisir un style spécifique de création d'objet et toujours l'utiliser afin de rester *cohérent*. + diff --git a/doc/fr/function/general.md b/doc/fr/function/general.md new file mode 100644 index 00000000..b6fe47ec --- /dev/null +++ b/doc/fr/function/general.md @@ -0,0 +1,38 @@ +## Déclaration des fonctions et expressions + +Les fonctions en JavaScript sont des objets de première classe. Cela signifie qu'elles peuvent être passées comme toute autre valeur. Une utilisation courante de cette caractéristique est de passer une *fonction anonyme* comme une fonction de rappel "callback" qui peut être asynchrone. + +### La déclaration `function` + + function foo() {} + +La fonction ci-dessus est [hissée](#function.scopes) "hoisted" avant le démarrage du programme; ainsi, elle est donc disponible partout dans la portée "scope" d'application où la fonction a été définie, même si appelé avant sa définition dans le code source. + + foo(); // Fonctionne car foo a été crée avant l'exécution de ce code + function foo() {} + +### L'expresssion `function` + + var foo = function() {}; + +Cet exemple attribue une fonction *anonyme* et sans nom à la variable `foo`. + + foo; // 'undefined' + foo(); // provoque un erreur de type TypeError + var foo = function() {}; + +En raison du fait que `var` est une déclaration qui hisse le nom de la variable `foo` avant que l'exécution réelle du code ne commence, `foo` est déjà déclarée lorsque le script est exécuté. + +Mais comme les assignements ne se produisent qu'au moment de l'exécution, la valeur de `foo` sera par défaut mise à [undefined](#core.undefined) avant l'exécution du code. + +### L'expression de fonction nommée + +Un autre cas est l'attribution de fonctions nommées. + + var foo = function bar() { + bar(); // Works + } + bar(); // erreur de reference ReferenceError + +Ici, `bar` n'est pas disponible dans la portée externe "outer scope", puisque la fonction est seulement assignée à `foo`, mais elle est disponible à l'intérieur de `bar`. Cela est dû à la méthode de [résolution de noms](#function.scopes) de JavaScript: le nom de la fonction est *toujours* disponible dans la portée locale "local scope" de la fonction elle-même. + diff --git a/doc/fr/function/scopes.md b/doc/fr/function/scopes.md new file mode 100644 index 00000000..7cd1d0b3 --- /dev/null +++ b/doc/fr/function/scopes.md @@ -0,0 +1,204 @@ +## Portées "scopes" et espaces de noms "namespaces" + +Bien que JavaScript utilise une syntaxe avec accolades pour les blocs, il ne crée **pas** de portée "scope" de bloc; par conséquent, la seule portée du langage est la portée de fonction. + + function test() { // une portée "scope" + for(var i = 0; i < 10; i++) { // pas une portée + // count + } + console.log(i); // 10 + } + +> **Remarque:** Lorsqu'elle n'est pas utilisé dans un assignement, une déclaration de retour, +> ou un argument de fonction, la notation `{...}` sera interprétée comme une déclaration +> de bloc et non **pas** comme un littéral d'objet. Ceci, quand combiné avec +> l'[insertion automatique des points-virgules](#de core.semicolon), peut conduire à des erreurs subtiles. + +Il n'existe pas d'espaces de noms "namespaces" en JavaScript, ce qui signifie que tout est défini dans un espace de noms commun partagé par tous. + +Chaque fois qu'une variable est référencée, JavaScript va traverser vers le haut toutes les portées jusqu'à ce qu'il la trouve. +S'il atteint la portée globale sans avoir trouvé le nom demandé, il va générer une erreur de référence `ReferenceError`. + +### Le fléau des variables globales + + // script A + foo = '42'; + + // script B + var foo = '42' + +Les deux scripts ci-dessus n'ont **pas** le même effet. Le script A définit une variable appelée `foo` dans la portée *globale*, le script B définit `foo` dans la portée actuelle. + +Ne pas utiliser `var` peut avoir des répercussions majeures. + + // portée globale + var foo = 42; + function test() { + // portée locale + foo = 21; + } + test(); + foo; // 21 + +En laissant de côté la déclaration `var` à l'intérieur de la fonction `test`, on remplace la valeur de `foo`. +Même si au premier abord cela ne semble pas être une grosse affaire, des milliers de lignes de JavaScript qui n'utilisent pas `var` créeront des bogues horribles qui seront très difficiles à dépister. + + // portée globale + var items = [/* some list */]; + for(var i = 0; i < 10; i++) { + subLoop(); + } + + function subLoop() { + // portée de subLoop + for(i = 0; i < 10; i++) { // var manquant + // ici, des choses incroyables! + } + } + +La boucle externe se terminera après le premier appel à `subLoop`, car `subLoop` écrase la valeur globale de `i`. +L'utilisation d'un `var` pour la deuxième boucle `for` aurait facilement évité cette erreur. +La déclaration de `var` devrait **jamais** être laissé de côté, sauf si l'*effet désiré* est d'affecter la portée externe. + +### Variables locales + +Seuls les paramètres de [fonction](#function.general) et les variables déclarées avec un `var` peuvent créer des variables locales en JavaScript. + + + // portée globale + var foo = 1; + var bar = 2; + var i = 2; + + function test(i) { + // portée locale de la fonction test + i = 5; + + var foo = 3; + bar = 4; + } + test(10); + +`foo` et `i` sont bien des variables locales à l'intérieur de la portée de la fonction `test`, mais l'assignment `bar` remplacera la variable globale portant le même nom. + +### Remontée "hoisting" + +JavaScript **hisse** les déclarations. Cela signifie que les déclarations de `var` et `function` seront déplacés vers le haut de leur portée englobante. + + bar(); + var bar = function() {}; + var someValue = 42; + + test(); + function test(data) { + if (false) { + goo = 1; + + } else { + var goo = 2; + } + for(var i = 0; i < 100; i++) { + var e = data[i]; + } + } + +Le code ci-dessus est transformé avant que l'exécution ne commence. JavaScript déplace les déclarations `var`, ainsi que les déclarations `function`, vers le haut de la portée la plus proche. + + // les déclarations var sont maintenant ici + var bar, someValue; // mis à 'undefined' par défaut + + // les déclarations de fonction aussi + function test(data) { + var goo, i, e; // pas de portée de bloc, + // donc déclarations var viennent ici + if (false) { + goo = 1; + + } else { + goo = 2; + } + for(i = 0; i < 100; i++) { + e = data[i]; + } + } + + bar(); // échoue avec TypeError puisque bar est toujours 'undefined' + someValue = 42; // les assignements ne sont pas concernés par la remontée + bar = function() {}; + + test(); + +L'inexistence des portées de bloc va non seulement déplacer les déclarations `var` en dehors du corps des boucles, mais va aussi rendre les résultats de certaines constructions de `if` non-intuitifs. + +Dans le code original, la déclaration `if` semblait modifier la *variable globale* `goo`, alors qu'en fait elle modifiait la *variable locale* - après la remontée appliquée. + +Sans la connaissance du concept de *remontée*, on pourrait soupçonner que le code ci-dessous produirait une erreur de référence `ReferenceError`. + + // verifie si SomeImportantThing a bien été initializé + if (!SomeImportantThing) { + var SomeImportantThing = {}; + } + +Le code fonctionne pourtant bien, car la déclaration de `var` est déplacé vers le haut de la *portée globale*. + + var SomeImportantThing; + + // du code peut, ou pas, initializer SomeImportantThing ici + + // soyons en sûr + if (!SomeImportantThing) { + SomeImportantThing = {}; + } + +### Ordre de la résolution de noms + +Toutes les portées en JavaScript, y compris la *portée globale*, ont le nom spécial [`this`](#function.this) défini qui se réfère à l'*objet courant*. + +Les portées de fonction ont aussi le nom [`arguments`](#Function.arguments) défini qui contient les arguments qui ont été transmis à la fonction. + +Par exemple, lorsque vous essayez d'accéder à une variable nommé `foo` l'intérieur de la portée d'une fonction, JavaScript va chercher le nom dans l'ordre suivant: + + 1. Si il y a une déclaration `var foo` var dans la portée courante, l'utiliser. + 2. Si l'un des paramètres de la fonction est nommé `foo`, l'utiliser. + 3. Si la fonction elle-même est appelée `foo`, l'utiliser. + 4. Sinon, accéder à la portée externe suivante, et recommencer à **#1** pour cette portée. + +**Remarque:** Avoir un paramètre appelé `arguments` va **empêcher** la création d'objet par défaut `arguments`. + +### Espaces de noms + +Le fait de n'avoir qu'un seul espace de noms global engendre un risque de conflit de noms de variables, un problème commun en JavaScript. +En JavaScript, ce problème peut facilement être évité grâces aux *enveloppes anonymes*. + + (function() { + // un "espace de nom" autonome + + window.foo = function() { + // une fermeture exposée + }; + + })(); // exécute la fonction immédiatement + +Les fonctions anonymes sont considérées comme des [expressions](#function.general); ainsi elles doivent d'abord être évaluées avant d'être appelées. + + ( // évaluer la fonction à l'intérieur des parenthèses + function() {} + ) // et retourner la fonction object + () // appeler le résultat de l'évaluation + +Il y a d'autres façons d'évaluer et d'appeler directement l'expression de fonction qui, bien que différentes dans la syntaxe, se comportent de la même manière. + + // Autres styles d'invocation directe + !function(){}() + +function(){}() + (function(){}()); + // etc. + +### En conclusion + +Il est recommandé de toujours utiliser une *enveloppe anonyme* pour encapsuler du code dans son propre espace de noms. +Non seulement cela protège des conflits de noms de code, cela permet également une meilleure modularisation des programmes. + +En outre, l'utilisation de variables globales est considéré comme une **mauvaise pratique**. +Leur utilisation indique un code mal écrit, sujet à des erreurs, et difficile à maintenir. + diff --git a/doc/fr/function/this.md b/doc/fr/function/this.md new file mode 100644 index 00000000..723c0255 --- /dev/null +++ b/doc/fr/function/this.md @@ -0,0 +1,100 @@ +## Comment marche `this` + +Pour JavaScript, ce que le nom spécial `this` réfère à diffère de la plupart des autres langages de programmation. Il y a exactement **cinq** façons différente de lier la valeur de `this` dans le langage. + +### Le contexte global "global scope" + + this; + +Lorsque vous utilisez `this` dans le contexte global, il va simplement référer à l'objet *global*. + +### Appel de fonction + + foo(); + +Ici, `this` va aussi référer à l'objet *global*. + +> **Remarque ES5:** En mode strict, le cas global **n'existe plus**: `this` aura la valeur `undefined`. + +### Appel de méthode + + test.foo(); + +Dans cet exemple, `this` va référer à `test`. + +### Appel de constructeur + + new foo(); + +Un appel de fonction qui est précédé par le mot clé `new` agit comme un [constructeur](#function.constructors). Dans la fonction, `this` va référer à un `Object` *nouvellement créé*. + +### Assignement direct de `this` + + function foo(a, b, c) {} + + var bar = {}; + foo.apply(bar, [1, 2, 3]); // table va s'étendre comme ci-dessous + foo.call(bar, 1, 2, 3); // mène à: a = 1, b = 2, c = 3 + +Lorsque vous utilisez les méthodes `call` (appeler) ou `apply` (appliquer) de `Function.prototype`, la valeur de `this` à l'intérieur de la fonction appelée est **directement définie** par le premier argument de l'appel correspondant. + +En conséquence, dans l'exemple ci-dessus le cas d'*appel de méthode* ne s'applique **pas**, et `this` à l'intérieur de `foo` va bien référer à `bar`. + +> **Remarque:** `this` ne peut **pas** être utilisé pour se référer à l'objet à l'intérieur d'un littéral `Object`. +> Donc dans `var obj = {moi: this}`, `moi` ne vas **pas** référer à `obj`, puisque `this` ne reçoit une valeur que dans l'un des cinq cas énumérés. + +### Pièges communs + +Bien que la plupart de ces cas ont du sens, le premier cas peut être considéré comme une autre faute de design du langage, car il n'est **jamais** d'aucune utilité pratique. + + Foo.method = function() { + function test() { + // this réfère à l'objet global + } + test(); + } + +Une autre erreur souvent commise est que `this` l'intérieur de `test` se réfère à `foo`; ce qui n'est **pas** du tout le cas. + +Pour accéder à `foo` de l'intérieur de `test`, vous pouvez créer une variable locale à intérieur de `method` qui fait référence à `foo`. + + Foo.method = function() { + var self = this; + function test() { + // Utilisez self au lieu de this ici + } + test(); + } + +`self` est juste une variable normale, couramment utilisée pour référencer un `this` extérieur. Combiné avec des [fermetures](# function.closures) "closures", on peut l'utiliser pour passer les valeurs de `this`. + +À partir d'ECMAScript 5, l'utilisation de la méthode `bind` avec une fonction anonyme mène au même resultat: + + Foo.method = function() { + var test = function() { + // maintenant, this réfère à Foo + }.bind(this); + test(); + } + +### Assignement de méthodes + +Une autre chose qui ne marche **pas** en JavaScript est l'alias de fonction, ou l'**assignement** d'une méthode à une variable. + + var test = someObject.methodTest; + test(); + +En raison du premier des cinq cas, `test` agit maintenant comme un appel de fonction normal; par conséquent, `this` à l'intérieur de la fonction ne va plus référer à `someObject`. + +Bien que la liaison tardive "late binding" de `this` pouvait sembler comme une mauvaise idée au premier abord, c'est en fait grâce à cela que l'[héritage prototypique](#Object.prototype) fonctionne. + + function Foo() {} + Foo.prototype.method = function() {}; + + function Bar() {} + Bar.prototype = Foo.prototype; + + new Bar().method(); + +Quand `method` est appelée d'une instance de `bar`, `this` va référer à cette même instance. + diff --git a/doc/fr/index.json b/doc/fr/index.json new file mode 100644 index 00000000..9f1bf373 --- /dev/null +++ b/doc/fr/index.json @@ -0,0 +1,69 @@ +{ + "title": "Le Jardin de JavaScript", + "langTitle": "JavaScript Garden en Français", + "description": "Un guide des defauts et excentricités de JavaScript", + "sections": [ + { + "title": "Introduction", + "dir": "intro", + "articles": ["index"] + }, + { + "title": "Objets", + "dir": "object", + "articles": [ + "general", + "prototype", + "hasownproperty", + "forinloop" + ] + }, + { + "title": "Fonctions", + "dir": "function", + "articles": [ + "general", + "this", + "closures", + "arguments", + "constructors", + "scopes" + ] + }, + { + "title": "Tableaux", + "dir": "array", + "articles": [ + "general", + "constructor" + ] + }, + { + "title": "Types", + "dir": "types", + "articles": [ + "equality", + "typeof", + "instanceof", + "casting" + ] + }, + { + "title": "Cœur", + "dir": "core", + "articles": [ + "eval", + "undefined", + "semicolon", + "delete" + ] + }, + { + "title": "Autres", + "dir": "other", + "articles": [ + "timeouts" + ] + } + ] +} diff --git a/doc/fr/intro/index.md b/doc/fr/intro/index.md new file mode 100644 index 00000000..71c6ac67 --- /dev/null +++ b/doc/fr/intro/index.md @@ -0,0 +1,36 @@ +## Introduction + +Le **Jardin de JavaScript** est une collection croissante de documentation liée aux aspects les plus excentriques du langage de programmation JavaScript. Il donne des conseils pour éviter les erreurs communes, les bugs subtils, ainsi que les problèmes de performance et de mauvaises pratiques, que les amateurs de JavaScript peuvent rencontrer dans leurs efforts d'apprentissage en profondeur du langage. + +Le Jardin de JavaScript ne cherche pas à vous enseigner JavaScript. Une connaissance préalable du langage est fortement recommandée afin de comprendre les sujets abordés dans ce guide. Veuillez vous référer à l'excellent [guide][1] du Mozilla Developer Network pour apprendre les rudiments du langage JavaScript. + +## Auteurs + +Ce guide est l'œuvre de deux charmants utilisateurs de [Stack Overflow][2]: [Ivo Wetzel][3] (écriture) et [Zhang Yi Jiang][4] (design). + +Actuellement maintenu par [Tim Ruffles](http://truffles.me.uk). + +## Collaborateurs + +- Trop nombreux pour être énumérés ici, [voir la liste des collaborateurs](https://github.com/BonsaiDen/JavaScript-Garden/graphs/contributors). + +## Hébergement + +Le Jardin de JavaScript est hébergé sur GitHub, mais [Cramer Développement][7] nous soutient avec un mirroir à [JavaScriptGarden.info][8]. + +## Licence + +Le Jardin de JavaScript est publié sous la [licence MIT][9] et hébergé sur [GitHub][10]. Si vous trouvez des erreurs ou fautes de frappe veuillez s'il vous plaît [déposer une question][11] ou une "pull request" sur le dépôt. Vous pouvez également nous trouver dans la [Salle JavaScript][12] sur Stack Overflow. + +[1]: https://developer.mozilla.org/en/JavaScript/Guide +[2]: http://stackoverflow.com/ +[3]: http://stackoverflow.com/users/170224/ivo-wetzel +[4]: http://stackoverflow.com/users/313758/yi-jiang +[5]: https://github.com/caio +[6]: https://github.com/blixt +[7]: http://cramerdev.com/ +[8]: http://javascriptgarden.info/ +[9]: https://github.com/BonsaiDen/JavaScript-Garden/blob/next/LICENSE +[10]: https://github.com/BonsaiDen/JavaScript-Garden +[11]: https://github.com/BonsaiDen/JavaScript-Garden/issues +[12]: http://chat.stackoverflow.com/rooms/17/javascript diff --git a/doc/fr/object/forinloop.md b/doc/fr/object/forinloop.md new file mode 100644 index 00000000..afc1a2d5 --- /dev/null +++ b/doc/fr/object/forinloop.md @@ -0,0 +1,44 @@ +## La boucle `for in` + +Tout comme l'opérateur `in`, la boucle `for in` traverse la chaîne de prototypes lors de l'itération sur les propriétés d'un objet. + +> **Remarque:** La boucle `for in` n'itérera **pas** sur les propriétés qui +> ont leur attribut `enumerable` à `false`; par exemple, la propriété `length` d'un tableau "array". + + // Empoisonnement d'Object.prototype + Object.prototype.bar = 1; + + var foo = {moo: 2}; + for(var i in foo) { + console.log(i); // imprime bar et moo + } + +Puisqu'il n'est pas possible de changer le comportement de la boucle `for in`, il est nécessaire de filtrer les propriétés indésirables à l'intérieur du corps de la boucle. Sous ECMAScript 3 et plus, cela se fait en utilisant la méthode [`hasOwnProperty`](#object.hasownproperty) de `Object.prototype`. + +Depuis ECMAScript 5, `Object.defineProperty` peut être utilisé avec `enumerable` mis à faux pour ajouter des propriétés à des objets (y compris `Object`) sans que ces propriétés soient énumérées. Il est raisonnable dans ce cas d'assumer que les propriétés énumérables ont été ajouté pour une raison, ce qui permet d'omettre les appels à `hasOwnProperty` qui réduisent la lisibilité du code. Dans du code de librairie, `hasOwnProperty` devrait toujours être utilisé car des propriétés énumérables pourraient résider sur la chaîne de prototypes sans qu'on le sache. + +> **Remarque:** Puisque la boucle `for in` traverse toujours la chaîne de prototypes complet, elle +> deviendra plus lente avec chaque couche supplémentaire d'héritage ajoutée à un objet. + +### Filtrer avec `hasOwnProperty` + + // le même foo qu'au dessus + for(var i in foo) { + if (foo.hasOwnProperty(i)) { + console.log(i); + } + } + +Cette version est la seule version correcte à utiliser avec les anciennes versions d'ECMAScript. +L'utilisation de `hasOwnProperty` nous garantie que seulement `moo` sera imprimé. +Quand `hasOwnProperty` n'est pas utilisé, les prototypes natifs - par exemple `Object.prototype` - qui ont peut-être été étendus, causeront probablement des erreurs. + +Avec les versions plus récentes d'ECMAScript, des propriétés non-dénombrables peuvent être définies avec `Object.defineProperty`, réduisant le risque d'itération sur les propriétés quand `hasOwnProperty` n'est pas utilisé. Néanmoins, il faut faire attention avec l'utilisation de vieilles librairies comme [Prototype][1] qui ne bénéficient pas des nouvelles fonctions d'ECMAScript. Dans ce cadre, écrire des boucles `for in` sans `hasOwnProperty` est garanti de causer des erreurs. + +### En conclusion + +Il est recommandé de **toujours** utiliser `hasOwnProperty` avec ECMAScript 3 ou moins, ou dans du code de librairie. Dans ces environnements, il ne faut jamais assumer que les prototypes natifs n'ont pas été étendus. Depuis ECMAScript 5, `Object.defineProperty` permet de définir les propriétés non-dénombrables et donc permet d'omettre les appels à `hasOwnProperty` dans le code de l'application. + + +[1]: http://www.prototypejs.org/ + diff --git a/doc/fr/object/general.md b/doc/fr/object/general.md new file mode 100644 index 00000000..afa2ea25 --- /dev/null +++ b/doc/fr/object/general.md @@ -0,0 +1,85 @@ +## Utilisation des objets et propriétés + + +En JavaScript, tout agit comme un objet, à part deux exceptions: [`null`](#core.undefined) et [`undefined`](#core.undefined). + + false.toString(); // 'false' + [1, 2, 3].toString(); // '1,2,3' + + function Foo(){} + Foo.bar = 1; + Foo.bar; // 1 + +Une méprise commune est que les littéraux numériques ne peuvent pas être utilisés comme objets, due à une imperfection de l'analyseur de JavaScript qui tente d'analyser la *notation à point* sur un nombre comme une virgule flottante. + + 2.toString(); // erreur de syntaxe SyntaxError + +Des solutions de contournement existent pour forcer les littéraux numériques à agir comme des objets. + + 2..toString(); // le second point est correctement reconnu + 2 .toString(); // notez l'espace à gauche du point + (2).toString(); // 2 est évalué en premier + +### Objets comme type de données + +Les objets en JavaScript peuvent également être utilisés comme [*HashMaps*][1]; essentiellement, des propriétés nommées pointant sur des valeurs. + +En utilisant un littéral d'objet - notation `{}` - il est possible de créer un objet vide. +Ce nouvel objet [hérite](#object.prototype) de `Object.prototype` et ne possède pas de [propriétés propres](#object.hasownproperty) définies. + + var foo = {}; // un nouvel objet vide + + // un nouvel objet avec une propriété 'test' à valeur 12 + var bar = {test: 12}; + +### Accéder aux propriétés + +Les propriétés d'un objet sont accessibles de deux façons, soit par la notation à point, soit par la notation à crochets. + + var foo = {name: 'kitten'} + foo.name; // kitten + foo['name']; // kitten + + var get = 'name'; + foo[get]; // kitten + + foo.1234; // SyntaxError + foo['1234']; // cela marche + +Les deux notations fonctionnent presque pareil, la seule différence étant que la notation à crochet permet l'écriture des propriétés et l'utilisation des noms de propriété qui autrement mèneraient à une erreur de syntaxe. + +### Supprimer des propriétés + +La seule façon de supprimer une propriété d'un objet est d'utiliser l'opérateur `delete`. +Mettre la propriété à `null` ou `undefined` ne supprime que la *valeur* associée à la propriété, et non pas la *propriété* elle-même. + + var obj = { + bar: 1, + foo: 2, + baz: 3 + }; + obj.bar = undefined; + obj.foo = null; + delete obj.baz; + + for(var i in obj) { + if (obj.hasOwnProperty(i)) { + console.log(i, '' + obj[i]); + } + } + +Les résultats du programme ci-dessus sont `bar undefined` et `foo null` - seul `baz` a été correctement supprimé. + +### Notation des clefs "keys" + + var test = { + 'case': 'Je suis un mot-clé, donc je dois etre écrit en tant que chaîne', + delete: 'Je suis un mot-clé, donc moi aussi' // erreur de syntaxe SyntaxError + }; + +Les propriétés d'objet peuvent être écrites simplement telles quelles ou comme des chaînes "string". Une autre imperfection de l'analyseur de JavaScript, avant ECMAScript 5, provoquera une erreur de syntaxe `SyntaxError` dans le programme qui précède. + +Cette erreur vient du fait que `delete` est un *mot-clé*; et par conséquent, il doit être écrit comme une *chaîne* littérale pour s'assurer qu'il sera correctement interprété par les vieux moteurs JavaScript. + +[1]: http://en.wikipedia.org/wiki/Hashmap + diff --git a/doc/fr/object/hasownproperty.md b/doc/fr/object/hasownproperty.md new file mode 100644 index 00000000..aa912107 --- /dev/null +++ b/doc/fr/object/hasownproperty.md @@ -0,0 +1,46 @@ +## `hasOwnProperty` + +Pour savoir si un objet possède une propriété définie, et non pas quelque part ailleurs sur sa [chaîne de prototype](#object.prototype), il est nécessaire d'utiliser la méthode `hasOwnProperty`, une méthode que tous les objets héritent d'`Object.prototype`. + +> **Remarque:** Il n'est **pas** suffisant de vérifier si une propriété est `undefined`, +> car la propriété peut très bien exister, mais avec une valeur `undefined`. + +`hasOwnProperty` est la seule chose en JavaScript qui traite des propriétés **sans** traverser la chaîne de prototypes. + + // Empoisonnement d'Object.prototype + Object.prototype.bar = 1; + var foo = {goo: undefined}; + + foo.bar; // 1 + 'bar' in foo; // vrai + + foo.hasOwnProperty('bar'); // faux + foo.hasOwnProperty('goo'); // vrai + +Seulement `hasOwnProperty` donnera le résultat attendu et correct. Voir la section sur [les boucles `for in`](#object.forinloop) pour plus de détails sur l'utilisation de `hasOwnProperty` pour traverser les propriétés d'un objet. + +### `hasOwnProperty` en tant que propriété + +JavaScript ne protège pas le nom de la propriété `hasOwnProperty`; ainsi, la possibilité existe qu'un objet peut avoir une propriété avec ce nom, et il est donc nécessaire d'utiliser une méthode `hasOwnProperty` *externe* pour obtenir des résultats corrects. + + var foo = { + hasOwnProperty: function() { + return false; + }, + bar: 'Here be dragons' + }; + + foo.hasOwnProperty('bar'); // toujours faux + + // Utiliser hasOwnProperty d'un autre object, + // et l'appeler avec foo assigné à 'this' + ({}).hasOwnProperty.call(foo, 'bar'); // vrai + + // Il est aussi possible d'utiliser hasOwnProperty + //du prototype d'Object + Object.prototype.hasOwnProperty.call(foo, 'bar'); // vrai + +### En conclusion + +Utiliser `hasOwnProperty` est la **seule** méthode fiable pour vérifier l'existence d'une propriété sur un objet. Il est recommandé d'utiliser `hasOwnProperty` pour itérer sur les propriétés des objets comme décrit dans la section sur [les boucles `for in`](#object.forinloop). + diff --git a/doc/fr/object/prototype.md b/doc/fr/object/prototype.md new file mode 100644 index 00000000..50b21f23 --- /dev/null +++ b/doc/fr/object/prototype.md @@ -0,0 +1,85 @@ +## Le prototype + +JavaScript n'utilise pas le modèle classique d'héritage, mais un modèle *prototypique*. + +Souvent considéré comme l'une des faiblesses de JavaScript, le modèle d'héritage prototypique est en fait plus puissant que le modèle classique. Par exemple, il est assez facile de construire un modèle classique à partir du modèle prototypique, tandis que l'inverse est une tâche beaucoup plus difficile à entreprendre. + +JavaScript étant le seul langage à héritage prototypique largement utilisé, s'adapter aux différences entre les deux modèles peut prendre du temps. + +La première différence majeure est que l'héritage en JavaScript utilise des *chaînes de prototypes*. + +> **Remarque:** Utiliser simplement `Bar.prototype = Foo.prototype` résultera aux deux objets +> partageant le **même** prototype. Par conséquent, le changement du prototype d'un objet aura une +> incidence sur le prototype de l'autre ce qui, dans la plupart des cas, n'est pas l'effet désiré. + + function Foo() { + this.value = 42; + } + Foo.prototype = { + method: function() {} + }; + + function Bar() {} + + // Assigner le prototype de Bar à une nouvelle instance de Foo + Bar.prototype = new Foo(); + Bar.prototype.foo = 'Hello World'; + + // S'assurer que Bar est le constructeur + Bar.prototype.constructor = Bar; + + var test = new Bar(); // crée une nouvelle instance de bar + + // La chaîne de prototypes qui en résulte + test [instance of Bar] + Bar.prototype [instance of Foo] + { foo: 'Hello World' } + Foo.prototype + { method: ... } + Object.prototype + { toString: ... /* etc. */ } + +Dans le code ci-dessus, l'objet `test` va hériter à la fois de `Bar.prototype` et de `Foo.prototype`; par conséquent, il aura accès à la fonction `method` qui était définie sur `Foo`. Il aura également accès à la propriété `value` de la **seule** instance de `Foo` qui est son prototype. Il est important de noter que le `new Bar()` ne crée **pas** une nouvelle instance de `Foo`, mais réutilise celui attribué à son prototype; ainsi, toutes les instances de `Bar` se partageront la **même** propriété `value`. + +> **Remarque:** Ne **pas** utiliser `Bar.prototype = Foo`, car il ne pointera pas vers +> le prototype de `Foo` mais plutôt à l'objet-fonction `Foo`. donc, la +> chaîne de prototypes ira sur `Function.prototype` et non pas sur `Foo.prototype`; +> et donc, `method` ne sera pas disponible sur la chaîne de prototypes. + +### Recherche des propriétés + +Lors de l'accès aux propriétés d'un objet, JavaScript traversera la chaîne de prototypes **vers le haut** jusqu'à ce qu'il trouve une propriété avec le nom demandé. + +S'il atteint le sommet de la chaîne - à savoir `Object.prototype` - sans avoir trouvé la propriété spécifiée, la valeur [undefined](#core.undefined) sera retournée. + +### La propriété prototype + +Bien que la propriété prototype est utilisé par le langage pour construire la chaîne de prototypes, il est toujours possible de lui attribuer une valeur quelconque, mais les types primitifs seront simplement ignorés. + + function Foo() {} + Foo.prototype = 1; // aucun effet + +Assigner des objets, comme le montre l'exemple ci-dessus, va marcher, et permet la création dynamique de chaînes de prototypes. + +### Performance + +Les temps de recherche pour des propriétés qui sont en haut de la chaîne de prototypes peuvent avoir un impact négatif qui être significatif pour du code où la performance est critique. Essayer d'accéder à des propriétés inexistantes causera toujours la traversée complète de la chaîne de prototypes. + +De plus, [itérer](#object.forinloop) sur les propriétés d'un objet va causer l'énumération de **toutes** les propriétés qui se trouve sur la chaîne de prototype. + +### Extension des prototypes natifs + +Une mauvaise technique souvent utilisée est d'étendre `Object.prototype` ou un des prototypes intégrés. + +Cette technique est appelée [monkey patching][1] et casse l'*encapsulation*. Bien qu'utilisée par des cadriciels "frameworks" populaires tels que [Prototype][2], il n'existe aucune bonne raison pour encombrer les types intégrés avec des fonctionnalités supplémentaires *non standards*. + +La **seule** bonne raison d'étendre un prototype intégré est le rétroportage de caractéristiques des nouveaux moteurs JavaScript; par exemple, [`Array.forEach`][3]. + +### En conclusion + +Il est **essentiel** de comprendre le modèle d'héritage prototypique avant d'écrire du code complexe qui l'utilise. Soyez conscient de la longueur des chaînes de prototypes dans votre code; découpez les si nécessaire pour éviter de possible problèmes de performance. En outre, les prototypes natifs ne devraient **jamais** être étendus, sauf pour des raisons de compatibilité avec de nouvelles caractéristiques du langage JavaScript. + +[1]: http://en.wikipedia.org/wiki/Monkey_patch +[2]: http://prototypejs.org/ +[3]: https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/forEach + diff --git a/doc/fr/other/timeouts.md b/doc/fr/other/timeouts.md new file mode 100644 index 00000000..f06623e9 --- /dev/null +++ b/doc/fr/other/timeouts.md @@ -0,0 +1,130 @@ +### `setTimeout` et `setInterval` + +Puisque JavaScript est asynchrone, il est possible de programmer l'exécution future d'une fonction en utilisant les fonctions `setTimeout` et `setInterval`. + +> **Remarque:** Les temps d'attente "timeouts" ne font **pas** partie de la norme ECMAScript. Ils sont implémentés dans les [BOM ou DOM Niveau 0][1], qui ne ne sont ni définies ni documentés formellement. +> Aucune spécification recommandée n'a été publiée jusqu'à présent, cependant, ils sont en voie de normalisation par [HTML5][2]. +> En raison de cela, l'implémentation peut varier entre navigateurs et moteurs. + + function foo() {} + var id = setTimeout(foo, 1000); // retourne un nombre > 0 + +Quand `setTimeout` est appelé, il renvoie l'identifiant de la temporisation et fixe la date de d'exécution de `foo` **approximativement** mille millisecondes dans le future. `foo` sera exécuté **une seule** fois. + +La résolution de l'horloge du moteur JavaScript exécutant le code, le fait que JavaScript est mono-thread, et la possibilité qu'autre code en cours d'exécution peut bloquer le fil "thread", font qu'il n'est **pas** possible de déterminer le temps exact d'attente spécifié dans l'appel `setTimeout`. + +La fonction passée en tant que premier paramètre sera appelé par l'*objet global*, ce qui signifie que [`this`](#function.this) à l'intérieur de la fonction appelée fait référence à l'objet global. + + function Foo() { + this.value = 42; + this.method = function() { + // this réfère a l'boject global + console.log(this.value); // enregistre undefined + }; + setTimeout(this.method, 500); + } + new Foo(); + +> **Remarque:** Comme `setTimeout` prend un **objet fonction** comme premier paramètre, une erreur commune est d'écrire `setTimeout(foo(), 1000)`, qui utilisera la **valeur de retour** de l'appel `foo` et non **pas** `foo`. Cette erreur est, la plupart du temps, silencieuse, car lorsque la fonction retourne `undefined`, `setTimeout` ne produira **pas** d'erreur. + +### Empilement des appels avec `setInterval` + +`setTimeout` exécute la fonction une seule fois. `setInterval` - comme son nom le suggère - exécutera la fonction toutes les 'X' millisecondes, mais son utilisation est découragée. + +Lorsque que du code en cours d'exécution bloque la temporisation, `setInterval` continuera a émettre plusieurs appels à la fonction spécifiée. Cela peut, en particulier avec un petit intervalle, résulter à un empilement d'appels de fonction. + + function foo(){ + // qq chose qui bloque pendant 1 seconde + } + setInterval(foo, 100); + +Dans le code ci-dessus, `foo` sera appelé une fois et bloquera pendant une seconde. + +Pendant ce temps, `setInterval` va continuer à planifier les appels à la fonction. Quand `foo` se termine, il y aura déjà **dix** autres appels qui attendent pour s'exécuter. + +### Traiter le code bloquant éventuel + +La solution la plus simple et qui offre le plus de contrôle est d'utiliser `setTimeout` dans la fonction elle-même. + + function foo(){ + // qq chose qui bloque pendant 1 seconde + setTimeout(foo, 100); + } + foo(); + +Non seulement cela encapsule l'appel `setTimeout`, mais il empêche également l'empilement des appels et donne un contrôle supplémentaire. La fonction `foo` elle-même peut maintenant décider si elle veut s'exécuter à nouveau ou non. + +### Effacer un délais d'attente + +L'effacement des délais d'attente et des intervalles fonctionne en transmettant l'identifiant retourné par la fonction `setTimeout` ou `setInterval` à `clearTimeout` ou `clearInterval`, respectivement. + + var id = setTimeout(foo, 1000); + clearTimeout(id); + +### Effacer tous les délais d'attente + +Comme il n'existe pas de méthode intégrée pour effacer tous les délais d'attente et/ou intervalles, il est nécessaire d'utiliser la force brute pour obtenir cette fonctionnalité. + + // Effacement de "tous" les délais d'attente + for(var i = 1; i < 1000; i++) { + clearTimeout(i); + } + +Mais il pourrait encore y avoir des délais d'attente qui ne sont pas effacés par ce nombre arbitraire. +Une autre façon de faire découle du fait que l'identifiant donné à un délai d'attente est incrémenté à chaque fois que vous appelez `setTimeout`. + + // Effacement de "tous" les délais d'attente + var identifiantLePlusGrand = window.setTimeout(function(){}, 1), + i; + for(i = 1; i <= identifiantLePlusGrand; i++) { + clearTimeout(i); + } + +Même si cela fonctionne sur tous les principaux navigateurs d'aujourd'hui, il ne est pas précisé que les identifiants doivent être ordonnés de cette façon et cela peut changer. Par conséquent, il est plutôt recommandé de garder une trace de tous les identifiant crées, pour qu'ils puissent être effacées spécifiquement. + +### Utilisation cachée de `eval` + +`setTimeout` et `setInterval` peuvent également prendre une chaîne de caractères comme premier paramètre. +Cette fonctionnalité ne devrait **jamais** être utilisée car elle utilise `eval` en interne. + +> **Remarque:** Les mécanismes précis pour quand une chaîne est passée peuvent différer entre les diverses implémentations de JavaScript. +> Par exemple, JScript de Microsoft utilise le constructeur `Function` à la place de `eval`. + + function foo() { + // sera appelé + } + + function bar() { + function foo() { + // ne sera jamais appelé + } + setTimeout('foo()', 1000); + } + bar(); + +Puisque `eval` n'est pas appelé [directement](#core.eval), la chaîne passé à `setTimeout` sera exécutée dans la *portée globale*; ainsi, la variable `foo` locale à `bar` ne sera pas utilisée. + +Il est aussi recommandé de ne **pas** utiliser une chaîne pour passer des arguments à la fonction qui sera appelée par l'une des fonctions de temporisation. + + function foo(a, b, c) {} + + // ne JAMAIS faire cela + setTimeout('foo(1, 2, 3)', 1000) + + // utiliser plutôt une fonction anonyme + setTimeout(function() { + foo(1, 2, 3); + }, 1000) + +>**Remarque:** Bien qu'il soit également possible d'utiliser la syntaxe `setTimeout(foo, 1000, 1, 2, 3)`, elle n'est pas recommandée, car son utilisation peut entraîner des erreurs subtiles lorsqu'elle est utilisée avec des [méthodes](#function.this). +>En outre, la syntaxe peut ne pas fonctionner dans certaines implémentations de JavaScript. Par exemple, Internet Explorer de Microsoft [ne passe **pas** les arguments directement à la fonction de rappel][3]. + +### En conclusion + +Une chaîne ne devrait **jamais** être passée comme paramètre de `setTimeout` ou `setInterval` pour passer des arguments à la fonction appelée. C'est un clair signe de **mauvais** code. Il faut appeler une *fonction anonyme* qui se charge d'appeler la fonction réelle avec les arguments nécessaires. + +En outre, l'utilisation de `setInterval` doit être évitée car son programmateur n'est pas bloqué par le code en train de s'exécuter. + +[1]: http://www.nczonline.net/blog/2009/09/29/web-definitions-dom-ajax-and-more/ "Web definitions: DOM, Ajax, and more" +[2]: http://www.w3.org/TR/2014/WD-html5-20140617/webappapis.html#timers "6 Web application APIs - HTML5" +[3]: http://msdn.microsoft.com/en-us/library/ie/ms536753(v=vs.85).aspx "setTimeout method (Internet Explorer)" diff --git a/doc/fr/types/casting.md b/doc/fr/types/casting.md new file mode 100644 index 00000000..a0158f6b --- /dev/null +++ b/doc/fr/types/casting.md @@ -0,0 +1,62 @@ +## Changements de types + +JavaScript est un langage *faiblement typé*, il appliquera la *coercition de type* partout où c'est possible. + + // Ceux-ci sont vrais + new Number(10) == 10; // Objet Number est converti + // en un nombre primitif via un appel implicite + // à la méthode Number.prototype.valueOf + + 10 == '10'; // Strings est converti en Number + 10 == '+10 '; // Encore aussi fou + 10 == '010'; // Et encore + isNaN(null) == false; // null est converti en 0 + // ce qui, bien sûr, n'est pas NaN + + // Ceux-ci sont faux + 10 == 010; + 10 == '-10'; + +> **Remarque ES5:** Les nombres littéraux qui commencent avec un '0' sont interprétés comme octal (Base 8). L'octal a été **retiré** dans ECMAScript 5 en mode stricte. + +Pour éviter les problèmes ci-dessus, l'utilisation de l'[opérateur d'égalité stricte](# types.equality) est **fortement** recommandé. +Bien que cela évite beaucoup de pièges communs, il y en reste encore beaucoup. Tous ces pièges découlent de la faiblesse du système de typage de JavaScript. + +### Constructeurs de types internes + +Les constructeurs de types internes comme `Number` et `String` se comportent différemment suivant s'ils sont utilisés avec ou sans le mot clé `new`. + + new Number(10) === 10; // Faux, Object et Number + Number(10) === 10; // Vrai, Number et Number + new Number(10) + 0 === 10; // Vrai, due à la reconversion implicite + +L'utilisation d'un type intégré comme `Number` en tant que constructeur va créer une nouvel objet `Number`. Mais sans le mot clé `new`, `Number` se comportera comme un convertisseur. + +De plus, passer des valeurs littérales ou des non-objets se traduira par encore plus de coercition de type. + +La meilleure option est de forcer **explicitement** le type à l'un des trois types possibles . + +### Forcer à String + + '' + 10 === '10'; // vrai + +En faisant précéder une **chaîne vide**, une valeur peut facilement être converti en une chaîne. + +### Forcer à Number + + +'10' === 10; // vrai + +L'utilisation de l'opérateur **plus unaire** converti une valeur en nombre. + +### Forcer à Boolean + +L'utilisation double de l'opérateur **non** converti une valeur en booléen. + + !!'foo'; // vrai + !!''; // faux + !!'0'; // vrai + !!'1'; // vrai + !!'-1' // vrai + !!{}; // vrai + !!true; // vrai + diff --git a/doc/fr/types/equality.md b/doc/fr/types/equality.md new file mode 100644 index 00000000..3c1c09dd --- /dev/null +++ b/doc/fr/types/equality.md @@ -0,0 +1,58 @@ +## Égalité et comparaisons + +JavaScript a deux façons de comparer les valeurs des objets pour égalité. + +### L'opérateur d'égalité + +L'opérateur d'égalité se compose de deux signes égal: `==`. + +JavaScript est un langage au *typage faible* "weak typing". Cela signifie que l'opérateur d'égalité va convertir les deux opérandes en un même type afin de les comparer. + + "" == "0" // faux + 0 == "" // vrai + 0 == "0" // vrai + false == "false" // faux + false == "0" // vrai + false == undefined // faux + false == null // faux + null == undefined // vrai + " \t\r\n" == 0 // vrai + +Le tableau ci-dessus montre les résultats de la coercition de type, et c'est la raison principale pourquoi l'utilisation de `==` est largement considéré comme une mauvaise pratique. Les règles de conversion de types compliquées introduisent des bogues difficiles à dépister. + +### L'opérateur d'égalité stricte + +L'opérateur d'égalité stricte se compose de **trois** signes égal: `===`. + +Il fonctionne comme l'opérateur d'égalité normale, sauf que l'égalité stricte ne converti **pas** le types de ses opérandes. + + "" === "0" // faux + 0 === "" // faux + 0 === "0" // faux + false === "false" // faux + false === "0" // faux + false === undefined // faux + false === null // faux + null === undefined // faux + " \t\r\n" === 0 // faux + +Les résultats ci-dessus sont beaucoup plus clairs et permettent la rupture précoce de code. +Cela durcit le code jusqu'à un certain degré, et améliore la performance dans le cas où les opérandes sont de types différents. + +### Comparaison d'objets + +Bien que `==` et `===` sont appelés **opérateurs d'égalité**, ils se comportent différement quand au moins un des opérandes est un objet `Object`. + + {} === {}; // faux + new String('foo') === 'foo'; // faux + new Number(10) === 10; // faux + var foo = {}; + foo === foo; // vrai + +En effet, les deux opérateurs comparent l'**identité** et non pas l'**égalité**. Autrement dit, ils comparent pour la même **instance** de l'objet, tout comme `is` en Python, ou la comparaison de pointeur en C. + +### En conclusion + +Il est fortement recommandé de n'utiliser que l'opérateur d'**égalité stricte**. Dans les cas où les types ont à être convertis, cela devraient être fait [explicitement](#types.casting) et non pas laissé aux règles complexes de coercition de type du langage. + + diff --git a/doc/fr/types/instanceof.md b/doc/fr/types/instanceof.md new file mode 100644 index 00000000..ba733e43 --- /dev/null +++ b/doc/fr/types/instanceof.md @@ -0,0 +1,35 @@ +## L'opérateur `instanceof` + +L'opérateur `instanceof` (instance de) compare les constructeurs de ses deux opérandes. Il est seulement utile pour comparer des objets faits sur mesure. Utilisé sur les types intégrés, il est +aussi inutile que l'[opérateur typeof](# types.typeof). + +### Comparer des objets personnalisés + + function Foo() {} + function Bar() {} + Bar.prototype = new Foo(); + + new Bar() instanceof Bar; // vrai + new Bar() instanceof Foo; // vrai + + // Ceci définit simplement Bar.prototype à l'objet de fonction Foo, + // mais pas à une instance réelle de Foo + Bar.prototype = Foo; + new Bar() instanceof Foo; // faux + +### Utiliser `instanceof` avec des types natifs + + new String('foo') instanceof String; // vrai + new String('foo') instanceof Object; // vrai + + 'foo' instanceof String; // faux + 'foo' instanceof Object; // faux + +Une chose importante à noter ici est que `instanceof` ne fonctionne pas sur les objets qui proviennent de différents contextes JavaScript (par exemple, différents documents +dans un navigateur web), car leurs constructeurs ne seront pas exactement le même objet. + +### En conclusion + +L'opérateur `instanceof` devrait **seulement** être utilisé sur des objets crées sur mesure provenant du même contexte JavaScript. +Tout comme l'opérateur [`typeof`](#types.typeof), chaque autre utilisation de celui-ci devrait être **évitée**. + diff --git a/doc/fr/types/typeof.md b/doc/fr/types/typeof.md new file mode 100644 index 00000000..186bfb32 --- /dev/null +++ b/doc/fr/types/typeof.md @@ -0,0 +1,66 @@ +## L'opérateur `typeof` + +L'opérateur `typeof` (avec [`instanceof`](#types.instanceof)) est probablement le plus grand défaut de design de JavaScript, car il est presque **complètement cassé**. + +Bien que `instanceof` (instance de) a quelques utilisations limitées, `typeof` (type de) n'a qu'un seul cas pratique d'utilisation, et ce cas n'est **pas** la vérification du type d'un objet. + +> **Remarque:** Alors que `typeof` peut être appelé comme une fonction, i.e. `typeof(obj)`, ce n'est pas un appel de fonction. +> Les parenthèses se comportent comme d'habitude et la valeur de retour sera utilisé comme opérande de l'opérateur `typeof`. La *fonction* `typeof` n'existe pas. + +### table de types JavaScript + + Valeur Class Type + ------------------------------------- + "foo" String string + new String("foo") String object + 1.2 Number number + new Number(1.2) Number object + true Boolean boolean + new Boolean(true) Boolean object + new Date() Date object + new Error() Error object + [1,2,3] Array object + new Array(1, 2, 3) Array object + new Function("") Function function + /abc/g RegExp object (function pour Nitro/V8) + new RegExp("meow") RegExp object (function pour Nitro/V8) + {} Object object + new Object() Object object + +Dans la table ci-dessus, *Type* se réfère à la valeur retournée pas l'opérateur `typeof`, et comme on peut le voir clairement, cette valeur est incohérente. + +*Class* se réfère à la valeur de la propriété interne `[[Class]]` d'un objet. + +> **D'après la spécification:** La valeur de `[[Class]]` peut être l'une des chaînes suivantes: `Arguments`, `Array`, `Boolean`, `Date`, `Error`, `Function`, `JSON`, `Math`, `Number`, `Object`, `RegExp`, `String`. + +Pour récupérer la valeur de `[[Class]]`, on peut utiliser la méthode `toString` de `Object.prototype`. + +### La classe d'un objet + +La spécification donne exactement un moyen d'accéder à la valeur `[[Class]]`: via `Object.prototype.toString`. + + function is(type, obj) { + var clas = Object.prototype.toString.call(obj).slice(8, -1); + return obj !== undefined && obj !== null && clas === type; + } + + is('String', 'test'); // vrai + is('String', new String('test')); // vrai + +Dans l'exemple ci-dessus, `Object.prototype.toString` est appelé avec la valeur [this](#function.this) pointant sur l'objet dont on cherche a récupérer la valeur de `[[Class]]`. + +> **Remarque ES5:** Pour plus de commodité la valeur de retour de `Object.prototype.toString` de `null` et `undefined` a été **changée** de `Object` à `Null` et `Undefined` avec ECMAScript 5. + +### Test pour les variables indéfinies + + typeof foo !== 'undefined' + +Ce qui précède vérifie si `foo` a été effectivement déclarée. Juste référencer la variable résulterait en une erreur de référence `ReferenceError`. C'est la seule chose pour laquelle `typeof` est réellement utile. + +### En conclusion + +Pour vérifier le type d'un objet, il est fortement recommandé d'utiliser `Object.prototype.toString` parce que c'est le seul moyen fiable de le faire. +Comme représenté dans la table de type ci-dessus, certaines valeurs de retour de `typeof` ne sont pas définies dans la spécification; et donc, elles peuvent différer entre les implémentations. + +If faut éviter d'utiliser `typeof`, sauf pour vérifier si une variable est définie. + diff --git a/doc/language.json b/doc/language.json index e862f82a..af707fb6 100644 --- a/doc/language.json +++ b/doc/language.json @@ -1,4 +1,4 @@ { "default": "en", - "listed": ["en","es","fi","hu","it","ja","ko","pl","ptbr","ru","tr","zh","zhtw"] + "listed": ["en","es","fi","fr","hu","it","ja","ko","pl","ptbr","ru","tr","zh","zhtw"] } diff --git a/garden.jade b/garden.jade index 63ce447b..f18a7523 100644 --- a/garden.jade +++ b/garden.jade @@ -1,4 +1,4 @@ -!!! 5 +doctype html html(lang=language) head title #{title} From a3e0c337ce5ea0d1c17656a37459cdc45e6d7c4b Mon Sep 17 00:00:00 2001 From: Calvin Jeng Date: Sun, 22 Mar 2015 00:31:38 +0800 Subject: [PATCH 030/105] Translation mistake in the zh-tw scopes.md. In the "When not used in an assignment, return statement or as a function argument, the {...} notation will get interpreted as a block statement and not as an object literal" paragraph, the meaning in the English ver. is different in the Chinese ver. I think there are translation faults which may lead to misunderstanding in the zh-tw version, so I make some corrections in that paragraph. Please check that. Thanks :-) --- doc/zhtw/function/scopes.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/zhtw/function/scopes.md b/doc/zhtw/function/scopes.md index 76a84a6c..3e151282 100644 --- a/doc/zhtw/function/scopes.md +++ b/doc/zhtw/function/scopes.md @@ -10,7 +10,7 @@ console.log(i); // 10 } -> **注意:** 如果不是在賦值語句中,而是在 return 表達式或者函數參數中, `{...}` 將會作為程式碼中的解析,而不是作為物件的字面語法解析。 +> **注意:** 如果不是用在變數賦予值的宣告中、return 的回傳值中或者函數的參數中, `{...}` 將會被解析為一個程式區塊(block scope),而不是被解析為物件實體語法(object literal)。 > 如果考慮到 [自動分號插入](#core.semicolon),可能會造成一些不易察覺的錯誤。 JavaScript 中沒有寫示的命名空間定義,這代表著它所有定義的東西都是 *全域共享* 在同一個命名空間下。 @@ -196,4 +196,4 @@ JavaScript 中所有的作用區,包括 *全域作用域*,都有一個特殊 建議最好是都用 *匿名包裝器* 來封裝你的程式碼在自己的命名區間內。這不僅是要防止命名衝突也可以使得程序更有模組化。 -另外,全域變數是個 **不好的** 習慣,因為它會帶來錯誤和更難去維護。 \ No newline at end of file +另外,全域變數是個 **不好的** 習慣,因為它會帶來錯誤和更難去維護。 From 09fb7eb6926b5ac2cb267791fb310a8d4b512a8f Mon Sep 17 00:00:00 2001 From: kamilmielnik Date: Sun, 29 Mar 2015 23:18:44 +0200 Subject: [PATCH 031/105] Typo in closures.md --- doc/en/function/closures.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/en/function/closures.md b/doc/en/function/closures.md index a0085a5c..a5fbc91e 100644 --- a/doc/en/function/closures.md +++ b/doc/en/function/closures.md @@ -96,7 +96,7 @@ above. })(i), 1000) } -The other popular way to acheive this is to add an additional argument to +The other popular way to achieve this is to add an additional argument to the setTimeout function, which passes these arguments to the callback. for(var i = 0; i < 10; i++) { From 02ad7c1cb4253aebf37616eb0f40a4f1c07d32a8 Mon Sep 17 00:00:00 2001 From: Peter West Date: Tue, 31 Mar 2015 14:54:52 +0100 Subject: [PATCH 032/105] FIxed a typo in the code in constructor section --- doc/en/function/constructors.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/en/function/constructors.md b/doc/en/function/constructors.md index f8a3d9c7..2fa3bda4 100644 --- a/doc/en/function/constructors.md +++ b/doc/en/function/constructors.md @@ -39,7 +39,7 @@ specified by that statement, but **only** if the return value is an `Object`. name: 'Charles' }; } - new Test(); // the returned object ({name:'Charles'}), not including someValue + new Person(); // the returned object ({name:'Charles'}), not including someValue When the `new` keyword is omitted, the function will **not** return a new object. From 6b282f9df64dcf00d7967694f1acb0d485b017f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=82=B9=E6=98=8E?= Date: Mon, 13 Apr 2015 12:04:08 +0800 Subject: [PATCH 033/105] [zh] change "assert" to "console.assert" in annotation, fixed "assert is not defined" issue on broswer --- doc/zh/function/arguments.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/zh/function/arguments.md b/doc/zh/function/arguments.md index d6f7f9db..69c07fe5 100755 --- a/doc/zh/function/arguments.md +++ b/doc/zh/function/arguments.md @@ -93,8 +93,8 @@ JavaScript 中每个函数内都能访问一个特别变量 `arguments`。这个 return [a, arguments[0]]; } var pair = f(17); - assert(pair[0] === 42); - assert(pair[1] === 17); + console.assert(pair[0] === 42); + console.assert(pair[1] === 17); 然而,的确有一种情况会显著的影响现代 JavaScript 引擎的性能。这就是使用 `arguments.callee`。 From f5c1108ce81334ed55868be88a94d885b42396fa Mon Sep 17 00:00:00 2001 From: Neil Taylor Date: Tue, 14 Apr 2015 11:17:53 -0400 Subject: [PATCH 034/105] Removing confusing un-needed code + method name change --- doc/en/function/constructors.md | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/doc/en/function/constructors.md b/doc/en/function/constructors.md index f8a3d9c7..1277dcb3 100644 --- a/doc/en/function/constructors.md +++ b/doc/en/function/constructors.md @@ -65,15 +65,12 @@ explicitly return a value. } } } - Robot.prototype = { - someFunction: function() {} - }; new Robot(); Robot(); Both calls to `Robot` return the same thing, a newly created object that -has a property called `method`, which is a +has a property called `getColor`, which is a [Closure](#function.closures). It should also be noted that the call `new Robot()` does **not** affect the From b62fc83e4dedb190797c0f1e70d9e8dcc4d78f73 Mon Sep 17 00:00:00 2001 From: Tim Ruffles Date: Sun, 19 Apr 2015 10:23:11 +0100 Subject: [PATCH 035/105] typo --- doc/en/function/constructors.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/en/function/constructors.md b/doc/en/function/constructors.md index 1277dcb3..e84a6cf8 100644 --- a/doc/en/function/constructors.md +++ b/doc/en/function/constructors.md @@ -39,7 +39,7 @@ specified by that statement, but **only** if the return value is an `Object`. name: 'Charles' }; } - new Test(); // the returned object ({name:'Charles'}), not including someValue + new Person(); // the returned object ({name:'Charles'}), not including someValue When the `new` keyword is omitted, the function will **not** return a new object. From e8c1b0330f1a765df80ee7282daee94e432adaf9 Mon Sep 17 00:00:00 2001 From: Tim Ruffles Date: Thu, 28 May 2015 11:33:06 +0100 Subject: [PATCH 036/105] doc build script --- package.json | 3 +++ 1 file changed, 3 insertions(+) diff --git a/package.json b/package.json index ea637eb1..a9662f9f 100644 --- a/package.json +++ b/package.json @@ -2,6 +2,9 @@ "name": "javascript-garden", "description": "A collection of documentation about the most quirky parts of the JavaScript language.", "version": "0.0.0", + "scripts": { + "build": "node build.js" + }, "dependencies": { "fomatto": "0.5.0", "forever": "0.10.8", From b10deb7ed1e8e41bfc24f530de0ffe9ba151f354 Mon Sep 17 00:00:00 2001 From: Tim Ruffles Date: Thu, 28 May 2015 11:33:29 +0100 Subject: [PATCH 037/105] [fix #285] be more specific about return value --- doc/en/types/typeof.md | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/doc/en/types/typeof.md b/doc/en/types/typeof.md index 637ea2bc..9eb3fbdc 100644 --- a/doc/en/types/typeof.md +++ b/doc/en/types/typeof.md @@ -42,13 +42,11 @@ The *Class* refers to the value of the internal `[[Class]]` property of an objec > following strings. `Arguments`, `Array`, `Boolean`, `Date`, `Error`, > `Function`, `JSON`, `Math`, `Number`, `Object`, `RegExp`, `String`. -In order to retrieve the value of `[[Class]]`, one has to make use of the -`toString` method of `Object.prototype`. - ### The Class of an Object -The specification gives exactly one way of accessing the `[[Class]]` value, -with the use of `Object.prototype.toString`. +The only way to determine an object's `[[Class]]` value is using `Object.prototype.toString`. It +returns a string in the following format: `'[object ' + valueOfClass + ']'`, e.g `[object String]` or +`[object Array]`: function is(type, obj) { var clas = Object.prototype.toString.call(obj).slice(8, -1); From 9d10a8dc9dc8cdde200f31651532ee72b39d5d5f Mon Sep 17 00:00:00 2001 From: Tim Ruffles Date: Thu, 28 May 2015 11:40:49 +0100 Subject: [PATCH 038/105] add symlink to make running locally easy --- JavaScript-Garden | 1 + 1 file changed, 1 insertion(+) create mode 120000 JavaScript-Garden diff --git a/JavaScript-Garden b/JavaScript-Garden new file mode 120000 index 00000000..dcc6db5e --- /dev/null +++ b/JavaScript-Garden @@ -0,0 +1 @@ +./site \ No newline at end of file From b6011af45609016cf7c11b9fefc8ecba23dfae13 Mon Sep 17 00:00:00 2001 From: Tim Ruffles Date: Thu, 28 May 2015 11:42:02 +0100 Subject: [PATCH 039/105] update contributing --- CONTRIBUTING.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index c4b42c85..20faf510 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -6,3 +6,14 @@ 1. Contributing to JS Garden makes you a fantastic person, and Brendan Eich will find you immensely attractive. Thank you for being kind enough to help out! + +## Testing locally + +1. Run `npm run build.js` to build +1. Run a webserver from the root of the repo to view + +## Getting changes merged + +1. Squash your changes into one commit +1. Make sure the site still works :) +1. Make a PR From e95816c2098e19b8de531c7c3b5809605419d7ab Mon Sep 17 00:00:00 2001 From: Tim Ruffles Date: Thu, 28 May 2015 11:43:42 +0100 Subject: [PATCH 040/105] improve gitignore --- .gitignore | 23 ++++++++--------------- 1 file changed, 8 insertions(+), 15 deletions(-) diff --git a/.gitignore b/.gitignore index 83ec89a6..2bfbed12 100644 --- a/.gitignore +++ b/.gitignore @@ -1,22 +1,15 @@ -/site/index.html /build /html /log /node_modules -/site/de -/site/ru -/site/zh -/site/en -/site/fi -/site/pl -/site/tr -/site/ko -/site/ja -/site/es -/site/hu -/site/zhtw -/site/it -/site/hu + +/site +!/site/favicon.ico +!/site/image +!/site/javascript +!/site/style +!/site/style + *.md~ *.src.md *.DS_store From 6a563ab7619597886d4d1035c5196206ab4f2d73 Mon Sep 17 00:00:00 2001 From: trauma2u Date: Wed, 8 Apr 2015 11:54:41 +0900 Subject: [PATCH 041/105] add ko translation --- doc/ko/array/general.md | 13 +++--- doc/ko/core/eval.md | 22 +++++----- doc/ko/function/arguments.md | 35 +++++++++++----- doc/ko/function/closures.md | 18 +++++++++ doc/ko/function/constructors.md | 72 +++++++++++++++++---------------- doc/ko/function/this.md | 18 +++++++-- 6 files changed, 112 insertions(+), 66 deletions(-) diff --git a/doc/ko/array/general.md b/doc/ko/array/general.md index 1a665fa3..12f66100 100644 --- a/doc/ko/array/general.md +++ b/doc/ko/array/general.md @@ -25,14 +25,15 @@ JavaScript에서는 배열(Array)도 객체(Object)지만 객체 순회(Iterate) `length` 프로퍼티의 *getter*는 단순히 Array 안에 있는 엘리먼트의 개수를 반환하고 *setter*는 배열을 할당한 수만큼 잘라 버린다. - var foo = [1, 2, 3, 4, 5, 6]; - foo.length = 3; - foo; // [1, 2, 3] + var arr = [1, 2, 3, 4, 5, 6]; + arr.length = 3; + arr; // [1, 2, 3] - foo.length = 6; - foo; // [1, 2, 3] + arr.length = 6; + arr.push(4); + arr; // [1, 2, 3, undefined, undefined, undefined, 4] -현재 크기보다 더 작은 값을 할당하면 배열을 자르지만, 현재 크기보다 더 큰 값을 할당한다고 해서 배열을 늘리진 않는다. +현재 크기보다 더 작은 값을 할당하면 배열을 자른다. 배열의 크기를 증가시키면 드문드문(sparse)한 배열을 생성한다. ### 결론 diff --git a/doc/ko/core/eval.md b/doc/ko/core/eval.md index 528b1883..2a97ebea 100644 --- a/doc/ko/core/eval.md +++ b/doc/ko/core/eval.md @@ -2,26 +2,26 @@ `eval` 함수는 JavaScript 문자열을 지역 스코프에서 실행한다. - var foo = 1; + var number = 1; function test() { - var foo = 2; - eval('foo = 3'); - return foo; + var number = 2; + eval('number = 3'); + return number; } test(); // 3 - foo; // 1 + number; // 1 `eval`함수는 `eval`이라는 이름으로 **직접** 실행할 때에만 지역 스코프에서 실행된다. 그리고 `eval`이라는 이름에 걸맞게 악명또한 높다. - var foo = 1; + var number = 1; function test() { - var foo = 2; - var bar = eval; - bar('foo = 3'); - return foo; + var number = 2; + var copyOfEval = eval; + copyOfEval('number = 3'); + return number; } test(); // 2 - foo; // 3 + number; // 3 어쨌든 `eval`은 사용하지 말아야 한다. eval을 사용하는 99.9%는 사실 eval 없이도 만들수있다. diff --git a/doc/ko/function/arguments.md b/doc/ko/function/arguments.md index 5ea383cb..88ce01bc 100644 --- a/doc/ko/function/arguments.md +++ b/doc/ko/function/arguments.md @@ -27,22 +27,37 @@ JavaScript의 모든 함수 스코프에는 `arguments`라는 특별한 변수 // 내곡동에 땅이라도 산다. } -또 다른 방법으로는 함수를 랩핑하지 않고, 풀어서 `call`과 `apply`를 함께 사용하는 방법이 있다. (역주: 프로토타입에 있는 method를 호출하기 전에 Foo 객체 안에 있는 method로 한번더 필터링하는 효과가 있다. ) +또 다른 트릭은 `call`과 `apply`를 함께 사용하여 메써드(`this`의 값과 인자들을 사용하는 함수)를 +단지 인자들만 사용하는 일반 함수로 바꾸는 것이다. - function Foo() {} + function Person(first, last) { + this.first = first; + this.last = last; + } - Foo.prototype.method = function(a, b, c) { - console.log(this, a, b, c); + Person.prototype.fullname = function(joiner, options) { + options = options || { order: "western" }; + var first = options.order === "western" ? this.first : this.last; + var last = options.order === "western" ? this.last : this.first; + return first + (joiner || " ") + last; }; - // "method"를 풀어 쓴(unbound) 버전 - // 이 Function의 인자: this, arg1, arg2...argN - Foo.method = function() { - - // 결과: Foo.prototype.method.call(this, arg1, arg2... argN) - Function.call.apply(Foo.prototype.method, arguments); + // "fullname" 메써드의 비결합(unbound) 버전을 생성한다. + // 첫번째 인자로 'first'와 'last' 속성을 가지고 있는 어떤 객체도 사용 가능하다. + // "fullname"의 인자 개수나 순서가 변경되더라도 이 랩퍼를 변경할 필요는 없을 것이다. + Person.fullname = function() { + // 결과: Person.prototype.fullname.call(this, joiner, ..., argN); + return Function.call.apply(Person.prototype.fullname, arguments); }; + var grace = new Person("Grace", "Hopper"); + + // 'Grace Hopper' + grace.fullname(); + + // 'Turing, Alan' + Person.fullname({ first: "Alan", last: "Turing" }, ", ", { order: "eastern" }); + ### 일반 파라미터와 arguments 객체의 인덱스 일반 파라미터와 `arguments` 객체의 프로퍼티는 모두 *getter*와 *setter*를 가진다. diff --git a/doc/ko/function/closures.md b/doc/ko/function/closures.md index 4d7463a6..4e5631fa 100644 --- a/doc/ko/function/closures.md +++ b/doc/ko/function/closures.md @@ -75,3 +75,21 @@ JavaScript에서는 스코프(Scope)를 어딘가에 할당해두거나 참조 } })(i), 1000) } + +즐겨 쓰이는 또 하나의 방법은 `setTimeout` 함수에 세번째 인자를 추가하는 방법이다. +추가된 인자는 콜백 함수에 전달된다. + + for(var i = 0; i < 10; i++) { + setTimeout(function(e) { + console.log(e); + }, 1000, i); + } + +레거시 JS 환경(Internet Explorer 9 이하)은 이 방법을 지원하지 않는다. + +`.bind`를 사용하는 방법도 있다. `.bind`는 `this` 컨텍스트와 인자들을 함수에 결속(bind)시킨다. +아래 코드는 위 코드와 동일하게 동작한다. + + for(var i = 0; i < 10; i++) { + setTimeout(console.log.bind(console, i), 1000); + } diff --git a/doc/ko/function/constructors.md b/doc/ko/function/constructors.md index 1aa6de4a..2b26dc24 100644 --- a/doc/ko/function/constructors.md +++ b/doc/ko/function/constructors.md @@ -6,40 +6,40 @@ JavaScript의 생성자는 다른 언어들과 다르게 `new` 키워드로 호 그리고 생성자에 명시적인 `return` 구문이 없으면 this가 가리키는 객체를 반환한다. - function Foo() { - this.bla = 1; + function Person(name) { + this.name = name; } - Foo.prototype.test = function() { - console.log(this.bla); + Person.prototype.logName = function() { + console.log(this.name); }; - var test = new Foo(); + var sean = new Person(); -위 코드는 `new` 키워드가 실행되는 시점에 `Foo`를 생성자로 호출하고 `Foo.prototype`을 새 객체의 prototype에 할당한다. +위 코드는 `Person`을 생성자로 호출하고 새로 생성된 객체의 `prototype`을 `Person.prototype`으로 설정한다. 아래 코드와 같이 생성자에 명시적인 `return` 문이 있는 경우에는 반환하는 값이 객체인 경우에만 그 값을 반환한다. - function Bar() { - return 2; + function Car() { + return 'ford'; } - new Bar(); // 새 객체를 만들어 반환 + new Car(); // 'ford'가 아닌 새로운 객체를 반환 - function Test() { - this.value = 2; + function Person() { + this.someValue = 2; return { - foo: 1 + name: 'Charles' }; } - new Test(); // 명시한 객체를 반환 + new Person(); // someValue가 포함되지 않은 ({name:'Charles'}) 객체 반환 new 키워드가 없으면 그 함수는 객체를 반환하지 않는다. - function Foo() { - this.bla = 1; // 전역객체에 할당된다. + function Pirate() { + this.hasEyePatch = true; // 전역 객체를 준비! } - Foo(); // undefined + var somePirate = Pirate(); // somePirate = undefined 위 예제는 그때그때 다르게 동작한다. 그리고 [`this`](#function.this) 객체의 동작 원리에 따라서 Foo 함수안의 `this`의 값은 *Global 객체*를 가리키게된다. (역주: 결국 new 키워드를 빼고, 코드를 작성할 경우 원치 않은 this 참조 오류가 발생할 수 있다.) @@ -48,24 +48,24 @@ new 키워드가 없으면 그 함수는 객체를 반환하지 않는다. 생성자가 객체를 반환하면 `new` 키워드를 생략할 수 있다. - function Bar() { - var value = 1; + function Robot() { + var color = 'gray'; return { - method: function() { - return value; + getColor: function() { + return color; } } } - Bar.prototype = { - foo: function() {} + Robot.prototype = { + someFunction: function() {} }; - new Bar(); - Bar(); + new Robot(); + Robot(); -new 키워드의 유무과 관계없이 `Bar` 생성자의 동작은 동일한다. 즉 [클로저](#function.closures)가 할당된 method 프로퍼티가 있는 새로운 객체를 만들어 반환한다. +new 키워드의 유무과 관계없이 `Robot` 생성자의 동작은 동일하다. 즉 [클로저](#function.closures)가 할당된 method 프로퍼티가 있는 새로운 객체를 만들어 반환한다. -`new Bar()`로 호출되는 생성자는 반환되는 객체의 prototype 프로퍼티에 아무런 영향을 주지 않는다. 객체를 반환하지 않는 생성자로 만들어지는 경우에만 객체의 prototype이 생성자의 것으로 할당된다. +`new Robot()`으로 호출되는 생성자는 반환되는 객체의 prototype 프로퍼티에 아무런 영향을 주지 않는다. 객체를 반환하지 않는 생성자로 만들어지는 경우에만 객체의 prototype이 생성자의 것으로 할당된다. 그러니까 이 예제에서 `new` 키워드의 유무는 아무런 차이가 없다. (역주: 생성자에 객체를 만들어 명시적으로 반환하면 new 키워드에 관계없이 잘 동작하는 생성자를 만들수있다. 즉, new 키워드가 빠졌을때 발생하는 this 참조 오류를 방어해준다.) @@ -76,19 +76,21 @@ new 키워드의 유무과 관계없이 `Bar` 생성자의 동작은 동일한 객체를 만들고 반환해주는 팩토리를 사용하여 `new` 키워드 문제를 회피할 수 있다. - function Foo() { - var obj = {}; - obj.value = 'blub'; + function CarFactory() { + var car = {}; + car.owner = 'nobody'; - var private = 2; - obj.someMethod = function(value) { - this.value = value; + var milesPerGallon = 2; + + car.setOwner = function(newOwner) { + this.owner = newOwner; } - obj.getPrivate = function() { - return private; + car.getMPG = function() { + return milesPerGallon; } - return obj; + + return car; } `new` 키워드가 없어도 잘 동작하고 [private 변수](#function.closures)를 사용하기도 쉽다. 그렇지만, 단점도 있다. diff --git a/doc/ko/function/this.md b/doc/ko/function/this.md index b6d57aa6..9230c5af 100644 --- a/doc/ko/function/this.md +++ b/doc/ko/function/this.md @@ -58,16 +58,26 @@ Global Scope에서도 this가 사용될 수 있고 이때에는 *Global* 객체 `test`에서 `Foo`에 접근하려면 method에 Local 변수를 하나 만들고 `Foo`를 가리키게 하여야 한다. Foo.method = function() { - var that = this; + var self = this; function test() { - // 여기에서 this 대신에 that을 사용하여 Foo에 접근한다. + // 여기에서 this 대신에 self를 사용하여 Foo에 접근한다 } test(); } -`that`은 this에 접근하기 위해 만든 변수다. [closures](#function.closures)와 함께 `this`의 값을 넘기는 데 사용할 수 있다. +`self`는 통상적인 변수 이름이지만, 바깥쪽의 `this`를 참조하기 위해 일반적으로 사용된다. +또한 [클로저](#function.closures)와 결합하여 `this`의 값을 주고 받는 용도로 사용할 수도 있다. -### Method할당 하기 +ECMAScript 5부터는 익명 함수와 결합된 `bind` 메써드를 사용하여 같은 결과를 얻을 수 있다. + + Foo.method = function() { + var test = function() { + // this는 이제 Foo를 참조한다 + }.bind(this); + test(); + } + +### Method 할당하기 JavaScript의 또다른 함정은 바로 함수의 별칭을 만들수 없다는 점이다. 별칭을 만들기 위해 메소드를 변수에 넣으면 자바스크립트는 별칭을 만들지 않고 바로 *할당*해 버린다. From 944755fd279623b190735b8824ceb725fe51847d Mon Sep 17 00:00:00 2001 From: trauma2u Date: Wed, 8 Apr 2015 11:54:41 +0900 Subject: [PATCH 042/105] fix typo --- doc/en/function/closures.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/en/function/closures.md b/doc/en/function/closures.md index a5fbc91e..58005a5e 100644 --- a/doc/en/function/closures.md +++ b/doc/en/function/closures.md @@ -97,7 +97,7 @@ above. } The other popular way to achieve this is to add an additional argument to -the setTimeout function, which passes these arguments to the callback. +the `setTimeout` function, which passes these arguments to the callback. for(var i = 0; i < 10; i++) { setTimeout(function(e) { From 5878e59c29fe7caaf46faa7e50f37ffec1c28507 Mon Sep 17 00:00:00 2001 From: Dauren Date: Fri, 29 May 2015 11:49:54 +0600 Subject: [PATCH 043/105] Update forinloop.md --- doc/ru/object/forinloop.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/ru/object/forinloop.md b/doc/ru/object/forinloop.md index 0b097259..3bc5c8d4 100644 --- a/doc/ru/object/forinloop.md +++ b/doc/ru/object/forinloop.md @@ -25,7 +25,7 @@ } } -Это единственная версия правильного использования цикла. Благодаря использованию `hasOwnPropery` будет выведено **только** свойство `moo`. Если же убрать `hasOwnProperty`, код становится нестабилен и могут возникнуть ошибки, особенно если кто-то изменил встроенные прототипы, такие как `Object.prototype`. +Это единственная версия правильного использования цикла. Благодаря использованию `hasOwnProperty` будет выведено **только** свойство `moo`. Если же убрать `hasOwnProperty`, код становится нестабилен и могут возникнуть ошибки, особенно если кто-то изменил встроенные прототипы, такие как `Object.prototype`. Один из самых популярных фреймворков [Prototype][1] как раз этим и славится, и если вы его подключаете, то не забудьте использовать `hasOwnProperty` внутри цикла `for in`, иначе у вас гарантированно возникнут проблемы. From 52d8e1278af98e3bf462967a88f9cff75cb37b33 Mon Sep 17 00:00:00 2001 From: Hugo Pineda Date: Fri, 29 May 2015 12:23:24 -0300 Subject: [PATCH 044/105] Added type equality spanish translation --- doc/es/index.json | 2 +- doc/es/types/equality.md | 58 ++++++++++++++++++++-------------------- 2 files changed, 30 insertions(+), 30 deletions(-) diff --git a/doc/es/index.json b/doc/es/index.json index 54d54e1c..1367f527 100644 --- a/doc/es/index.json +++ b/doc/es/index.json @@ -39,7 +39,7 @@ ] }, { - "title": "Types", + "title": "Tipos", "dir": "types", "articles": [ "equality", diff --git a/doc/es/types/equality.md b/doc/es/types/equality.md index 5665917f..f933d495 100644 --- a/doc/es/types/equality.md +++ b/doc/es/types/equality.md @@ -1,13 +1,13 @@ -## Equality and Comparisons +## Igualdad y Comparación -JavaScript has two different ways of comparing the values of objects for equality. +JavaScript posee 2 maneras diferentes para comparar valores entre objetos para comprobar igualdad. -### The Equality Operator +### El Operador de Igualdad -The equality operator consists of two equal signs: `==` +El operador de igualdad consiste en 2 signos es igual: `==` -JavaScript features *weak typing*. This means that the equality operator -**coerces** types in order to compare them. +JavaScript utiliza *tipado débil*. Esto significa que el operador de igualdad +**obliga** una conversión de tipos para poder compararlos. "" == "0" // false 0 == "" // true @@ -19,20 +19,20 @@ JavaScript features *weak typing*. This means that the equality operator null == undefined // true " \t\r\n" == 0 // true -The above table shows the results of the type coercion, and it is the main reason -why the use of `==` is widely regarded as bad practice. It introduces -hard-to-track-down bugs due to its complicated conversion rules. +La tabla anterior muestra los resultados de la conversión de tipos, éste es el motivo principal +de por qué el uso de `==` es ampliamente considerado una mala práctica. Introduce errores +difíciles de identificar debido a la complejidad de sus reglas de conversión. -Additionally, there is also a performance impact when type coercion is in play; -for example, a string has to be converted to a number before it can be compared -to another number. +Además, existe un impacto en el rendimiento cuando entra en juego la conversión de tipos; +por ejemplo, una cadena debe ser convertida a número antes de poder ser comparada +con otro número. -### The Strict Equality Operator +### El Operador de Igualdad Estricto -The strict equality operator consists of **three** equal signs: `===`. +El operador de igualdad estricto consiste en **tres** signos es igual: `===`: -It works exactly like the normal equality operator, except that strict equality -operator does **not** perform type coercion between its operands. +Funciona exactamente igual que el operador de igualdad, excepto que el operador de igualdad +estricto **no** utiliza conversión de tipos entre sus operandos. "" === "0" // false 0 === "" // false @@ -44,14 +44,14 @@ operator does **not** perform type coercion between its operands. null === undefined // false " \t\r\n" === 0 // false -The above results are a lot clearer and allow for early breakage of code. This -hardens code to a certain degree and also gives performance improvements in case -the operands are of different types. +Los resultados anteriores son mucho más claros y permiten una detección de errores temprana. +Esto permite un código más sólido en cierto grado y también mejora el rendimiento +en el caso que los operandos sean de tipos diferentes. -### Comparing Objects +### Comparando Objetos -While both `==` and `===` are stated as **equality** operators, they behave -differently when at least one of their operands happens to be an `Object`. +Aunque `==` como `===` son considerados operadores de **igualdad**, se comportan +de maneras diferentes cuando al menos uno de sus operandos es `Object`. {} === {}; // false new String('foo') === 'foo'; // false @@ -59,13 +59,13 @@ differently when at least one of their operands happens to be an `Object`. var foo = {}; foo === foo; // true -Here, both operators compare for **identity** and **not** equality; that is, they -will compare for the same **instance** of the object, much like `is` in Python -and pointer comparison in C. +En este caso, los dos operadores comparan por **referencia** y **no** por igualdad; esto es, +comparan por la misma **instancia** del objeto, parecido +al operador `is` en Python y la comparación entre punteros en C. -### In Conclusion +### En Conclusión -It is highly recommended to only use the **strict equality** operator. In cases -where types need to be coerced, it should be done [explicitly](#types.casting) -and not left to the language's complicated coercion rules. +Es altamente recomendable usar sólo el operador de **igualdad estricta**. En los casos +donde los tipos de datos necesitan ser convertidos, debe hacerse [explícitamente](#types.casting) +y no dejárselo a las complicadas reglas de conversión del lenguaje. From 93a8b60e0e16b5130524aaf0ed10bb7d0604cd35 Mon Sep 17 00:00:00 2001 From: tienslebien Date: Mon, 8 Jun 2015 14:57:22 +0200 Subject: [PATCH 045/105] Fix typo --- doc/fr/array/general.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/fr/array/general.md b/doc/fr/array/general.md index ab9183a0..aecec798 100644 --- a/doc/fr/array/general.md +++ b/doc/fr/array/general.md @@ -1,7 +1,7 @@ ## Tableaux: iteration et propriétés Bien que les tableaux soient des objets en JavaScript, il n'y a pas de bonnes raisons d'utiliser la boucle [`for in`](#object.forinloop). -En fait, il un certain nombre de bonnes raisons **contre** l'utilisation de `for in` sur les tableaux. +En fait, il y a un certain nombre de bonnes raisons **contre** l'utilisation de `for in` sur les tableaux. **Remarque:** Les tableaux JavaScript ne sont **pas** *associatifs*. JavaScript n'offre que les [objets](#object.general) pour associer des clés à des valeurs. Contrairement aux tableaux associatifs, les objets ne préservent **pas** l'ordre. From 1e504dc28599d8db935aadaa7855aacc655c65ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Sieniarski?= Date: Sun, 14 Jun 2015 23:17:38 +0200 Subject: [PATCH 046/105] unnecessary translation --- doc/pl/object/prototype.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/pl/object/prototype.md b/doc/pl/object/prototype.md index c538ee8a..75884618 100644 --- a/doc/pl/object/prototype.md +++ b/doc/pl/object/prototype.md @@ -48,7 +48,7 @@ tak zwanych *łańcuchów prototypów*. { toString: ... /* etc. */ } W powyższym przykładzie obiekt `test` będzie dziedziczył z obydwu, tj. -`Bar.prototyp` i `Foo.prototyp`, stąd będzie miał dostęp do funkcji `method`, +`Bar.prototype` i `Foo.prototype`, stąd będzie miał dostęp do funkcji `method`, która była zdefiniowana w `Foo`. Ponadto obiekt będzie miał dostęp do właściwości `value`, która jest jedyną instancją `Foo` i stała się jego prototypem. Należy pamiętać, że `new Bar` **nie** tworzy nowej instancji `Foo`, From 0d78202cda49e40715a6343908a99ee5f5c22626 Mon Sep 17 00:00:00 2001 From: Igor APA Date: Fri, 19 Jun 2015 14:27:24 -0300 Subject: [PATCH 047/105] Correction in the text [pt-BR] forinloop.md If the Famework extends the Object.prototype then need to filter before passing through an object, it means if not to use hasOwnProperty will be unprotected against errors. No? --- doc/ptbr/object/forinloop.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/ptbr/object/forinloop.md b/doc/ptbr/object/forinloop.md index fc35f5b2..e3e09efa 100644 --- a/doc/ptbr/object/forinloop.md +++ b/doc/ptbr/object/forinloop.md @@ -31,7 +31,7 @@ Esta é única forma correta de usar. Devido ao uso de `hasOwnProperty`, o exemp Um framework largamente utilizado que estende o `Object.prototype` é [Prototype][1]. Quando este framework é utilizado, laços `for in` que não utilizam -`hasOwnProperty` ficam protegidos contra erros. +`hasOwnProperty` ficam desprotegidos contra erros. ### Conclusão From f9ed91462490596344f7bebe16691cc1e7fa1fd8 Mon Sep 17 00:00:00 2001 From: Zhang Zhuo Bin Date: Mon, 22 Jun 2015 23:59:27 +0800 Subject: [PATCH 048/105] revise an error about object type String type,number type and boolean type are not real objects ,but act as objects. --- doc/zh/object/general.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/zh/object/general.md b/doc/zh/object/general.md index 58f20810..a97b6d86 100755 --- a/doc/zh/object/general.md +++ b/doc/zh/object/general.md @@ -1,6 +1,6 @@ ##对象使用和属性 -JavaScript 中所有变量都是对象,除了两个例外 [`null`](#core.undefined) 和 [`undefined`](#core.undefined)。 +JavaScript 中所有变量都可以当作对象使用,除了两个例外 [`null`](#core.undefined) 和 [`undefined`](#core.undefined)。 false.toString(); // 'false' [1, 2, 3].toString(); // '1,2,3' @@ -9,7 +9,7 @@ JavaScript 中所有变量都是对象,除了两个例外 [`null`](#core.undef Foo.bar = 1; Foo.bar; // 1 -一个常见的误解是数字的字面值(literal)不是对象。这是因为 JavaScript 解析器的一个错误, +一个常见的误解是数字的字面值(literal)不能当作对象使用。这是因为 JavaScript 解析器的一个错误, 它试图将*点操作符*解析为浮点数字面值的一部分。 2.toString(); // 出错:SyntaxError From 80a1dbf4cf70955934a7970913be05a5f01fcd82 Mon Sep 17 00:00:00 2001 From: SWANIRIS Date: Tue, 21 Jul 2015 17:59:16 +0900 Subject: [PATCH 049/105] fixed for word unity --- doc/ko/function/arguments.md | 4 ++-- doc/ko/function/this.md | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/ko/function/arguments.md b/doc/ko/function/arguments.md index 88ce01bc..288928f5 100644 --- a/doc/ko/function/arguments.md +++ b/doc/ko/function/arguments.md @@ -27,7 +27,7 @@ JavaScript의 모든 함수 스코프에는 `arguments`라는 특별한 변수 // 내곡동에 땅이라도 산다. } -또 다른 트릭은 `call`과 `apply`를 함께 사용하여 메써드(`this`의 값과 인자들을 사용하는 함수)를 +또 다른 트릭은 `call`과 `apply`를 함께 사용하여 메소드(`this`의 값과 인자들을 사용하는 함수)를 단지 인자들만 사용하는 일반 함수로 바꾸는 것이다. function Person(first, last) { @@ -42,7 +42,7 @@ JavaScript의 모든 함수 스코프에는 `arguments`라는 특별한 변수 return first + (joiner || " ") + last; }; - // "fullname" 메써드의 비결합(unbound) 버전을 생성한다. + // "fullname" 메소드의 비결합(unbound) 버전을 생성한다. // 첫번째 인자로 'first'와 'last' 속성을 가지고 있는 어떤 객체도 사용 가능하다. // "fullname"의 인자 개수나 순서가 변경되더라도 이 랩퍼를 변경할 필요는 없을 것이다. Person.fullname = function() { diff --git a/doc/ko/function/this.md b/doc/ko/function/this.md index 9230c5af..019b4458 100644 --- a/doc/ko/function/this.md +++ b/doc/ko/function/this.md @@ -68,7 +68,7 @@ Global Scope에서도 this가 사용될 수 있고 이때에는 *Global* 객체 `self`는 통상적인 변수 이름이지만, 바깥쪽의 `this`를 참조하기 위해 일반적으로 사용된다. 또한 [클로저](#function.closures)와 결합하여 `this`의 값을 주고 받는 용도로 사용할 수도 있다. -ECMAScript 5부터는 익명 함수와 결합된 `bind` 메써드를 사용하여 같은 결과를 얻을 수 있다. +ECMAScript 5부터는 익명 함수와 결합된 `bind` 메소드를 사용하여 같은 결과를 얻을 수 있다. Foo.method = function() { var test = function() { From b30ef5fd4cb22cf6be93cbe90ca04c82075631f5 Mon Sep 17 00:00:00 2001 From: kevingo Date: Thu, 17 Sep 2015 22:59:30 +0800 Subject: [PATCH 050/105] add timeout zhtw translate --- doc/zhtw/other/timeouts.md | 42 +++++++++++++++++--------------------- 1 file changed, 19 insertions(+), 23 deletions(-) diff --git a/doc/zhtw/other/timeouts.md b/doc/zhtw/other/timeouts.md index 3fe9a6da..d717a81e 100644 --- a/doc/zhtw/other/timeouts.md +++ b/doc/zhtw/other/timeouts.md @@ -1,13 +1,13 @@ ### `setTimeout` 和 `setInterval` -由於 Javascript 是一個非同步傳輸的系統,因此可以執行一個函式用 `setTimeout` 和 `setInterval`。 +由於 Javascript 具有非同步的特性,因此可以用 `setTimeout` 和 `setInterval` 來執行一個函式。 > **注意:** Timeouts 不在 ECMAScript 的標準中。它們是 [DOM][1] 其中的一部分 function foo() {} var id = setTimeout(foo, 1000); // returns a Number > 0 -當 `setTimeout` 被呼叫,它會回傳一個 ID 標準並是計畫在將來 **大約** 1000 毫秒後在在去呼叫 `foo` 函式。 +當 `setTimeout` 被呼叫,它會回傳一個 ID 標準並且 **大約** 1000 毫秒後在在去呼叫 `foo` 函式。 `foo` 函式只會被執行 **一次**。 基於 JavaScript 引擎的計時策略,以及基本的單線程運行的方式,所以其他的程式碼可以被阻塞。 @@ -85,13 +85,15 @@ ### 隱藏使用 `eval` -`setTimeout` and `setInterval` can also take a string as their first parameter. -This feature should **never** be used because it internally makes use of `eval`. +`setTimeout` and `setInterval` 也可以使用字串當作他們的第一個參數. +不過這個特性 **絕對** 不要使用, 因為在內部他將利用 `eval` 來實作。 + +> **注意:** 由於 timeout 函式 **並未** 被列入 ECMAScript +> 標準中,當你將字串當成參數傳入時,在不同的 Javscript +> 實作中很有可能會造成不一樣的行為。比如說:在 Microsoft 的 JScript 中,就使用 `Function` +> 建構子來取代 `eval`。 + -> **Note:** Since the timeout functions are **not** specified by the ECMAScript -> standard, the exact workings when a string is passed to them might differ in -> various JavaScript implementations. For example, Microsoft's JScript uses -> the `Function` constructor in place of `eval`. function foo() { // will get called @@ -105,12 +107,10 @@ This feature should **never** be used because it internally makes use of `eval`. } bar(); -Since `eval` is not getting called [directly](#core.eval) in this case, the string -passed to `setTimeout` will be executed in the *global scope*; thus, it will -not use the local variable `foo` from the scope of `bar`. +在這個範例中,由於 `eval` 沒有被[直接](#core.eval)呼叫,在 `setTimeout` 中被傳入的字串將會在 *全域* 範圍中被執行,因此,他將不會使用在 `bar` 區域的 `foo`。 + +我們進一步建議 **不要** 用字串當作參數傳到會被 timeout 呼叫的函式中。 -It is further recommended to **not** use a string to pass arguments to the -function that will get called by either of the timeout functions. function foo(a, b, c) {} @@ -122,18 +122,14 @@ function that will get called by either of the timeout functions. foo(1, 2, 3); }, 1000) -> **Note:** While it is also possible to use the syntax -> `setTimeout(foo, 1000, 1, 2, 3)`, it is not recommended, as its use may lead -> to subtle errors when used with [methods](#function.this). +> **注意** 儘管使用 `setTimeout(foo, 1000, 1, 2, 3)` +> 這樣的文法是可能的,但我們卻不建議這樣做,因為這和 [方法](#function.this) +> 一起使用時可能會導致微妙的錯誤。 -### In Conclusion +### 結論 -A string should **never** be used as the parameter of `setTimeout` or -`setInterval`. It is a clear sign of **really** bad code, when arguments need -to be supplied to the function that gets called. An *anonymous function* should -be passed that then takes care of the actual call. +**絕對** 不要使用字串當作 `setTimeout` 或 `setInterval` 參數。當參數要被當成呼叫的函式時,這絕對是 **不好** 的程式碼,相反的,利用 *匿名函式* 來完成這樣的行為。 -Furthermore, the use of `setInterval` should be avoided because its scheduler is not -blocked by executing JavaScript. +此外,應該避免使用 `setInterval`,因為他將不會被 Javascript 給中斷。 [1]: http://en.wikipedia.org/wiki/Document_Object_Model "Document Object Model" From f3bea7f2f28b70e90f6cb2753e9067877cd9ca17 Mon Sep 17 00:00:00 2001 From: kevingo Date: Fri, 18 Sep 2015 17:13:20 +0800 Subject: [PATCH 051/105] modify general translation --- doc/zhtw/object/general.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/doc/zhtw/object/general.md b/doc/zhtw/object/general.md index 01c98bc5..aee1885c 100644 --- a/doc/zhtw/object/general.md +++ b/doc/zhtw/object/general.md @@ -1,6 +1,6 @@ ## 物件的使用和屬性 -每個變數可以表現像 JavaScript 物件,除了 [`null`](#core.undefined) 和 [`undefined`](#core.undefined)。 +在 Javascript 中全部都是物件,除了 [`null`](#core.undefined) 和 [`undefined`](#core.undefined)。 false.toString(); // 'false' [1, 2, 3].toString(); // '1,2,3' @@ -23,7 +23,7 @@ JavaScript 的物件可以作為 [*Hashmaps*][1]使用,主要用來保存命名的鍵與值的對應關係。 -使用物件的字面語法 - `{}` - 可以創建一個簡單的物件。 這個新創建的物件從 `Object.prototype` [繼承](#object.prototype),下面,沒有任何 [自定義屬性](#object.hasownproperty)。 +使用物件的字面語法 - `{}` - 可以創建一個簡單的物件。 這個新創建的物件[繼承](#object.prototype) 自 `Object.prototype` ,沒有任何 [自定義屬性](#object.hasownproperty)。 var foo = {}; // 一個空的物件 @@ -32,7 +32,7 @@ JavaScript 的物件可以作為 [*Hashmaps*][1]使用,主要用來保存命 ### 訪問屬性 -有兩種訪問物件的屬性,點操作或是中括號操作。 +有兩種方式來訪問物件的屬性,點操作或是中括號操作。 var foo = {name: 'kitten'} foo.name; // kitten @@ -76,7 +76,7 @@ JavaScript 的物件可以作為 [*Hashmaps*][1]使用,主要用來保存命 delete: 'I am a keyword, so me too' // raises SyntaxError }; -物件的屬性名可以使用字符串或是普通的宣告。但是由於 JavaScript 編譯器有個另外一個錯誤設計。 +物件的屬性名可以使用字符串或是普通的宣告。但是由於 JavaScript 編譯器存在一個錯誤設計。 上面的兩種方式在 ECMAScript 5之前都會拋出 `SyntaxError` 的錯誤。 這個錯誤的原因是 `delete` 是 JavaScript 語言的一個 *關鍵字* 因此為了在更低的版本能執行最好用 *string literal* From 6fa3df0da117614e79f7fc45b72f3358fc57c1bb Mon Sep 17 00:00:00 2001 From: kevingo Date: Fri, 18 Sep 2015 17:21:19 +0800 Subject: [PATCH 052/105] modify trans --- doc/zhtw/object/prototype.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/zhtw/object/prototype.md b/doc/zhtw/object/prototype.md index f2bcaff3..e861a1ab 100644 --- a/doc/zhtw/object/prototype.md +++ b/doc/zhtw/object/prototype.md @@ -1,9 +1,9 @@ ## Prototype -JavaScript 不包含原本繼承的模型。然而它使用的是*原型*模型。 +JavaScript 不包含傳統繼承的模型,它使用的是*原型*模型。 -然而常常有人提及 JavaScript 的缺點,就是基於原本繼承模型比類繼承更強大。 -現實傳統的類繼承模型是很簡單。但是在 JavaScript 中實現元繼承則要困難很多。 +儘管常常有人提及 JavaScript 的缺點,但基於原型的繼承模型比傳統繼承更強大。 +實現傳統的類繼承模型是很簡單。但是在 JavaScript 中實現原型的繼承模型則要困難很多。 由於 JavaScript 是唯一一個被廣泛使用的基於原型繼承的語言,所以我們必須要花時間來理解這兩者的不同。 From 6695f87e3c673189d316e6c5d802853d8b0dbbd5 Mon Sep 17 00:00:00 2001 From: Hugo Pineda Date: Fri, 29 May 2015 12:23:24 -0300 Subject: [PATCH 053/105] Added type equality spanish translation --- doc/es/index.json | 2 +- doc/es/types/equality.md | 58 ++++++++++++++++++++-------------------- 2 files changed, 30 insertions(+), 30 deletions(-) diff --git a/doc/es/index.json b/doc/es/index.json index 54d54e1c..1367f527 100644 --- a/doc/es/index.json +++ b/doc/es/index.json @@ -39,7 +39,7 @@ ] }, { - "title": "Types", + "title": "Tipos", "dir": "types", "articles": [ "equality", diff --git a/doc/es/types/equality.md b/doc/es/types/equality.md index 5665917f..f933d495 100644 --- a/doc/es/types/equality.md +++ b/doc/es/types/equality.md @@ -1,13 +1,13 @@ -## Equality and Comparisons +## Igualdad y Comparación -JavaScript has two different ways of comparing the values of objects for equality. +JavaScript posee 2 maneras diferentes para comparar valores entre objetos para comprobar igualdad. -### The Equality Operator +### El Operador de Igualdad -The equality operator consists of two equal signs: `==` +El operador de igualdad consiste en 2 signos es igual: `==` -JavaScript features *weak typing*. This means that the equality operator -**coerces** types in order to compare them. +JavaScript utiliza *tipado débil*. Esto significa que el operador de igualdad +**obliga** una conversión de tipos para poder compararlos. "" == "0" // false 0 == "" // true @@ -19,20 +19,20 @@ JavaScript features *weak typing*. This means that the equality operator null == undefined // true " \t\r\n" == 0 // true -The above table shows the results of the type coercion, and it is the main reason -why the use of `==` is widely regarded as bad practice. It introduces -hard-to-track-down bugs due to its complicated conversion rules. +La tabla anterior muestra los resultados de la conversión de tipos, éste es el motivo principal +de por qué el uso de `==` es ampliamente considerado una mala práctica. Introduce errores +difíciles de identificar debido a la complejidad de sus reglas de conversión. -Additionally, there is also a performance impact when type coercion is in play; -for example, a string has to be converted to a number before it can be compared -to another number. +Además, existe un impacto en el rendimiento cuando entra en juego la conversión de tipos; +por ejemplo, una cadena debe ser convertida a número antes de poder ser comparada +con otro número. -### The Strict Equality Operator +### El Operador de Igualdad Estricto -The strict equality operator consists of **three** equal signs: `===`. +El operador de igualdad estricto consiste en **tres** signos es igual: `===`: -It works exactly like the normal equality operator, except that strict equality -operator does **not** perform type coercion between its operands. +Funciona exactamente igual que el operador de igualdad, excepto que el operador de igualdad +estricto **no** utiliza conversión de tipos entre sus operandos. "" === "0" // false 0 === "" // false @@ -44,14 +44,14 @@ operator does **not** perform type coercion between its operands. null === undefined // false " \t\r\n" === 0 // false -The above results are a lot clearer and allow for early breakage of code. This -hardens code to a certain degree and also gives performance improvements in case -the operands are of different types. +Los resultados anteriores son mucho más claros y permiten una detección de errores temprana. +Esto permite un código más sólido en cierto grado y también mejora el rendimiento +en el caso que los operandos sean de tipos diferentes. -### Comparing Objects +### Comparando Objetos -While both `==` and `===` are stated as **equality** operators, they behave -differently when at least one of their operands happens to be an `Object`. +Aunque `==` como `===` son considerados operadores de **igualdad**, se comportan +de maneras diferentes cuando al menos uno de sus operandos es `Object`. {} === {}; // false new String('foo') === 'foo'; // false @@ -59,13 +59,13 @@ differently when at least one of their operands happens to be an `Object`. var foo = {}; foo === foo; // true -Here, both operators compare for **identity** and **not** equality; that is, they -will compare for the same **instance** of the object, much like `is` in Python -and pointer comparison in C. +En este caso, los dos operadores comparan por **referencia** y **no** por igualdad; esto es, +comparan por la misma **instancia** del objeto, parecido +al operador `is` en Python y la comparación entre punteros en C. -### In Conclusion +### En Conclusión -It is highly recommended to only use the **strict equality** operator. In cases -where types need to be coerced, it should be done [explicitly](#types.casting) -and not left to the language's complicated coercion rules. +Es altamente recomendable usar sólo el operador de **igualdad estricta**. En los casos +donde los tipos de datos necesitan ser convertidos, debe hacerse [explícitamente](#types.casting) +y no dejárselo a las complicadas reglas de conversión del lenguaje. From 7c3e2f7219d1f024e9026817238681c4335389b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Sieniarski?= Date: Sun, 14 Jun 2015 23:17:38 +0200 Subject: [PATCH 054/105] unnecessary translation --- doc/pl/object/prototype.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/pl/object/prototype.md b/doc/pl/object/prototype.md index c538ee8a..75884618 100644 --- a/doc/pl/object/prototype.md +++ b/doc/pl/object/prototype.md @@ -48,7 +48,7 @@ tak zwanych *łańcuchów prototypów*. { toString: ... /* etc. */ } W powyższym przykładzie obiekt `test` będzie dziedziczył z obydwu, tj. -`Bar.prototyp` i `Foo.prototyp`, stąd będzie miał dostęp do funkcji `method`, +`Bar.prototype` i `Foo.prototype`, stąd będzie miał dostęp do funkcji `method`, która była zdefiniowana w `Foo`. Ponadto obiekt będzie miał dostęp do właściwości `value`, która jest jedyną instancją `Foo` i stała się jego prototypem. Należy pamiętać, że `new Bar` **nie** tworzy nowej instancji `Foo`, From e3131fd8710b805f059c18ac14d93faf64cc9194 Mon Sep 17 00:00:00 2001 From: vaukalak Date: Tue, 22 Sep 2015 07:44:06 +0300 Subject: [PATCH 055/105] added translation into Belarussian --- doc/by/array/constructor.md | 31 +++++ doc/by/array/general.md | 56 ++++++++ doc/by/core/delete.md | 81 +++++++++++ doc/by/core/eval.md | 47 +++++++ doc/by/core/semicolon.md | 109 +++++++++++++++ doc/by/core/undefined.md | 69 ++++++++++ doc/by/function/arguments.md | 130 ++++++++++++++++++ doc/by/function/closures.md | 113 ++++++++++++++++ doc/by/function/constructors.md | 122 +++++++++++++++++ doc/by/function/general.md | 48 +++++++ doc/by/function/scopes.md | 230 ++++++++++++++++++++++++++++++++ doc/by/function/this.md | 118 ++++++++++++++++ doc/by/index.json | 69 ++++++++++ doc/by/intro/index.md | 56 ++++++++ doc/by/object/forinloop.md | 63 +++++++++ doc/by/object/general.md | 98 ++++++++++++++ doc/by/object/hasownproperty.md | 55 ++++++++ doc/by/object/prototype.md | 115 ++++++++++++++++ doc/by/other/timeouts.md | 168 +++++++++++++++++++++++ doc/by/types/casting.md | 71 ++++++++++ doc/by/types/equality.md | 70 ++++++++++ doc/by/types/instanceof.md | 37 +++++ doc/by/types/typeof.md | 80 +++++++++++ doc/language.json | 4 +- 24 files changed, 2038 insertions(+), 2 deletions(-) create mode 100644 doc/by/array/constructor.md create mode 100644 doc/by/array/general.md create mode 100644 doc/by/core/delete.md create mode 100644 doc/by/core/eval.md create mode 100644 doc/by/core/semicolon.md create mode 100644 doc/by/core/undefined.md create mode 100644 doc/by/function/arguments.md create mode 100644 doc/by/function/closures.md create mode 100644 doc/by/function/constructors.md create mode 100644 doc/by/function/general.md create mode 100644 doc/by/function/scopes.md create mode 100644 doc/by/function/this.md create mode 100644 doc/by/index.json create mode 100644 doc/by/intro/index.md create mode 100644 doc/by/object/forinloop.md create mode 100644 doc/by/object/general.md create mode 100644 doc/by/object/hasownproperty.md create mode 100644 doc/by/object/prototype.md create mode 100644 doc/by/other/timeouts.md create mode 100644 doc/by/types/casting.md create mode 100644 doc/by/types/equality.md create mode 100644 doc/by/types/instanceof.md create mode 100644 doc/by/types/typeof.md diff --git a/doc/by/array/constructor.md b/doc/by/array/constructor.md new file mode 100644 index 00000000..6eaa5f2a --- /dev/null +++ b/doc/by/array/constructor.md @@ -0,0 +1,31 @@ +## Канструктар `Array` + +Праз тое, што канструктар `Array` неадназначна апрацоўвае свае параметры, +крайне рэкамендуецца выкарыстоўваць літэрал - `[]` - для стварэння масіваў. + + [1, 2, 3]; // Вынік: [1, 2, 3] + new Array(1, 2, 3); // Вынік: [1, 2, 3] + + [3]; // Вынік: [3] + new Array(3); // Вынік: [] + new Array('3') // Вынік: ['3'] + +У выпадку, калі канструктару `Array` перадаецца толькі адзін параметр, і калі гэты +аргумент тыпу `Number`, канструктар верне *разрэджаны* масіў, які мае уласціваць +`length` са значэннем аргумента. Варта адзначыць, што такім чынам будзе зменена +**толькі** значэнне ўласцівасці `length` масіва; індэксы масіва не будуць +праініцыялізаваныя. + + var arr = new Array(3); + arr[1]; // undefined + 1 in arr; // false, індэкс не праініцыялізаваны + +Магчымасць загадзя вызначыць даўжыню масіва карысна толькі ў рэдкіх выпадках, +напрыклад, паўтор радка без выкарыстання цыкла. + + new Array(count + 1).join(stringToRepeat); + +### У заключэнне + +Літэралы маюць перавагі над канструктарам Array. Яны карацейшыя, маюць больш чысты +сінтаксіс і робяць код больш чытэльным. diff --git a/doc/by/array/general.md b/doc/by/array/general.md new file mode 100644 index 00000000..3e358d5a --- /dev/null +++ b/doc/by/array/general.md @@ -0,0 +1,56 @@ +## Ітэрацыі па масівам і ўласцівасці + +Хоць масівы ў JavaScript — аб'екты, няма добрых падставаў для таго, каб +выкарыстоўваць [цыкл `for in`](#object.forinloop) для ітэрацыі па масівах. +Фактычна, ёсць шэраг добрых падстаў **супраць** гэтага. + +> **Заўвага:** масівы JavaScript **не** *асацыятыўныя масівы*. JavaScript мае +> [аб'екты](#object.general) для структуры ключ-значэнне. Але калі асацыятыўныя +> масівы **захоўваюць** парадак, аб'екты — **не**. + +З той прычыны, што цыкл `for in` пералічвае ўсе ўласцівасці, якія ёсць у ланцужку прататыпаў, +і таму, што адзіны спосаб выключыць гэтыя значэнні — [`hasOwnProperty`](#object.hasownproperty), +ітэрацыя атрымліваецца ў **20 разоў** марудней за звычайны цыкл `for`. + +### Ітэрацыя + +Для таго, каб атрымаць найлепшую прадукцыйнасць у ітэрацыі па масіву, лепш +выкарыстаць класічны цыкл `for`. + + var list = [1, 2, 3, 4, 5, ...... 100000000]; + for(var i = 0, l = list.length; i < l; i++) { + console.log(list[i]); + } + +У вышэйпрыведзеным прыкладзе ёсць яшчэ адзін прыём, з дапамогай якога можна кэшаваць +памер масіва: `l = list.length`. + +Негледзячы на тое, што ўласцівасць `length` вызначана ў самім масіве, пошук +гэтай уласцівасці накладвае выдаткі на пошук пры кожнай ітэрацыі цыкла. І хоць +новыя рухавікі JavaScript **могуць** прымяніць аптымізацыю у гэтым выпадку, няма +магчымасці дакладна ведаць, ці будзе код выкананы на гэтых новых рухавіках. + +Фактычна, адсутнасць кэшавання можа зрабіць выкананне цыкла **ў два разы больш +марудным**, чым з кэшаваным 'length'. + +### Уласцівасць `length` + +Хоць *гэтэр* уласцівасці `length` проста вяртае колькасць элементаў, што +знаходзяцца у масіве, *сэтэр* можа быць выкарыстаны для **абразання** масіва. + + var arr = [1, 2, 3, 4, 5, 6]; + arr.length = 3; + arr; // [1, 2, 3] + + arr.length = 6; + arr.push(4); + arr; // [1, 2, 3, undefined, undefined, undefined, 4] + +Прысвойванне ўласцівасці 'length' меншага значэння абразае масіў. Прысваенне большага +значэнне створыць разрэджаны масіў. + +### У заключэнне + +Для лепшай прадукцыйнасці рэкамендуецца заўсёды выкарыстоўваць звычайны цыкл `for`, +і кэшаваць уласціваць `length`. Выкарыстоўванне `for in` для ітэрацыі па масіву — +прыкмета дрэнна напісанага коду, схільнага да памылак і дрэннай прадукцыйнасці. diff --git a/doc/by/core/delete.md b/doc/by/core/delete.md new file mode 100644 index 00000000..07e2c1ce --- /dev/null +++ b/doc/by/core/delete.md @@ -0,0 +1,81 @@ +## Аператар `delete` + +У JavaScript *немагчыма* выдаліць глабальныя пераменныя, функцыі і некаторыя іншыя +рэчы, што маюць атрыбут `DontDelete`. + +### Глабальны код і код функцый. + +Калі пераменная або функцыя аб'яўленыя ў глабальнай зоне бачнасці, або [зоне бачнасці +функцыі](#function.scopes) то яна будзе ўласцівасцю або аб'екта актывацыі, або +глабальнай зоны бачнасці. Такія ўласцівасці маюць набор атрыбутаў, адзін з іх — +`DontDelete`. Пераменныя і функцыі, аб'яўленыя ў глабальнай зоне бачнасці і зоне +бачнасці функцыі, заўсёды ствараюцца з уласцівасцю `DontDelete`, а таму не могуць +быць выдаленыя. + + // глабальная пераменная: + var a = 1; // мае ўласцівасць DontDelete + delete a; // false + a; // 1 + + // звычайная функцыя: + function f() {} // мае ўласціваць DontDelete + delete f; // false + typeof f; // "function" + + // перапрызначэнне не дапамагае: + f = 1; + delete f; // false + f; // 1 + +### Яўна прызначаныя ўласцівасці + +Яўна прызначаныя ўласцівасці могуць быць лёгка выдаленыя. + + // яўна прызначаныя ўласцівасці: + var obj = {x: 1}; + obj.y = 2; + delete obj.x; // true + delete obj.y; // true + obj.x; // undefined + obj.y; // undefined + +У вышэйпрыведзеным прыкладзе, `obj.x` і `obj.y` могуць быць выдаленыя, бо не маюць +атрыбута `DontDelete`. Таму і прыкад ніжэй працуе: + + // Гэта працуе правільна, акрамя IE: + var GLOBAL_OBJECT = this; + GLOBAL_OBJECT.a = 1; + a === GLOBAL_OBJECT.a; // true — глабальная пераменная + delete GLOBAL_OBJECT.a; // true + GLOBAL_OBJECT.a; // undefined + +Гэта прыём, каб выдаліць `a`. [`this`](#function.this) спасылаецца на глабальны +аб'ект, і мы яўна аб'яўляем пераменную `a` як яго ўласцівасць, што дазваляе нам +выдаліць яе. + +IE (прынамсі 6-8) мае хібы, таму вышэйпрыведзены код там працаваць не будзе. + +### Аргументы функцый і ўбудаваныя ўласцівасці + +Звычайныя аргументы функцыі, [аб'ект `arguments`](#function.arguments), а таксама +убудаваныя ўласцівасці таксама маюць атрыбут `DontDelete`. + + // аргументы функцыі і ўласцівасці: + (function (x) { + + delete arguments; // false + typeof arguments; // "object" + + delete x; // false + x; // 1 + + function f(){} + delete f.length; // false + typeof f.length; // "number" + + })(1); + +### У заключэнне + +Аператар `delete` часта паводзіць сябе нечакана, таму адзінае надзейнае выкарыстанне +`delete` — выдаленне яўна прызначаных уласцівасцяў. diff --git a/doc/by/core/eval.md b/doc/by/core/eval.md new file mode 100644 index 00000000..7e07dbcd --- /dev/null +++ b/doc/by/core/eval.md @@ -0,0 +1,47 @@ +## Чаму не варта выкарыстоўваць `eval` + +Функцыя `eval` выконвае радок JavaScript коду ў лакальнай зоне бачнасці. + + var number = 1; + function test() { + var number = 2; + eval('number = 3'); + return number; + } + test(); // 3 + number; // 1 + +Тым не менш, `eval` выконваецца ў лакальнай прасторы імён толькі ў тым выпадку, калі +яна была выклікана наўпрост *і* імя выкліканай функцыі — `eval`. + + var number = 1; + function test() { + var number = 2; + var copyOfEval = eval; + copyOfEval('number = 3'); + return number; + } + test(); // 2 + number; // 3 + +Лепш пазбягаць выкарыстоўвання `eval`. 99,9% яе «выкарыстанняў» можа быць дасягнута +**без** яе. + +### Схаваны `eval` + +Абедзве [функцыі тайм-аўты](#other.timeouts) `setTimeout` і `setInterval` могуць +прымаць радок у якасці першага аргумента. Гэты радок будзе **заўсёды** выконвацца +ў глабальнай прасторы імёнаў, бо `eval` не выклікаецца наўпрост у дадзеным выпадку. + +### Праблемы з бяспекаю + +Таксама `eval` мае праблемы з бяспекаю, бо ён выконвае **любы** перададзены код. +Таму яе **ніколі** не варта выкарыстоўваць з радкамі, што паходзяць з ненадзейных +крыніцаў. + +### Заключэнне + +Лепш ніколі не выкарыстоўваць `eval`. Любы код, што выкарыстоўвае яе, спрэчны ў +плане якасці, карэктнасці, прадукцыйнасці і бяспекі. Калі для таго, каб нешта +працавала, патрэбны `eval`, **не** трэба прымаць гэта рашэнне ў першую чаргу. +*Лепшым рашэннем* будзе тое, што не будзе выкарыстоўваць `eval`. diff --git a/doc/by/core/semicolon.md b/doc/by/core/semicolon.md new file mode 100644 index 00000000..db78ed7d --- /dev/null +++ b/doc/by/core/semicolon.md @@ -0,0 +1,109 @@ +## Аўтаматычная ўстаўка кропкі з коскай + +Хаця JavaScript мае C-падобны сінтакс, ён **не** прымушае выкарыстоўваць кропку +з коскай у кодзе, таму ёсць магчымасць прапускаць іх. + +Але JavaScript — не мова без кропак з коскай. Насамрэч яны патрэбны ёй, каб разумець +зыходны код. Таму парсер JavaScript **аўтаматычна** ўстаўляе іх паўсюль, дзе +сустракае памылку адсутнасці кропкі з коскай. + + var foo = function() { + } // памылка разбора, парсер чакаў кропку з коскай + test() + +Адбываецца ўстаўка, парсер спрабуе зноў. + + var foo = function() { + }; // памылкі няма, парсер працягвае + test() + +Аўтаматычная ўстаўка кропкі з коскай лічыцца адной з **найвялікшых** архітэктурных +памылак у мове, бо *можа* змяніць паводзіны кода. + +### Як яно працуе + +Ніжэйпрыведзены код не мае кропак з коскай, таму парсер вырашае дзе іх уставіць. + + (function(window, undefined) { + function test(options) { + log('testing!') + + (options.list || []).forEach(function(i) { + + }) + + options.value.test( + 'long string to pass here', + 'and another long string to pass' + ) + + return + { + foo: function() {} + } + } + window.test = test + + })(window) + + (function(window) { + window.someLibrary = {} + + })(window) + +Ніжэй — вынік гульні парсера ў адгадванне. + + (function(window, undefined) { + function test(options) { + + // Не ўстаўлена, радкі былі аб'яднаныя + log('testing!')(options.list || []).forEach(function(i) { + + }); // <- устаўлена + + options.value.test( + 'long string to pass here', + 'and another long string to pass' + ); // <- устаўлена + + return; // <- устаўлена, разбіў аператар return на два блока + { // парсер лічыць гэты блок асобным + foo: function() {} + }; // <- устаўлена + } + window.test = test; // <- устаўлена + + // Радкі зноў аб'ядналіся + })(window)(function(window) { + window.someLibrary = {}; // <- устаўлена + + })(window); //<- устаўлена + +> **Заўвага:** Парсер JavaScript не апрацоўвае "карэктна" аператар return, калі +> пасля яго пачынаецца новы радок. Магчыма прычына і не ў аўтаматычнай устаўцы +> кропак з коскай, але гэта, тым не менш, непажаданы эфект. + +Парсер кардынальна памяняў паводзіны кода. У пэўных выпадках ён прымае **памылковыя +рашэнні**. + +### Вядучыя дужкі + +У выпадку вядучай дужкі парсер **не** уставіць кропку з коскай. + + log('testing!') + (options.list || []).forEach(function(i) {}) + +Гэты код ператворыцца ў радок. + + log('testing!')(options.list || []).forEach(function(i) {}) + +**Вельмі** верагодна, што `log` **не** вяртае функцыю; Таму вышэйпрыведзены +код справакуе `TypeError` з заявай, што `undefined` не з'яўляецца функцыяй. + +### Заключэнне + +Крайне рэкамендуецца **ніколі** не прапускаць кропку з коскай. Таксама заўсёды +рэкамендуецца ставіць дужкі на той жа лініі, што і адпаведныя канструкцыі, і ніколі +не прапускаць іх у аднарадковых канструкцыях `if` / `else`. Гэтыя меры не толькі +павысяць кансістэнтнасць кода, але таксама прадухіляць ад таго, што парсер +JavaScript зменіць паводзіны кода. diff --git a/doc/by/core/undefined.md b/doc/by/core/undefined.md new file mode 100644 index 00000000..18af0f2d --- /dev/null +++ b/doc/by/core/undefined.md @@ -0,0 +1,69 @@ +## `undefined` і `null` + +JavaScript мае два розныя значэнні для 'нічога' - гэта `null` і `undefined`, пры +гэтым апошняе больш карыснае. + +### Значэнне `undefined` + +`undefined` — гэта тып з роўна адным значэннем: `undefined`. + +Мова таксама аб'яўляе глабальную пераменную, што мае значэнне `undefined`; Гэта +пераменная таксама называецца `undefined`. Тым не менш, гэта пераменная, а **не** +канстанта, ці ключавое слова. Гэта азначае, што яе *значэнне* можа быць +з лёгкасцю перазапісаным. + +> **Заўвага для ES5:** у ECMAScript 5 `undefined` **больш** *нельга запісваць* у +> строгім рэжыме, але гэта імя можа ўся яшчэ быць перакрыта праз выкарыстанне +> функцыі з іменем `undefined`. + +Ніжэй пералічаныя некалькі выпадкаў, калі вяртаецца `undefined`: + + - Доступ да (немадыфікаванай) глабальнай пераменнай `undefined`. + - Доступ да аб'яўленай, *але яшчэ не* ініцыалізаванай пераменнай. + - Няяўна вернутае значэнне функцыі праз адсутнасць аператара `return`. + - З аператара `return`, які нічога яўна не вяртае. + - У выніку пошуку неіснуючай уласцівасці аб'екта. + - Параметры функцыі, якім яўна не было прысвоена значэнне. + - Усё, чаму было прысвоена значэнне `undefined`. + - Любы выраз у форме `void(expression)`. + +### Апрацоўка зменаў значэння `undefined` + +З той прычыны, што глабальная пераменная `undefined` утрымлівае толькі копію +актуальнага *значэння* `undefined`, прысвойванне ёй новага значэння **не** мяняе +значэнне *тыпа* `undefined`. + +Таксама для таго, каб параўнаць што-небудзь з значэннем `undefined`, спачатку +трэба атрымаць значэнне `undefined`. + +Звыклая тэхніка абароны ад магчымага перазапісвання пераменнай `undefined` — +дадатковы параметр у [ананімнай абгортцы](#function.scopes), што выкарыстоўвае +адсутны аргумент. + + var undefined = 123; + (function(something, foo, undefined) { + // цяпер undefined у лакальнай зоне бачнасці + // зноў спасылаецца на значэнне `undefined` + + })('Hello World', 42); + +Гэтага ж выніку можна дасягнуць праз аб'яўленне ўнутры абгорткі. + + var undefined = 123; + (function(something, foo) { + var undefined; + ... + + })('Hello World', 42); + +Адзіная розніца ў тым, што гэта апошняя версія будзе большай на 4 байты пры +мініфікацыі, а ў першым унутры ананімнай абгорткі не будзе аператара `var`. + +### Выкарыстоўванне `null` + +Хаця `undefined` у кантэксце мовы JavaScript у асноўным выкарыстоўваецца ў сэнсе +традыйнага *null*, сам `null` (і літэрал і тып) з'яўляецца яшчэ адным тыпам дадзеных. + +Выкарыстоўваецца ў некаторых унутранных механізмах JavaScript (напрыклад аб'яўленне +канца ланцужка прататыпаў пазначаючы `Foo.prototype = null`), але амаль што ва ўсіх +выпадках ён можа быць заменены на `undefined`. diff --git a/doc/by/function/arguments.md b/doc/by/function/arguments.md new file mode 100644 index 00000000..98ac3d2b --- /dev/null +++ b/doc/by/function/arguments.md @@ -0,0 +1,130 @@ +## Аб'ект `arguments` + +У зоне бачнасці любой функцыі JavaScript ёсць доступ да адмысловай пераменнай +`arguments`. Гэтая пераменная утрымлівае спіс усіх аргументаў, што былі +перададзеныя функцыі. + +> **Заўвага:** У выпадку, калі `arguments` ужо быў створаны ўнутры зоны бачнасці +> функцыі праз выраз `var`, або з'яўляецца фармальным параметрам, +> аб'ект `arguments` не будзе створаны. + +Аб'ект `arguments` **не з'яўляецца** спадкаемцам `Array`. Ён мае падабенствы +з масівам, напрыклад уласцівасць `length`. Але ён не ўспадкоўвае `Array.prototype`, +а ўяўляе з сябе `Object`. + +Таму **не**магчыма выклікаць стандартныя метады `push`, `pop` або `slice` +у аб'екта `arguments`. Тым не менш, ітэрацыя з звычайным цыклам `for` працуе карэктна. +Неабходна канвертаваць яго ў сапраўдны аб'ект `Array`, каб прымяніць стандартныя +метады масіваў. + +### Канвертацыя ў масіў + +Ніжэйпрыведезны код верне новы масіў, які будзе ўтрымліваць усе элементы аб'екта +`arguments`. + + Array.prototype.slice.call(arguments); + +Такая канвертацыя **марудная**, яе **не рэкамендуецца** выкарыстоўваць у крытычных +у плане прадукцыйнасці частках кода. + +### Перадача `arguments` + +Ніжэй прадстаўлены рэкамендаваны спосаб перадачы аргументаў з адной функцыі ў іншую. + + function foo() { + bar.apply(null, arguments); + } + function bar(a, b, c) { + // тут робім што-небудзь + } + +Яшчэ адзін прыём — гэта выкарыстанне `call` і `apply` разам, каб ператварыць метады, +што выкарыстоўваюць значэнне `this` як і свае аргументы, у звычайныя функцыі, +што выкарыстоўваюць толькі аргументы. + + function Person(first, last) { + this.first = first; + this.last = last; + } + + Person.prototype.fullname = function(joiner, options) { + options = options || { order: "western" }; + var first = options.order === "western" ? this.first : this.last; + var last = options.order === "western" ? this.last : this.first; + return first + (joiner || " ") + last; + }; + + // Ствараем незвязаную версію "fullname", што можа быць выкарыстана з любым + // аб'ектам, які мае ўласцівасці 'first' і 'last', перададзеным у якасці + // першага параметра. Гэтую абгортку не трэба будзе мяняць, калі колькасць або + // парадак аргументаў fullname зменяцца. + Person.fullname = function() { + // Result: Person.prototype.fullname.call(this, joiner, ..., argN); + return Function.call.apply(Person.prototype.fullname, arguments); + }; + + var grace = new Person("Grace", "Hopper"); + + // 'Grace Hopper' + grace.fullname(); + + // 'Turing, Alan' + Person.fullname({ first: "Alan", last: "Turing" }, ", ", { order: "eastern" }); + + +### Фармальныя параметры і індэксы аргументаў + +Аб'ект `arguments` стварае *гэтэр* і *сэтэр* як да кожнай са сваіх уласцівасцяў, +так і да фармальных параметраў функцыі. + +У выніку змена значэння фармальнага параметра зменіць таксама адпаведную ўласцівасць +аб'екта `arguments`, і наадварот. + + function foo(a, b, c) { + arguments[0] = 2; + a; // 2 + + b = 4; + arguments[1]; // 4 + + var d = c; + d = 9; + c; // 3 + } + foo(1, 2, 3); + +### Міфы і праўда аб прадукцыйнасці + +Адзінае, калі `arguments` не ствараецца, — гэта калі ёсць фармальны аргумент функцыі +або пераменная ўнутры яе з такім іменем. Не важна, выкарыстоўваюцца яны ці не. + +Як *гэтэры*, так і *сэтэры* ствараюцца **заўсёды**, таму іх выкарыстоўванне не +мае амаль ніякага ўплыву на прадукцыйнасць. + +> **Заўвага для ES5:** *гэтэры* і *сэтэры* не ствараюцца ў строгім рэжыме. + +Тым не менш, ёсць адна рэч, якая можа жахліва знізіць прадукцыйнасць у сучасных +рухавіках JavaScript — гэта выкарыстанне `arguments.callee`. + + function foo() { + arguments.callee; // робім што-небудзь з функцыяй foo + arguments.callee.caller; // і з функцыяй, якая выклікала foo + } + + function bigLoop() { + for(var i = 0; i < 100000; i++) { + foo(); // Звычайна ўстаўляецца... + } + } + +У вышэйпрыведзеным кодзе `foo` больш не можа быць [устаўлена][1], бо ёй трэба +ведаць аб сабе і аб функцыі, што яе выклікала. Гэта не толькі знішчае павышэнне +прадукцыйнасці, якое магло адбыцца дзякуючы ўстаўцы, але і парушае інкапсуляцыю, бо +функцыя цяпер залежыць ад спецыфічнага кантэксту, які яе выклікае. + +Выкарыстоўванне `arguments.callee` або яго ўласцівасцяў **вельмі непажадана**. + +> **Заўвага для ES5:** У строгім рэжыме `arguments.callee` кіне памылку `TypeError`, +> бо яго выкарыстанне аб'яўлена састарэлым. + +[1]: http://en.wikipedia.org/wiki/Inlining diff --git a/doc/by/function/closures.md b/doc/by/function/closures.md new file mode 100644 index 00000000..23911e6a --- /dev/null +++ b/doc/by/function/closures.md @@ -0,0 +1,113 @@ +## Замыканні і спасылкі + +Адна з найбольш магутных магчымасцяў JavaScript — магчымасць ствараць *замыканні*. +Зона бачнасці замыканняў **заўсёды** мае доступ да знешняй зоны бачнасці, у якой +замыканне было аб'яўлена. З той прычыны, што ў JavaScript адзіны механізм працы +з зонай бачнасці — гэта [зоны бачнасці функцыі](#function.scopes), усе функцыі +выступаюць у якасці замыканняў. + +### Эмуляцыя прыватных пераменных + + function Counter(start) { + var count = start; + return { + increment: function() { + count++; + }, + + get: function() { + return count; + } + } + } + + var foo = Counter(4); + foo.increment(); + foo.get(); // 5 + +Тут `Counter` вяртае **два** замыканні: функцыю `increment` і функцыю `get`. +Абедзьве функцыі маюць **спасылку** на зону бачнасці `Counter` і таму заўсёды +маюць доступ да пераменнай `count`, што была аб'яўлена ў гэтай зоне бачнасці. + +### Якім чынам гэта працуе + +З той прычыны, што ў JavaScript немагчыма спасылацца або прысвойваць зоны бачнасці, +**немагчыма** атрымаць доступ да пераменнай `count` звонку. Адзіны спосаб +узаемадзейнічаць з ім — выкарыстоўваць два замыканні. + + var foo = new Counter(4); + foo.hack = function() { + count = 1337; + }; + +Вышэйпрыведзены код **не** памяняе значэнне пераменнай `count` у зоне бачнасці +`Counter`, бо `foo.hack` не быў аб'яўлены у **гэтай** зоне бачнасці. Замест гэтага +ён створыць або перазапіша *глабальную* пераменную `count`. + +### Замыканні ўнутры цыклаў + +Частая памылка - выкарыстанне замыканняў унутры цыклаў, як быццам бы яны капіруюць +значэнне пераменнай індэксу цыкла. + + for(var i = 0; i < 10; i++) { + setTimeout(function() { + console.log(i); + }, 1000); + } + +Вышэйпрыведзены код **не** выведзе нумары ад `0` да `9`, ён проста выведзе +нумар `10` дзесяць разоў. + +*Ананімная* функцыя захоўвае **спасылку** на `i`. У той час, калі функцыя `console.log` +выклікаецца, `цыкл for` ужо адпрацаваў, а значэнне `i` ўжо стала `10`. + +Каб атрымаць пажаданыя паводзіны, неабходна стварыць **копію** значэння `i`. + +### Як абыйсці праблемы спасылкі + +Каб стварыць копію значэння пераменнай індэкса цыкла, лепшы спосаб — стварэнне +[ананімнай абгорткі](#function.scopes). + + for(var i = 0; i < 10; i++) { + (function(e) { + setTimeout(function() { + console.log(e); + }, 1000); + })(i); + } + +Знешняя ананімная функцыя выконваецца імгненна з `i` ў якасці першага аргумента +і атрымае копію **значэння** `i` ў якасці параметра `e`. + +Ананімная функцыя, што перадаецца метаду `setTimeout`, цяпер мае спасылку на +`e`, чыё значэнне **не** мяняецца на працягу цыкла. + +Яшчэ адзін спосаб атрымаць такі вынік — вяртаць функцыю з ананімнай абгорткі, +што будзе паводзіць сябе такім жа чынам, як і папярэдні прыклад. + + for(var i = 0; i < 10; i++) { + setTimeout((function(e) { + return function() { + console.log(e); + } + })(i), 1000) + } + +Яшчэ адзін папулярны спосаб дасягнуць гэтага — дадаць яшчэ адзін аргумент выкліку +функцыі `setTimeout`, якая перадасць агрумент функцыі зваротнага выкліку. + + for(var i = 0; i < 10; i++) { + setTimeout(function(e) { + console.log(e); + }, 1000, i); + } + +Некаторыя старыя асяродкі JS (Internet Explorer 9 і ніжэй) не падтрымліваюць +гэтую магчымасць. + +Таксама магчыма выканаць гэта выкарыстоўваючы `.bind`, якая можа звязаць +`this` і аргументы функцыі. Ніжэйпрыведзены прыклад працуе як папярэднія. + + for(var i = 0; i < 10; i++) { + setTimeout(console.log.bind(console, i), 1000); + } diff --git a/doc/by/function/constructors.md b/doc/by/function/constructors.md new file mode 100644 index 00000000..1da70bf5 --- /dev/null +++ b/doc/by/function/constructors.md @@ -0,0 +1,122 @@ +## Канструктары + +Канструктары ў JavaScript таксама адрозніваюцца ад большасці іншых моваў. Любы +выклік функцыі, якому папярэднічае ключавое слова `new` з'яўляецца канструктарам. + +Унутры канструктара (выкліканай функцыі) - значэнне `this` спасылаецца на +новаствораны аб'ект. [Прататыпам](#object.prototype) **новага** +аб'екта прызначаецца `prototype` функцыі, што была выклікана ў якасці канструктара. + +У выпадку, калі выкліканая функцыя не вяртае яўнага значэння праз `return`, будзе +не яўна вернута значэнне `this`, то бок новы аб'ект. + + function Person(name) { + this.name = name; + } + + Person.prototype.logName = function() { + console.log(this.name); + }; + + var sean = new Person(); + +У гэтым прыкладзе `Person` выклікаецца ў якасці канструктара, адпаведна `prototype` +створанага аб'екта будзе прывязаны да `Person.prototype`. + +Вярнуць яўнае значэнне праз `return`, можна **толькі** калі гэта значэнне - `Object`. + + function Car() { + return 'ford'; + } + new Car(); // новы аб'ект, не 'ford' + + function Person() { + this.someValue = 2; + + return { + name: 'Charles' + }; + } + new Person(); // вяртае аб'ект ({name:'Charles'}), які не ўтрымлівае someValue + +Калі ключавое слова `new` прапушчана, функцыя **не** верне аб'ект. + + function Pirate() { + // пазначыць значэнне ў глабальным аб'екце! + this.hasEyePatch = true; + } + var somePirate = Pirate(); // somePirate == undefined + +Гэты прыклад можа спрацаваць у некаторых выпадках, праз тое як працуе +[`this`](#function.this) у JavaScript. Значэннем `this` тут будзе +*глабальны аб'ект*. + +### Фабрыкі + +Каб мець магчымасць прапусціць ключавое слова `new`, канструктар функцыі мае яўна +вяртаць значэнне. + + function Robot() { + var color = 'gray'; + return { + getColor: function() { + return color; + } + } + } + + new Robot(); + Robot(); + +Абодва выклікі `Robot` вернуць тое ж самае, новы аб'ект, які мае ўласцівасць +`getColor`, што з'яўляецца [замыканнем](#function.closures). + +Таксама варта адзначыць, што выклік `new Robot()` **не** ўплывае на прататып +вернутага аб'екта. Хаця прататып будзе прызначаны новастворанаму аб'екту, `Robot` +ніколі не верне гэты аб'ект. + +У прыкладзе вышэй, няма розніцы паміж выклікам функцыі з аператарам `new` або +без яго. + + +### Стварэнне новых аб'ектаў з выкарыстаннем фабрык + +Часта рэкамендуюць **не** выкарыстоўваць `new` бо забыўшыся выкарыстаць яго, можна +стварыць памылку. + +Каб стварыць новы аб'ект, лепш выкарыстоўваць фабрыку і стварыць новы аб'ект +*унутры фабрыкі*. + + function CarFactory() { + var car = {}; + car.owner = 'nobody'; + + var milesPerGallon = 2; + + car.setOwner = function(newOwner) { + this.owner = newOwner; + } + + car.getMPG = function() { + return milesPerGallon; + } + + return car; + } + +Хоць гэты прыклад і спрацуе негледзячы на забытае `new`, і бясспрэчна выкарыстоўвае +[прыватныя пераменныя](#function.closures), ён мае некалькі недахопаў. + + 1. Ён выкарыстоўвае больш памяці, бо функцыі створаных аб'ектаў **не** захоўваюццца + у прататыпе, а ствараюцца на нова для кожнага аб'екта. + 2. Каб эмуляваць спадкаемства, фабрыка мае скапіраваць метады іншага аб'екта, або + пазначыць прататыпам новага аб'екта стары. + 3. Разрыў ланцужка прататыпаў, проста па прычыне забытага ключавога слова `new`, + не адпавядае духу мовы JavaScript. + +### У заключэнне + +Негледзячы на тое, што прапушчанае `new` можа выліцца ў памылку, гэта **не** +прычына адмовіцца ад выкарыстання прататыпаў. У выніку лепш высвятліць якое рашэнне +больш адпавядае патрабаванням праграмы. Асабліва важна выбраць пэўны стыль і +**паслядоўна** выкарыстоўваць яго. diff --git a/doc/by/function/general.md b/doc/by/function/general.md new file mode 100644 index 00000000..da5f4ba3 --- /dev/null +++ b/doc/by/function/general.md @@ -0,0 +1,48 @@ +## Выразы і аб'яўленне функцый + +У JavaScript функцыі таксама з'яўляюцца аб'ектамі. Гэта значыць іх можна перадаваць +і прысвойваць як і любыя іншыя аб'екты. Адзін, часта выкарыстоўваемы варыянт, +гэтай магчымасці - перадача *ананімнага метада* як функцыі зваротнага выкліку +іншай, магчыма асінхроннай функцыі. + +### Аб'яўленне `function` + + function foo() {} + +У вышэй прыведзеным прыкладзе функцыя [уздымаецца](#function.scopes) перад тым +як пачынаецца выконванне праграмы; Такім чынам, яна даступная *паўсюль* у зоне +бачнасці, у якой яна была *аб'яўлена*, нават калі выклік адбываецца да фактычнага +аб'яўлення ў кодзе. + + foo(); // Працуе, бо функцыя будзе створана да выконвання кода + function foo() {} + +### `function` як выраз + + var foo = function() {}; + +У гэтым прыкладзе пераменнай `foo` прысвойваецца *ананімная* функцыя. + + foo; // 'undefined' + foo(); // уздыме TypeError + var foo = function() {}; + +Праз тое, што `var` - гэта аб'яўленне якое уздымае імя пераменнай `foo` перад тым +як код будзе выкананы, `foo` будзе ўжо аб'яўленым калі ён пачне выконвацца. + +Але так як прысвойванні адбываюцца толькі пад час выконвання, значэнне `foo` +будзе змоўчанным ([undefined](#core.undefined)) да выконвання адпаведнага кода. + +### Выразы з іменаванымі функцыямі + +Яшчэ адзін выбітны выпадак - прысвойванне іменавай функцыі. + + var foo = function bar() { + bar(); // працуе + } + bar(); // ReferenceError + +Тут, `bar` не даступны ў знешнім скоўпе, бо функцыя толькі прысвойваецца пераменнай +`foo`; аднак, унутры `bar`, імя даступнае. Так адбываецца праз асаблівасці працы +з [прастранствамі імён](#function.scopes) у JavaScript - імя функцыі *заўсёды* +даступнае ў лакальным скоўпе функцыі. diff --git a/doc/by/function/scopes.md b/doc/by/function/scopes.md new file mode 100644 index 00000000..7ade2cfd --- /dev/null +++ b/doc/by/function/scopes.md @@ -0,0 +1,230 @@ +## Зоны бачнасці і прасторы імёнаў + +Негледзячы на тое, што JavaScript добра працуе з сінтаксісам фігурных дужак для +блокаў, у ім **няма** падтрымкі блочнай зоны бачнасці; усё што ёсць на гэты конт +у мове - *зона бачнасці функцыі*. + + function test() { // зона бачнасці + for(var i = 0; i < 10; i++) { // не зона бачнасці + // лічым + } + console.log(i); // 10 + } + +> **Заўвага:** Калі не выкарыстана ў прысвойванні, аператары return або аргуменце +> функцыі, натацыя `{...}` будзе інтэрпрэтавана як блочны выраз, а **не** як літэрал +> аб'екта. Гэта з'ява, сумесна з [аўтаматычнай устаўкай коскі з кропкай](#core.semicolon), +> можа прывесці да хітрых памылак. + +Таксама JavaScript не падтрымлівае выразныя прасторы імёнаў, усё аб'яўляецца ў +агульнадаступнай прасторы імёнаў. + +Для кожнай спасылкі на пераменную, JavaScript пойдзе ўверх па ўсіх зонах бачнасці, +пакуль не знойдзе яе. У выпадку, калі ён дойдзе да глабальнай прасторы імён і ўсё +яшчэ не знойдзе неабходнае імя, ён уздыме `ReferenceError`. + +### Атрута глабальнымі пераменнымі + + // скрыпт A + foo = '42'; + + // скрыпт B + var foo = '42' + +Вышэйпрыведзеныя скрыпты маюць **розныя** вынікі. Скрыпт A аб'яўляе пераменную +`foo` у *глабальнай* зоне бачнасці, скрыпт B аб'яўляе `foo` у *актуальнай* зоне +бачнасці. + +Паўторымся, гэта абсалютна **не** *той жа самы вынік*: не выкарыстоўваенне `var` +можа мець сур'ёзныя наступствы. + + // глабальная зона бачнасці + var foo = 42; + function test() { + // лакальная зона бачнасці + foo = 21; + } + test(); + foo; // 21 + +З-за таго, што аператар `var` прапушчаны ўнутры функцыі `test`, значэнне `foo` +у глабальнай прасторы імён будзе перазапісаным. Хаця першапачаткова гэта можа +падацца невялікай праблемай, не выкарыстоўванне `var` у кодзе на тысячы радкоў, +прывядзе да жахлівых, цяжкіх для адладкі памылак. + + // глабальная прастора імёнаў + for(var i = 0; i < 10; i++) { + subLoop(); + } + + function subLoop() { + // прастора імёнаў subLoop + for(i = 0; i < 10; i++) { // аператар var прапушчаны + // робім чароўныя рэчы! + } + } + +Знешні цыкл скончыцца пасля першага выкліка `subLoop`, бо `subLoop` перазапісвае +глабальную пераменную `i`. Выкарыстоўваючы `var` для другога цыкла `for` можна +было б пазбегнуць памылкі. **Ніколі** не прапускайце аператар `var`, акрамя +выпадкаў, калі змена дадзеных у знешняй зоне бачнасці ёсць *пажаданым вынікам*. + +### Лакальныя пераменныя + +Адзіная крыніца лакальных пераменных у JavaScript гэта параметры [функцыі](#function.general) +і пераменныя аб'яўленыя праз аператар `var`. + + // глабальная зона бачнасці + var foo = 1; + var bar = 2; + var i = 2; + + function test(i) { + // лакальная зона бачнасці функцыі test + i = 5; + + var foo = 3; + bar = 4; + } + test(10); + +`foo` і `i` гэта лакальныя пераменныя унутры зоны бачнасці функцыі `test`, +а вось прызначэнне `bar` перазапіша глабальныю пераменную з тым жа іменем. + +### Падыманне + +JavaScript **падымае** аб'яўленні. Гэта азначае, што абодва аб'яўленні аператараў +`var` і `function` падымуцца на верх іх зоны бачнасці. + + bar(); + var bar = function() {}; + var someValue = 42; + + test(); + function test(data) { + if (false) { + goo = 1; + + } else { + var goo = 2; + } + for(var i = 0; i < 100; i++) { + var e = data[i]; + } + } + +Вышэйпрыведзены код трансфармуецца перад пачаткам выконвання. JavaScript падымае +аператары `var`, як і аб'яўленне `function`, наверх бліжэйшай зоны бачнасці. + + // аператар var перамяшчаецца сюды + var bar, someValue; // па змоўчванню - 'undefined' + + // аб'яўленне функцыі таксама падымаецца наверх + function test(data) { + var goo, i, e; // адсутная блочная зона бачнасці перайшла сюды + if (false) { + goo = 1; + + } else { + goo = 2; + } + for(i = 0; i < 100; i++) { + e = data[i]; + } + } + + bar(); // падае з TypeError бо ўсё яшчэ 'undefined' + someValue = 42; // прысвойванні не падымаюцца + bar = function() {}; + + test(); + +Адсутнасць блочнай зоны бачнасці не толькі падыме аператар `var` па-за межы цыкла +і яго цела, але таскама зробіць вынік некаторых канструкцый `if` не-інтуітыўным. + +Хоць у арыгінальным кодзе падаецца што канструкцыя `if` змяняе *глабальную +пераменную* `goo`, на дадзены момант гэта мяняе *лакальную пераменную* - пасля +таго, як было прыменена падыманне. + +Без ведаў аб *падыманні*, можна падумаць што код ніжэй кіне `ReferenceError`. + + // правярае ці было SomeImportantThing праініцыалізавана + if (!SomeImportantThing) { + var SomeImportantThing = {}; + } + +Але канешне, гэта працуе праз тое, што аператар `var` быў падняты на верх +глабальнай *зоны бачнасці*. + + var SomeImportantThing; + + // тут нейкі код можа ініцыалізаваць SomeImportantThing, або не + + // тут у гэтым можна ўпэўніцца + if (!SomeImportantThing) { + SomeImportantThing = {}; + } + +### Парадак доступу да пераменных + +Усе зоны бачнасці ў JavaScript, уключаючы *глабальную зону бачнасці*, маюць +адмысловае імя [`this`](#function.this), аб'яўленае ўнутры іх, якое спасылаецца +на *актуальны аб'ект*. + +Зоны бачнасці функцый таксама маюць імя [`arguments`](#function.arguments), +аб'яўленае ў іх, якое спасылаецца на аргументы, што былі перададзеныя ў функцыю. + +Напрыклад, калі паспрабаваць атрымаць доступ да пераменнай `foo` унутры зоны +бачнасці функцыі, JavaScript будзе шукаць імя ў наступным парадку: + + 1. У выпадку калі прысутнічае канструкцыя `var foo` у актуальнай зоне бачнасці, + ёна і выкарыстоўваецца. + 2. Калі параметр функцыі мае імя `foo`, ён будзе выкарыстаны. + 3. Калі сама функцыя называецца `foo`, яна будзе выкарыстана. + 4. Пераходзіць у знешнюю зону бачнасці, і пачынае з пункта **#1**. + +> **Заўвага:** Наява параметра названага `arguments` **перадухіліць** стварэнне +> параметра `arguments` па змоўчванні. + +### Прасторы імёнаў + +Вялікая праблема, звязаная з выкарыстоўваннем глабальнай прасторы імёнаў, гэта +высокая верагоднасць перасячэння імёнаў пераменных. У JavaScript, гэта праблема +можа быць лёгка пазбегнута праз выкарыстанне *ананімных абгортак*. + + (function() { + // аўтаномная "прастора імён" + + window.foo = function() { + // адкрытае замыканне + }; + + })(); // імгненнае выкананне функцыі + + +Ананімныя функцыі з'яўляюцца [выразамі](#function.general); таму каб быць выкліканымі, +яны спачатку маюць быць ацэненымі. + + ( // ацэньваем функцыю ўнутры дужак + function() {} + ) // вяртаем аб'ект функцыі + () // выклік выніку ацэнкі + +Ёсць і іншыя спосабы ацаніць і імгненна выклікаць выраз функцыі, хаця яны і +адрозніваюцца па сінтаксісу, паводзяць сябе аднолькава. + + // Яшчэ некалькі спосабаў наўпрост выклікаць функцыю + !function(){}() + +function(){}() + (function(){}()); + // і так далей... + +### Заключэнне + +Рэкамендуецца заўсёды выкарыстоўваць *ананімную абгортку* каб інкапсуліраваць код +у яго асабістай прасторы імёнаў. Гэта не толькі абараняе код ад перасячэння імёнаў, +але і дапамагае падзяляць праграму на модулі. + +Таксама выкарыстанне глабальных пераменных лічыцца **дрэннай практыкай**. **Любое** +іх выкарыстоўванне - прыкмета дрэнна напісанага кода, схільнага да памылак, і цяжага +ў падтрымцы. diff --git a/doc/by/function/this.md b/doc/by/function/this.md new file mode 100644 index 00000000..5b0f555d --- /dev/null +++ b/doc/by/function/this.md @@ -0,0 +1,118 @@ +## Як працуе `this` + +У JavaScript `this` азначае канцэптуальна іншую рэч, чым у іншых мовах праграмавання. +Існуе роўна **пяць** варыянтаў таго, да чаго можа быць прывязана `this`. + +### Глабальна зона бачнасці + + this; + +Калі `this` выкарыстоўваецца ў глабальнай зоне бачнасці - яна спасылаецца на *глабальны* аб'ект + + +### Выклік функцыі + + foo(); + +Тут, `this` усё яшчэ спасылаецца на *глабальны* аб'ект. + +> **Заўвага для ES5:** У строгім рэжыме, паняцця глабальнасці **больш не існуе**. +> `this` у такім выпадку будзе мець значэнне `undefined`. + +### Выклік метада + + test.foo(); + +У гэтым выпадку, `this` будзе спасылацца на аб'ект `test`. + +### Выклік канструктара + + new foo(); + +Выклік функцыі, перад якім прысутнічае ключавое слова `new`, выступае ў якасці +[канструктара](#function.constructors). Унутры функцыі, `this` будзе спасылацца +на *новаствораны* аб'ект. + +### Яўная ўстаноўка `this` + + function foo(a, b, c) {} + + var bar = {}; + foo.apply(bar, [1, 2, 3]); // масіў разгорнецца ў ніжэйпрыведзенае + foo.call(bar, 1, 2, 3); // вынікам будзе a = 1, b = 2, c = 3 + +Пры выкарыстоўванні метадаў `call` або `apply` з `Function.prototype`, значэнню +`this` унутры выкліканай функцыі **яўна прысвойваецца** значэнне першага +аргумента адпаведнага выкліка функцыі. + +Як вынік, у вышэйпрыведзеным прыкладзе *правіла метада* **не** працуе, і `this` +унутры `foo` будзе мець значэнне `bar`. + +> **Заўвага:** `this` **не можа** быць выкарыстаны як спасылка ўнутры літэрала +> `Object`. Таму ў кодзе `var obj = {me: this}` `me` **не** будзе спасылацца на +> `obj`, бо `this` прывязваецца толькі па пяці вышэйапісаных правілах. + +### Магчымыя пасткі + +Не гледзячы на тое, што большасць гэтых прыкладаў лагічныя, першы можна лічыць +яшчэ адным недаглядам мовы, бо ён **ніколі** не мае практычнага прымянення. + + Foo.method = function() { + function test() { + // this спасылаецца на глабальны аб'ект + } + test(); + } + +Памылковым меркаваннем будзе тое, што `this` унутры `test` будзе спасылацца на +`Foo`; Але на самрэч **гэта не так**. + +Каб атрымаць доступ да `Foo` з цела `test`, вы можаце стварыць лакальную +пераменную унутры `метада` што будзе спасылацца на `Foo`. + + Foo.method = function() { + var self = this; + function test() { + // Тут выкарыстоўвайце self замест this + } + test(); + } + +`self` гэта звычайнае імя пераменнай, але яно часта выкарыстоўваецца для спасылкі +на знешні `this`. У камбінацыі з [замыканнямі](#function.closures), яно можа быць +выкарыстана для перадачы `this` навокал. + +У ECMAScript 5 можна выкарыстаць метад `bind` у камбінацыі з ананімнай функцыяй, +дзеля таго каб атрымаць аналагічны вынік. + + Foo.method = function() { + var test = function() { + // this цяпер спасылаецца на Foo + }.bind(this); + test(); + } + +### Прысвойванне метадаў + +Яшчэ адна рэч якая **не** працуе ў JavaScript - гэта стварэнне псэўданімаў функцый, +то бок **прысвойванне** значэння метада пераменнай. + + var test = someObject.methodTest; + test(); + +Паводле першага правіла, `test` цяпер працуе як звычайны выклік функцыі; +адпаведна, `this` унутры больш не будзе спасылацца на `someObject`. + +Поздняе звязванне `this` можа падацца дрэннай ідэяй, але насамрэч якраз дзякуючы +гэтаму працуе [спадкаемства прататыпаў](#object.prototype). + + function Foo() {} + Foo.prototype.method = function() {}; + + function Bar() {} + Bar.prototype = Foo.prototype; + + new Bar().method(); + +Калі выклікаецца `method` новага экзэмпляра `Bar`, `this` будзе спасылацца на гэты +экзэмпляр. diff --git a/doc/by/index.json b/doc/by/index.json new file mode 100644 index 00000000..1ed0abaa --- /dev/null +++ b/doc/by/index.json @@ -0,0 +1,69 @@ +{ + "title": "JavaScript Garden", + "langTitle": "JavaScript Garden па Беларуску", + "description": "Мануал па недахопаў і дзівосах JavaScript", + "sections": [ + { + "title": "Уводзіны", + "dir": "intro", + "articles": ["index"] + }, + { + "title": "Аб'екты", + "dir": "object", + "articles": [ + "general", + "prototype", + "hasownproperty", + "forinloop" + ] + }, + { + "title": "Функцыі", + "dir": "function", + "articles": [ + "general", + "this", + "closures", + "arguments", + "constructors", + "scopes" + ] + }, + { + "title": "Масівы", + "dir": "array", + "articles": [ + "general", + "constructor" + ] + }, + { + "title": "Тыпы", + "dir": "types", + "articles": [ + "equality", + "typeof", + "instanceof", + "casting" + ] + }, + { + "title": "Ядро", + "dir": "core", + "articles": [ + "eval", + "undefined", + "semicolon", + "delete" + ] + }, + { + "title": "Рэшта", + "dir": "other", + "articles": [ + "timeouts" + ] + } + ] +} diff --git a/doc/by/intro/index.md b/doc/by/intro/index.md new file mode 100644 index 00000000..ea82a31e --- /dev/null +++ b/doc/by/intro/index.md @@ -0,0 +1,56 @@ +## Уступ + +**JavaScript Garden** гэта растучы набор дакументацыі аб найбольш +цікавых частках мовы праграмавання JavaScript. Ён дае парады аб тым як прадухіліць +частыя і непрадказальныя памылкі, а таксама праблемы з хуткасцю выконвання і +дрэннымі практыкамі, якія праграмісты, не з'яўляючыяся экспертамі у JavaScript +маглі сустрэць падчас сваіх пошукаў у глыбіні мовы. + +JavaScript Garden **не** ставіць сваёй мэтай навучыць вас мове JavaScript. Былыя +веды мовы рэкамендаваныя, каб вы змаглі зразумець пытанні разглядаемыя ў гэтым +мануале. Каб зразумець базавыя рэчы мовы, калі ласка прачытайце цудоўны [мануал][1] +у сетцы распрацоўшчыкаў Mozilla. + +## Аўтары + +Гэты мануал - праца двух выбітных карыстальнікаў [Stack Overflow][2] , [Ivo Wetzel][3] +(Тэкст) і [Zhang Yi Jiang][4] (Дызайн). + +На дадзены момант падтрымліваецца [Tim Ruffles](http://truffles.me.uk). + +## Удзельнікі + +- Зашмат каб пералічыць тут, [паглядзіце спіс](https://github.com/BonsaiDen/JavaScript-Garden/graphs/contributors). + + +## Хостынг + +JavaScript Garden хосціцца на GitHub, але [Cramer Development][7] падтрымлівае нас +люстэркам на [JavaScriptGarden.info][8]. У Беларускамоўнай версіі таксама ёсць +сваё [люстэрка на GitHub][13] + +## Пераклад + +Перакладзена на Беларускую мову супольнасцю [it-mova][14]. + +## Ліцэнзія + +JavaScript Garden апублікаваны пад [MIT ліцэнзіяй][9] і хосціцца на +[GitHub][10]. Калі вы знойдзеце апячатку або памылку - [пазначце памылку][11] або +адпраўце pull request у сховішча. Вы таксама можаце знайсці нас у +[JavaScript room][12] на чаце Stack Overflow. + +[1]: https://developer.mozilla.org/en/JavaScript/Guide +[2]: http://stackoverflow.com/ +[3]: http://stackoverflow.com/users/170224/ivo-wetzel +[4]: http://stackoverflow.com/users/313758/yi-jiang +[5]: https://github.com/caio +[6]: https://github.com/blixt +[7]: http://cramerdev.com/ +[8]: http://javascriptgarden.info/ +[9]: https://github.com/BonsaiDen/JavaScript-Garden/blob/next/LICENSE +[10]: https://github.com/it-na-move/JavaScript-Garden/ +[11]: https://github.com/it-na-move/JavaScript-Garden/issues +[12]: http://chat.stackoverflow.com/rooms/17/javascript +[13]: http://it-na-move.github.io/JavaScript-Garden/ +[14]: https://github.com/it-na-move diff --git a/doc/by/object/forinloop.md b/doc/by/object/forinloop.md new file mode 100644 index 00000000..fbe52f15 --- /dev/null +++ b/doc/by/object/forinloop.md @@ -0,0 +1,63 @@ +## Цыкл `for in` + +Як і аператар `in`, цыкл `for in` праходзіць па ўсім ланцужку прататыпаў +пры ітэрацыі па ўласцівасцях аб'екта. + +> **Заўвага:** Цыкл `for in` **не** ітэруе па уласцівасцях, у якіх атрыбут +> `enumerable` мае значэнне `false`; напрыклад, уласцівасць `length` +> масіва (Array). + + // Атруцім Object.prototype + Object.prototype.bar = 1; + + var foo = {moo: 2}; + for(var i in foo) { + console.log(i); // вывядзе і bar і moo + } + +Праз тое, што немагчыма памяняць паводзіны самаго цыкла `for in`, неабходна фільтраваць +непажаданыя ўласцівасці аб'екта ўнутры цыкла. У версіях ECMAScript 3 і пазней, +гэта можна зрабіць праз метад [`hasOwnProperty`](#object.hasownproperty). + +Пачынаючы з ECMAScript 5, `Object.defineProperty` можа быць выкарыстана з +`enumerable` роўным `false`, каб дадаць уласцівасці аб'екту такім чынам, што яны +не будуць пералічаны. У такім выпадку было б справядлівым меркаваць, што любая +`enumerable` уласціваць была дададзена адмыслова і прапусціць `hasOwnProperty`, бо +гэта робіць код больш шматслоўным і цяжэйшым для чытання. У бібліятэчным кодзе +`hasOwnProperty` мае быць усё роўна выкарыстаны, бо не варта рабіць здагадкі аб +тым, якія `enumerable` уласцівасці могуць пражываць у ланцужку прататыпаў. + +> **Заўвага:** праз тое, што `for in` заўсёды праходзіць праз увесць ланцужок прататыпаў, +> ён будзе працаваць усё марудней з кожным новым слоем спадкаемства. + +### Выкарыстоўванне `hasOwnProperty` для фільтрацыі + + // возьмем foo з прыкладу + for(var i in foo) { + if (foo.hasOwnProperty(i)) { + console.log(i); + } + } + +Гэта адзіная правільная версія выкарыстоўвання цыкла. Дзякуючы выкарыстоўванню +`hasOwnProperty`, быдзе выведзена **толькі** `moo`. +Калі прыбраць `hasOwnProperty`, код будзе схільны да памылак у выпадку, калі +натыўныя прататыпы — напрыклад, `Object.prototype` — былі змененыя. + +У новых версіях ECMAScript уласцівасці, пазначаныя як не enumerable, могуць быць +вызначыныя праз `Object.defineProperty`, змяншаючы рызыку ітэрацыі праз іх без +выкарыстання `hasOwnProperty`. Тым не менш, трэба быць уважлівым пры выкарыстанні +старых бібліятэк, такіх як [Prototype][1], якая не выкарыстроўвае новымя магчымасці +ECMAScript. +Пры выкарыстоўванні гэтай бібліятэкі, цыклы `for in`, якія не выкарыстоўваюць +`hasOwnProperty`, гарантавана не будуць працаваць. + +### У заключэнне + +Рэкамендавана **заўсёды** выкарыстоўваць `hasOwnProperty` як у ECMAScript 3 або +ніжэй, так і ў бібліятэчным кодзе. У гэтых асяродках ніколі не варта рабіць +здагадкі аб тым, быў зменены натыўны прататып ці не. Пачынаючы з ECMAScript 5, +`Object.defineProperty` дазваляе пазначаць уласцівасці як не `enumerable` і прапускаць +выкарыстоўванне `hasOwnProperty` у кодзе праграмы. + +[1]: http://www.prototypejs.org/ diff --git a/doc/by/object/general.md b/doc/by/object/general.md new file mode 100644 index 00000000..6977d8a3 --- /dev/null +++ b/doc/by/object/general.md @@ -0,0 +1,98 @@ +## Выкарыстанне і ўласцівасці аб'ектаў + +Усё ў JavaScript дзейнічае як аб'ект, апроч двух выключэнняў — гэта +[`null`](#core.undefined) і [`undefined`](#core.undefined). + + false.toString(); // 'false' + [1, 2, 3].toString(); // '1,2,3' + + function Foo(){} + Foo.bar = 1; + Foo.bar; // 1 + +Часта распрацоўшчыкі думаюць, што лічбавыя літэралы не могуць быць выкарыстаны як +аб'екты. Гэта праз тое, што сінтаксічны аналізатар JavaScript стараецца прывесці +*натацыю кропка* пасля нумара да літэрала з плаваючай кропкай. + + 2.toString(); // уздымае SyntaxError + +Ёсць некалькі падыходаў, якія могуць дазволіць выкарыстаць лікавыя літэралы як +аб'екты'. + + 2..toString(); // другая кропка распазнаецца слушна + 2 .toString(); // заўважце прабел з лева ад кропкі + (2).toString(); // 2 распазнаецца першым чынам + +### Аб'ект як тып дадзеных + +Аб'екты ў JavaScript таксама могуць быць выкарыстаныя як [*хэш-табліцы*][1]; яны ў асноўным +складаюцца з іменаваных уласцівасцяў з адпаведнымі значэннямі. + +Выкарыстоўваючы натацыю літэрала аб'екта — `{}` — магчыма стварыць +просты аб'ект. Гэты новы аб'ект [пашырае](#object.prototype) `Object.prototype` і +не мае [сваіх уласцівасцяў](#object.hasownproperty) якія былі б вызначыныя. + + var foo = {}; // новы пусты аб'ект + + // новы аб'ект з уласціваццю 'test', якая мае значэнне 12 + var bar = {test: 12}; + +### Доступ да ўласцівасцяў + +Доступ да ўласцівасцяў аб'екта можа быць здейснены двумя спосабамі, праз кропкавую +натацыю або натацыю з квадратнымі дужкамі. + + var foo = {name: 'кацяня'} + foo.name; // кацяня + foo['name']; // кацяня + + var get = 'name'; + foo[get]; // кацяня + + foo.1234; // SyntaxError + foo['1234']; // працуе + +Натацыі працуюць амаль што ідэнтычна, з адзінай розніцай у тым, што +натацыя з квадратнымі дужкамі дазваляе дынамічную устаноўку ўласцівасцяў і +выкарыстанне імёнаў уласцівасцяў, якія інакш прывялі б да сінтаксічных памылак. + +### Выдаленне ўласцівасцяў + +Адзіны спосаб выдаліць уласціваць з аб'екта — гэта выкарыстаць аператар `delete`; +пазначэнне уласціваці як `undefined` або `null` толькі прыбірае +*значэнне* звязанае з уласцівацю, але не *ключ*. + + var obj = { + bar: 1, + foo: 2, + baz: 3 + }; + obj.bar = undefined; + obj.foo = null; + delete obj.baz; + + for(var i in obj) { + if (obj.hasOwnProperty(i)) { + console.log(i, '' + obj[i]); + } + } + +Вышэй прыведзены код вывядзе `bar undefined` і `foo null` — толькі `baz` быў +выдалены і таму адсутнічае ў вывадзе. + +### Натацыя ключэй + + var test = { + 'case': 'Я ключавое слова, таму я павінна быць пазначана як радок', + delete: 'Я таксама ключавое слова, таму і я' // уздымае SyntaxError + }; + +Уласцівасці аб'ектаў могуць быць пазначаныя як сімваламі, так і ў выглядзе радкоў. +Праз яшчэ адну хібу сінтаксічнага аналізатара JavaScript, вышэй прыведзены код +кіне `SyntaxError` у весіях ранейшых за ECMAScript 5. + +Гэта памылка ўздымаецца праз тое, што `delete` - гэта *ключавое слова*; такім чынам, +яно мае быць пазначана як *літэрал радка* каб забяспечыць, што яно будзе какрэктна +інтэрпрэтавана старымі рухавікамі JavaScript. + +[1]: http://en.wikipedia.org/wiki/Hashmap diff --git a/doc/by/object/hasownproperty.md b/doc/by/object/hasownproperty.md new file mode 100644 index 00000000..730ce942 --- /dev/null +++ b/doc/by/object/hasownproperty.md @@ -0,0 +1,55 @@ +## Метад `hasOwnProperty` + +Каб праверыць, ці ёсць у аб'екта ўласцівасць, вызначаная ў *ім самім*, а не дзе-небудзь +у яго [ланцужку прататыпаў](#object.prototype), неабходна выкарыстаць метад +`hasOwnProperty`, які ўсе аб'екты ўспадкоўваюць ад `Object.prototype`. + +> **Заўвага:** **недастаткова** праверыць, ці значэнне уласцівасці — `undefined`. +> Уласцівасць можа існаваць, але яе значэнне было пазначана як `undefined`. + +`hasOwnProperty` — адзіная функцыя ў JavaScript, якая дазваляе атрымаць уласцівасці +аб'екта **без** зварота да ланцужка прататыпаў. + + // Сапсуем Object.prototype + Object.prototype.bar = 1; + var foo = {goo: undefined}; + + foo.bar; // 1 + 'bar' in foo; // true + + foo.hasOwnProperty('bar'); // false + foo.hasOwnProperty('goo'); // true + +Толькі `hasOwnProperty` дасць правільны чаканы вынік. Паглядзіце секцыю аб +[цыкле `for in`](#object.forinloop) для падрабязнейшых звестак аб тым, як +выкарыстоўваць `hasOwnProperty` падчас ітэрацыі па ўласцівасцях аб'екта. + +### `hasOwnProperty` як уласцівасць + +JavaScript не абараняе ўласцівасць `hasOwnProperty`; такім чынам, ёсць верагоднасць +што ў аб'екта можа быць уласцівасць з такім імем, неабходна выкарыстаць +*знешні* `hasOwnProperty` для карэктнага выніку. + + var foo = { + hasOwnProperty: function() { + return false; + }, + bar: 'Тут жывуць драконы' + }; + + foo.hasOwnProperty('bar'); // заўсёды верне false + + // выкарыстайце hasOwnProperty іншага аб'екта + // і перадайце foo у якасці this + ({}).hasOwnProperty.call(foo, 'bar'); // true + + // Такасама магчыма выкарыстаць hasOwnProperty з Object.prototype + Object.prototype.hasOwnProperty.call(foo, 'bar'); // true + + +### Заключэнне + +Выкарыстоўванне `hasOwnProperty` ёсць **адзіным** надзейным спосабам, каб +праверыць існаванне ўласцівасці ў аб'екце. Рэкамендуецца выкарыстоўваць +`hasOwnProperty` пры ітэрацыі па ўласцівасцях аб'екта, як апісана ў секцыі +[цыкла `for in` ](#object.forinloop). diff --git a/doc/by/object/prototype.md b/doc/by/object/prototype.md new file mode 100644 index 00000000..f5f8c985 --- /dev/null +++ b/doc/by/object/prototype.md @@ -0,0 +1,115 @@ +## Прататып + +JavaScript не прадастаўляе класічную мадэль спадкаемства; замест гэтага, ён +выкарыстоўвае *прататыпную* мадэль. + +Негледзячы на тое, што гэта лічыцца адной з слабасцяў JavaScript, мадэль +прататыпнага спадкаемства больш эфэктыўная за класічную. +Напрыклад, даволі трывіальна пабудаваць класічную мадэль паверх прататыпнай мадэлі, +у той час як адваротнае было б значна больш складаным. + +JavaScript гэта адзіная шырока выкарыстоўваемая мова, якая падтрымлівае +прататыпнае спадкаемства, таму можа спатрэбіцца час, каб прызвычаіцца да гэтай мадэлі. + +Першая вялікая розніца заключаецца ў тым, што JavaScript выкастроўвае *прататыпныя +ланужкі*. + +> **Заўвага:** простае выкарыстоўванне `Bar.prototype = Foo.prototype` прывядзе +> да таго, што абодва аб'екта будуць выкарыстоўваць **той жа** прататып. +> Такім чынам, змены ў прататыпе любога з аб'ектаў паўплываюць на прататып іншага, +> што звычайна не ёсць пажаданым эфэктам. + + function Foo() { + this.value = 42; + } + Foo.prototype = { + method: function() {} + }; + + function Bar() {} + + // Пазначае прататыпам Bar новы асобнік Foo + Bar.prototype = new Foo(); + Bar.prototype.foo = 'Hello World'; + + // Упэнімся, што Bar з'яўляецца дзейсным канструктарам + Bar.prototype.constructor = Bar; + + var test = new Bar(); // стварае новы асобнік Bar + + // Выніковы ланцужок прататыпаў + test [instance of Bar] + Bar.prototype [instance of Foo] + { foo: 'Hello World' } + Foo.prototype + { method: ... } + Object.prototype + { toString: ... /* і г.д. */ } + +У вышэй прыведзеным кодзе аб'ект `test` атрымае спадчыну і ад `Bar.prototype`, +і ад `Foo.prototype`; такім чынам, ён будзе мець доступ да функцыі `method`, якая +вызначана ў `Foo`. А таксама доступ да ўласцівасці `value` +**аднаго унікальнага асобніка** `Foo`, які з'яўляецца яго прататыпам. Важна заўважыць, +што `new Bar()` **не** стварае новы асобнік `Foo`, але выкарыстоўвае функцыю, +пазначаную яго прататыпам; такім чынам, усе асобнікі `Bar` будуць выкарыстоўваць +**тую ж** уласціваць `value`. + +> **Заўвага:** **не** выкарыстоўвайце `Bar.prototype = Foo`, бо гэта будзе +> ўказваць не на прататып `Foo`, а на аб'ект фукцыі `Foo`. Таму ланцужок +> прататыпаў будзе праходзіць праз `Function.prototype`, а не `Foo.prototype`; +> па гэтай прычыне `method` не будзе прысутнічаць у ланцужку прататыпаў. + +### Пошук уласцівасцяў + +Калі адбываецца зварот да ўласцівасці, JavaScript пройдзе па ўсім +ланцужку прататыпаў **уверх** да таго моманту, як знойдзе ўласціваць з запытаным імем. + +У той момант, калі дасягнуты верх ланцужка - а менавіта `Object.prototype` - і ўсё яшчэ +не знойдзена адпаведная ўласцівасць, будзе вернута значэнне [undefined](#core.undefined). + +### Уласцівасць prototype + +Нягледзячы на тое, што ўласцівасць prototype выкарыстоўваецца мовай, каб пабудаваць +ланцужок прататыпаў, магчыма прызначыць яму **любое** значэнне. Аднак, прызначэнне +прымітываў будузе праігнараваным. + + function Foo() {} + Foo.prototype = 1; // без эфекту + +Прызначэнне аб'ектаў, як паказана ў прыкладзе вышэй, будзе працаваць, і дазволіць +дынамічна ствараць ланцужкі прататыпаў. + +### Хуткасць выканання + +Пошук уласцівасцяў, якія знаходзяцца высока ў ланцужку прататыпаў, можа +негатыўна адбіцца на хуткасці выканання, і гэта можа быць прыкметным у кодзе, у якім +чыннік хуткасці крытычны. У выпадку спробы доступа да неіснуючых уласцівасцяў +будзе пройдзены ўвесь ланцужок прататыпаў. + +У дадатак, пры [ітэрацыі](#object.forinloop) па ўласцівасцях аб'екта +**кожная** уласціваць, што ёсць у ланцужку прататыпаў будзе апрацавана. + +### Расшырэнне ўбудаваных прататыпаў + +Адна з дрэнных магчымасцяў, што сустракаецца даволі часта — расшырэнне прататыпа +`Object.prototype` або аднаго з іншых убудаваных тыпаў. + +Такая практыка называецца [monkey patching][1] і парушае *інкапсуляцыю*. Хаця +папулярныя фрэймворкі, такія як [Prototype][2] шырока выкарыстоўваюць гэтую +мачымасць, няма добрых матываў для нагрувашчвання ўбудаваных тыпаў дадатковай +*нестандартнай* функцыянальнасцю. + +**Адзіным** добрым матывам расшырэння убудаваных прататыпаў — гэта дадаванне функцыянала, +што з'явіўся у новых рухавіках JavaScript; напрыклад, [`Array.forEach`][3]. + +### У завяршэнне + +**Вельмі важна** разумець, як працуе мадэль прататыпнага спадкаемства да таго, як +пісаць код, які яе выкарыстоўвае. Таксама сачыце за даўжынёй ланцужка прататыпаў +і драбіце іх, калі ёсць магчымасць, каб пазбегнуць праблем з прадукцыйнасцю. +Таксама ўбудаваныя прататыпы **ніколі** не павінны расшырацца, акрамя як для +таго, каб падтрымаць новыя магчымасці JavaScript. + +[1]: http://en.wikipedia.org/wiki/Monkey_patch +[2]: http://prototypejs.org/ +[3]: https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/forEach diff --git a/doc/by/other/timeouts.md b/doc/by/other/timeouts.md new file mode 100644 index 00000000..1ed49dc4 --- /dev/null +++ b/doc/by/other/timeouts.md @@ -0,0 +1,168 @@ +### `setTimeout` і `setInterval` + +Дзякуючы асінхроннасці JavaScript магчыма запланаваць выкананне функцыі з дапамогай +метадаў `setTimeout` і `setInterval`. + +> **Заўвага:** Таймаўты **не** з'яўляюцца часткай стандарта ECMAScript. Яны былі +> распрацаваны ў [BOM, ці DOM Узровень 0][1], якія ніколі не былі аб'яўлены ці +> задакументаваны фармальна. Да гэтага часу няма рэкамендацыйных спецыфікацый, +> аднак, у дадзены момант яны стандартызаваны ў [HTML5][2]. У сувязі з гэтым +> рэалізацыя можа адрознівацца ў залежнасці ад браўзера і рухавіка + + function foo() {} + var id = setTimeout(foo, 1000); // вяртае Number > 0 + +Калі функцыя `setTimeout` выклікана, яна вяртае ID таймаўта і плануе выкананне +`foo` **прыблізна** праз тысячу мілісекунд. +`foo` будзе выканана **аднойчы**. + +Улічваючы вырашэнні таймера рухавіка Javascript, які выконвае код, +аднапаточнасць JavaScript і тое, што іншы код, які выконваецца +можа блакаваць паток, **нельга** быць упэўненым, што вы атрымаеце затрымку, +пазначанаю ў выкліку `setTimeout`. + +Функцыя, якая была перададзена як першы параметр, будзе выклікана +*глабальным аб'ектам*, гэта азначае, што [`this`](#function.this) унутры выкліканай функцыі +спасылаецца на глабальны аб'ект. + + function Foo() { + this.value = 42; + this.method = function() { + // this спасылаецца на глабальны аб'ект + console.log(this.value); // выведзе undefined + }; + setTimeout(this.method, 500); + } + new Foo(); + + +> **Заўвага:** Так як `setTimeout` прымае **функцыю** як першы параметр, +> распаўсюджанай з'яўляецца памылка выкарыстоўвання `setTimeout(foo(), 1000)`, у гэтым выпадку +> будзе выкарыстоўвацца **вернутае значэнне** выкліка `foo`, а **не** `foo`. Гэта, у большасці выпадкаў, +> маўклівая памылка, так як калі функцыя вяртае `undefined`, `setTimeout` +> **не** выклікае памылкі. + +### Паслядоўныя выклікі з дапамогай `setInterval` + +У той час калі `setTimeout` выконвае функцыю толькі адзін раз, `setInterval` - як бачна з назвы - +выконвае функцыю **кожныя** `X` milliseconds, але яе выкарыстанне не пажадана. + +Код, які выконваецца, блакуе выклік з таймаўтам, у той час `setInterval` будзе +планаваць выклікі зададзенай функцыі. Гэта можа, асабліва з маленькімі інтэрваламі, +прывесці да стварэння чаргі выклікаў функцый. + + function foo(){ + // нешта, што блакуе на 1 секунду + } + setInterval(foo, 100); + +У прыведзеным кодзе `foo` будзе выклікана аднойчы і заблакуе выкананне на адну секунду. + +У той час калі `foo` блакуе код, `setInterval` будзе планаваць наступныя яе выклікі +А калі выкананне `foo` скончана, ужо **дзесяць** наступных выклікаў будуць чакаць выканання. + +### Праца з магчыма блакуючым кодам + +Найбольш простае і кіруемае рашэнне гэта выкарыстоўваць `setTimeout` унутры самой функцыі. + + function foo(){ + // нешта, што блакуе на 1 секунду + setTimeout(foo, 100); + } + foo(); + +Гэты падыход не толькі інкапсулюе выклік `setTimeout`, але таксама прадухіляе +стварэнне чаргі выклікаў і дае дадатковы кантроль. Цяпер `foo` можа сама вырашыць +хоча яна выконвацца яшчэ раз ці не. + +### Ручная чыстка таймаўтаў + +Чыстка таймаўтаў і інтэрвалаў здзяйсняецца перадачай адпаведнага ID у +`clearTimeout` або `clearInterval`, гледзячы якая `set` функцыя была выкарыстана +да гэтага. + + var id = setTimeout(foo, 1000); + clearTimeout(id); + +### Чыстка ўсіх таймаўтаў + +Так як няма ўбудаванага метада для выдалення ўсіх таймаўтаў і/або інтэрвалаў, +для гэтага неабходна выкарыстоўваць брутфорс. + + // выдаліць "усе" таймаўты + for(var i = 1; i < 1000; i++) { + clearTimeout(i); + } + +Але могуць быць таймаўты, якія не закрануты гэтым адвольным нумарам. +Іншы шлях ажыццяўлення гэтага - прыняць, што ID таймаўта павялічваецца на +адзін пасля кожнага выкліку `setTimeout`. + + // выдаліць "усе" таймаўты + var biggestTimeoutId = window.setTimeout(function(){}, 1), + i; + for(i = 1; i <= biggestTimeoutId; i++) { + clearTimeout(i); + } + +Не гледзячы на тое, што зараз гэта працуе на ўсіх асноўных браўзерах, тое, што ID +павінны быць арганізаваны такім шляхам не пазначана ў спецыфікацыі і можа змяніцца. Таму +замест гэтага рэкамендуецца сачыць за ўсімі ID таймаўтаў, каб яны маглі быць выдалены паасобку. + +### Схаванае выкарыстанне `eval` + +`setTimeout` і `setInterval` таксама могуць прымаць радок у якасці першага параметра. +Гэту магчымасць **ніколі** не трэба выкарыстоўваць, бо ўнутрана вызываецца `eval`. + +> **Заўвага:** Дакладны механізм работы пры перадачы радка можа адрозніваецца ў +> розных JavaScript рэалізацыях. Напрыклад, JScript ад Microsoft выкарыстоўвае +> канструктар `Function` замест `eval`. + + function foo() { + // будзе выклікана + } + + function bar() { + function foo() { + // ніколі не будзе выклікана + } + setTimeout('foo()', 1000); + } + bar(); + +Паколькі `eval` не выклікана [напрамую](#core.eval), радок, які перададзены +`setTimeout` будзе выкананы ў *глабальным скоўпе*; такім чынам, не будзе выкарыстана +лакальная пераменная `foo` са скоўпа `bar`. + +Адсюль вынікае рэкамендацыя **не** выкарыстоўваць радок для перадачы аргументаў у +функцыю, якая будзе вызывацца адной з таймаўт функцый. + + function foo(a, b, c) {} + + // НІКОЛІ так не рабіце + setTimeout('foo(1, 2, 3)', 1000) + + // Замест выкарыстоўвайце ананімныя функцыі + setTimeout(function() { + foo(1, 2, 3); + }, 1000) + +> **Заўвага:** Нягледзячы на тое, што сінтаксіс `setTimeout(foo, 1000, 1, 2, 3)` можна выкарыстоўваць, +> гэта не рэкамендуецца, так як можа прывесці да +> непрыкметных памылак пры выкарыстанні з [метадамі](#function.this). +> Больш таго, сінтаксіс можа не працаваць у некаторых рэалізацыях JavaScript. +> Напрыклад, Internet Explorer ад Microsoft [**не** перадае аргументы напрамую зваротнаму выкліку](3). + +### У заключэнне + +Радок **ніколі** не павінен быць выкарыстаны як параметр `setTimeout` ці +`setInterval`. Відавочны знак **сапраўды** благога кода гэта калі функцыя, якая будзе выклікана, +патрабуе аргументы. Трэба перадаваць *ананімную функцыю*, якая будзе адказваць за +выклік патрэбнай функцыі. + +Больш таго, трэба пазбягаць выкарыстання `setInterval`, таму што яе планавальнік не блакуецца +выкананнем JavaScript. + +[1]: http://www.nczonline.net/blog/2009/09/29/web-definitions-dom-ajax-and-more/ "Web definitions: DOM, Ajax, and more" +[2]: http://www.w3.org/TR/2014/WD-html5-20140617/webappapis.html#timers "6 Web application APIs - HTML5" +[3]: http://msdn.microsoft.com/en-us/library/ie/ms536753(v=vs.85).aspx "setTimeout method (Internet Explorer)" diff --git a/doc/by/types/casting.md b/doc/by/types/casting.md new file mode 100644 index 00000000..763bf3a1 --- /dev/null +++ b/doc/by/types/casting.md @@ -0,0 +1,71 @@ +## Прывядзенне тыпаў + +JavaScript - *слаба тыпізаваная* мова, таму *прывядзенне тыпаў* адбываецца +**паўсюль** дзе магчыма. + + // Гэтыя равенствы - праўдзівыя + new Number(10) == 10; // аб'ект тыпа Number пераўтвараецца у + // лікавы прымітыў, праз няяўны выклік + // метада Number.prototype.valueOf + + 10 == '10'; // Strings пераўтвараецца ў Number + 10 == '+10 '; // Троху вар'яцтва з радкамі + 10 == '010'; // і яшчэ + isNaN(null) == false; // null пераўтвараецца ў 0 + // які вядома ж не NaN + + // Гэтыя равенствы - ілжывыя + 10 == 010; + 10 == '-10'; + +> **Заўвага для ES5:** Лічбавыя літэралы, што пачынаюцца з `0` інтэрпрэтуюцца як +> васьмірычныя (Base 8). Падтрымка васьмірычнай сістэмы была **прыбраная** у +> ECMAScript 5 strict mode. + +Каб пазбегнуць вышэйпрыведзеных праблемаў, **настойліва** ракамендуецца выкарыстоўваць +[аператар строгай роўнасці](#types.equality). Зрэшты, хоць гэта і пазбаўляе ад +многіх распаўсюджаных праблемаў, існуе яшчэ шмат праблемаў, які ўзнікаюць праз +слабую тыпізацыю JavaScript. + +### Канструктары ўбудаваных тыпаў + +Канструктары ўбудаваных тыпаў, напрыклад, `Number` і `String` паводзяць сябе +па рознаму, у залежнасці ад таго, выклікаюцца яны з ключавым словам `new` або без яго. + + new Number(10) === 10; // False, Object і Number + Number(10) === 10; // True, Number і Number + new Number(10) + 0 === 10; // True, праз неяўнае прывядзенне + +Выкарыстанне ўбудаванага тыпу, такога як `Number` у якасці канструкта створыць новы +экзэмпляр аб'екта `Number`, але пры адсутнасці ключавога слова `new` функцыя +`Number` будзе паводзіць сябе як канвертар. + +У дадатак, выкарытоўванне літэралаў, або значэнняў якія не з'яўляюцца аб'ектамі +прывядзе да дадатковых прывядзенняў тыпаў. + +Лепшы варыянт - гэта **яўнае** прывядзенне да аднаго з трох магчымых тыпаў. + +### Прывядзенне да радка + + '' + 10 === '10'; // true + +Праз даданне да значэння пустога радка, яно лёгка прыводзіцца да радка. + +### Прывядзенне да лікавага тыпу + + +'10' === 10; // true + +Выкарыстоўваючы **унарны** аператар плюс, магчыма пераўтварыць значэнне ў нумар. + +### Прывядзенне да булевага тыпу + +Выкарыстоўваючы аператар **адмаўленне (!)** двойчы, значэнне можна прыведзена +да лагічнага (булевага) тыпу. + + !!'foo'; // true + !!''; // false + !!'0'; // true + !!'1'; // true + !!'-1' // true + !!{}; // true + !!true; // true diff --git a/doc/by/types/equality.md b/doc/by/types/equality.md new file mode 100644 index 00000000..0859ce03 --- /dev/null +++ b/doc/by/types/equality.md @@ -0,0 +1,70 @@ +## Роўнасць і параўнанне + +У JavaScript роўнасць значэнняў аб'ектаў можна вызначыць двумя спосабамі. + +### Аператар роўнасці + +Аператар роўнасці складаецца з двух сімвалаў 'роўна': `==` + +JavaScript мае *слабую тыпізацыю*. Гэта значыць што аператар роўнасці +**прыводзіць** тыпы аб'ектаў, каб параўнаць іх. + + "" == "0" // false + 0 == "" // true + 0 == "0" // true + false == "false" // false + false == "0" // true + false == undefined // false + false == null // false + null == undefined // true + " \t\r\n" == 0 // true + +Вышэй прыведзеная табліца паказвае вынікі прывядзення тыпаў, і гэта галоўная прычына +па якой выкаростоўванне `==` лічыцца дрэннай практыкай. Яно прыводзіць да памылак +якія цяжка адсачыць праз складаны механізм прывядзення тыпаў. + +Акрамя гэтага, прывядзенне тыпаў таксама ўплывае на вытворчасць; +напрыклад, радок мае быць ператвораны ў нумар, перад тым як быць параўнаным з +іншым нумарам. + +### Аператар строгай роўнасці + +Аператар строгай роўнасці складаецца з **трох** сімвалаў 'роўна': `===`. + +Ён дзейнічае як звычайны аператар роўнасці, за выключэннем таго, што строгая +роўнасць **не** прыводзіць аперанды да агульнага тыпу. + + "" === "0" // false + 0 === "" // false + 0 === "0" // false + false === "false" // false + false === "0" // false + false === undefined // false + false === null // false + null === undefined // false + " \t\r\n" === 0 // false + +Вышэй прыведзеныя вынікі значна больш зразумелыя і даюць магчымасць хутчэй выявіць +памылкі ў кодзе. Гэта паляпшае код, а таксама дае прырост вытворчасці, у выпадку +калі аперанды розных тыпаў. + +### Параўнанне аб'ектаў + +Хоць абодва аператар `==` і `===` называюцца аператарамі **роўнасці**, яны паводзяць +сабе па рознаму калі хоць адзін аперанд тыпа `Object`. + + {} === {}; // false + new String('foo') === 'foo'; // false + new Number(10) === 10; // false + var foo = {}; + foo === foo; // true + +Тут абодва аператанда параўноўваюцца на **ідэнтычнасць**, а **не** на роўнасць; +то бок будзе праверана, ці з'яўляюцца яны адным **экзэмплярам** аб'екта. Гэтак жа, +як `is` у Python, або параўнанне ўказальнікаў у C. + +### У заключэнне + +Настойліва рэкамендуецца выкарыстоўваць толькі аператар **строгай роўнасці**. +У выпадку, калі тыпы маюць быць прыведзеныя, гэта варта рабіць [яўна](#types.casting), +а не пакідаць іх на сумленні складаных правілаў прывядзення мовы праграмавання. diff --git a/doc/by/types/instanceof.md b/doc/by/types/instanceof.md new file mode 100644 index 00000000..220bc3c3 --- /dev/null +++ b/doc/by/types/instanceof.md @@ -0,0 +1,37 @@ +## Аператар `instanceof` + +Аператар `instanceof` параўноўвае канструктары двух аперандаў. Гэта карысна толькі +для параўнання аб'ектаў не ўбудаваных тыпаў. Выкарыстоўванне на ўбудаваных тыпах не +мае сэнсу, як і [аператар typeof](#types.typeof). + +### Параўнанне адвольных аб'ектаў + + function Foo() {} + function Bar() {} + Bar.prototype = new Foo(); + + new Bar() instanceof Bar; // true + new Bar() instanceof Foo; // true + + // Калі толькі прысвоім Bar.prototype аб'ект функцыі Foo, + // але не самаго экзэмпляра Foo + Bar.prototype = Foo; + new Bar() instanceof Foo; // false + +### Выкарыстоўванне `instanceof` з убудаванымі тыпамі + + new String('foo') instanceof String; // true + new String('foo') instanceof Object; // true + + 'foo' instanceof String; // false + 'foo' instanceof Object; // false + +Варта адзначыць, што `instanceof` не працуе на аб'ектах, якія паходзяць з розных +кантэкстаў JavaScript (напрыклад, розных дакументаў у web-браузеры), бо іх канструктары +насамрэч не будуць канструктарамі тых самых аб'ектаў. + +### У заключэнне + +Аператар `instanceof` мае быць выкарыстаны **толькі** для працы з аб'ектамі не +ўбудаваных тыпаў якія паходзяць з аднаго кантэкста JavaScript. Як і ў выпадку з +[аператарам `typeof`](#types.typeof), трэба **пазбягаць** любога іншага яго выкарыстання. diff --git a/doc/by/types/typeof.md b/doc/by/types/typeof.md new file mode 100644 index 00000000..7fb16ba9 --- /dev/null +++ b/doc/by/types/typeof.md @@ -0,0 +1,80 @@ +## Аператар `typeof` + +Аператар `typeof` (разам з [`instanceof`](#types.instanceof)) магчыма найбольшая +хіба мовы JavaScript, таму што ён амаль што **цалкам зламаны**. + +Хаця `instanceof` усё яшчэ мае абмежаванае ўжыванне, `typeof` можа быць выкарыстаны +толькі з адной мэтай, і гэта дарэчы **не** праверка тыпа. + +> **Заўвага:** Хаця для выкліка `typeof` можна выкарыстаць сінтаксіс функцыі, то бок +> `typeof(obj)`, гэта не выклік функцыі. Дужкі будуць апрацоўвацца нармальна +> і вернутае значэнне будзе выкарыстана як аперанд аператара `typeof`. +> **Не існуе** функцыі `typeof`. + +### Табліца тыпаў JavaScript + + Значэнне Клас Тып + ------------------------------------- + "foo" String string + new String("foo") String object + 1.2 Number number + new Number(1.2) Number object + true Boolean boolean + new Boolean(true) Boolean object + new Date() Date object + new Error() Error object + [1,2,3] Array object + new Array(1, 2, 3) Array object + new Function("") Function function + /abc/g RegExp object (function in Nitro/V8) + new RegExp("meow") RegExp object (function in Nitro/V8) + {} Object object + new Object() Object object + +У вышэй прыведзенай табыліцы, *Тып* паказвае значэнне вернутае аператарам `typeof`. +Як можна пабачыць, гэта значэнне абсалютна не кансістэнтнае. + +*Клас* паказвае значэнне ўнутраннай уласцівасці `[[Class]]` аб'екта. + +> **З спецыфікацыі:** значэнне `[[Class]]` можа быць быць адным з наступных +> радкоў. `Arguments`, `Array`, `Boolean`, `Date`, `Error`, +> `Function`, `JSON`, `Math`, `Number`, `Object`, `RegExp`, `String`. + +### Клас аб'екта + +Адзіны спосаб атрымаць значэнне `[[Class]]` аб'екта - выклікаць метад `Object.prototype.toString`. +Ён верне радок у наступным фармаце: `'[object ' + valueOfClass + ']'`, напрыклад +`[object String]` або `[object Array]`: + + function is(type, obj) { + var clas = Object.prototype.toString.call(obj).slice(8, -1); + return obj !== undefined && obj !== null && clas === type; + } + + is('String', 'test'); // true + is('String', new String('test')); // true + +У вышэйпрыведзеным прыкладзе, `Object.prototype.toString` выклікаецца са значэннем +[this](#function.this) пазначаным як аб'ект чыё значэнне `[[Class]]` мае быць +атрыманым. + +> **Заўвага для ES5:** у ECMAScript 5, для зручнасці, значэнне `Object.prototype.toString` +> для `null` і `undefined` было **зменена** з `Object` на `Null` і +> `Undefined` адпаведна. + +### Праверка вызначанасці пераменных + + typeof foo !== 'undefined' + +Вышэйпрыведзены код праверыць ці было вызначана `foo`; просты зварот да пераменнай +прывядзе да `ReferenceError`. Гэта адзінае для чаго карысны `typeof`. + +### У заключэнне + +Каб праверыць тып аб'екта, настойліва рэкамендуецца выкарыстоўваць +`Object.prototype.toString` - гэта адзіны надзейны спосаб. +Як паказана ў вышэйпрыведзенай табліцы, некаторыя значэнні вернутыя аператарам +`typeof` не вызначаныя ў спецыфікацыі; такім чынам, яны могуць быць рознымі ў +розных рэалізацыях. + +Акрамя як для праверкі вызначанасці пераменнай, `typeof` мае быць пазбегнуты. diff --git a/doc/language.json b/doc/language.json index af707fb6..df12ab7d 100644 --- a/doc/language.json +++ b/doc/language.json @@ -1,4 +1,4 @@ { "default": "en", - "listed": ["en","es","fi","fr","hu","it","ja","ko","pl","ptbr","ru","tr","zh","zhtw"] -} + "listed": ["by","en","es","fi","fr","hu","it","ja","ko","pl","ptbr","ru","tr","zh","zhtw"] +} From 746a2ea8fc111bbd5a94653675248a3fb4651b50 Mon Sep 17 00:00:00 2001 From: Fenix Su Date: Wed, 30 Sep 2015 13:12:41 -0700 Subject: [PATCH 056/105] Changed a translatation sentence The original translation is improper. It is more like the translation of the following sentence: "It is fairly trivival to build a classic inheritance model, but not so trivival to build a JavaScript prototype inheritance model." My translation would be an improvement. --- doc/zh/object/prototype.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/zh/object/prototype.md b/doc/zh/object/prototype.md index 0d0079c4..dff5cdbd 100755 --- a/doc/zh/object/prototype.md +++ b/doc/zh/object/prototype.md @@ -3,7 +3,7 @@ JavaScript 不包含传统的类继承模型,而是使用 *prototype* 原型模型。 虽然这经常被当作是 JavaScript 的缺点被提及,其实基于原型的继承模型比传统的类继承还要强大。 -实现传统的类继承模型是很简单,但是实现 JavaScript 中的原型继承则要困难的多。 +例如,很容易通过原型继承实现传统的类继承模型,但是反过来,通过传统的类继承模型来实现原型继承模型就困难得多。 (It is for example fairly trivial to build a classic model on top of it, while the other way around is a far more difficult task.) From 8d4b8cbc81491ecd2c40e9cdbb2c278870f43d10 Mon Sep 17 00:00:00 2001 From: Timothy Lee Date: Wed, 14 Oct 2015 02:02:02 +0800 Subject: [PATCH 057/105] modified some sentences and fixed typo --- doc/zhtw/core/eval.md | 2 +- doc/zhtw/function/general.md | 8 ++++---- doc/zhtw/function/this.md | 6 +++--- doc/zhtw/object/forinloop.md | 6 +++--- doc/zhtw/object/hasownproperty.md | 4 ++-- doc/zhtw/object/prototype.md | 4 ++-- 6 files changed, 15 insertions(+), 15 deletions(-) diff --git a/doc/zhtw/core/eval.md b/doc/zhtw/core/eval.md index fb9e36bb..26b7d332 100644 --- a/doc/zhtw/core/eval.md +++ b/doc/zhtw/core/eval.md @@ -32,7 +32,7 @@ ### 安全上的顧慮 `eval` 同樣有安全上的問題,因為所有的程式碼都可以被直接執行。 -而他不應去執行一串未知的字串或是來自不幸任的來源。 +而他不應去執行一串未知的字串或是來自不信任的來源。 ### 結語 diff --git a/doc/zhtw/function/general.md b/doc/zhtw/function/general.md index 84a2bb3c..fe400880 100644 --- a/doc/zhtw/function/general.md +++ b/doc/zhtw/function/general.md @@ -25,19 +25,19 @@ 由於 `var` 已經宣告變數 `foo` 在所有的程式碼執行之前。 所以 `foo`已經在程式運行前就已經被定義過了。 -但是因為賦值只會在運行時去職情,所以在程式碼執行前,`foo` 的值還沒被宣告所以為 [undefined](#core.undefined)。 +但是因為賦值只會在運行時去執行,所以在程式碼執行前,`foo` 的值還沒被宣告所以為 [undefined](#core.undefined)。 ### 命名函式的賦值表達式 -另一個特殊狀況就勢將一個命名函式賦值給一個變數。 +另一個特殊狀況是將一個命名函式賦值給一個變數。 var foo = function bar() { bar(); // 可以運行 } bar(); // 錯誤:ReferenceError -`bar` 不可以在外部的區域被執行,因為它只有在 `foo` 的函式內才可以去執行。 +`bar` 不可以在外部的區域被執行,因為它只有在 `foo` 的函式內才可以執行。 然而在 `bar` 內部還是可以看見。這是由於 JavaScript的 [命名處理](#function.scopes)所致。 -函式名在函式內 *都* 可以去使用。 +函式名在函式內 *都* 可以使用。 diff --git a/doc/zhtw/function/this.md b/doc/zhtw/function/this.md index d919c228..c5bf8d60 100644 --- a/doc/zhtw/function/this.md +++ b/doc/zhtw/function/this.md @@ -1,7 +1,7 @@ ## `this` 的工作原理 JavaScript 有移到完全部屬於其他語言處理 `this` 的處理機制。 -在 **五** 種物同的情況下, `this` 指向的個不相同 +在 **五** 種不同的情況下, `this` 指向的各不相同 ### 全域變數 @@ -14,12 +14,12 @@ JavaScript 有移到完全部屬於其他語言處理 `this` 的處理機制。 foo(); -這裡 `this` 也會指向 *全域* 對象。 +這裡 `this` 也會指向 *全域* 物件。 > **ES5 注意:** 在嚴格模式下,不存在全域變數。 > `this` 將會是 `undefined`。 -### 方法調用 +### 呼叫一個方法 test.foo(); diff --git a/doc/zhtw/object/forinloop.md b/doc/zhtw/object/forinloop.md index 67fa8915..06b248a6 100644 --- a/doc/zhtw/object/forinloop.md +++ b/doc/zhtw/object/forinloop.md @@ -27,10 +27,10 @@ } 這個版本的程式碼是唯一正確的寫法。由於我們使用了 `hasOwnProperty`,這次 **只** 輸出 `moo`。 -如果不只用這個程式碼在原型物件中(比如 `Object.prototype`)被擴展可能會出錯。 +如果不使用這個程式碼在原型物件中(比如 `Object.prototype`)被擴展可能會出錯。 -一個廣泛的模組 [Prototype][1]就礦展了圓型的 JavaScript 物件。 -因此,但這模組包含在頁面中時,不使用 `hasOwnProperty` 過濾的 `for in` 尋難免會出問題。 +一個廣泛使用的舊函式庫 [Prototype][1]就擴展了原型的 JavaScript 物件。 +因此,當這個函式庫包含在頁面中時,不使用 `hasOwnProperty` 過濾的 `for in` 迴圈難免會出問題。 ### 總結 diff --git a/doc/zhtw/object/hasownproperty.md b/doc/zhtw/object/hasownproperty.md index d35d49e2..5d8403b4 100644 --- a/doc/zhtw/object/hasownproperty.md +++ b/doc/zhtw/object/hasownproperty.md @@ -1,6 +1,6 @@ ## `hasOwnProperty` -為了判斷一個物件是否包含 *自定義* 屬性而 *不是* [原形](#object.prototype)上的屬性,我們需要使用繼承 `Object.prototype` 的 `hasOwnProperty` 方法。 +為了判斷一個物件是否包含 *自定義* 屬性而 *不是* [原型](#object.prototype)上的屬性,我們需要使用繼承 `Object.prototype` 的 `hasOwnProperty` 方法。 > **注意:** 判斷一個屬性是否 `undefined` 是 **不夠的**。 > 因為一個屬性可能存在,但是它的值被設成 `undefined`。 @@ -42,4 +42,4 @@ JavaScript **不會** 保護 `hasOwnProperty`被占用,因此如果碰到存 當檢查一個物件是否存在的時候, `hasOwnProperty` 是 **唯一** 可用的方法。 同時在使用 [`for in loop`](#object.forinloop) -建議使用 `hasOwnProperty` 避免 [原型](#object.prototype)所帶來的干擾。 \ No newline at end of file +建議使用 `hasOwnProperty` 避免 [原型](#object.prototype)所帶來的干擾。 diff --git a/doc/zhtw/object/prototype.md b/doc/zhtw/object/prototype.md index e861a1ab..d4df339f 100644 --- a/doc/zhtw/object/prototype.md +++ b/doc/zhtw/object/prototype.md @@ -72,14 +72,14 @@ JavaScript 不包含傳統繼承的模型,它使用的是*原型*模型。 一個經常發生的錯誤,那就是擴展 `Object.prototype` 或者是其他內建類型的原型物件。 -這種技術叫做 [monkey patching][1] 並且會破壞 *封裝*。雖然被廣泛的應用到一些 Javascript 的架構,像是 [Prototype](http://prototypejs.org) , 但仍然沒有好的理由新增一個 *非標準* 的功能去搞亂內建型別 +這種技術叫做 [monkey patching][1] 並且會破壞 *封裝*。雖然被廣泛的應用到一些 Javascript 的架構,像是 [Prototype](http://prototypejs.org) , 但仍然沒有好的理由新增一個 *非標準* 的功能去搞亂內建型別。 擴展內置類型的 **唯一** 理由是為了和新的 JavaScript 保持一致,比如說 [`Array.forEach`][3] ### 總結 在寫複雜的程式碼的時候,要 **充分理解** 所有程式繼承的屬性還有原型鏈。 -還要堤防原型鏈過長帶來的性能問題,並知道如何通過縮短原型鏈來提高性能。 +還要提防原型鏈過長帶來的性能問題,並知道如何通過縮短原型鏈來提高性能。 絕對 **不要使用** `native prototype` 除非是為了和新的 JavaScript 引擎作兼容。 [1]: http://en.wikipedia.org/wiki/Monkey_patch From f356598bc0e4a842ada5a3b586119bcfb173e111 Mon Sep 17 00:00:00 2001 From: Thomas Gratier Date: Wed, 21 Oct 2015 16:43:56 +0200 Subject: [PATCH 058/105] Unify comment and code concerning setTimeout value The unit is millisecond in setTimeout first arg but in both corrected comments, it was mentioned 1 second whereas value was 100 --- doc/en/other/timeouts.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/en/other/timeouts.md b/doc/en/other/timeouts.md index 8fe66d81..e27ccacf 100644 --- a/doc/en/other/timeouts.md +++ b/doc/en/other/timeouts.md @@ -55,7 +55,7 @@ intervals, result in function calls stacking up. function foo(){ // something that blocks for 1 second } - setInterval(foo, 100); + setInterval(foo, 1000); In the above code, `foo` will get called once and will then block for one second. @@ -70,7 +70,7 @@ the function itself. function foo(){ // something that blocks for 1 second - setTimeout(foo, 100); + setTimeout(foo, 1000); } foo(); From 967cbeb0b8addab0b2c68e88fe1ea0e81f8431e1 Mon Sep 17 00:00:00 2001 From: andrepolischuk Date: Tue, 27 Oct 2015 17:01:53 +0300 Subject: [PATCH 059/105] Fix typo and inline code quotes --- CONTRIBUTING.md | 2 +- doc/ru/object/hasownproperty.md | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 20faf510..fe3c6b6f 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -9,7 +9,7 @@ Thank you for being kind enough to help out! ## Testing locally -1. Run `npm run build.js` to build +1. Run `npm run build` to build 1. Run a webserver from the root of the repo to view ## Getting changes merged diff --git a/doc/ru/object/hasownproperty.md b/doc/ru/object/hasownproperty.md index d46d7f10..89b950ca 100644 --- a/doc/ru/object/hasownproperty.md +++ b/doc/ru/object/hasownproperty.md @@ -16,7 +16,7 @@ foo.hasOwnProperty('bar'); // false foo.hasOwnProperty('goo'); // true -Только используя `hasOwnProperty` можно гарантировать правильный результат при переборе свойств объекта. И **нет** иного способа для определения свойств, которые определены в *самом* объекте, а не где-то в цепочке его прототипов. +Только используя `hasOwnProperty` можно гарантировать правильный результат при переборе свойств объекта. И **нет** иного способа для определения свойств, которые определены в *самом* объекте, а не где-то в цепочке его прототипов. ### `hasOwnProperty` как свойство @@ -38,4 +38,3 @@ JavaScript **не** резервирует свойство с именем `has ### Заключение **Единственным** способом проверить существование свойства у объекта является использование метода `hasOwnProperty`. При этом рекомендуется использовать этот метод в **каждом** [цикле `for in`](#object.forinloop) вашего проекта, чтобы избежать возможных ошибок с ошибочным заимствованием свойств из [прототипов](#object.prototype) родительских объектов. Также вы можете использовать конструкцию `{}.hasOwnProperty.call(...)` на случай, если кто-то вздумает расширить [прототипы](#object.prototype) встроенных объектов. - From 868a2dc16bef2fc00554fa024ab272b46c8c0087 Mon Sep 17 00:00:00 2001 From: Rocco Musolino Date: Wed, 4 Nov 2015 16:28:17 +0100 Subject: [PATCH 060/105] typos corrected --- doc/it/function/constructors.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/it/function/constructors.md b/doc/it/function/constructors.md index 45983b2c..61099937 100644 --- a/doc/it/function/constructors.md +++ b/doc/it/function/constructors.md @@ -41,7 +41,7 @@ specificato da quell'istruzione, ma **solo** se il valore di ritorno è un name: 'Charles' }; } - new Test(); // l'oggetto ritornato ({name: 'Charles'}), escluso someValue + new Person(); // l'oggetto ritornato ({name: 'Charles'}), escluso someValue Quando la parola chiave `new` viene omessa, la funzione **non** ritornerà un nuovo oggetto. From cbcf7f772945aadee3e316e703712f89ec229b61 Mon Sep 17 00:00:00 2001 From: Rocco Musolino Date: Wed, 4 Nov 2015 16:30:18 +0100 Subject: [PATCH 061/105] fix typo --- doc/it/function/constructors.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/it/function/constructors.md b/doc/it/function/constructors.md index 61099937..1273e87c 100644 --- a/doc/it/function/constructors.md +++ b/doc/it/function/constructors.md @@ -116,7 +116,7 @@ esso ha alcuni aspetti negativi. 1. Usa più memoria dal momento che gli oggetti creati **non** condividono i metodi di un prototipo. 2. Per poter ereditare, la factory deve copiare tutti i metodi da un altro - oggetto oppure mettere quell'oggetto nel proptotipo del nuovo oggetto. + oggetto oppure mettere quell'oggetto nel prototipo del nuovo oggetto. 3. Perdere la catena di prototipi solo perché si vuole tralasciare la parola chiave `new` è contrario allo spirito del linguaggio. From e2b5b52498df061f680e25e5d74102473939acf5 Mon Sep 17 00:00:00 2001 From: Rocco Musolino Date: Wed, 4 Nov 2015 16:31:41 +0100 Subject: [PATCH 062/105] fix typo --- doc/it/function/scopes.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/it/function/scopes.md b/doc/it/function/scopes.md index 812e4fbd..24f6d250 100644 --- a/doc/it/function/scopes.md +++ b/doc/it/function/scopes.md @@ -127,7 +127,7 @@ vicino scope che le racchiude. // le istruzioni var vengono spostate qui var bar, someValue; // di default a 'undefined' - // la dichiarazione function viene spostate qui + // la dichiarazione function viene spostata qui function test(data) { var goo, i, e; // il blocco scope mancante sposta qui queste istruzioni if (false) { From 9ac7d337624bc09df045e44bd8644c70fd7a104e Mon Sep 17 00:00:00 2001 From: Rocco Musolino Date: Wed, 4 Nov 2015 16:37:01 +0100 Subject: [PATCH 063/105] fix typo --- doc/it/function/general.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/it/function/general.md b/doc/it/function/general.md index f78ef846..9181ad88 100644 --- a/doc/it/function/general.md +++ b/doc/it/function/general.md @@ -3,7 +3,7 @@ Le funzioni in JavaScript sono oggetti di prima classe. Ciò significa che possono essere usate come ogni altro valore. Un uso comune di questa caratteristica è quello di passare una *funzione anonima* come funzione di -callback ad un'altra, possibilmente asincrona, funzione. +callback ad un'altra funzione, possibilmente asincrona. ### La dichiarazione di `function` From 6b22f631b6a0378b76b0782eebe385d47826c27c Mon Sep 17 00:00:00 2001 From: Rocco Musolino Date: Sat, 21 Nov 2015 17:52:55 +0100 Subject: [PATCH 064/105] typo fix --- doc/it/types/instanceof.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/it/types/instanceof.md b/doc/it/types/instanceof.md index 04ba1e93..8ff454f4 100644 --- a/doc/it/types/instanceof.md +++ b/doc/it/types/instanceof.md @@ -34,7 +34,7 @@ esattamente lo stesso oggetto. ### In conclusione -L'operatore `instanceof` dovrebbe essere usto **solo** quando si ha a che fare +L'operatore `instanceof` dovrebbe essere usato **solo** quando si ha a che fare con oggetti personalizzati creati dal programmatore, che provengono dallo stesso contesto JavaScript. Proprio come per l'operatore [`typeof`](#types.typeof), ogni altro tipo di utilizzo dovrebbe essere **evitato**. From 1ff1ce7aedb927aa7e5a295142937ae9319ef00f Mon Sep 17 00:00:00 2001 From: Rocco Musolino Date: Sat, 21 Nov 2015 17:55:30 +0100 Subject: [PATCH 065/105] typo fix --- doc/it/types/casting.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/it/types/casting.md b/doc/it/types/casting.md index 743ee317..5da767f0 100644 --- a/doc/it/types/casting.md +++ b/doc/it/types/casting.md @@ -25,7 +25,7 @@ una *conversione di tipo* **ovunque** sia possibile. Per evitare i problemi appena visti, l'uso dell'[operatore di uguaglianza stretta](#types.equality) è **altamente** raccomandato. Sebbene questo eviti molti dei comuni problemi, ci sono ancora -molti ulteriori problemi che possono essere generati dal sistema debolemente +molti ulteriori problemi che possono essere generati dal sistema debolmente tipizzato di JavaScript. ### Costruttori di tipi interni From e471c8db77fc877467041ccc59299b5fd06246ee Mon Sep 17 00:00:00 2001 From: Doug Shamoo Date: Thu, 10 Dec 2015 14:05:56 -0800 Subject: [PATCH 066/105] Update general.md change wording to be more clear --- doc/en/object/general.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/en/object/general.md b/doc/en/object/general.md index 9300b18e..5ee2e0de 100644 --- a/doc/en/object/general.md +++ b/doc/en/object/general.md @@ -20,7 +20,7 @@ There are a couple of workarounds that can be used to make number literals act as objects too. 2..toString(); // the second point is correctly recognized - 2 .toString(); // note the space left to the dot + 2 .toString(); // note the space left of the dot (2).toString(); // 2 is evaluated first ### Objects as a Data Type From 1688ab5985dc672467328ff776d6d63a0db24dd6 Mon Sep 17 00:00:00 2001 From: Nikita Liashenko Date: Tue, 15 Dec 2015 15:53:50 +0200 Subject: [PATCH 067/105] Changing comment about throwing Syntax Error if there is no quotes in object property name --- doc/ru/object/general.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/ru/object/general.md b/doc/ru/object/general.md index 9490570f..aa5ad534 100644 --- a/doc/ru/object/general.md +++ b/doc/ru/object/general.md @@ -73,7 +73,7 @@ var test = { 'case': 'Я — ключевое слово, поэтому меня надо записывать строкой', - delete: 'Я тоже ключевое слово, так что я' // бросаю SyntaxError + delete: 'Я тоже ключевое слово, так что я' // не является ошибкой, бросает SyntaxError только в версиях ECMAScript ниже 5ой версии }; Свойства объектов могут записываться как явно символами, так и в виде закавыченных строк. В связи с другим упущением в парсере JavaScript, этот код выбросит `SyntaxError` во всех версиях ранее ECMAScript 5. From bc00418a7d3db3eab7bb42878c1d00bca748175c Mon Sep 17 00:00:00 2001 From: Murtaza Haveliwala Date: Wed, 16 Dec 2015 14:22:37 +0530 Subject: [PATCH 068/105] Updated prototype sample output --- doc/by/object/prototype.md | 2 +- doc/en/object/prototype.md | 2 +- doc/es/object/prototype.md | 2 +- doc/fi/object/prototype.md | 2 +- doc/fr/object/prototype.md | 2 +- doc/hu/object/prototype.md | 2 +- doc/it/object/prototype.md | 2 +- doc/ja/object/prototype.md | 2 +- doc/ko/object/prototype.md | 2 +- doc/pl/object/prototype.md | 2 +- doc/ptbr/object/prototype.md | 2 +- doc/ru/object/prototype.md | 2 +- doc/tr/object/prototype.md | 2 +- doc/zh/object/prototype.md | 2 +- doc/zhtw/object/prototype.md | 2 +- 15 files changed, 15 insertions(+), 15 deletions(-) diff --git a/doc/by/object/prototype.md b/doc/by/object/prototype.md index f5f8c985..ec80e801 100644 --- a/doc/by/object/prototype.md +++ b/doc/by/object/prototype.md @@ -40,7 +40,7 @@ JavaScript гэта адзіная шырока выкарыстоўваемая // Выніковы ланцужок прататыпаў test [instance of Bar] Bar.prototype [instance of Foo] - { foo: 'Hello World' } + { foo: 'Hello World', value: 42 } Foo.prototype { method: ... } Object.prototype diff --git a/doc/en/object/prototype.md b/doc/en/object/prototype.md index cb053526..f63abaa9 100644 --- a/doc/en/object/prototype.md +++ b/doc/en/object/prototype.md @@ -41,7 +41,7 @@ chains*. // The resulting prototype chain test [instance of Bar] Bar.prototype [instance of Foo] - { foo: 'Hello World' } + { foo: 'Hello World', value: 42 } Foo.prototype { method: ... } Object.prototype diff --git a/doc/es/object/prototype.md b/doc/es/object/prototype.md index 363c4d48..0461d1ff 100644 --- a/doc/es/object/prototype.md +++ b/doc/es/object/prototype.md @@ -41,7 +41,7 @@ llamadas de *cadenas de prototipo* (*prototype chains*). // Resultado de cadena de prototipos (prototype chain) test [instance of Bar] Bar.prototype [instance of Foo] - { foo: 'Hello World' } + { foo: 'Hello World', value: 42 } Foo.prototype { method: ... } Object.prototype diff --git a/doc/fi/object/prototype.md b/doc/fi/object/prototype.md index 4ecdae89..f2497e05 100644 --- a/doc/fi/object/prototype.md +++ b/doc/fi/object/prototype.md @@ -31,7 +31,7 @@ Ensimmäinen suuri ero liittyy siihen, kuinka perintä toimii. JavaScriptissä s // Prototyyppiketju test [Bar-olio] Bar.prototype [Foo-olio] - { foo: 'Terve maailma' } + { foo: 'Terve maailma', value: 42 } Foo.prototype { method: ... } Object.prototype diff --git a/doc/fr/object/prototype.md b/doc/fr/object/prototype.md index 50b21f23..c1a471aa 100644 --- a/doc/fr/object/prototype.md +++ b/doc/fr/object/prototype.md @@ -33,7 +33,7 @@ La première différence majeure est que l'héritage en JavaScript utilise des * // La chaîne de prototypes qui en résulte test [instance of Bar] Bar.prototype [instance of Foo] - { foo: 'Hello World' } + { foo: 'Hello World', value: 42 } Foo.prototype { method: ... } Object.prototype diff --git a/doc/hu/object/prototype.md b/doc/hu/object/prototype.md index 2822188e..95e45b3c 100644 --- a/doc/hu/object/prototype.md +++ b/doc/hu/object/prototype.md @@ -40,7 +40,7 @@ használ. // A kapott prototípus lánc test [instance of Bar] Bar.prototype [instance of Foo] - { foo: 'Hello World' } + { foo: 'Hello World', value: 42 } Foo.prototype { method: ... } Object.prototype diff --git a/doc/it/object/prototype.md b/doc/it/object/prototype.md index 4c34fada..8f8111d1 100644 --- a/doc/it/object/prototype.md +++ b/doc/it/object/prototype.md @@ -43,7 +43,7 @@ La prima grande differenza è che l'ereditarietà in JavaScript utilizza le // La catena di prototipi finale test [istanza di Bar] Bar.prototype [istanza di Foo] - { foo: 'Hello World' } + { foo: 'Hello World', value: 42 } Foo.prototype { method: ... } Object.prototype diff --git a/doc/ja/object/prototype.md b/doc/ja/object/prototype.md index 4a5ad300..a38ff3f5 100644 --- a/doc/ja/object/prototype.md +++ b/doc/ja/object/prototype.md @@ -33,7 +33,7 @@ JavaScriptはプロトタイプベースが採用されている唯一の広範 // プロトタイプチェーンの結果 test [instance of Bar] Bar.prototype [instance of Foo] - { foo: 'Hello World' } + { foo: 'Hello World', value: 42 } Foo.prototype { method: ... } Object.prototype diff --git a/doc/ko/object/prototype.md b/doc/ko/object/prototype.md index 9e8ffb2a..606d8105 100644 --- a/doc/ko/object/prototype.md +++ b/doc/ko/object/prototype.md @@ -31,7 +31,7 @@ Javascript는 클래스 스타일의 상속 모델을 사용하지 않고 *프 // 결과적으로 만들어진 프로토타입 체인은 다음과 같다. test [instance of Bar] Bar.prototype [instance of Foo] - { foo: 'Hello World' } + { foo: 'Hello World', value: 42 } Foo.prototype { method: ... } Object.prototype diff --git a/doc/pl/object/prototype.md b/doc/pl/object/prototype.md index 75884618..3cabc20e 100644 --- a/doc/pl/object/prototype.md +++ b/doc/pl/object/prototype.md @@ -41,7 +41,7 @@ tak zwanych *łańcuchów prototypów*. // The resulting prototype chain test [instance of Bar] Bar.prototype [instance of Foo] - { foo: 'Hello World' } + { foo: 'Hello World', value: 42 } Foo.prototype { method: ... } Object.prototype diff --git a/doc/ptbr/object/prototype.md b/doc/ptbr/object/prototype.md index a44bb25e..c9411640 100644 --- a/doc/ptbr/object/prototype.md +++ b/doc/ptbr/object/prototype.md @@ -37,7 +37,7 @@ A primeira grande diferença é que herança em JavaScript utiliza o conceito de // A cadeia prototype resultante test [instance of Bar] Bar.prototype [instance of Foo] - { foo: 'Hello World' } + { foo: 'Hello World', value: 42 } Foo.prototype { method: ... } Object.prototype diff --git a/doc/ru/object/prototype.md b/doc/ru/object/prototype.md index 7ae8ed99..0bb9f3ae 100644 --- a/doc/ru/object/prototype.md +++ b/doc/ru/object/prototype.md @@ -31,7 +31,7 @@ // Цепочка прототипов, которая получится в результате test [instance of Bar] Bar.prototype [instance of Foo] - { foo: 'Hello World' } + { foo: 'Hello World', value: 42 } Foo.prototype { method: ... } Object.prototype diff --git a/doc/tr/object/prototype.md b/doc/tr/object/prototype.md index 1a2d09a1..d8b8522a 100644 --- a/doc/tr/object/prototype.md +++ b/doc/tr/object/prototype.md @@ -39,7 +39,7 @@ yapılmasıdır. // Sonuçta ortaya çıkan prototip zinciri test [bir Bar sınıfı nesnesi] Bar.prototype [bir Foo sınıfı nesnesi] - { foo: 'Hello World' } + { foo: 'Hello World', value: 42 } Foo.prototype { method: ... } Object.prototype diff --git a/doc/zh/object/prototype.md b/doc/zh/object/prototype.md index 0d0079c4..ee6137d3 100755 --- a/doc/zh/object/prototype.md +++ b/doc/zh/object/prototype.md @@ -35,7 +35,7 @@ other way around is a far more difficult task.) // 原型链 test [Bar的实例] Bar.prototype [Foo的实例] - { foo: 'Hello World' } + { foo: 'Hello World', value: 42 } Foo.prototype {method: ...}; Object.prototype diff --git a/doc/zhtw/object/prototype.md b/doc/zhtw/object/prototype.md index e861a1ab..8283865e 100644 --- a/doc/zhtw/object/prototype.md +++ b/doc/zhtw/object/prototype.md @@ -33,7 +33,7 @@ JavaScript 不包含傳統繼承的模型,它使用的是*原型*模型。 // 原型鏈 test [instance of Bar] Bar.prototype [instance of Foo] - { foo: 'Hello World' } + { foo: 'Hello World', value: 42 } Foo.prototype { method: ... } Object.prototype From 8a9e032321f83c8770f34932fd17fab693edb8f0 Mon Sep 17 00:00:00 2001 From: shakvaal Date: Mon, 1 Feb 2016 18:33:07 +0300 Subject: [PATCH 069/105] Explicitly show that code fails `foo.hack` text makes it more difficult to understand at once when you are a quick reader and check code before description. --- doc/en/function/closures.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/en/function/closures.md b/doc/en/function/closures.md index 58005a5e..aef633b9 100644 --- a/doc/en/function/closures.md +++ b/doc/en/function/closures.md @@ -36,12 +36,12 @@ Since it is not possible to reference or assign scopes in JavaScript, there is interact with it is via the two closures. var foo = new Counter(4); - foo.hack = function() { + foo.hackFail = function() { count = 1337; }; The above code will **not** change the variable `count` in the scope of `Counter`, -since `foo.hack` was not defined in **that** scope. It will instead create - or +since `foo.hackFail` was not defined in **that** scope. It will instead create - or override - the *global* variable `count`. ### Closures Inside Loops From 8d85cd6164bc8b139557eb73edf2b311bd9312f9 Mon Sep 17 00:00:00 2001 From: shakvaal Date: Mon, 1 Feb 2016 18:35:14 +0300 Subject: [PATCH 070/105] Added another function-as-expression example --- doc/en/function/scopes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/en/function/scopes.md b/doc/en/function/scopes.md index 28caddbd..33d525e1 100644 --- a/doc/en/function/scopes.md +++ b/doc/en/function/scopes.md @@ -220,6 +220,7 @@ which, while different in syntax, behave the same way. !function(){}() +function(){}() (function(){}()); + void function(){}(); // and so on... ### In Conclusion From c0e3401d2525456f2710960a25fbb711091a1eac Mon Sep 17 00:00:00 2001 From: Nikita Shulipa Date: Thu, 4 Feb 2016 17:34:17 +0200 Subject: [PATCH 071/105] Remove redundant 'loop' word --- doc/ru/array/constructor.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/ru/array/constructor.md b/doc/ru/array/constructor.md index 0bfec314..13f58846 100644 --- a/doc/ru/array/constructor.md +++ b/doc/ru/array/constructor.md @@ -15,7 +15,7 @@ arr[1]; // не определён, undefined 1 in arr; // false, индекс не был установлен -Поведение, которое позволяет изначально установить только размер массива, может пригодиться лишь в нескольких случаях, таких как повторение строк, за счёт чего избегается использование цикла `for loop`. +Поведение, которое позволяет изначально установить только размер массива, может пригодиться лишь в нескольких случаях, таких как повторение строк, за счёт чего избегается использование цикла `for`. new Array(count + 1).join(stringToRepeat); From ace0d129fe646d225f73fb527ac030d47f5f4298 Mon Sep 17 00:00:00 2001 From: Inomdzhon Mirdzhamolov Date: Mon, 29 Feb 2016 22:52:38 +0300 Subject: [PATCH 072/105] Changing way to inheritance --- doc/ru/object/prototype.md | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/doc/ru/object/prototype.md b/doc/ru/object/prototype.md index 7ae8ed99..edc03efb 100644 --- a/doc/ru/object/prototype.md +++ b/doc/ru/object/prototype.md @@ -10,17 +10,19 @@ > **Замечание:** В результате выполнения конструкции `Bar.prototype = Foo.prototype` оба объекта будут делить друг с другом **один и тот же** прототип. Так что изменение прототипа одного из объектов повлечёт за собой изменение прототипа другого и наоборот — вряд ли это окажется тем, чего вы ожидали. +> **Замечание:** Для объявления наследования вместо `Bar.prototype = Object.create(Foo.prototype)` можно воспользоваться конструкций `Bar.prototype = new Foo()`, но у нее есть пару недостатков: 1) как правило требуется унаследовать только методы и свойства прототипа, а не создавать для этого новый объект; 2) создание объекта может требовать обязательные аргументы. + +> **Примечание:** Метод `Object.create` отсутствует в IE8 и ниже, но его легко реализовать созданием своей такой функции или же можно подключить библиотеку для поддержки старых IE [*es5-shim*][5] + function Foo() { this.value = 42; } - Foo.prototype = { - method: function() {} - }; + Foo.prototype.method = function() {} function Bar() {} - // Установим значением прототипа Bar новый экземпляр Foo - Bar.prototype = new Foo(); + // Зададим наследование от Foo + Bar.prototype = Object.create(Foo.prototype); Bar.prototype.foo = 'Hello World'; // Убедимся, что Bar является действующим конструктором @@ -81,4 +83,5 @@ [2]: http://en.wikipedia.org/wiki/Monkey_patch [3]: http://prototypejs.org/ [4]: https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/forEach +[5]: https://github.com/es-shims/es5-shim From 8ac5774572514b134526132c8725395d8940002f Mon Sep 17 00:00:00 2001 From: M Date: Wed, 9 Mar 2016 12:33:17 +0100 Subject: [PATCH 073/105] semicola to terminate function expressions --- doc/by/function/this.md | 6 +++--- doc/en/function/this.md | 6 +++--- doc/es/function/this.md | 4 ++-- doc/fi/function/this.md | 4 ++-- doc/fr/function/this.md | 6 +++--- doc/hu/function/this.md | 4 ++-- doc/it/function/this.md | 6 +++--- doc/ja/function/this.md | 4 ++-- doc/ko/function/this.md | 6 +++--- doc/pl/function/this.md | 4 ++-- doc/ptbr/function/this.md | 4 ++-- doc/ru/function/this.md | 4 ++-- doc/tr/function/this.md | 4 ++-- doc/zh/function/this.md | 4 ++-- doc/zhtw/function/this.md | 13 +++++++++++-- 15 files changed, 44 insertions(+), 35 deletions(-) diff --git a/doc/by/function/this.md b/doc/by/function/this.md index 5b0f555d..0a85ef5f 100644 --- a/doc/by/function/this.md +++ b/doc/by/function/this.md @@ -62,7 +62,7 @@ // this спасылаецца на глабальны аб'ект } test(); - } + }; Памылковым меркаваннем будзе тое, што `this` унутры `test` будзе спасылацца на `Foo`; Але на самрэч **гэта не так**. @@ -76,7 +76,7 @@ // Тут выкарыстоўвайце self замест this } test(); - } + }; `self` гэта звычайнае імя пераменнай, але яно часта выкарыстоўваецца для спасылкі на знешні `this`. У камбінацыі з [замыканнямі](#function.closures), яно можа быць @@ -90,7 +90,7 @@ // this цяпер спасылаецца на Foo }.bind(this); test(); - } + }; ### Прысвойванне метадаў diff --git a/doc/en/function/this.md b/doc/en/function/this.md index f123f336..83abff00 100644 --- a/doc/en/function/this.md +++ b/doc/en/function/this.md @@ -63,7 +63,7 @@ mis-design of the language because it **never** has any practical use. // this is set to the global object } test(); - } + }; A common misconception is that `this` inside of `test` refers to `Foo`; while in fact, it **does not**. @@ -77,7 +77,7 @@ local variable inside of `method` that refers to `Foo`. // Use self instead of this here } test(); - } + }; `self` is just a normal variable name, but it is commonly used for the reference to an outer `this`. In combination with [closures](#function.closures), it can also @@ -90,7 +90,7 @@ As of ECMAScript 5 you can use the `bind` method combined with an anonymous func // this now refers to Foo }.bind(this); test(); - } + }; ### Assigning Methods diff --git a/doc/es/function/this.md b/doc/es/function/this.md index 7b1c0554..78ba9df3 100644 --- a/doc/es/function/this.md +++ b/doc/es/function/this.md @@ -63,7 +63,7 @@ mal diseño del lenguaje, ya que **nunca** tiene un uso práctico. // this es establecido como un objeto global } test(); - } + }; Un error común es que `this` dentro de `test` haga referencia a `Foo`, mientras que en realidad esto **no es así**. @@ -77,7 +77,7 @@ dentro del `método` para referirse a `Foo`. // Use that instead of this here } test(); - } + }; `that` es justo un nombre normal, pero es comúnmente usado para referenciar a `this` de forma externa. En combinación con [closures](#function.closures), esto puede ser diff --git a/doc/fi/function/this.md b/doc/fi/function/this.md index 3ebf0a7b..3e2b09d2 100644 --- a/doc/fi/function/this.md +++ b/doc/fi/function/this.md @@ -51,7 +51,7 @@ Useimmat näistä tapauksista ovat järkeviä. Ensimmäistä niistä tosin voida // this asettuu globaaliin olioon } test(); - } + }; Yleisesti luullaan, että test-funktion sisältämä `this` viittaa tässä tapauksessa `Foo`-olioon. Todellisuudessa se **ei** kuitenkaan tee näin. @@ -63,7 +63,7 @@ Jotta `Foo`-olioon voidaan päästä käsiksi `test`-funktion sisällä, tulee m // Käytä thatia thissin sijasta } test(); - } + }; `that` on normaali nimi, jota käytetään yleisesti viittaamaan ulompaan `this`-muuttujaan. [Sulkeumia](#function.closures) käytettäessä `this`-arvoa voidaan myös välittää edelleen. diff --git a/doc/fr/function/this.md b/doc/fr/function/this.md index 723c0255..aed2301c 100644 --- a/doc/fr/function/this.md +++ b/doc/fr/function/this.md @@ -52,7 +52,7 @@ Bien que la plupart de ces cas ont du sens, le premier cas peut être considér // this réfère à l'objet global } test(); - } + }; Une autre erreur souvent commise est que `this` l'intérieur de `test` se réfère à `foo`; ce qui n'est **pas** du tout le cas. @@ -64,7 +64,7 @@ Pour accéder à `foo` de l'intérieur de `test`, vous pouvez créer une variabl // Utilisez self au lieu de this ici } test(); - } + }; `self` est juste une variable normale, couramment utilisée pour référencer un `this` extérieur. Combiné avec des [fermetures](# function.closures) "closures", on peut l'utiliser pour passer les valeurs de `this`. @@ -75,7 +75,7 @@ Pour accéder à `foo` de l'intérieur de `test`, vous pouvez créer une variabl // maintenant, this réfère à Foo }.bind(this); test(); - } + }; ### Assignement de méthodes diff --git a/doc/hu/function/this.md b/doc/hu/function/this.md index 938385f4..4b2efd74 100644 --- a/doc/hu/function/this.md +++ b/doc/hu/function/this.md @@ -63,7 +63,7 @@ praktikus felhasználási módja. // A this itt a globális ojjektum. } test(); - } + }; Gyakori hiba, hogy úgy gondolják a fenti példában az emberek, hogy a `this` a `test` függvényen belül az őt körülvevő `Foo`-ra fog mutatni, pedig **nem**. @@ -77,7 +77,7 @@ lokálisan elhelyezni a `method`-on belül, ami már valóban a kívánt `this`- // Használjuk a that-et a this helyett } test(); - } + }; A `that` tuladjonképpen egy mezei változónév (nem kulcsszó), de sokszor használják arra, hogy egy másik `this`-re hivatkozzanak vele. A [colsureökkel](#function.closures) kombinálva diff --git a/doc/it/function/this.md b/doc/it/function/this.md index 5bee4398..258086a3 100644 --- a/doc/it/function/this.md +++ b/doc/it/function/this.md @@ -66,7 +66,7 @@ uso pratico. // this viene impostato all'oggetto globale } test(); - } + }; Una comune credenza è che `this` all'interno di `test` faccia riferimento a `Foo` mentre, invece, **non** è così. @@ -80,7 +80,7 @@ una variabile locale all'interno di `method` che faccia riferimento a `Foo`. // Qui viene usato self invece di this } test(); - } + }; `self` è solo un normale nome di variabile, ma viene comunemente usato come riferimento ad un `this` più esterno. Abbinato alle [closures](#function.closures) @@ -94,7 +94,7 @@ con una funziona anonima // this ora fa riferimento a Foo }.bind(this); test(); - } + }; ### Metodi di asseganzione diff --git a/doc/ja/function/this.md b/doc/ja/function/this.md index 4e6e27aa..88a35390 100644 --- a/doc/ja/function/this.md +++ b/doc/ja/function/this.md @@ -55,7 +55,7 @@ JavaScriptの`this`と名付けられた特殊なキーワードは他のプロ // このファンクションはグローバルオブジェクトに設定される } test(); - } + }; 良くある誤解として`test`の中の`this`が`Foo`を参照しているというものがありますが、そのような事実は**一切**ありません。 @@ -67,7 +67,7 @@ JavaScriptの`this`と名付けられた特殊なキーワードは他のプロ // ここでthisの代わりに使用する } test(); - } + }; `that`は通常の変数名ですが、外部の`this`の参照の為に良く使われます。[クロージャ](#function.closures)と組み合わせる事で`this`の値を渡す事ができるようになります。 diff --git a/doc/ko/function/this.md b/doc/ko/function/this.md index 019b4458..0ad51ad9 100644 --- a/doc/ko/function/this.md +++ b/doc/ko/function/this.md @@ -51,7 +51,7 @@ Global Scope에서도 this가 사용될 수 있고 이때에는 *Global* 객체 // 여기에서 this는 Global 객체를 가리킨다. } test(); - } + }; `test` 에서 `this`가 `Foo`를 가리킬 것으로 생각할 테지만 틀렸다. 실제로는 그렇지 않다. @@ -63,7 +63,7 @@ Global Scope에서도 this가 사용될 수 있고 이때에는 *Global* 객체 // 여기에서 this 대신에 self를 사용하여 Foo에 접근한다 } test(); - } + }; `self`는 통상적인 변수 이름이지만, 바깥쪽의 `this`를 참조하기 위해 일반적으로 사용된다. 또한 [클로저](#function.closures)와 결합하여 `this`의 값을 주고 받는 용도로 사용할 수도 있다. @@ -75,7 +75,7 @@ ECMAScript 5부터는 익명 함수와 결합된 `bind` 메소드를 사용하 // this는 이제 Foo를 참조한다 }.bind(this); test(); - } + }; ### Method 할당하기 diff --git a/doc/pl/function/this.md b/doc/pl/function/this.md index 3819cac7..adf7e1d0 100644 --- a/doc/pl/function/this.md +++ b/doc/pl/function/this.md @@ -63,7 +63,7 @@ w praktyce. // wewnątrz tej funkcji this wskazuje na obiekt global } test(); - } + }; Powszechnym błędem jest myślenie, że `this` wewnątrz `test` wskazuje na `Foo`, podczas gdy w rzeczywistości tak **nie jest**. @@ -77,7 +77,7 @@ metody lokalnej zmiennej, która będzie wskazywała na `Foo`. // Należy używać that zamiast this wewnątrz tej funkcji } test(); - } + }; `that` jest zwykłą zmienną, ale jest to powszechnie stosowana konwencja otrzymywania wartości zewnętrznego `this`. W połączeniu z [domknięciami(closures)](#function.closures), diff --git a/doc/ptbr/function/this.md b/doc/ptbr/function/this.md index 6f8c45d9..daacb9a9 100644 --- a/doc/ptbr/function/this.md +++ b/doc/ptbr/function/this.md @@ -61,7 +61,7 @@ como um engano de concepção da linguagem, já que **nunca** se mostrou útil. // this referencia o objeto global } test(); - } + }; Um erro comum é achar que `this` dentro de `test` referencia `Foo`; enquanto que, na realidade **não é isto que acontece**. @@ -75,7 +75,7 @@ uma variável global dentro do método para se referir à `Foo`. // Utilize that no lugar de this aqui } test(); - } + }; `that` trata-se de uma variável normal, porém é normalmente utilizada para referências externas de `this`. Quando combinadas com [closures](#function.closures), também podem ser utilizadas para repassar `this` como valor. diff --git a/doc/ru/function/this.md b/doc/ru/function/this.md index d50f9403..6883a546 100644 --- a/doc/ru/function/this.md +++ b/doc/ru/function/this.md @@ -51,7 +51,7 @@ // this ссылается на глобальный объект } test(); - } + }; Распространенным заблуждением будет то, что `this` внутри `test` ссылается на `Foo`, но это **не так**. @@ -63,7 +63,7 @@ // Здесь используем that вместо this } test(); - } + }; Подходящее имя для переменной - `that`, его часто используют для ссылки на внешний `this`. В комбинации с [замыканиями](#function.closures) `this` можно пробрасывать в глобальную область или в любой другой объект. diff --git a/doc/tr/function/this.md b/doc/tr/function/this.md index de24190a..b589dc42 100644 --- a/doc/tr/function/this.md +++ b/doc/tr/function/this.md @@ -65,7 +65,7 @@ kullanılımı yoktur. // this genel nesneye işaret eder } test(); - } + }; Bir başka yanılgı `test` fonksiyonunun içinde `this` 'in `Foo` 'ya işaret edeceğinin sanılmasıdır, ama bu **doğru değildir**. @@ -79,7 +79,7 @@ değişken oluşturmaktır. // Burada this yerine that kullanın } test(); - } + }; `that` kelimesinin dilde özel bir anlamı yoktur, ama sıklıkla dış kapsamdaki `this` 'e işaret etmek için kullanılır. Bu yöntem [`closure`](#function.closures) diff --git a/doc/zh/function/this.md b/doc/zh/function/this.md index 0930ef26..54144292 100755 --- a/doc/zh/function/this.md +++ b/doc/zh/function/this.md @@ -60,7 +60,7 @@ JavaScript 有一套完全不同于其它语言的对 `this` 的处理机制。 // this 将会被设置为全局对象(译者注:浏览器环境中也就是 window 对象) } test(); - } + }; 一个常见的误解是 `test` 中的 `this` 将会指向 `Foo` 对象,实际上**不是**这样子的。 @@ -72,7 +72,7 @@ JavaScript 有一套完全不同于其它语言的对 `this` 的处理机制。 // 使用 that 来指向 Foo 对象 } test(); - } + }; `that` 只是我们随意起的名字,不过这个名字被广泛的用来指向外部的 `this` 对象。 在 [闭包](#function.closures) 一节,我们可以看到 `that` 可以作为参数传递。 diff --git a/doc/zhtw/function/this.md b/doc/zhtw/function/this.md index d919c228..4c4c924b 100644 --- a/doc/zhtw/function/this.md +++ b/doc/zhtw/function/this.md @@ -59,7 +59,7 @@ mis-design of the language because it **never** has any practical use. // this is set to the global object } test(); - } + }; A common misconception is that `this` inside of `test` refers to `Foo`; while in fact, it **does not**. @@ -73,12 +73,21 @@ local variable inside of `method` that refers to `Foo`. // Use that instead of this here } test(); - } + }; `that` is just a normal variable name, but it is commonly used for the reference to an outer `this`. In combination with [closures](#function.closures), it can also be used to pass `this` values around. +As of ECMAScript 5 you can use the `bind` method combined with an anonymous function to achieve the same result. + + Foo.method = function() { + var test = function() { + // this now refers to Foo + }.bind(this); + test(); + }; + ### Assigning Methods Another thing that does **not** work in JavaScript is function aliasing, which is From 38dba0df1f407501b98f2c0711e16c687dd5c4f4 Mon Sep 17 00:00:00 2001 From: EngHell Date: Wed, 23 Mar 2016 12:54:32 -0600 Subject: [PATCH 074/105] Update some verbiage to make clear the concepts in each paragraph who was updated, also updated .gitignore to ignore netbrain's ides' files. --- .gitignore | 1 + doc/es/function/general.md | 4 ++-- doc/es/function/this.md | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index 2bfbed12..c37ad084 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ /html /log /node_modules +/.idea/* /site !/site/favicon.ico diff --git a/doc/es/function/general.md b/doc/es/function/general.md index d9621bc5..c051373a 100644 --- a/doc/es/function/general.md +++ b/doc/es/function/general.md @@ -1,7 +1,7 @@ ## La declaración de funciones y expresiones -Las funciones en JavaScript son las primeras clases de objetos. Esto significa que se -puede pasar como cualquier otro valor. Un uso común de está característica es pasar de +Las funciones en JavaScript son funciones de primera clase `(first class functions)`. +Esto significa que se pueden tratar como objetos. Un uso común de esta característica es pasar de una *función anónima* a otra, posiblemente una función asíncrona. Esto se conoce como `callback`. ### La declaración `function` diff --git a/doc/es/function/this.md b/doc/es/function/this.md index 7b1c0554..65d0be5f 100644 --- a/doc/es/function/this.md +++ b/doc/es/function/this.md @@ -17,7 +17,7 @@ Cuando se utiliza `this` en el ámbito global, simplemente se refiere al objeto Aquí `this` se refiere al objeto *global*. -> **Nota ES5:** En modo estricto (strict mode), global **ya no** existe. +> **Nota ES5:** En modo estricto (strict mode), el objeto global **ya no** es accesible a través de this. > `this` tendrá el valor de `undefined` en este caso. ### Llamar a un método From 19f9e63bcde0169008337a3010907c6343cd6005 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sercan=20=C3=87ak=C4=B1r?= Date: Fri, 10 Jun 2016 16:10:34 +0300 Subject: [PATCH 075/105] fix typo --- doc/tr/function/scopes.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/tr/function/scopes.md b/doc/tr/function/scopes.md index d826f1aa..211c45f7 100644 --- a/doc/tr/function/scopes.md +++ b/doc/tr/function/scopes.md @@ -178,7 +178,7 @@ adında bir özel değişken tanımlanmıştır, bu değişken *geçerli nesneyi Fonksiyon kapsamlarında aynı zamanda [`arguments`](#function.arguments) adında bir değişken tanımlanmıştır ve fonksiyonun argümanlarını içerir. -Örnek olarak bir fonksiyon kapsamında `foo` değişkenine eriğildiğinde JavaScript +Örnek olarak bir fonksiyon kapsamında `foo` değişkenine erişildiğinde JavaScript isim çözümlemeyi aşağıdaki sıra ile yapacaktır: 1. Geçerli kapsamda bir `var foo` ifadesi mevcutsa bu kullanılır. From 564f58a43ea00cceddc61c3b6b8ff5dd9750b62b Mon Sep 17 00:00:00 2001 From: PoppinL Date: Mon, 27 Jun 2016 15:33:12 +0800 Subject: [PATCH 076/105] fix typo --- doc/zh/function/arguments.md | 8 ++++---- doc/zh/function/closures.md | 14 ++++++++------ doc/zh/function/general.md | 9 ++++----- doc/zh/function/this.md | 11 ++++++----- doc/zh/intro/license.md | 2 +- doc/zh/object/forinloop.md | 1 - doc/zh/object/general.md | 4 ++-- doc/zh/object/hasownproperty.md | 11 +++++------ doc/zh/object/prototype.md | 14 +++++++------- 9 files changed, 37 insertions(+), 37 deletions(-) diff --git a/doc/zh/function/arguments.md b/doc/zh/function/arguments.md index 69c07fe5..ac6967eb 100755 --- a/doc/zh/function/arguments.md +++ b/doc/zh/function/arguments.md @@ -9,7 +9,7 @@ JavaScript 中每个函数内都能访问一个特别变量 `arguments`。这个 `arguments` 变量**不是**一个数组(`Array`)。 尽管在语法上它有数组相关的属性 `length`,但它不从 `Array.prototype` 继承,实际上它是一个对象(`Object`)。 -因此,无法对 `arguments` 变量使用标准的数组方法,比如 `push`, `pop` 或者 `slice`。 +因此,无法对 `arguments` 变量使用标准的数组方法,比如 `push`、`pop` 或者 `slice`。 虽然使用 `for` 循环遍历也是可以的,但是为了更好的使用数组方法,最好把它转化为一个真正的数组。 ###转化为数组 @@ -99,13 +99,13 @@ JavaScript 中每个函数内都能访问一个特别变量 `arguments`。这个 然而,的确有一种情况会显著的影响现代 JavaScript 引擎的性能。这就是使用 `arguments.callee`。 function foo() { - arguments.callee; // do something with this function object - arguments.callee.caller; // and the calling function object + arguments.callee; // 使用这个函数对象 + arguments.callee.caller; // 以及这个函数对象的调用者 } function bigLoop() { for(var i = 0; i < 100000; i++) { - foo(); // Would normally be inlined... + foo(); // 通常情况会作为内联函数... } } diff --git a/doc/zh/function/closures.md b/doc/zh/function/closures.md index 77f69e4c..df474a65 100755 --- a/doc/zh/function/closures.md +++ b/doc/zh/function/closures.md @@ -3,6 +3,8 @@ 闭包是 JavaScript 一个非常重要的特性,这意味着当前作用域**总是**能够访问外部作用域中的变量。 因为 [函数](#function.scopes) 是 JavaScript 中唯一拥有自身作用域的结构,因此闭包的创建依赖于函数。 +> 译者注:ES2015 中增加了块级作用域。 + ###模拟私有变量 function Counter(start) { @@ -23,7 +25,7 @@ foo.get(); // 5 这里,`Counter` 函数返回两个闭包,函数 `increment` 和函数 `get`。 这两个函数都维持着 -对外部作用域 `Counter` 的引用,因此总可以访问此作用域内定义的变量 `count`. +对外部作用域 `Counter` 的引用,因此总可以访问此作用域内定义的变量 `count`。 ###为什么不可以在外部访问私有变量 @@ -44,13 +46,13 @@ for(var i = 0; i < 10; i++) { setTimeout(function() { - console.log(i); + console.log(i); }, 1000); } 上面的代码不会输出数字 `0` 到 `9`,而是会输出数字 `10` 十次。 -当 `console.log` 被调用的时候,*匿名*函数保持对外部变量 `i` 的引用,此时 `for`循环已经结束, `i` 的值被修改成了 `10`. +当 `console.log` 被调用的时候,*匿名*函数保持对外部变量 `i` 的引用,此时 `for`循环已经结束, `i` 的值被修改成了 `10`。 为了得到想要的结果,需要在每次循环中创建变量 `i` 的**拷贝**。 @@ -61,7 +63,7 @@ for(var i = 0; i < 10; i++) { (function(e) { setTimeout(function() { - console.log(e); + console.log(e); }, 1000); })(i); } @@ -76,8 +78,8 @@ setTimeout((function(e) { return function() { console.log(e); - } - })(i), 1000) + }; + })(i), 1000); } diff --git a/doc/zh/function/general.md b/doc/zh/function/general.md index 6269ee16..04414900 100755 --- a/doc/zh/function/general.md +++ b/doc/zh/function/general.md @@ -1,6 +1,6 @@ ##函数声明与表达式 -函数是JavaScript中的一等对象,这意味着可以把函数像其它值一样传递。 +函数是 JavaScript 中的一等对象,这意味着可以把函数像其它值一样传递。 一个常见的用法是把*匿名函数*作为回调函数传递到异步函数中。 ###函数声明 @@ -8,9 +8,9 @@ function foo() {} 上面的方法会在执行前被 [解析(hoisted)](#function.scopes),因此它存在于当前上下文的*任意*一个地方, -即使在函数定义体的上面被调用也是对的。 +即使在函数定义体的上面被调用也是对的。 - foo(); // 正常运行,因为foo在代码运行前已经被创建 + foo(); // 正常运行,因为 foo 在代码运行前已经被创建 function foo() {} ### 函数赋值表达式 @@ -39,7 +39,6 @@ `bar` 函数声明外是不可见的,这是因为我们已经把函数赋值给了 `foo`; 然而在 `bar` 内部依然可见。这是由于 JavaScript 的 [命名处理](#function.scopes) 所致, 函数名在函数内*总是*可见的。 -> **注意:**在IE8及IE8以下版本浏览器bar在外部也是可见的,是因为浏览器对命名函数赋值表达式进行了错误的解析, +> **注意: **在 IE8 及 IE8 以下版本浏览器 bar 在外部也是可见的,是因为浏览器对命名函数赋值表达式进行了错误的解析, > 解析成两个函数 `foo` 和 `bar` -[30]: http://cnblogs.com/sanshi/ diff --git a/doc/zh/function/this.md b/doc/zh/function/this.md index 0930ef26..eac3ddef 100755 --- a/doc/zh/function/this.md +++ b/doc/zh/function/this.md @@ -9,7 +9,8 @@ JavaScript 有一套完全不同于其它语言的对 `this` 的处理机制。 当在全部范围内使用 `this`,它将会指向*全局*对象。 -> **[译者注][30]:**浏览器中运行的 JavaScript 脚本,这个全局对象是 `window`。 +> **[译者注][30]:**浏览器中运行的 JavaScript 脚本,这个全局对象是 `window`; +> 在 nodejs 环境中运行的 Javascript 脚本,这个全局对象是 `global`。 ###函数调用 @@ -22,13 +23,13 @@ JavaScript 有一套完全不同于其它语言的对 `this` 的处理机制。 ###方法调用 - test.foo(); + test.foo(); 这个例子中,`this` 指向 `test` 对象。 ###调用构造函数 - new foo(); + new foo(); 如果函数倾向于和 `new` 关键词一块使用,则我们称这个函数是 [构造函数](#function.constructors)。 在函数内部,`this` 指向*新创建*的对象。 @@ -39,7 +40,7 @@ JavaScript 有一套完全不同于其它语言的对 `this` 的处理机制。 var bar = {}; foo.apply(bar, [1, 2, 3]); // 数组将会被扩展,如下所示 - foo.call(bar, 1, 2, 3); // 传递到foo的参数是:a = 1, b = 2, c = 3 + foo.call(bar, 1, 2, 3); // 传递到 foo 的参数是:a = 1, b = 2, c = 3 当使用 `Function.prototype` 上的 `call` 或者 `apply` 方法时,函数内的 `this` 将会被 **显式设置**为函数调用的第一个参数。 @@ -53,7 +54,7 @@ JavaScript 有一套完全不同于其它语言的对 `this` 的处理机制。 ###常见误解 尽管大部分的情况都说的过去,不过第一个规则(**[译者注][30]:**这里指的应该是第二个规则,也就是直接调用函数时,`this` 指向全局对象) -被认为是JavaScript语言另一个错误设计的地方,因为它**从来**就没有实际的用途。 +被认为是 JavaScript 语言另一个错误设计的地方,因为它**从来**就没有实际的用途。 Foo.method = function() { function test() { diff --git a/doc/zh/intro/license.md b/doc/zh/intro/license.md index 33aa7406..057dd8a6 100755 --- a/doc/zh/intro/license.md +++ b/doc/zh/intro/license.md @@ -1,7 +1,7 @@ ##许可 JavaScript 秘密花园在 [MIT license][1] 许可协议下发布,并存放在 [GitHub][2] 开源社区。 -如果你发现错误或者打字错误,请[新建一个任务单][3]或者发一个抓取请求。 +如果你发现错误,请[新建一个任务单][3]或者发一个抓取请求(Pull Request)。 你也可以在 Stack Overflow 的 [JavaScript 聊天室][4]找到我们。 [1]: https://github.com/BonsaiDen/JavaScript-Garden/blob/next/LICENSE diff --git a/doc/zh/object/forinloop.md b/doc/zh/object/forinloop.md index a0360e7e..16f9faaa 100755 --- a/doc/zh/object/forinloop.md +++ b/doc/zh/object/forinloop.md @@ -37,5 +37,4 @@ 推荐**总是**使用 `hasOwnProperty`。不要对代码运行的环境做任何假设,不要假设原生对象是否已经被扩展了。 [1]: http://www.prototypejs.org/ -[30]: http://cnblogs.com/sanshi/ diff --git a/doc/zh/object/general.md b/doc/zh/object/general.md index a97b6d86..3ada17fa 100755 --- a/doc/zh/object/general.md +++ b/doc/zh/object/general.md @@ -25,7 +25,7 @@ JavaScript 中所有变量都可以当作对象使用,除了两个例外 [`nul JavaScript 的对象可以作为[*哈希表*][1]使用,主要用来保存命名的键与值的对应关系。 使用对象的字面语法 - `{}` - 可以创建一个简单对象。这个新创建的对象从 `Object.prototype` -[继承](#object.prototype)下面,没有任何[自定义属性](#object.hasownproperty)。 +[继承](#object.prototype)下来,没有任何[自定义属性](#object.hasownproperty)。 var foo = {}; // 一个空对象 @@ -34,7 +34,7 @@ JavaScript 的对象可以作为[*哈希表*][1]使用,主要用来保存命 ### 访问属性 -有两种方式来访问对象的属性,点操作符或者中括号操作符。 +有两种方式来访问对象的属性,点操作符和中括号操作符。 var foo = {name: 'kitten'} foo.name; // kitten diff --git a/doc/zh/object/hasownproperty.md b/doc/zh/object/hasownproperty.md index 2466f8c5..c9b3fc21 100755 --- a/doc/zh/object/hasownproperty.md +++ b/doc/zh/object/hasownproperty.md @@ -8,8 +8,8 @@ `hasOwnProperty` 是 JavaScript 中唯一一个处理属性但是**不**查找原型链的函数。 - // 修改Object.prototype - Object.prototype.bar = 1; + // 修改 Object.prototype + Object.prototype.bar = 1; var foo = {goo: undefined}; foo.bar; // 1 @@ -18,8 +18,8 @@ foo.hasOwnProperty('bar'); // false foo.hasOwnProperty('goo'); // true -只有 `hasOwnProperty` 可以给出正确和期望的结果,这在遍历对象的属性时会很有用。 -**没有**其它方法可以用来排除原型链上的属性,而不是定义在对象*自身*上的属性。 +只有 `hasOwnProperty` 可以给出正确和期望的结果。可以查看 [`for in` 循环](#object.forinloop) +章节来获取关于在迭代遍历对象属性的时候,何时使用 `hasOwnProperty` 的更多信息。 ###`hasOwnProperty` 作为属性 @@ -35,7 +35,7 @@ JavaScript **不会**保护 `hasOwnProperty` 被非法占用,因此如果一 foo.hasOwnProperty('bar'); // 总是返回 false - // 使用其它对象的 hasOwnProperty,并将其上下文设置为foo + // 使用其它对象的 hasOwnProperty,并将其上下文设置为 foo ({}).hasOwnProperty.call(foo, 'bar'); // true ###结论 @@ -44,4 +44,3 @@ JavaScript **不会**保护 `hasOwnProperty` 被非法占用,因此如果一 同时在使用 [`for in` loop](#object.forinloop) 遍历对象时,推荐**总是**使用 `hasOwnProperty` 方法, 这将会避免[原型](#object.prototype)对象扩展带来的干扰。 -[30]: http://cnblogs.com/sanshi/ diff --git a/doc/zh/object/prototype.md b/doc/zh/object/prototype.md index 56f126bf..a8f08448 100755 --- a/doc/zh/object/prototype.md +++ b/doc/zh/object/prototype.md @@ -23,14 +23,14 @@ other way around is a far more difficult task.) function Bar() {} - // 设置Bar的prototype属性为Foo的实例对象 + // 设置 Bar 的 prototype 属性为 Foo 的实例对象 Bar.prototype = new Foo(); Bar.prototype.foo = 'Hello World'; - // 修正Bar.prototype.constructor为Bar本身 + // 修正 Bar.prototype.constructor 为 Bar 本身 Bar.prototype.constructor = Bar; - var test = new Bar() // 创建Bar的一个新实例 + var test = new Bar(); // 创建Bar的一个新实例 // 原型链 test [Bar的实例] @@ -58,7 +58,7 @@ other way around is a far more difficult task.) ###原型属性 当原型属性用来创建原型链时,可以把**任何**类型的值赋给它(prototype)。 -然而将原子类型赋给 prototype 的操作将会被忽略。 +然而将原子类型(primitives)赋给 prototype 的操作将会被忽略。 function Foo() {} Foo.prototype = 1; // 无效 @@ -67,16 +67,16 @@ other way around is a far more difficult task.) ###性能 -如果一个属性在原型链的上端,则对于查找时间将带来不利影响。特别的,试图获取一个不存在的属性将会遍历整个原型链。 +如果一个属性在原型链的上端,则对于查找时间将带来不利影响。注意,试图获取一个不存在的属性将会遍历整个原型链。 并且,当使用 [`for in`](#object.forinloop) 循环遍历对象的属性时,原型链上的**所有**属性都将被访问。 ###扩展内置类型的原型 -一个错误特性被经常使用,那就是扩展 `Object.prototype` 或者其他内置类型的原型对象。 +扩展 `Object.prototype` 或者其他内置类型的原型对象,作为一个错误特性,经常被使用。 这种技术被称之为 [monkey patching][1] 并且会破坏*封装*。虽然它被广泛的应用到一些 JavaScript 类库中比如 [Prototype][2], -但是我仍然不认为为内置类型添加一些*非标准*的函数是个好主意。 +但是我仍然不赞同为内置类型添加一些*非标准*的函数。 扩展内置类型的**唯一**理由是为了和新的 JavaScript 保持一致,比如 [`Array.forEach`][3]。 From 4cfc00369fc053cbc6a034dd585f3e64975cd700 Mon Sep 17 00:00:00 2001 From: PoppinL Date: Mon, 27 Jun 2016 15:37:41 +0800 Subject: [PATCH 077/105] update zh translation --- .gitignore | 22 ++- CONTRIBUTING.md | 19 ++- JavaScript-Garden | 1 + doc/by/array/constructor.md | 31 ++++ doc/by/array/general.md | 56 ++++++++ doc/by/core/delete.md | 81 +++++++++++ doc/by/core/eval.md | 47 ++++++ doc/by/core/semicolon.md | 109 ++++++++++++++ doc/by/core/undefined.md | 69 +++++++++ doc/by/function/arguments.md | 130 +++++++++++++++++ doc/by/function/closures.md | 113 +++++++++++++++ doc/by/function/constructors.md | 122 ++++++++++++++++ doc/by/function/general.md | 48 +++++++ doc/by/function/scopes.md | 230 ++++++++++++++++++++++++++++++ doc/by/function/this.md | 118 +++++++++++++++ doc/by/index.json | 69 +++++++++ doc/by/intro/index.md | 56 ++++++++ doc/by/object/forinloop.md | 63 ++++++++ doc/by/object/general.md | 98 +++++++++++++ doc/by/object/hasownproperty.md | 55 +++++++ doc/by/object/prototype.md | 115 +++++++++++++++ doc/by/other/timeouts.md | 168 ++++++++++++++++++++++ doc/by/types/casting.md | 71 +++++++++ doc/by/types/equality.md | 70 +++++++++ doc/by/types/instanceof.md | 37 +++++ doc/by/types/typeof.md | 80 +++++++++++ doc/en/array/general.md | 12 +- doc/en/core/delete.md | 2 +- doc/en/core/eval.md | 22 +-- doc/en/function/arguments.md | 36 +++-- doc/en/function/closures.md | 15 +- doc/en/function/constructors.md | 81 ++++++----- doc/en/function/scopes.md | 1 + doc/en/function/this.md | 17 ++- doc/en/object/forinloop.md | 41 ++++-- doc/en/object/general.md | 2 +- doc/en/object/hasownproperty.md | 12 +- doc/en/object/prototype.md | 2 +- doc/en/other/timeouts.md | 4 +- doc/en/types/casting.md | 7 +- doc/en/types/typeof.md | 8 +- doc/es/index.json | 2 +- doc/es/object/general.md | 2 +- doc/es/object/prototype.md | 2 +- doc/es/types/equality.md | 58 ++++---- doc/fi/object/prototype.md | 2 +- doc/fr/array/constructor.md | 27 ++++ doc/fr/array/general.md | 46 ++++++ doc/fr/core/delete.md | 76 ++++++++++ doc/fr/core/eval.md | 42 ++++++ doc/fr/core/semicolon.md | 100 +++++++++++++ doc/fr/core/undefined.md | 55 +++++++ doc/fr/function/arguments.md | 118 +++++++++++++++ doc/fr/function/closures.md | 97 +++++++++++++ doc/fr/function/constructors.md | 109 ++++++++++++++ doc/fr/function/general.md | 38 +++++ doc/fr/function/scopes.md | 204 ++++++++++++++++++++++++++ doc/fr/function/this.md | 100 +++++++++++++ doc/fr/index.json | 69 +++++++++ doc/fr/intro/index.md | 36 +++++ doc/fr/object/forinloop.md | 44 ++++++ doc/fr/object/general.md | 85 +++++++++++ doc/fr/object/hasownproperty.md | 46 ++++++ doc/fr/object/prototype.md | 85 +++++++++++ doc/fr/other/timeouts.md | 130 +++++++++++++++++ doc/fr/types/casting.md | 62 ++++++++ doc/fr/types/equality.md | 58 ++++++++ doc/fr/types/instanceof.md | 35 +++++ doc/fr/types/typeof.md | 66 +++++++++ doc/hu/function/arguments.md | 5 +- doc/hu/function/constructors.md | 6 +- doc/hu/function/general.md | 2 +- doc/hu/function/scopes.md | 6 +- doc/hu/index.json | 2 +- doc/hu/intro/index.md | 13 +- doc/hu/object/prototype.md | 2 +- doc/it/array/general.md | 13 +- doc/it/core/eval.md | 23 ++- doc/it/function/constructors.md | 78 +++++----- doc/it/function/general.md | 2 +- doc/it/function/scopes.md | 2 +- doc/it/function/this.md | 19 ++- doc/it/object/forinloop.md | 38 +++-- doc/it/object/hasownproperty.md | 14 +- doc/it/object/prototype.md | 2 +- doc/it/other/timeouts.md | 23 +-- doc/it/types/casting.md | 9 +- doc/it/types/instanceof.md | 2 +- doc/ja/object/prototype.md | 2 +- doc/ko/array/general.md | 13 +- doc/ko/core/eval.md | 22 +-- doc/ko/function/arguments.md | 35 +++-- doc/ko/function/closures.md | 18 +++ doc/ko/function/constructors.md | 72 +++++----- doc/ko/function/this.md | 18 ++- doc/ko/object/prototype.md | 2 +- doc/language.json | 3 +- doc/pl/array/constructor.md | 4 +- doc/pl/array/general.md | 16 +-- doc/pl/core/eval.md | 2 +- doc/pl/function/closures.md | 2 +- doc/pl/function/general.md | 2 +- doc/pl/function/scopes.md | 38 ++--- doc/pl/function/this.md | 4 +- doc/pl/object/general.md | 14 +- doc/pl/object/hasownproperty.md | 2 +- doc/pl/object/prototype.md | 16 +-- doc/pl/other/timeouts.md | 2 +- doc/pl/types/casting.md | 2 +- doc/pl/types/typeof.md | 2 +- doc/ptbr/array/constructor.md | 29 ++++ doc/ptbr/array/general.md | 59 ++++++++ doc/ptbr/core/delete.md | 85 +++++++++++ doc/ptbr/core/eval.md | 45 ++++++ doc/ptbr/core/semicolon.md | 106 ++++++++++++++ doc/ptbr/core/undefined.md | 68 +++++++++ doc/ptbr/function/arguments.md | 113 +++++++++++++++ doc/ptbr/function/closures.md | 83 +++++++++++ doc/ptbr/function/constructors.md | 115 +++++++++++++++ doc/ptbr/function/general.md | 46 ++++++ doc/ptbr/function/scopes.md | 225 +++++++++++++++++++++++++++++ doc/ptbr/function/this.md | 108 ++++++++++++++ doc/ptbr/index.json | 69 +++++++++ doc/ptbr/intro/index.md | 38 +++++ doc/ptbr/object/forinloop.md | 41 ++++++ doc/ptbr/object/general.md | 83 +++++++++++ doc/ptbr/object/hasownproperty.md | 56 ++++++++ doc/ptbr/object/prototype.md | 109 ++++++++++++++ doc/ptbr/other/timeouts.md | 161 +++++++++++++++++++++ doc/ptbr/types/casting.md | 67 +++++++++ doc/ptbr/types/equality.md | 70 +++++++++ doc/ptbr/types/instanceof.md | 38 +++++ doc/ptbr/types/typeof.md | 83 +++++++++++ doc/ru/array/constructor.md | 2 +- doc/ru/core/delete.md | 88 ++++++++++++ doc/ru/object/forinloop.md | 2 +- doc/ru/object/general.md | 2 +- doc/ru/object/hasownproperty.md | 3 +- doc/ru/object/prototype.md | 15 +- doc/ru/types/casting.md | 5 +- doc/tr/function/scopes.md | 2 +- doc/tr/object/prototype.md | 2 +- doc/zh/function/arguments.md | 12 +- doc/zh/function/closures.md | 14 +- doc/zh/function/general.md | 9 +- doc/zh/function/scopes.md | 2 +- doc/zh/function/this.md | 11 +- doc/zh/intro/license.md | 2 +- doc/zh/object/forinloop.md | 1 - doc/zh/object/general.md | 8 +- doc/zh/object/hasownproperty.md | 11 +- doc/zh/object/prototype.md | 20 +-- doc/zh/types/equality.md | 1 + doc/zh/types/typeof.md | 2 +- doc/zhtw/core/eval.md | 2 +- doc/zhtw/function/general.md | 8 +- doc/zhtw/function/scopes.md | 4 +- doc/zhtw/function/this.md | 6 +- doc/zhtw/object/forinloop.md | 6 +- doc/zhtw/object/general.md | 8 +- doc/zhtw/object/hasownproperty.md | 4 +- doc/zhtw/object/prototype.md | 12 +- doc/zhtw/other/timeouts.md | 42 +++--- garden.jade | 30 ++-- package.json | 3 + site/javascript/garden.js | 51 +++---- site/javascript/plugin.js | 12 -- site/style/garden.css | 102 +++++++------ 168 files changed, 6480 insertions(+), 607 deletions(-) create mode 120000 JavaScript-Garden create mode 100644 doc/by/array/constructor.md create mode 100644 doc/by/array/general.md create mode 100644 doc/by/core/delete.md create mode 100644 doc/by/core/eval.md create mode 100644 doc/by/core/semicolon.md create mode 100644 doc/by/core/undefined.md create mode 100644 doc/by/function/arguments.md create mode 100644 doc/by/function/closures.md create mode 100644 doc/by/function/constructors.md create mode 100644 doc/by/function/general.md create mode 100644 doc/by/function/scopes.md create mode 100644 doc/by/function/this.md create mode 100644 doc/by/index.json create mode 100644 doc/by/intro/index.md create mode 100644 doc/by/object/forinloop.md create mode 100644 doc/by/object/general.md create mode 100644 doc/by/object/hasownproperty.md create mode 100644 doc/by/object/prototype.md create mode 100644 doc/by/other/timeouts.md create mode 100644 doc/by/types/casting.md create mode 100644 doc/by/types/equality.md create mode 100644 doc/by/types/instanceof.md create mode 100644 doc/by/types/typeof.md create mode 100644 doc/fr/array/constructor.md create mode 100644 doc/fr/array/general.md create mode 100644 doc/fr/core/delete.md create mode 100644 doc/fr/core/eval.md create mode 100644 doc/fr/core/semicolon.md create mode 100644 doc/fr/core/undefined.md create mode 100644 doc/fr/function/arguments.md create mode 100644 doc/fr/function/closures.md create mode 100644 doc/fr/function/constructors.md create mode 100644 doc/fr/function/general.md create mode 100644 doc/fr/function/scopes.md create mode 100644 doc/fr/function/this.md create mode 100644 doc/fr/index.json create mode 100644 doc/fr/intro/index.md create mode 100644 doc/fr/object/forinloop.md create mode 100644 doc/fr/object/general.md create mode 100644 doc/fr/object/hasownproperty.md create mode 100644 doc/fr/object/prototype.md create mode 100644 doc/fr/other/timeouts.md create mode 100644 doc/fr/types/casting.md create mode 100644 doc/fr/types/equality.md create mode 100644 doc/fr/types/instanceof.md create mode 100644 doc/fr/types/typeof.md create mode 100644 doc/ptbr/array/constructor.md create mode 100644 doc/ptbr/array/general.md create mode 100644 doc/ptbr/core/delete.md create mode 100644 doc/ptbr/core/eval.md create mode 100644 doc/ptbr/core/semicolon.md create mode 100644 doc/ptbr/core/undefined.md create mode 100644 doc/ptbr/function/arguments.md create mode 100644 doc/ptbr/function/closures.md create mode 100644 doc/ptbr/function/constructors.md create mode 100644 doc/ptbr/function/general.md create mode 100644 doc/ptbr/function/scopes.md create mode 100644 doc/ptbr/function/this.md create mode 100644 doc/ptbr/index.json create mode 100644 doc/ptbr/intro/index.md create mode 100644 doc/ptbr/object/forinloop.md create mode 100644 doc/ptbr/object/general.md create mode 100644 doc/ptbr/object/hasownproperty.md create mode 100644 doc/ptbr/object/prototype.md create mode 100644 doc/ptbr/other/timeouts.md create mode 100644 doc/ptbr/types/casting.md create mode 100644 doc/ptbr/types/equality.md create mode 100644 doc/ptbr/types/instanceof.md create mode 100644 doc/ptbr/types/typeof.md create mode 100644 doc/ru/core/delete.md delete mode 100644 site/javascript/plugin.js diff --git a/.gitignore b/.gitignore index b5dca426..2bfbed12 100644 --- a/.gitignore +++ b/.gitignore @@ -1,21 +1,15 @@ -/site/index.html /build /html /log /node_modules -/site/de -/site/ru -/site/zh -/site/en -/site/fi -/site/pl -/site/tr -/site/ko -/site/ja -/site/es -/site/hu -/site/zhtw -/site/it + +/site +!/site/favicon.ico +!/site/image +!/site/javascript +!/site/style +!/site/style + *.md~ *.src.md *.DS_store diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index df0b041b..fe3c6b6f 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,8 +1,19 @@ # Contributing to Javascript Garden -1. we're about Javascript AKA [ECMA script](http://www.ecma-international.org/ecma-262/5.1/) not a specific implementation. So we don't cover issues specific to one environment or interpreter, like browsers or V8 for node. -1. micro-performance is out of scope: anything that's not a result of essential algorithmic complexity (e.g O(log n) vs O(n^2)) is down to a specific version of a specific interpreter (see 1). -1. please test code examples to ensure they work, there's nothing more confusing than incorrect examples! -1. contributing to JS garden makes you a fantastic person, and Brendan Eich will find you immensely attrative. +1. We're about Javascript AKA [ECMA script](http://www.ecma-international.org/ecma-262/5.1/) not a specific implementation. So we don't cover issues specific to one environment or interpreter, like browsers or V8 for node. +1. Micro-performance is out of scope: anything that's not a result of essential algorithmic complexity (e.g O(log n) vs O(n^2)) is down to a specific version of a specific interpreter (see 1). +1. Please test code examples to ensure they work, there's nothing more confusing than incorrect examples! +1. Contributing to JS Garden makes you a fantastic person, and Brendan Eich will find you immensely attractive. Thank you for being kind enough to help out! + +## Testing locally + +1. Run `npm run build` to build +1. Run a webserver from the root of the repo to view + +## Getting changes merged + +1. Squash your changes into one commit +1. Make sure the site still works :) +1. Make a PR diff --git a/JavaScript-Garden b/JavaScript-Garden new file mode 120000 index 00000000..dcc6db5e --- /dev/null +++ b/JavaScript-Garden @@ -0,0 +1 @@ +./site \ No newline at end of file diff --git a/doc/by/array/constructor.md b/doc/by/array/constructor.md new file mode 100644 index 00000000..6eaa5f2a --- /dev/null +++ b/doc/by/array/constructor.md @@ -0,0 +1,31 @@ +## Канструктар `Array` + +Праз тое, што канструктар `Array` неадназначна апрацоўвае свае параметры, +крайне рэкамендуецца выкарыстоўваць літэрал - `[]` - для стварэння масіваў. + + [1, 2, 3]; // Вынік: [1, 2, 3] + new Array(1, 2, 3); // Вынік: [1, 2, 3] + + [3]; // Вынік: [3] + new Array(3); // Вынік: [] + new Array('3') // Вынік: ['3'] + +У выпадку, калі канструктару `Array` перадаецца толькі адзін параметр, і калі гэты +аргумент тыпу `Number`, канструктар верне *разрэджаны* масіў, які мае уласціваць +`length` са значэннем аргумента. Варта адзначыць, што такім чынам будзе зменена +**толькі** значэнне ўласцівасці `length` масіва; індэксы масіва не будуць +праініцыялізаваныя. + + var arr = new Array(3); + arr[1]; // undefined + 1 in arr; // false, індэкс не праініцыялізаваны + +Магчымасць загадзя вызначыць даўжыню масіва карысна толькі ў рэдкіх выпадках, +напрыклад, паўтор радка без выкарыстання цыкла. + + new Array(count + 1).join(stringToRepeat); + +### У заключэнне + +Літэралы маюць перавагі над канструктарам Array. Яны карацейшыя, маюць больш чысты +сінтаксіс і робяць код больш чытэльным. diff --git a/doc/by/array/general.md b/doc/by/array/general.md new file mode 100644 index 00000000..3e358d5a --- /dev/null +++ b/doc/by/array/general.md @@ -0,0 +1,56 @@ +## Ітэрацыі па масівам і ўласцівасці + +Хоць масівы ў JavaScript — аб'екты, няма добрых падставаў для таго, каб +выкарыстоўваць [цыкл `for in`](#object.forinloop) для ітэрацыі па масівах. +Фактычна, ёсць шэраг добрых падстаў **супраць** гэтага. + +> **Заўвага:** масівы JavaScript **не** *асацыятыўныя масівы*. JavaScript мае +> [аб'екты](#object.general) для структуры ключ-значэнне. Але калі асацыятыўныя +> масівы **захоўваюць** парадак, аб'екты — **не**. + +З той прычыны, што цыкл `for in` пералічвае ўсе ўласцівасці, якія ёсць у ланцужку прататыпаў, +і таму, што адзіны спосаб выключыць гэтыя значэнні — [`hasOwnProperty`](#object.hasownproperty), +ітэрацыя атрымліваецца ў **20 разоў** марудней за звычайны цыкл `for`. + +### Ітэрацыя + +Для таго, каб атрымаць найлепшую прадукцыйнасць у ітэрацыі па масіву, лепш +выкарыстаць класічны цыкл `for`. + + var list = [1, 2, 3, 4, 5, ...... 100000000]; + for(var i = 0, l = list.length; i < l; i++) { + console.log(list[i]); + } + +У вышэйпрыведзеным прыкладзе ёсць яшчэ адзін прыём, з дапамогай якога можна кэшаваць +памер масіва: `l = list.length`. + +Негледзячы на тое, што ўласцівасць `length` вызначана ў самім масіве, пошук +гэтай уласцівасці накладвае выдаткі на пошук пры кожнай ітэрацыі цыкла. І хоць +новыя рухавікі JavaScript **могуць** прымяніць аптымізацыю у гэтым выпадку, няма +магчымасці дакладна ведаць, ці будзе код выкананы на гэтых новых рухавіках. + +Фактычна, адсутнасць кэшавання можа зрабіць выкананне цыкла **ў два разы больш +марудным**, чым з кэшаваным 'length'. + +### Уласцівасць `length` + +Хоць *гэтэр* уласцівасці `length` проста вяртае колькасць элементаў, што +знаходзяцца у масіве, *сэтэр* можа быць выкарыстаны для **абразання** масіва. + + var arr = [1, 2, 3, 4, 5, 6]; + arr.length = 3; + arr; // [1, 2, 3] + + arr.length = 6; + arr.push(4); + arr; // [1, 2, 3, undefined, undefined, undefined, 4] + +Прысвойванне ўласцівасці 'length' меншага значэння абразае масіў. Прысваенне большага +значэнне створыць разрэджаны масіў. + +### У заключэнне + +Для лепшай прадукцыйнасці рэкамендуецца заўсёды выкарыстоўваць звычайны цыкл `for`, +і кэшаваць уласціваць `length`. Выкарыстоўванне `for in` для ітэрацыі па масіву — +прыкмета дрэнна напісанага коду, схільнага да памылак і дрэннай прадукцыйнасці. diff --git a/doc/by/core/delete.md b/doc/by/core/delete.md new file mode 100644 index 00000000..07e2c1ce --- /dev/null +++ b/doc/by/core/delete.md @@ -0,0 +1,81 @@ +## Аператар `delete` + +У JavaScript *немагчыма* выдаліць глабальныя пераменныя, функцыі і некаторыя іншыя +рэчы, што маюць атрыбут `DontDelete`. + +### Глабальны код і код функцый. + +Калі пераменная або функцыя аб'яўленыя ў глабальнай зоне бачнасці, або [зоне бачнасці +функцыі](#function.scopes) то яна будзе ўласцівасцю або аб'екта актывацыі, або +глабальнай зоны бачнасці. Такія ўласцівасці маюць набор атрыбутаў, адзін з іх — +`DontDelete`. Пераменныя і функцыі, аб'яўленыя ў глабальнай зоне бачнасці і зоне +бачнасці функцыі, заўсёды ствараюцца з уласцівасцю `DontDelete`, а таму не могуць +быць выдаленыя. + + // глабальная пераменная: + var a = 1; // мае ўласцівасць DontDelete + delete a; // false + a; // 1 + + // звычайная функцыя: + function f() {} // мае ўласціваць DontDelete + delete f; // false + typeof f; // "function" + + // перапрызначэнне не дапамагае: + f = 1; + delete f; // false + f; // 1 + +### Яўна прызначаныя ўласцівасці + +Яўна прызначаныя ўласцівасці могуць быць лёгка выдаленыя. + + // яўна прызначаныя ўласцівасці: + var obj = {x: 1}; + obj.y = 2; + delete obj.x; // true + delete obj.y; // true + obj.x; // undefined + obj.y; // undefined + +У вышэйпрыведзеным прыкладзе, `obj.x` і `obj.y` могуць быць выдаленыя, бо не маюць +атрыбута `DontDelete`. Таму і прыкад ніжэй працуе: + + // Гэта працуе правільна, акрамя IE: + var GLOBAL_OBJECT = this; + GLOBAL_OBJECT.a = 1; + a === GLOBAL_OBJECT.a; // true — глабальная пераменная + delete GLOBAL_OBJECT.a; // true + GLOBAL_OBJECT.a; // undefined + +Гэта прыём, каб выдаліць `a`. [`this`](#function.this) спасылаецца на глабальны +аб'ект, і мы яўна аб'яўляем пераменную `a` як яго ўласцівасць, што дазваляе нам +выдаліць яе. + +IE (прынамсі 6-8) мае хібы, таму вышэйпрыведзены код там працаваць не будзе. + +### Аргументы функцый і ўбудаваныя ўласцівасці + +Звычайныя аргументы функцыі, [аб'ект `arguments`](#function.arguments), а таксама +убудаваныя ўласцівасці таксама маюць атрыбут `DontDelete`. + + // аргументы функцыі і ўласцівасці: + (function (x) { + + delete arguments; // false + typeof arguments; // "object" + + delete x; // false + x; // 1 + + function f(){} + delete f.length; // false + typeof f.length; // "number" + + })(1); + +### У заключэнне + +Аператар `delete` часта паводзіць сябе нечакана, таму адзінае надзейнае выкарыстанне +`delete` — выдаленне яўна прызначаных уласцівасцяў. diff --git a/doc/by/core/eval.md b/doc/by/core/eval.md new file mode 100644 index 00000000..7e07dbcd --- /dev/null +++ b/doc/by/core/eval.md @@ -0,0 +1,47 @@ +## Чаму не варта выкарыстоўваць `eval` + +Функцыя `eval` выконвае радок JavaScript коду ў лакальнай зоне бачнасці. + + var number = 1; + function test() { + var number = 2; + eval('number = 3'); + return number; + } + test(); // 3 + number; // 1 + +Тым не менш, `eval` выконваецца ў лакальнай прасторы імён толькі ў тым выпадку, калі +яна была выклікана наўпрост *і* імя выкліканай функцыі — `eval`. + + var number = 1; + function test() { + var number = 2; + var copyOfEval = eval; + copyOfEval('number = 3'); + return number; + } + test(); // 2 + number; // 3 + +Лепш пазбягаць выкарыстоўвання `eval`. 99,9% яе «выкарыстанняў» можа быць дасягнута +**без** яе. + +### Схаваны `eval` + +Абедзве [функцыі тайм-аўты](#other.timeouts) `setTimeout` і `setInterval` могуць +прымаць радок у якасці першага аргумента. Гэты радок будзе **заўсёды** выконвацца +ў глабальнай прасторы імёнаў, бо `eval` не выклікаецца наўпрост у дадзеным выпадку. + +### Праблемы з бяспекаю + +Таксама `eval` мае праблемы з бяспекаю, бо ён выконвае **любы** перададзены код. +Таму яе **ніколі** не варта выкарыстоўваць з радкамі, што паходзяць з ненадзейных +крыніцаў. + +### Заключэнне + +Лепш ніколі не выкарыстоўваць `eval`. Любы код, што выкарыстоўвае яе, спрэчны ў +плане якасці, карэктнасці, прадукцыйнасці і бяспекі. Калі для таго, каб нешта +працавала, патрэбны `eval`, **не** трэба прымаць гэта рашэнне ў першую чаргу. +*Лепшым рашэннем* будзе тое, што не будзе выкарыстоўваць `eval`. diff --git a/doc/by/core/semicolon.md b/doc/by/core/semicolon.md new file mode 100644 index 00000000..db78ed7d --- /dev/null +++ b/doc/by/core/semicolon.md @@ -0,0 +1,109 @@ +## Аўтаматычная ўстаўка кропкі з коскай + +Хаця JavaScript мае C-падобны сінтакс, ён **не** прымушае выкарыстоўваць кропку +з коскай у кодзе, таму ёсць магчымасць прапускаць іх. + +Але JavaScript — не мова без кропак з коскай. Насамрэч яны патрэбны ёй, каб разумець +зыходны код. Таму парсер JavaScript **аўтаматычна** ўстаўляе іх паўсюль, дзе +сустракае памылку адсутнасці кропкі з коскай. + + var foo = function() { + } // памылка разбора, парсер чакаў кропку з коскай + test() + +Адбываецца ўстаўка, парсер спрабуе зноў. + + var foo = function() { + }; // памылкі няма, парсер працягвае + test() + +Аўтаматычная ўстаўка кропкі з коскай лічыцца адной з **найвялікшых** архітэктурных +памылак у мове, бо *можа* змяніць паводзіны кода. + +### Як яно працуе + +Ніжэйпрыведзены код не мае кропак з коскай, таму парсер вырашае дзе іх уставіць. + + (function(window, undefined) { + function test(options) { + log('testing!') + + (options.list || []).forEach(function(i) { + + }) + + options.value.test( + 'long string to pass here', + 'and another long string to pass' + ) + + return + { + foo: function() {} + } + } + window.test = test + + })(window) + + (function(window) { + window.someLibrary = {} + + })(window) + +Ніжэй — вынік гульні парсера ў адгадванне. + + (function(window, undefined) { + function test(options) { + + // Не ўстаўлена, радкі былі аб'яднаныя + log('testing!')(options.list || []).forEach(function(i) { + + }); // <- устаўлена + + options.value.test( + 'long string to pass here', + 'and another long string to pass' + ); // <- устаўлена + + return; // <- устаўлена, разбіў аператар return на два блока + { // парсер лічыць гэты блок асобным + foo: function() {} + }; // <- устаўлена + } + window.test = test; // <- устаўлена + + // Радкі зноў аб'ядналіся + })(window)(function(window) { + window.someLibrary = {}; // <- устаўлена + + })(window); //<- устаўлена + +> **Заўвага:** Парсер JavaScript не апрацоўвае "карэктна" аператар return, калі +> пасля яго пачынаецца новы радок. Магчыма прычына і не ў аўтаматычнай устаўцы +> кропак з коскай, але гэта, тым не менш, непажаданы эфект. + +Парсер кардынальна памяняў паводзіны кода. У пэўных выпадках ён прымае **памылковыя +рашэнні**. + +### Вядучыя дужкі + +У выпадку вядучай дужкі парсер **не** уставіць кропку з коскай. + + log('testing!') + (options.list || []).forEach(function(i) {}) + +Гэты код ператворыцца ў радок. + + log('testing!')(options.list || []).forEach(function(i) {}) + +**Вельмі** верагодна, што `log` **не** вяртае функцыю; Таму вышэйпрыведзены +код справакуе `TypeError` з заявай, што `undefined` не з'яўляецца функцыяй. + +### Заключэнне + +Крайне рэкамендуецца **ніколі** не прапускаць кропку з коскай. Таксама заўсёды +рэкамендуецца ставіць дужкі на той жа лініі, што і адпаведныя канструкцыі, і ніколі +не прапускаць іх у аднарадковых канструкцыях `if` / `else`. Гэтыя меры не толькі +павысяць кансістэнтнасць кода, але таксама прадухіляць ад таго, што парсер +JavaScript зменіць паводзіны кода. diff --git a/doc/by/core/undefined.md b/doc/by/core/undefined.md new file mode 100644 index 00000000..18af0f2d --- /dev/null +++ b/doc/by/core/undefined.md @@ -0,0 +1,69 @@ +## `undefined` і `null` + +JavaScript мае два розныя значэнні для 'нічога' - гэта `null` і `undefined`, пры +гэтым апошняе больш карыснае. + +### Значэнне `undefined` + +`undefined` — гэта тып з роўна адным значэннем: `undefined`. + +Мова таксама аб'яўляе глабальную пераменную, што мае значэнне `undefined`; Гэта +пераменная таксама называецца `undefined`. Тым не менш, гэта пераменная, а **не** +канстанта, ці ключавое слова. Гэта азначае, што яе *значэнне* можа быць +з лёгкасцю перазапісаным. + +> **Заўвага для ES5:** у ECMAScript 5 `undefined` **больш** *нельга запісваць* у +> строгім рэжыме, але гэта імя можа ўся яшчэ быць перакрыта праз выкарыстанне +> функцыі з іменем `undefined`. + +Ніжэй пералічаныя некалькі выпадкаў, калі вяртаецца `undefined`: + + - Доступ да (немадыфікаванай) глабальнай пераменнай `undefined`. + - Доступ да аб'яўленай, *але яшчэ не* ініцыалізаванай пераменнай. + - Няяўна вернутае значэнне функцыі праз адсутнасць аператара `return`. + - З аператара `return`, які нічога яўна не вяртае. + - У выніку пошуку неіснуючай уласцівасці аб'екта. + - Параметры функцыі, якім яўна не было прысвоена значэнне. + - Усё, чаму было прысвоена значэнне `undefined`. + - Любы выраз у форме `void(expression)`. + +### Апрацоўка зменаў значэння `undefined` + +З той прычыны, што глабальная пераменная `undefined` утрымлівае толькі копію +актуальнага *значэння* `undefined`, прысвойванне ёй новага значэння **не** мяняе +значэнне *тыпа* `undefined`. + +Таксама для таго, каб параўнаць што-небудзь з значэннем `undefined`, спачатку +трэба атрымаць значэнне `undefined`. + +Звыклая тэхніка абароны ад магчымага перазапісвання пераменнай `undefined` — +дадатковы параметр у [ананімнай абгортцы](#function.scopes), што выкарыстоўвае +адсутны аргумент. + + var undefined = 123; + (function(something, foo, undefined) { + // цяпер undefined у лакальнай зоне бачнасці + // зноў спасылаецца на значэнне `undefined` + + })('Hello World', 42); + +Гэтага ж выніку можна дасягнуць праз аб'яўленне ўнутры абгорткі. + + var undefined = 123; + (function(something, foo) { + var undefined; + ... + + })('Hello World', 42); + +Адзіная розніца ў тым, што гэта апошняя версія будзе большай на 4 байты пры +мініфікацыі, а ў першым унутры ананімнай абгорткі не будзе аператара `var`. + +### Выкарыстоўванне `null` + +Хаця `undefined` у кантэксце мовы JavaScript у асноўным выкарыстоўваецца ў сэнсе +традыйнага *null*, сам `null` (і літэрал і тып) з'яўляецца яшчэ адным тыпам дадзеных. + +Выкарыстоўваецца ў некаторых унутранных механізмах JavaScript (напрыклад аб'яўленне +канца ланцужка прататыпаў пазначаючы `Foo.prototype = null`), але амаль што ва ўсіх +выпадках ён можа быць заменены на `undefined`. diff --git a/doc/by/function/arguments.md b/doc/by/function/arguments.md new file mode 100644 index 00000000..98ac3d2b --- /dev/null +++ b/doc/by/function/arguments.md @@ -0,0 +1,130 @@ +## Аб'ект `arguments` + +У зоне бачнасці любой функцыі JavaScript ёсць доступ да адмысловай пераменнай +`arguments`. Гэтая пераменная утрымлівае спіс усіх аргументаў, што былі +перададзеныя функцыі. + +> **Заўвага:** У выпадку, калі `arguments` ужо быў створаны ўнутры зоны бачнасці +> функцыі праз выраз `var`, або з'яўляецца фармальным параметрам, +> аб'ект `arguments` не будзе створаны. + +Аб'ект `arguments` **не з'яўляецца** спадкаемцам `Array`. Ён мае падабенствы +з масівам, напрыклад уласцівасць `length`. Але ён не ўспадкоўвае `Array.prototype`, +а ўяўляе з сябе `Object`. + +Таму **не**магчыма выклікаць стандартныя метады `push`, `pop` або `slice` +у аб'екта `arguments`. Тым не менш, ітэрацыя з звычайным цыклам `for` працуе карэктна. +Неабходна канвертаваць яго ў сапраўдны аб'ект `Array`, каб прымяніць стандартныя +метады масіваў. + +### Канвертацыя ў масіў + +Ніжэйпрыведезны код верне новы масіў, які будзе ўтрымліваць усе элементы аб'екта +`arguments`. + + Array.prototype.slice.call(arguments); + +Такая канвертацыя **марудная**, яе **не рэкамендуецца** выкарыстоўваць у крытычных +у плане прадукцыйнасці частках кода. + +### Перадача `arguments` + +Ніжэй прадстаўлены рэкамендаваны спосаб перадачы аргументаў з адной функцыі ў іншую. + + function foo() { + bar.apply(null, arguments); + } + function bar(a, b, c) { + // тут робім што-небудзь + } + +Яшчэ адзін прыём — гэта выкарыстанне `call` і `apply` разам, каб ператварыць метады, +што выкарыстоўваюць значэнне `this` як і свае аргументы, у звычайныя функцыі, +што выкарыстоўваюць толькі аргументы. + + function Person(first, last) { + this.first = first; + this.last = last; + } + + Person.prototype.fullname = function(joiner, options) { + options = options || { order: "western" }; + var first = options.order === "western" ? this.first : this.last; + var last = options.order === "western" ? this.last : this.first; + return first + (joiner || " ") + last; + }; + + // Ствараем незвязаную версію "fullname", што можа быць выкарыстана з любым + // аб'ектам, які мае ўласцівасці 'first' і 'last', перададзеным у якасці + // першага параметра. Гэтую абгортку не трэба будзе мяняць, калі колькасць або + // парадак аргументаў fullname зменяцца. + Person.fullname = function() { + // Result: Person.prototype.fullname.call(this, joiner, ..., argN); + return Function.call.apply(Person.prototype.fullname, arguments); + }; + + var grace = new Person("Grace", "Hopper"); + + // 'Grace Hopper' + grace.fullname(); + + // 'Turing, Alan' + Person.fullname({ first: "Alan", last: "Turing" }, ", ", { order: "eastern" }); + + +### Фармальныя параметры і індэксы аргументаў + +Аб'ект `arguments` стварае *гэтэр* і *сэтэр* як да кожнай са сваіх уласцівасцяў, +так і да фармальных параметраў функцыі. + +У выніку змена значэння фармальнага параметра зменіць таксама адпаведную ўласцівасць +аб'екта `arguments`, і наадварот. + + function foo(a, b, c) { + arguments[0] = 2; + a; // 2 + + b = 4; + arguments[1]; // 4 + + var d = c; + d = 9; + c; // 3 + } + foo(1, 2, 3); + +### Міфы і праўда аб прадукцыйнасці + +Адзінае, калі `arguments` не ствараецца, — гэта калі ёсць фармальны аргумент функцыі +або пераменная ўнутры яе з такім іменем. Не важна, выкарыстоўваюцца яны ці не. + +Як *гэтэры*, так і *сэтэры* ствараюцца **заўсёды**, таму іх выкарыстоўванне не +мае амаль ніякага ўплыву на прадукцыйнасць. + +> **Заўвага для ES5:** *гэтэры* і *сэтэры* не ствараюцца ў строгім рэжыме. + +Тым не менш, ёсць адна рэч, якая можа жахліва знізіць прадукцыйнасць у сучасных +рухавіках JavaScript — гэта выкарыстанне `arguments.callee`. + + function foo() { + arguments.callee; // робім што-небудзь з функцыяй foo + arguments.callee.caller; // і з функцыяй, якая выклікала foo + } + + function bigLoop() { + for(var i = 0; i < 100000; i++) { + foo(); // Звычайна ўстаўляецца... + } + } + +У вышэйпрыведзеным кодзе `foo` больш не можа быць [устаўлена][1], бо ёй трэба +ведаць аб сабе і аб функцыі, што яе выклікала. Гэта не толькі знішчае павышэнне +прадукцыйнасці, якое магло адбыцца дзякуючы ўстаўцы, але і парушае інкапсуляцыю, бо +функцыя цяпер залежыць ад спецыфічнага кантэксту, які яе выклікае. + +Выкарыстоўванне `arguments.callee` або яго ўласцівасцяў **вельмі непажадана**. + +> **Заўвага для ES5:** У строгім рэжыме `arguments.callee` кіне памылку `TypeError`, +> бо яго выкарыстанне аб'яўлена састарэлым. + +[1]: http://en.wikipedia.org/wiki/Inlining diff --git a/doc/by/function/closures.md b/doc/by/function/closures.md new file mode 100644 index 00000000..23911e6a --- /dev/null +++ b/doc/by/function/closures.md @@ -0,0 +1,113 @@ +## Замыканні і спасылкі + +Адна з найбольш магутных магчымасцяў JavaScript — магчымасць ствараць *замыканні*. +Зона бачнасці замыканняў **заўсёды** мае доступ да знешняй зоны бачнасці, у якой +замыканне было аб'яўлена. З той прычыны, што ў JavaScript адзіны механізм працы +з зонай бачнасці — гэта [зоны бачнасці функцыі](#function.scopes), усе функцыі +выступаюць у якасці замыканняў. + +### Эмуляцыя прыватных пераменных + + function Counter(start) { + var count = start; + return { + increment: function() { + count++; + }, + + get: function() { + return count; + } + } + } + + var foo = Counter(4); + foo.increment(); + foo.get(); // 5 + +Тут `Counter` вяртае **два** замыканні: функцыю `increment` і функцыю `get`. +Абедзьве функцыі маюць **спасылку** на зону бачнасці `Counter` і таму заўсёды +маюць доступ да пераменнай `count`, што была аб'яўлена ў гэтай зоне бачнасці. + +### Якім чынам гэта працуе + +З той прычыны, што ў JavaScript немагчыма спасылацца або прысвойваць зоны бачнасці, +**немагчыма** атрымаць доступ да пераменнай `count` звонку. Адзіны спосаб +узаемадзейнічаць з ім — выкарыстоўваць два замыканні. + + var foo = new Counter(4); + foo.hack = function() { + count = 1337; + }; + +Вышэйпрыведзены код **не** памяняе значэнне пераменнай `count` у зоне бачнасці +`Counter`, бо `foo.hack` не быў аб'яўлены у **гэтай** зоне бачнасці. Замест гэтага +ён створыць або перазапіша *глабальную* пераменную `count`. + +### Замыканні ўнутры цыклаў + +Частая памылка - выкарыстанне замыканняў унутры цыклаў, як быццам бы яны капіруюць +значэнне пераменнай індэксу цыкла. + + for(var i = 0; i < 10; i++) { + setTimeout(function() { + console.log(i); + }, 1000); + } + +Вышэйпрыведзены код **не** выведзе нумары ад `0` да `9`, ён проста выведзе +нумар `10` дзесяць разоў. + +*Ананімная* функцыя захоўвае **спасылку** на `i`. У той час, калі функцыя `console.log` +выклікаецца, `цыкл for` ужо адпрацаваў, а значэнне `i` ўжо стала `10`. + +Каб атрымаць пажаданыя паводзіны, неабходна стварыць **копію** значэння `i`. + +### Як абыйсці праблемы спасылкі + +Каб стварыць копію значэння пераменнай індэкса цыкла, лепшы спосаб — стварэнне +[ананімнай абгорткі](#function.scopes). + + for(var i = 0; i < 10; i++) { + (function(e) { + setTimeout(function() { + console.log(e); + }, 1000); + })(i); + } + +Знешняя ананімная функцыя выконваецца імгненна з `i` ў якасці першага аргумента +і атрымае копію **значэння** `i` ў якасці параметра `e`. + +Ананімная функцыя, што перадаецца метаду `setTimeout`, цяпер мае спасылку на +`e`, чыё значэнне **не** мяняецца на працягу цыкла. + +Яшчэ адзін спосаб атрымаць такі вынік — вяртаць функцыю з ананімнай абгорткі, +што будзе паводзіць сябе такім жа чынам, як і папярэдні прыклад. + + for(var i = 0; i < 10; i++) { + setTimeout((function(e) { + return function() { + console.log(e); + } + })(i), 1000) + } + +Яшчэ адзін папулярны спосаб дасягнуць гэтага — дадаць яшчэ адзін аргумент выкліку +функцыі `setTimeout`, якая перадасць агрумент функцыі зваротнага выкліку. + + for(var i = 0; i < 10; i++) { + setTimeout(function(e) { + console.log(e); + }, 1000, i); + } + +Некаторыя старыя асяродкі JS (Internet Explorer 9 і ніжэй) не падтрымліваюць +гэтую магчымасць. + +Таксама магчыма выканаць гэта выкарыстоўваючы `.bind`, якая можа звязаць +`this` і аргументы функцыі. Ніжэйпрыведзены прыклад працуе як папярэднія. + + for(var i = 0; i < 10; i++) { + setTimeout(console.log.bind(console, i), 1000); + } diff --git a/doc/by/function/constructors.md b/doc/by/function/constructors.md new file mode 100644 index 00000000..1da70bf5 --- /dev/null +++ b/doc/by/function/constructors.md @@ -0,0 +1,122 @@ +## Канструктары + +Канструктары ў JavaScript таксама адрозніваюцца ад большасці іншых моваў. Любы +выклік функцыі, якому папярэднічае ключавое слова `new` з'яўляецца канструктарам. + +Унутры канструктара (выкліканай функцыі) - значэнне `this` спасылаецца на +новаствораны аб'ект. [Прататыпам](#object.prototype) **новага** +аб'екта прызначаецца `prototype` функцыі, што была выклікана ў якасці канструктара. + +У выпадку, калі выкліканая функцыя не вяртае яўнага значэння праз `return`, будзе +не яўна вернута значэнне `this`, то бок новы аб'ект. + + function Person(name) { + this.name = name; + } + + Person.prototype.logName = function() { + console.log(this.name); + }; + + var sean = new Person(); + +У гэтым прыкладзе `Person` выклікаецца ў якасці канструктара, адпаведна `prototype` +створанага аб'екта будзе прывязаны да `Person.prototype`. + +Вярнуць яўнае значэнне праз `return`, можна **толькі** калі гэта значэнне - `Object`. + + function Car() { + return 'ford'; + } + new Car(); // новы аб'ект, не 'ford' + + function Person() { + this.someValue = 2; + + return { + name: 'Charles' + }; + } + new Person(); // вяртае аб'ект ({name:'Charles'}), які не ўтрымлівае someValue + +Калі ключавое слова `new` прапушчана, функцыя **не** верне аб'ект. + + function Pirate() { + // пазначыць значэнне ў глабальным аб'екце! + this.hasEyePatch = true; + } + var somePirate = Pirate(); // somePirate == undefined + +Гэты прыклад можа спрацаваць у некаторых выпадках, праз тое як працуе +[`this`](#function.this) у JavaScript. Значэннем `this` тут будзе +*глабальны аб'ект*. + +### Фабрыкі + +Каб мець магчымасць прапусціць ключавое слова `new`, канструктар функцыі мае яўна +вяртаць значэнне. + + function Robot() { + var color = 'gray'; + return { + getColor: function() { + return color; + } + } + } + + new Robot(); + Robot(); + +Абодва выклікі `Robot` вернуць тое ж самае, новы аб'ект, які мае ўласцівасць +`getColor`, што з'яўляецца [замыканнем](#function.closures). + +Таксама варта адзначыць, што выклік `new Robot()` **не** ўплывае на прататып +вернутага аб'екта. Хаця прататып будзе прызначаны новастворанаму аб'екту, `Robot` +ніколі не верне гэты аб'ект. + +У прыкладзе вышэй, няма розніцы паміж выклікам функцыі з аператарам `new` або +без яго. + + +### Стварэнне новых аб'ектаў з выкарыстаннем фабрык + +Часта рэкамендуюць **не** выкарыстоўваць `new` бо забыўшыся выкарыстаць яго, можна +стварыць памылку. + +Каб стварыць новы аб'ект, лепш выкарыстоўваць фабрыку і стварыць новы аб'ект +*унутры фабрыкі*. + + function CarFactory() { + var car = {}; + car.owner = 'nobody'; + + var milesPerGallon = 2; + + car.setOwner = function(newOwner) { + this.owner = newOwner; + } + + car.getMPG = function() { + return milesPerGallon; + } + + return car; + } + +Хоць гэты прыклад і спрацуе негледзячы на забытае `new`, і бясспрэчна выкарыстоўвае +[прыватныя пераменныя](#function.closures), ён мае некалькі недахопаў. + + 1. Ён выкарыстоўвае больш памяці, бо функцыі створаных аб'ектаў **не** захоўваюццца + у прататыпе, а ствараюцца на нова для кожнага аб'екта. + 2. Каб эмуляваць спадкаемства, фабрыка мае скапіраваць метады іншага аб'екта, або + пазначыць прататыпам новага аб'екта стары. + 3. Разрыў ланцужка прататыпаў, проста па прычыне забытага ключавога слова `new`, + не адпавядае духу мовы JavaScript. + +### У заключэнне + +Негледзячы на тое, што прапушчанае `new` можа выліцца ў памылку, гэта **не** +прычына адмовіцца ад выкарыстання прататыпаў. У выніку лепш высвятліць якое рашэнне +больш адпавядае патрабаванням праграмы. Асабліва важна выбраць пэўны стыль і +**паслядоўна** выкарыстоўваць яго. diff --git a/doc/by/function/general.md b/doc/by/function/general.md new file mode 100644 index 00000000..da5f4ba3 --- /dev/null +++ b/doc/by/function/general.md @@ -0,0 +1,48 @@ +## Выразы і аб'яўленне функцый + +У JavaScript функцыі таксама з'яўляюцца аб'ектамі. Гэта значыць іх можна перадаваць +і прысвойваць як і любыя іншыя аб'екты. Адзін, часта выкарыстоўваемы варыянт, +гэтай магчымасці - перадача *ананімнага метада* як функцыі зваротнага выкліку +іншай, магчыма асінхроннай функцыі. + +### Аб'яўленне `function` + + function foo() {} + +У вышэй прыведзеным прыкладзе функцыя [уздымаецца](#function.scopes) перад тым +як пачынаецца выконванне праграмы; Такім чынам, яна даступная *паўсюль* у зоне +бачнасці, у якой яна была *аб'яўлена*, нават калі выклік адбываецца да фактычнага +аб'яўлення ў кодзе. + + foo(); // Працуе, бо функцыя будзе створана да выконвання кода + function foo() {} + +### `function` як выраз + + var foo = function() {}; + +У гэтым прыкладзе пераменнай `foo` прысвойваецца *ананімная* функцыя. + + foo; // 'undefined' + foo(); // уздыме TypeError + var foo = function() {}; + +Праз тое, што `var` - гэта аб'яўленне якое уздымае імя пераменнай `foo` перад тым +як код будзе выкананы, `foo` будзе ўжо аб'яўленым калі ён пачне выконвацца. + +Але так як прысвойванні адбываюцца толькі пад час выконвання, значэнне `foo` +будзе змоўчанным ([undefined](#core.undefined)) да выконвання адпаведнага кода. + +### Выразы з іменаванымі функцыямі + +Яшчэ адзін выбітны выпадак - прысвойванне іменавай функцыі. + + var foo = function bar() { + bar(); // працуе + } + bar(); // ReferenceError + +Тут, `bar` не даступны ў знешнім скоўпе, бо функцыя толькі прысвойваецца пераменнай +`foo`; аднак, унутры `bar`, імя даступнае. Так адбываецца праз асаблівасці працы +з [прастранствамі імён](#function.scopes) у JavaScript - імя функцыі *заўсёды* +даступнае ў лакальным скоўпе функцыі. diff --git a/doc/by/function/scopes.md b/doc/by/function/scopes.md new file mode 100644 index 00000000..7ade2cfd --- /dev/null +++ b/doc/by/function/scopes.md @@ -0,0 +1,230 @@ +## Зоны бачнасці і прасторы імёнаў + +Негледзячы на тое, што JavaScript добра працуе з сінтаксісам фігурных дужак для +блокаў, у ім **няма** падтрымкі блочнай зоны бачнасці; усё што ёсць на гэты конт +у мове - *зона бачнасці функцыі*. + + function test() { // зона бачнасці + for(var i = 0; i < 10; i++) { // не зона бачнасці + // лічым + } + console.log(i); // 10 + } + +> **Заўвага:** Калі не выкарыстана ў прысвойванні, аператары return або аргуменце +> функцыі, натацыя `{...}` будзе інтэрпрэтавана як блочны выраз, а **не** як літэрал +> аб'екта. Гэта з'ява, сумесна з [аўтаматычнай устаўкай коскі з кропкай](#core.semicolon), +> можа прывесці да хітрых памылак. + +Таксама JavaScript не падтрымлівае выразныя прасторы імёнаў, усё аб'яўляецца ў +агульнадаступнай прасторы імёнаў. + +Для кожнай спасылкі на пераменную, JavaScript пойдзе ўверх па ўсіх зонах бачнасці, +пакуль не знойдзе яе. У выпадку, калі ён дойдзе да глабальнай прасторы імён і ўсё +яшчэ не знойдзе неабходнае імя, ён уздыме `ReferenceError`. + +### Атрута глабальнымі пераменнымі + + // скрыпт A + foo = '42'; + + // скрыпт B + var foo = '42' + +Вышэйпрыведзеныя скрыпты маюць **розныя** вынікі. Скрыпт A аб'яўляе пераменную +`foo` у *глабальнай* зоне бачнасці, скрыпт B аб'яўляе `foo` у *актуальнай* зоне +бачнасці. + +Паўторымся, гэта абсалютна **не** *той жа самы вынік*: не выкарыстоўваенне `var` +можа мець сур'ёзныя наступствы. + + // глабальная зона бачнасці + var foo = 42; + function test() { + // лакальная зона бачнасці + foo = 21; + } + test(); + foo; // 21 + +З-за таго, што аператар `var` прапушчаны ўнутры функцыі `test`, значэнне `foo` +у глабальнай прасторы імён будзе перазапісаным. Хаця першапачаткова гэта можа +падацца невялікай праблемай, не выкарыстоўванне `var` у кодзе на тысячы радкоў, +прывядзе да жахлівых, цяжкіх для адладкі памылак. + + // глабальная прастора імёнаў + for(var i = 0; i < 10; i++) { + subLoop(); + } + + function subLoop() { + // прастора імёнаў subLoop + for(i = 0; i < 10; i++) { // аператар var прапушчаны + // робім чароўныя рэчы! + } + } + +Знешні цыкл скончыцца пасля першага выкліка `subLoop`, бо `subLoop` перазапісвае +глабальную пераменную `i`. Выкарыстоўваючы `var` для другога цыкла `for` можна +было б пазбегнуць памылкі. **Ніколі** не прапускайце аператар `var`, акрамя +выпадкаў, калі змена дадзеных у знешняй зоне бачнасці ёсць *пажаданым вынікам*. + +### Лакальныя пераменныя + +Адзіная крыніца лакальных пераменных у JavaScript гэта параметры [функцыі](#function.general) +і пераменныя аб'яўленыя праз аператар `var`. + + // глабальная зона бачнасці + var foo = 1; + var bar = 2; + var i = 2; + + function test(i) { + // лакальная зона бачнасці функцыі test + i = 5; + + var foo = 3; + bar = 4; + } + test(10); + +`foo` і `i` гэта лакальныя пераменныя унутры зоны бачнасці функцыі `test`, +а вось прызначэнне `bar` перазапіша глабальныю пераменную з тым жа іменем. + +### Падыманне + +JavaScript **падымае** аб'яўленні. Гэта азначае, што абодва аб'яўленні аператараў +`var` і `function` падымуцца на верх іх зоны бачнасці. + + bar(); + var bar = function() {}; + var someValue = 42; + + test(); + function test(data) { + if (false) { + goo = 1; + + } else { + var goo = 2; + } + for(var i = 0; i < 100; i++) { + var e = data[i]; + } + } + +Вышэйпрыведзены код трансфармуецца перад пачаткам выконвання. JavaScript падымае +аператары `var`, як і аб'яўленне `function`, наверх бліжэйшай зоны бачнасці. + + // аператар var перамяшчаецца сюды + var bar, someValue; // па змоўчванню - 'undefined' + + // аб'яўленне функцыі таксама падымаецца наверх + function test(data) { + var goo, i, e; // адсутная блочная зона бачнасці перайшла сюды + if (false) { + goo = 1; + + } else { + goo = 2; + } + for(i = 0; i < 100; i++) { + e = data[i]; + } + } + + bar(); // падае з TypeError бо ўсё яшчэ 'undefined' + someValue = 42; // прысвойванні не падымаюцца + bar = function() {}; + + test(); + +Адсутнасць блочнай зоны бачнасці не толькі падыме аператар `var` па-за межы цыкла +і яго цела, але таскама зробіць вынік некаторых канструкцый `if` не-інтуітыўным. + +Хоць у арыгінальным кодзе падаецца што канструкцыя `if` змяняе *глабальную +пераменную* `goo`, на дадзены момант гэта мяняе *лакальную пераменную* - пасля +таго, як было прыменена падыманне. + +Без ведаў аб *падыманні*, можна падумаць што код ніжэй кіне `ReferenceError`. + + // правярае ці было SomeImportantThing праініцыалізавана + if (!SomeImportantThing) { + var SomeImportantThing = {}; + } + +Але канешне, гэта працуе праз тое, што аператар `var` быў падняты на верх +глабальнай *зоны бачнасці*. + + var SomeImportantThing; + + // тут нейкі код можа ініцыалізаваць SomeImportantThing, або не + + // тут у гэтым можна ўпэўніцца + if (!SomeImportantThing) { + SomeImportantThing = {}; + } + +### Парадак доступу да пераменных + +Усе зоны бачнасці ў JavaScript, уключаючы *глабальную зону бачнасці*, маюць +адмысловае імя [`this`](#function.this), аб'яўленае ўнутры іх, якое спасылаецца +на *актуальны аб'ект*. + +Зоны бачнасці функцый таксама маюць імя [`arguments`](#function.arguments), +аб'яўленае ў іх, якое спасылаецца на аргументы, што былі перададзеныя ў функцыю. + +Напрыклад, калі паспрабаваць атрымаць доступ да пераменнай `foo` унутры зоны +бачнасці функцыі, JavaScript будзе шукаць імя ў наступным парадку: + + 1. У выпадку калі прысутнічае канструкцыя `var foo` у актуальнай зоне бачнасці, + ёна і выкарыстоўваецца. + 2. Калі параметр функцыі мае імя `foo`, ён будзе выкарыстаны. + 3. Калі сама функцыя называецца `foo`, яна будзе выкарыстана. + 4. Пераходзіць у знешнюю зону бачнасці, і пачынае з пункта **#1**. + +> **Заўвага:** Наява параметра названага `arguments` **перадухіліць** стварэнне +> параметра `arguments` па змоўчванні. + +### Прасторы імёнаў + +Вялікая праблема, звязаная з выкарыстоўваннем глабальнай прасторы імёнаў, гэта +высокая верагоднасць перасячэння імёнаў пераменных. У JavaScript, гэта праблема +можа быць лёгка пазбегнута праз выкарыстанне *ананімных абгортак*. + + (function() { + // аўтаномная "прастора імён" + + window.foo = function() { + // адкрытае замыканне + }; + + })(); // імгненнае выкананне функцыі + + +Ананімныя функцыі з'яўляюцца [выразамі](#function.general); таму каб быць выкліканымі, +яны спачатку маюць быць ацэненымі. + + ( // ацэньваем функцыю ўнутры дужак + function() {} + ) // вяртаем аб'ект функцыі + () // выклік выніку ацэнкі + +Ёсць і іншыя спосабы ацаніць і імгненна выклікаць выраз функцыі, хаця яны і +адрозніваюцца па сінтаксісу, паводзяць сябе аднолькава. + + // Яшчэ некалькі спосабаў наўпрост выклікаць функцыю + !function(){}() + +function(){}() + (function(){}()); + // і так далей... + +### Заключэнне + +Рэкамендуецца заўсёды выкарыстоўваць *ананімную абгортку* каб інкапсуліраваць код +у яго асабістай прасторы імёнаў. Гэта не толькі абараняе код ад перасячэння імёнаў, +але і дапамагае падзяляць праграму на модулі. + +Таксама выкарыстанне глабальных пераменных лічыцца **дрэннай практыкай**. **Любое** +іх выкарыстоўванне - прыкмета дрэнна напісанага кода, схільнага да памылак, і цяжага +ў падтрымцы. diff --git a/doc/by/function/this.md b/doc/by/function/this.md new file mode 100644 index 00000000..5b0f555d --- /dev/null +++ b/doc/by/function/this.md @@ -0,0 +1,118 @@ +## Як працуе `this` + +У JavaScript `this` азначае канцэптуальна іншую рэч, чым у іншых мовах праграмавання. +Існуе роўна **пяць** варыянтаў таго, да чаго можа быць прывязана `this`. + +### Глабальна зона бачнасці + + this; + +Калі `this` выкарыстоўваецца ў глабальнай зоне бачнасці - яна спасылаецца на *глабальны* аб'ект + + +### Выклік функцыі + + foo(); + +Тут, `this` усё яшчэ спасылаецца на *глабальны* аб'ект. + +> **Заўвага для ES5:** У строгім рэжыме, паняцця глабальнасці **больш не існуе**. +> `this` у такім выпадку будзе мець значэнне `undefined`. + +### Выклік метада + + test.foo(); + +У гэтым выпадку, `this` будзе спасылацца на аб'ект `test`. + +### Выклік канструктара + + new foo(); + +Выклік функцыі, перад якім прысутнічае ключавое слова `new`, выступае ў якасці +[канструктара](#function.constructors). Унутры функцыі, `this` будзе спасылацца +на *новаствораны* аб'ект. + +### Яўная ўстаноўка `this` + + function foo(a, b, c) {} + + var bar = {}; + foo.apply(bar, [1, 2, 3]); // масіў разгорнецца ў ніжэйпрыведзенае + foo.call(bar, 1, 2, 3); // вынікам будзе a = 1, b = 2, c = 3 + +Пры выкарыстоўванні метадаў `call` або `apply` з `Function.prototype`, значэнню +`this` унутры выкліканай функцыі **яўна прысвойваецца** значэнне першага +аргумента адпаведнага выкліка функцыі. + +Як вынік, у вышэйпрыведзеным прыкладзе *правіла метада* **не** працуе, і `this` +унутры `foo` будзе мець значэнне `bar`. + +> **Заўвага:** `this` **не можа** быць выкарыстаны як спасылка ўнутры літэрала +> `Object`. Таму ў кодзе `var obj = {me: this}` `me` **не** будзе спасылацца на +> `obj`, бо `this` прывязваецца толькі па пяці вышэйапісаных правілах. + +### Магчымыя пасткі + +Не гледзячы на тое, што большасць гэтых прыкладаў лагічныя, першы можна лічыць +яшчэ адным недаглядам мовы, бо ён **ніколі** не мае практычнага прымянення. + + Foo.method = function() { + function test() { + // this спасылаецца на глабальны аб'ект + } + test(); + } + +Памылковым меркаваннем будзе тое, што `this` унутры `test` будзе спасылацца на +`Foo`; Але на самрэч **гэта не так**. + +Каб атрымаць доступ да `Foo` з цела `test`, вы можаце стварыць лакальную +пераменную унутры `метада` што будзе спасылацца на `Foo`. + + Foo.method = function() { + var self = this; + function test() { + // Тут выкарыстоўвайце self замест this + } + test(); + } + +`self` гэта звычайнае імя пераменнай, але яно часта выкарыстоўваецца для спасылкі +на знешні `this`. У камбінацыі з [замыканнямі](#function.closures), яно можа быць +выкарыстана для перадачы `this` навокал. + +У ECMAScript 5 можна выкарыстаць метад `bind` у камбінацыі з ананімнай функцыяй, +дзеля таго каб атрымаць аналагічны вынік. + + Foo.method = function() { + var test = function() { + // this цяпер спасылаецца на Foo + }.bind(this); + test(); + } + +### Прысвойванне метадаў + +Яшчэ адна рэч якая **не** працуе ў JavaScript - гэта стварэнне псэўданімаў функцый, +то бок **прысвойванне** значэння метада пераменнай. + + var test = someObject.methodTest; + test(); + +Паводле першага правіла, `test` цяпер працуе як звычайны выклік функцыі; +адпаведна, `this` унутры больш не будзе спасылацца на `someObject`. + +Поздняе звязванне `this` можа падацца дрэннай ідэяй, але насамрэч якраз дзякуючы +гэтаму працуе [спадкаемства прататыпаў](#object.prototype). + + function Foo() {} + Foo.prototype.method = function() {}; + + function Bar() {} + Bar.prototype = Foo.prototype; + + new Bar().method(); + +Калі выклікаецца `method` новага экзэмпляра `Bar`, `this` будзе спасылацца на гэты +экзэмпляр. diff --git a/doc/by/index.json b/doc/by/index.json new file mode 100644 index 00000000..1ed0abaa --- /dev/null +++ b/doc/by/index.json @@ -0,0 +1,69 @@ +{ + "title": "JavaScript Garden", + "langTitle": "JavaScript Garden па Беларуску", + "description": "Мануал па недахопаў і дзівосах JavaScript", + "sections": [ + { + "title": "Уводзіны", + "dir": "intro", + "articles": ["index"] + }, + { + "title": "Аб'екты", + "dir": "object", + "articles": [ + "general", + "prototype", + "hasownproperty", + "forinloop" + ] + }, + { + "title": "Функцыі", + "dir": "function", + "articles": [ + "general", + "this", + "closures", + "arguments", + "constructors", + "scopes" + ] + }, + { + "title": "Масівы", + "dir": "array", + "articles": [ + "general", + "constructor" + ] + }, + { + "title": "Тыпы", + "dir": "types", + "articles": [ + "equality", + "typeof", + "instanceof", + "casting" + ] + }, + { + "title": "Ядро", + "dir": "core", + "articles": [ + "eval", + "undefined", + "semicolon", + "delete" + ] + }, + { + "title": "Рэшта", + "dir": "other", + "articles": [ + "timeouts" + ] + } + ] +} diff --git a/doc/by/intro/index.md b/doc/by/intro/index.md new file mode 100644 index 00000000..ea82a31e --- /dev/null +++ b/doc/by/intro/index.md @@ -0,0 +1,56 @@ +## Уступ + +**JavaScript Garden** гэта растучы набор дакументацыі аб найбольш +цікавых частках мовы праграмавання JavaScript. Ён дае парады аб тым як прадухіліць +частыя і непрадказальныя памылкі, а таксама праблемы з хуткасцю выконвання і +дрэннымі практыкамі, якія праграмісты, не з'яўляючыяся экспертамі у JavaScript +маглі сустрэць падчас сваіх пошукаў у глыбіні мовы. + +JavaScript Garden **не** ставіць сваёй мэтай навучыць вас мове JavaScript. Былыя +веды мовы рэкамендаваныя, каб вы змаглі зразумець пытанні разглядаемыя ў гэтым +мануале. Каб зразумець базавыя рэчы мовы, калі ласка прачытайце цудоўны [мануал][1] +у сетцы распрацоўшчыкаў Mozilla. + +## Аўтары + +Гэты мануал - праца двух выбітных карыстальнікаў [Stack Overflow][2] , [Ivo Wetzel][3] +(Тэкст) і [Zhang Yi Jiang][4] (Дызайн). + +На дадзены момант падтрымліваецца [Tim Ruffles](http://truffles.me.uk). + +## Удзельнікі + +- Зашмат каб пералічыць тут, [паглядзіце спіс](https://github.com/BonsaiDen/JavaScript-Garden/graphs/contributors). + + +## Хостынг + +JavaScript Garden хосціцца на GitHub, але [Cramer Development][7] падтрымлівае нас +люстэркам на [JavaScriptGarden.info][8]. У Беларускамоўнай версіі таксама ёсць +сваё [люстэрка на GitHub][13] + +## Пераклад + +Перакладзена на Беларускую мову супольнасцю [it-mova][14]. + +## Ліцэнзія + +JavaScript Garden апублікаваны пад [MIT ліцэнзіяй][9] і хосціцца на +[GitHub][10]. Калі вы знойдзеце апячатку або памылку - [пазначце памылку][11] або +адпраўце pull request у сховішча. Вы таксама можаце знайсці нас у +[JavaScript room][12] на чаце Stack Overflow. + +[1]: https://developer.mozilla.org/en/JavaScript/Guide +[2]: http://stackoverflow.com/ +[3]: http://stackoverflow.com/users/170224/ivo-wetzel +[4]: http://stackoverflow.com/users/313758/yi-jiang +[5]: https://github.com/caio +[6]: https://github.com/blixt +[7]: http://cramerdev.com/ +[8]: http://javascriptgarden.info/ +[9]: https://github.com/BonsaiDen/JavaScript-Garden/blob/next/LICENSE +[10]: https://github.com/it-na-move/JavaScript-Garden/ +[11]: https://github.com/it-na-move/JavaScript-Garden/issues +[12]: http://chat.stackoverflow.com/rooms/17/javascript +[13]: http://it-na-move.github.io/JavaScript-Garden/ +[14]: https://github.com/it-na-move diff --git a/doc/by/object/forinloop.md b/doc/by/object/forinloop.md new file mode 100644 index 00000000..fbe52f15 --- /dev/null +++ b/doc/by/object/forinloop.md @@ -0,0 +1,63 @@ +## Цыкл `for in` + +Як і аператар `in`, цыкл `for in` праходзіць па ўсім ланцужку прататыпаў +пры ітэрацыі па ўласцівасцях аб'екта. + +> **Заўвага:** Цыкл `for in` **не** ітэруе па уласцівасцях, у якіх атрыбут +> `enumerable` мае значэнне `false`; напрыклад, уласцівасць `length` +> масіва (Array). + + // Атруцім Object.prototype + Object.prototype.bar = 1; + + var foo = {moo: 2}; + for(var i in foo) { + console.log(i); // вывядзе і bar і moo + } + +Праз тое, што немагчыма памяняць паводзіны самаго цыкла `for in`, неабходна фільтраваць +непажаданыя ўласцівасці аб'екта ўнутры цыкла. У версіях ECMAScript 3 і пазней, +гэта можна зрабіць праз метад [`hasOwnProperty`](#object.hasownproperty). + +Пачынаючы з ECMAScript 5, `Object.defineProperty` можа быць выкарыстана з +`enumerable` роўным `false`, каб дадаць уласцівасці аб'екту такім чынам, што яны +не будуць пералічаны. У такім выпадку было б справядлівым меркаваць, што любая +`enumerable` уласціваць была дададзена адмыслова і прапусціць `hasOwnProperty`, бо +гэта робіць код больш шматслоўным і цяжэйшым для чытання. У бібліятэчным кодзе +`hasOwnProperty` мае быць усё роўна выкарыстаны, бо не варта рабіць здагадкі аб +тым, якія `enumerable` уласцівасці могуць пражываць у ланцужку прататыпаў. + +> **Заўвага:** праз тое, што `for in` заўсёды праходзіць праз увесць ланцужок прататыпаў, +> ён будзе працаваць усё марудней з кожным новым слоем спадкаемства. + +### Выкарыстоўванне `hasOwnProperty` для фільтрацыі + + // возьмем foo з прыкладу + for(var i in foo) { + if (foo.hasOwnProperty(i)) { + console.log(i); + } + } + +Гэта адзіная правільная версія выкарыстоўвання цыкла. Дзякуючы выкарыстоўванню +`hasOwnProperty`, быдзе выведзена **толькі** `moo`. +Калі прыбраць `hasOwnProperty`, код будзе схільны да памылак у выпадку, калі +натыўныя прататыпы — напрыклад, `Object.prototype` — былі змененыя. + +У новых версіях ECMAScript уласцівасці, пазначаныя як не enumerable, могуць быць +вызначыныя праз `Object.defineProperty`, змяншаючы рызыку ітэрацыі праз іх без +выкарыстання `hasOwnProperty`. Тым не менш, трэба быць уважлівым пры выкарыстанні +старых бібліятэк, такіх як [Prototype][1], якая не выкарыстроўвае новымя магчымасці +ECMAScript. +Пры выкарыстоўванні гэтай бібліятэкі, цыклы `for in`, якія не выкарыстоўваюць +`hasOwnProperty`, гарантавана не будуць працаваць. + +### У заключэнне + +Рэкамендавана **заўсёды** выкарыстоўваць `hasOwnProperty` як у ECMAScript 3 або +ніжэй, так і ў бібліятэчным кодзе. У гэтых асяродках ніколі не варта рабіць +здагадкі аб тым, быў зменены натыўны прататып ці не. Пачынаючы з ECMAScript 5, +`Object.defineProperty` дазваляе пазначаць уласцівасці як не `enumerable` і прапускаць +выкарыстоўванне `hasOwnProperty` у кодзе праграмы. + +[1]: http://www.prototypejs.org/ diff --git a/doc/by/object/general.md b/doc/by/object/general.md new file mode 100644 index 00000000..6977d8a3 --- /dev/null +++ b/doc/by/object/general.md @@ -0,0 +1,98 @@ +## Выкарыстанне і ўласцівасці аб'ектаў + +Усё ў JavaScript дзейнічае як аб'ект, апроч двух выключэнняў — гэта +[`null`](#core.undefined) і [`undefined`](#core.undefined). + + false.toString(); // 'false' + [1, 2, 3].toString(); // '1,2,3' + + function Foo(){} + Foo.bar = 1; + Foo.bar; // 1 + +Часта распрацоўшчыкі думаюць, што лічбавыя літэралы не могуць быць выкарыстаны як +аб'екты. Гэта праз тое, што сінтаксічны аналізатар JavaScript стараецца прывесці +*натацыю кропка* пасля нумара да літэрала з плаваючай кропкай. + + 2.toString(); // уздымае SyntaxError + +Ёсць некалькі падыходаў, якія могуць дазволіць выкарыстаць лікавыя літэралы як +аб'екты'. + + 2..toString(); // другая кропка распазнаецца слушна + 2 .toString(); // заўважце прабел з лева ад кропкі + (2).toString(); // 2 распазнаецца першым чынам + +### Аб'ект як тып дадзеных + +Аб'екты ў JavaScript таксама могуць быць выкарыстаныя як [*хэш-табліцы*][1]; яны ў асноўным +складаюцца з іменаваных уласцівасцяў з адпаведнымі значэннямі. + +Выкарыстоўваючы натацыю літэрала аб'екта — `{}` — магчыма стварыць +просты аб'ект. Гэты новы аб'ект [пашырае](#object.prototype) `Object.prototype` і +не мае [сваіх уласцівасцяў](#object.hasownproperty) якія былі б вызначыныя. + + var foo = {}; // новы пусты аб'ект + + // новы аб'ект з уласціваццю 'test', якая мае значэнне 12 + var bar = {test: 12}; + +### Доступ да ўласцівасцяў + +Доступ да ўласцівасцяў аб'екта можа быць здейснены двумя спосабамі, праз кропкавую +натацыю або натацыю з квадратнымі дужкамі. + + var foo = {name: 'кацяня'} + foo.name; // кацяня + foo['name']; // кацяня + + var get = 'name'; + foo[get]; // кацяня + + foo.1234; // SyntaxError + foo['1234']; // працуе + +Натацыі працуюць амаль што ідэнтычна, з адзінай розніцай у тым, што +натацыя з квадратнымі дужкамі дазваляе дынамічную устаноўку ўласцівасцяў і +выкарыстанне імёнаў уласцівасцяў, якія інакш прывялі б да сінтаксічных памылак. + +### Выдаленне ўласцівасцяў + +Адзіны спосаб выдаліць уласціваць з аб'екта — гэта выкарыстаць аператар `delete`; +пазначэнне уласціваці як `undefined` або `null` толькі прыбірае +*значэнне* звязанае з уласцівацю, але не *ключ*. + + var obj = { + bar: 1, + foo: 2, + baz: 3 + }; + obj.bar = undefined; + obj.foo = null; + delete obj.baz; + + for(var i in obj) { + if (obj.hasOwnProperty(i)) { + console.log(i, '' + obj[i]); + } + } + +Вышэй прыведзены код вывядзе `bar undefined` і `foo null` — толькі `baz` быў +выдалены і таму адсутнічае ў вывадзе. + +### Натацыя ключэй + + var test = { + 'case': 'Я ключавое слова, таму я павінна быць пазначана як радок', + delete: 'Я таксама ключавое слова, таму і я' // уздымае SyntaxError + }; + +Уласцівасці аб'ектаў могуць быць пазначаныя як сімваламі, так і ў выглядзе радкоў. +Праз яшчэ адну хібу сінтаксічнага аналізатара JavaScript, вышэй прыведзены код +кіне `SyntaxError` у весіях ранейшых за ECMAScript 5. + +Гэта памылка ўздымаецца праз тое, што `delete` - гэта *ключавое слова*; такім чынам, +яно мае быць пазначана як *літэрал радка* каб забяспечыць, што яно будзе какрэктна +інтэрпрэтавана старымі рухавікамі JavaScript. + +[1]: http://en.wikipedia.org/wiki/Hashmap diff --git a/doc/by/object/hasownproperty.md b/doc/by/object/hasownproperty.md new file mode 100644 index 00000000..730ce942 --- /dev/null +++ b/doc/by/object/hasownproperty.md @@ -0,0 +1,55 @@ +## Метад `hasOwnProperty` + +Каб праверыць, ці ёсць у аб'екта ўласцівасць, вызначаная ў *ім самім*, а не дзе-небудзь +у яго [ланцужку прататыпаў](#object.prototype), неабходна выкарыстаць метад +`hasOwnProperty`, які ўсе аб'екты ўспадкоўваюць ад `Object.prototype`. + +> **Заўвага:** **недастаткова** праверыць, ці значэнне уласцівасці — `undefined`. +> Уласцівасць можа існаваць, але яе значэнне было пазначана як `undefined`. + +`hasOwnProperty` — адзіная функцыя ў JavaScript, якая дазваляе атрымаць уласцівасці +аб'екта **без** зварота да ланцужка прататыпаў. + + // Сапсуем Object.prototype + Object.prototype.bar = 1; + var foo = {goo: undefined}; + + foo.bar; // 1 + 'bar' in foo; // true + + foo.hasOwnProperty('bar'); // false + foo.hasOwnProperty('goo'); // true + +Толькі `hasOwnProperty` дасць правільны чаканы вынік. Паглядзіце секцыю аб +[цыкле `for in`](#object.forinloop) для падрабязнейшых звестак аб тым, як +выкарыстоўваць `hasOwnProperty` падчас ітэрацыі па ўласцівасцях аб'екта. + +### `hasOwnProperty` як уласцівасць + +JavaScript не абараняе ўласцівасць `hasOwnProperty`; такім чынам, ёсць верагоднасць +што ў аб'екта можа быць уласцівасць з такім імем, неабходна выкарыстаць +*знешні* `hasOwnProperty` для карэктнага выніку. + + var foo = { + hasOwnProperty: function() { + return false; + }, + bar: 'Тут жывуць драконы' + }; + + foo.hasOwnProperty('bar'); // заўсёды верне false + + // выкарыстайце hasOwnProperty іншага аб'екта + // і перадайце foo у якасці this + ({}).hasOwnProperty.call(foo, 'bar'); // true + + // Такасама магчыма выкарыстаць hasOwnProperty з Object.prototype + Object.prototype.hasOwnProperty.call(foo, 'bar'); // true + + +### Заключэнне + +Выкарыстоўванне `hasOwnProperty` ёсць **адзіным** надзейным спосабам, каб +праверыць існаванне ўласцівасці ў аб'екце. Рэкамендуецца выкарыстоўваць +`hasOwnProperty` пры ітэрацыі па ўласцівасцях аб'екта, як апісана ў секцыі +[цыкла `for in` ](#object.forinloop). diff --git a/doc/by/object/prototype.md b/doc/by/object/prototype.md new file mode 100644 index 00000000..ec80e801 --- /dev/null +++ b/doc/by/object/prototype.md @@ -0,0 +1,115 @@ +## Прататып + +JavaScript не прадастаўляе класічную мадэль спадкаемства; замест гэтага, ён +выкарыстоўвае *прататыпную* мадэль. + +Негледзячы на тое, што гэта лічыцца адной з слабасцяў JavaScript, мадэль +прататыпнага спадкаемства больш эфэктыўная за класічную. +Напрыклад, даволі трывіальна пабудаваць класічную мадэль паверх прататыпнай мадэлі, +у той час як адваротнае было б значна больш складаным. + +JavaScript гэта адзіная шырока выкарыстоўваемая мова, якая падтрымлівае +прататыпнае спадкаемства, таму можа спатрэбіцца час, каб прызвычаіцца да гэтай мадэлі. + +Першая вялікая розніца заключаецца ў тым, што JavaScript выкастроўвае *прататыпныя +ланужкі*. + +> **Заўвага:** простае выкарыстоўванне `Bar.prototype = Foo.prototype` прывядзе +> да таго, што абодва аб'екта будуць выкарыстоўваць **той жа** прататып. +> Такім чынам, змены ў прататыпе любога з аб'ектаў паўплываюць на прататып іншага, +> што звычайна не ёсць пажаданым эфэктам. + + function Foo() { + this.value = 42; + } + Foo.prototype = { + method: function() {} + }; + + function Bar() {} + + // Пазначае прататыпам Bar новы асобнік Foo + Bar.prototype = new Foo(); + Bar.prototype.foo = 'Hello World'; + + // Упэнімся, што Bar з'яўляецца дзейсным канструктарам + Bar.prototype.constructor = Bar; + + var test = new Bar(); // стварае новы асобнік Bar + + // Выніковы ланцужок прататыпаў + test [instance of Bar] + Bar.prototype [instance of Foo] + { foo: 'Hello World', value: 42 } + Foo.prototype + { method: ... } + Object.prototype + { toString: ... /* і г.д. */ } + +У вышэй прыведзеным кодзе аб'ект `test` атрымае спадчыну і ад `Bar.prototype`, +і ад `Foo.prototype`; такім чынам, ён будзе мець доступ да функцыі `method`, якая +вызначана ў `Foo`. А таксама доступ да ўласцівасці `value` +**аднаго унікальнага асобніка** `Foo`, які з'яўляецца яго прататыпам. Важна заўважыць, +што `new Bar()` **не** стварае новы асобнік `Foo`, але выкарыстоўвае функцыю, +пазначаную яго прататыпам; такім чынам, усе асобнікі `Bar` будуць выкарыстоўваць +**тую ж** уласціваць `value`. + +> **Заўвага:** **не** выкарыстоўвайце `Bar.prototype = Foo`, бо гэта будзе +> ўказваць не на прататып `Foo`, а на аб'ект фукцыі `Foo`. Таму ланцужок +> прататыпаў будзе праходзіць праз `Function.prototype`, а не `Foo.prototype`; +> па гэтай прычыне `method` не будзе прысутнічаць у ланцужку прататыпаў. + +### Пошук уласцівасцяў + +Калі адбываецца зварот да ўласцівасці, JavaScript пройдзе па ўсім +ланцужку прататыпаў **уверх** да таго моманту, як знойдзе ўласціваць з запытаным імем. + +У той момант, калі дасягнуты верх ланцужка - а менавіта `Object.prototype` - і ўсё яшчэ +не знойдзена адпаведная ўласцівасць, будзе вернута значэнне [undefined](#core.undefined). + +### Уласцівасць prototype + +Нягледзячы на тое, што ўласцівасць prototype выкарыстоўваецца мовай, каб пабудаваць +ланцужок прататыпаў, магчыма прызначыць яму **любое** значэнне. Аднак, прызначэнне +прымітываў будузе праігнараваным. + + function Foo() {} + Foo.prototype = 1; // без эфекту + +Прызначэнне аб'ектаў, як паказана ў прыкладзе вышэй, будзе працаваць, і дазволіць +дынамічна ствараць ланцужкі прататыпаў. + +### Хуткасць выканання + +Пошук уласцівасцяў, якія знаходзяцца высока ў ланцужку прататыпаў, можа +негатыўна адбіцца на хуткасці выканання, і гэта можа быць прыкметным у кодзе, у якім +чыннік хуткасці крытычны. У выпадку спробы доступа да неіснуючых уласцівасцяў +будзе пройдзены ўвесь ланцужок прататыпаў. + +У дадатак, пры [ітэрацыі](#object.forinloop) па ўласцівасцях аб'екта +**кожная** уласціваць, што ёсць у ланцужку прататыпаў будзе апрацавана. + +### Расшырэнне ўбудаваных прататыпаў + +Адна з дрэнных магчымасцяў, што сустракаецца даволі часта — расшырэнне прататыпа +`Object.prototype` або аднаго з іншых убудаваных тыпаў. + +Такая практыка называецца [monkey patching][1] і парушае *інкапсуляцыю*. Хаця +папулярныя фрэймворкі, такія як [Prototype][2] шырока выкарыстоўваюць гэтую +мачымасць, няма добрых матываў для нагрувашчвання ўбудаваных тыпаў дадатковай +*нестандартнай* функцыянальнасцю. + +**Адзіным** добрым матывам расшырэння убудаваных прататыпаў — гэта дадаванне функцыянала, +што з'явіўся у новых рухавіках JavaScript; напрыклад, [`Array.forEach`][3]. + +### У завяршэнне + +**Вельмі важна** разумець, як працуе мадэль прататыпнага спадкаемства да таго, як +пісаць код, які яе выкарыстоўвае. Таксама сачыце за даўжынёй ланцужка прататыпаў +і драбіце іх, калі ёсць магчымасць, каб пазбегнуць праблем з прадукцыйнасцю. +Таксама ўбудаваныя прататыпы **ніколі** не павінны расшырацца, акрамя як для +таго, каб падтрымаць новыя магчымасці JavaScript. + +[1]: http://en.wikipedia.org/wiki/Monkey_patch +[2]: http://prototypejs.org/ +[3]: https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/forEach diff --git a/doc/by/other/timeouts.md b/doc/by/other/timeouts.md new file mode 100644 index 00000000..1ed49dc4 --- /dev/null +++ b/doc/by/other/timeouts.md @@ -0,0 +1,168 @@ +### `setTimeout` і `setInterval` + +Дзякуючы асінхроннасці JavaScript магчыма запланаваць выкананне функцыі з дапамогай +метадаў `setTimeout` і `setInterval`. + +> **Заўвага:** Таймаўты **не** з'яўляюцца часткай стандарта ECMAScript. Яны былі +> распрацаваны ў [BOM, ці DOM Узровень 0][1], якія ніколі не былі аб'яўлены ці +> задакументаваны фармальна. Да гэтага часу няма рэкамендацыйных спецыфікацый, +> аднак, у дадзены момант яны стандартызаваны ў [HTML5][2]. У сувязі з гэтым +> рэалізацыя можа адрознівацца ў залежнасці ад браўзера і рухавіка + + function foo() {} + var id = setTimeout(foo, 1000); // вяртае Number > 0 + +Калі функцыя `setTimeout` выклікана, яна вяртае ID таймаўта і плануе выкананне +`foo` **прыблізна** праз тысячу мілісекунд. +`foo` будзе выканана **аднойчы**. + +Улічваючы вырашэнні таймера рухавіка Javascript, які выконвае код, +аднапаточнасць JavaScript і тое, што іншы код, які выконваецца +можа блакаваць паток, **нельга** быць упэўненым, што вы атрымаеце затрымку, +пазначанаю ў выкліку `setTimeout`. + +Функцыя, якая была перададзена як першы параметр, будзе выклікана +*глабальным аб'ектам*, гэта азначае, што [`this`](#function.this) унутры выкліканай функцыі +спасылаецца на глабальны аб'ект. + + function Foo() { + this.value = 42; + this.method = function() { + // this спасылаецца на глабальны аб'ект + console.log(this.value); // выведзе undefined + }; + setTimeout(this.method, 500); + } + new Foo(); + + +> **Заўвага:** Так як `setTimeout` прымае **функцыю** як першы параметр, +> распаўсюджанай з'яўляецца памылка выкарыстоўвання `setTimeout(foo(), 1000)`, у гэтым выпадку +> будзе выкарыстоўвацца **вернутае значэнне** выкліка `foo`, а **не** `foo`. Гэта, у большасці выпадкаў, +> маўклівая памылка, так як калі функцыя вяртае `undefined`, `setTimeout` +> **не** выклікае памылкі. + +### Паслядоўныя выклікі з дапамогай `setInterval` + +У той час калі `setTimeout` выконвае функцыю толькі адзін раз, `setInterval` - як бачна з назвы - +выконвае функцыю **кожныя** `X` milliseconds, але яе выкарыстанне не пажадана. + +Код, які выконваецца, блакуе выклік з таймаўтам, у той час `setInterval` будзе +планаваць выклікі зададзенай функцыі. Гэта можа, асабліва з маленькімі інтэрваламі, +прывесці да стварэння чаргі выклікаў функцый. + + function foo(){ + // нешта, што блакуе на 1 секунду + } + setInterval(foo, 100); + +У прыведзеным кодзе `foo` будзе выклікана аднойчы і заблакуе выкананне на адну секунду. + +У той час калі `foo` блакуе код, `setInterval` будзе планаваць наступныя яе выклікі +А калі выкананне `foo` скончана, ужо **дзесяць** наступных выклікаў будуць чакаць выканання. + +### Праца з магчыма блакуючым кодам + +Найбольш простае і кіруемае рашэнне гэта выкарыстоўваць `setTimeout` унутры самой функцыі. + + function foo(){ + // нешта, што блакуе на 1 секунду + setTimeout(foo, 100); + } + foo(); + +Гэты падыход не толькі інкапсулюе выклік `setTimeout`, але таксама прадухіляе +стварэнне чаргі выклікаў і дае дадатковы кантроль. Цяпер `foo` можа сама вырашыць +хоча яна выконвацца яшчэ раз ці не. + +### Ручная чыстка таймаўтаў + +Чыстка таймаўтаў і інтэрвалаў здзяйсняецца перадачай адпаведнага ID у +`clearTimeout` або `clearInterval`, гледзячы якая `set` функцыя была выкарыстана +да гэтага. + + var id = setTimeout(foo, 1000); + clearTimeout(id); + +### Чыстка ўсіх таймаўтаў + +Так як няма ўбудаванага метада для выдалення ўсіх таймаўтаў і/або інтэрвалаў, +для гэтага неабходна выкарыстоўваць брутфорс. + + // выдаліць "усе" таймаўты + for(var i = 1; i < 1000; i++) { + clearTimeout(i); + } + +Але могуць быць таймаўты, якія не закрануты гэтым адвольным нумарам. +Іншы шлях ажыццяўлення гэтага - прыняць, што ID таймаўта павялічваецца на +адзін пасля кожнага выкліку `setTimeout`. + + // выдаліць "усе" таймаўты + var biggestTimeoutId = window.setTimeout(function(){}, 1), + i; + for(i = 1; i <= biggestTimeoutId; i++) { + clearTimeout(i); + } + +Не гледзячы на тое, што зараз гэта працуе на ўсіх асноўных браўзерах, тое, што ID +павінны быць арганізаваны такім шляхам не пазначана ў спецыфікацыі і можа змяніцца. Таму +замест гэтага рэкамендуецца сачыць за ўсімі ID таймаўтаў, каб яны маглі быць выдалены паасобку. + +### Схаванае выкарыстанне `eval` + +`setTimeout` і `setInterval` таксама могуць прымаць радок у якасці першага параметра. +Гэту магчымасць **ніколі** не трэба выкарыстоўваць, бо ўнутрана вызываецца `eval`. + +> **Заўвага:** Дакладны механізм работы пры перадачы радка можа адрозніваецца ў +> розных JavaScript рэалізацыях. Напрыклад, JScript ад Microsoft выкарыстоўвае +> канструктар `Function` замест `eval`. + + function foo() { + // будзе выклікана + } + + function bar() { + function foo() { + // ніколі не будзе выклікана + } + setTimeout('foo()', 1000); + } + bar(); + +Паколькі `eval` не выклікана [напрамую](#core.eval), радок, які перададзены +`setTimeout` будзе выкананы ў *глабальным скоўпе*; такім чынам, не будзе выкарыстана +лакальная пераменная `foo` са скоўпа `bar`. + +Адсюль вынікае рэкамендацыя **не** выкарыстоўваць радок для перадачы аргументаў у +функцыю, якая будзе вызывацца адной з таймаўт функцый. + + function foo(a, b, c) {} + + // НІКОЛІ так не рабіце + setTimeout('foo(1, 2, 3)', 1000) + + // Замест выкарыстоўвайце ананімныя функцыі + setTimeout(function() { + foo(1, 2, 3); + }, 1000) + +> **Заўвага:** Нягледзячы на тое, што сінтаксіс `setTimeout(foo, 1000, 1, 2, 3)` можна выкарыстоўваць, +> гэта не рэкамендуецца, так як можа прывесці да +> непрыкметных памылак пры выкарыстанні з [метадамі](#function.this). +> Больш таго, сінтаксіс можа не працаваць у некаторых рэалізацыях JavaScript. +> Напрыклад, Internet Explorer ад Microsoft [**не** перадае аргументы напрамую зваротнаму выкліку](3). + +### У заключэнне + +Радок **ніколі** не павінен быць выкарыстаны як параметр `setTimeout` ці +`setInterval`. Відавочны знак **сапраўды** благога кода гэта калі функцыя, якая будзе выклікана, +патрабуе аргументы. Трэба перадаваць *ананімную функцыю*, якая будзе адказваць за +выклік патрэбнай функцыі. + +Больш таго, трэба пазбягаць выкарыстання `setInterval`, таму што яе планавальнік не блакуецца +выкананнем JavaScript. + +[1]: http://www.nczonline.net/blog/2009/09/29/web-definitions-dom-ajax-and-more/ "Web definitions: DOM, Ajax, and more" +[2]: http://www.w3.org/TR/2014/WD-html5-20140617/webappapis.html#timers "6 Web application APIs - HTML5" +[3]: http://msdn.microsoft.com/en-us/library/ie/ms536753(v=vs.85).aspx "setTimeout method (Internet Explorer)" diff --git a/doc/by/types/casting.md b/doc/by/types/casting.md new file mode 100644 index 00000000..763bf3a1 --- /dev/null +++ b/doc/by/types/casting.md @@ -0,0 +1,71 @@ +## Прывядзенне тыпаў + +JavaScript - *слаба тыпізаваная* мова, таму *прывядзенне тыпаў* адбываецца +**паўсюль** дзе магчыма. + + // Гэтыя равенствы - праўдзівыя + new Number(10) == 10; // аб'ект тыпа Number пераўтвараецца у + // лікавы прымітыў, праз няяўны выклік + // метада Number.prototype.valueOf + + 10 == '10'; // Strings пераўтвараецца ў Number + 10 == '+10 '; // Троху вар'яцтва з радкамі + 10 == '010'; // і яшчэ + isNaN(null) == false; // null пераўтвараецца ў 0 + // які вядома ж не NaN + + // Гэтыя равенствы - ілжывыя + 10 == 010; + 10 == '-10'; + +> **Заўвага для ES5:** Лічбавыя літэралы, што пачынаюцца з `0` інтэрпрэтуюцца як +> васьмірычныя (Base 8). Падтрымка васьмірычнай сістэмы была **прыбраная** у +> ECMAScript 5 strict mode. + +Каб пазбегнуць вышэйпрыведзеных праблемаў, **настойліва** ракамендуецца выкарыстоўваць +[аператар строгай роўнасці](#types.equality). Зрэшты, хоць гэта і пазбаўляе ад +многіх распаўсюджаных праблемаў, існуе яшчэ шмат праблемаў, які ўзнікаюць праз +слабую тыпізацыю JavaScript. + +### Канструктары ўбудаваных тыпаў + +Канструктары ўбудаваных тыпаў, напрыклад, `Number` і `String` паводзяць сябе +па рознаму, у залежнасці ад таго, выклікаюцца яны з ключавым словам `new` або без яго. + + new Number(10) === 10; // False, Object і Number + Number(10) === 10; // True, Number і Number + new Number(10) + 0 === 10; // True, праз неяўнае прывядзенне + +Выкарыстанне ўбудаванага тыпу, такога як `Number` у якасці канструкта створыць новы +экзэмпляр аб'екта `Number`, але пры адсутнасці ключавога слова `new` функцыя +`Number` будзе паводзіць сябе як канвертар. + +У дадатак, выкарытоўванне літэралаў, або значэнняў якія не з'яўляюцца аб'ектамі +прывядзе да дадатковых прывядзенняў тыпаў. + +Лепшы варыянт - гэта **яўнае** прывядзенне да аднаго з трох магчымых тыпаў. + +### Прывядзенне да радка + + '' + 10 === '10'; // true + +Праз даданне да значэння пустога радка, яно лёгка прыводзіцца да радка. + +### Прывядзенне да лікавага тыпу + + +'10' === 10; // true + +Выкарыстоўваючы **унарны** аператар плюс, магчыма пераўтварыць значэнне ў нумар. + +### Прывядзенне да булевага тыпу + +Выкарыстоўваючы аператар **адмаўленне (!)** двойчы, значэнне можна прыведзена +да лагічнага (булевага) тыпу. + + !!'foo'; // true + !!''; // false + !!'0'; // true + !!'1'; // true + !!'-1' // true + !!{}; // true + !!true; // true diff --git a/doc/by/types/equality.md b/doc/by/types/equality.md new file mode 100644 index 00000000..0859ce03 --- /dev/null +++ b/doc/by/types/equality.md @@ -0,0 +1,70 @@ +## Роўнасць і параўнанне + +У JavaScript роўнасць значэнняў аб'ектаў можна вызначыць двумя спосабамі. + +### Аператар роўнасці + +Аператар роўнасці складаецца з двух сімвалаў 'роўна': `==` + +JavaScript мае *слабую тыпізацыю*. Гэта значыць што аператар роўнасці +**прыводзіць** тыпы аб'ектаў, каб параўнаць іх. + + "" == "0" // false + 0 == "" // true + 0 == "0" // true + false == "false" // false + false == "0" // true + false == undefined // false + false == null // false + null == undefined // true + " \t\r\n" == 0 // true + +Вышэй прыведзеная табліца паказвае вынікі прывядзення тыпаў, і гэта галоўная прычына +па якой выкаростоўванне `==` лічыцца дрэннай практыкай. Яно прыводзіць да памылак +якія цяжка адсачыць праз складаны механізм прывядзення тыпаў. + +Акрамя гэтага, прывядзенне тыпаў таксама ўплывае на вытворчасць; +напрыклад, радок мае быць ператвораны ў нумар, перад тым як быць параўнаным з +іншым нумарам. + +### Аператар строгай роўнасці + +Аператар строгай роўнасці складаецца з **трох** сімвалаў 'роўна': `===`. + +Ён дзейнічае як звычайны аператар роўнасці, за выключэннем таго, што строгая +роўнасць **не** прыводзіць аперанды да агульнага тыпу. + + "" === "0" // false + 0 === "" // false + 0 === "0" // false + false === "false" // false + false === "0" // false + false === undefined // false + false === null // false + null === undefined // false + " \t\r\n" === 0 // false + +Вышэй прыведзеныя вынікі значна больш зразумелыя і даюць магчымасць хутчэй выявіць +памылкі ў кодзе. Гэта паляпшае код, а таксама дае прырост вытворчасці, у выпадку +калі аперанды розных тыпаў. + +### Параўнанне аб'ектаў + +Хоць абодва аператар `==` і `===` называюцца аператарамі **роўнасці**, яны паводзяць +сабе па рознаму калі хоць адзін аперанд тыпа `Object`. + + {} === {}; // false + new String('foo') === 'foo'; // false + new Number(10) === 10; // false + var foo = {}; + foo === foo; // true + +Тут абодва аператанда параўноўваюцца на **ідэнтычнасць**, а **не** на роўнасць; +то бок будзе праверана, ці з'яўляюцца яны адным **экзэмплярам** аб'екта. Гэтак жа, +як `is` у Python, або параўнанне ўказальнікаў у C. + +### У заключэнне + +Настойліва рэкамендуецца выкарыстоўваць толькі аператар **строгай роўнасці**. +У выпадку, калі тыпы маюць быць прыведзеныя, гэта варта рабіць [яўна](#types.casting), +а не пакідаць іх на сумленні складаных правілаў прывядзення мовы праграмавання. diff --git a/doc/by/types/instanceof.md b/doc/by/types/instanceof.md new file mode 100644 index 00000000..220bc3c3 --- /dev/null +++ b/doc/by/types/instanceof.md @@ -0,0 +1,37 @@ +## Аператар `instanceof` + +Аператар `instanceof` параўноўвае канструктары двух аперандаў. Гэта карысна толькі +для параўнання аб'ектаў не ўбудаваных тыпаў. Выкарыстоўванне на ўбудаваных тыпах не +мае сэнсу, як і [аператар typeof](#types.typeof). + +### Параўнанне адвольных аб'ектаў + + function Foo() {} + function Bar() {} + Bar.prototype = new Foo(); + + new Bar() instanceof Bar; // true + new Bar() instanceof Foo; // true + + // Калі толькі прысвоім Bar.prototype аб'ект функцыі Foo, + // але не самаго экзэмпляра Foo + Bar.prototype = Foo; + new Bar() instanceof Foo; // false + +### Выкарыстоўванне `instanceof` з убудаванымі тыпамі + + new String('foo') instanceof String; // true + new String('foo') instanceof Object; // true + + 'foo' instanceof String; // false + 'foo' instanceof Object; // false + +Варта адзначыць, што `instanceof` не працуе на аб'ектах, якія паходзяць з розных +кантэкстаў JavaScript (напрыклад, розных дакументаў у web-браузеры), бо іх канструктары +насамрэч не будуць канструктарамі тых самых аб'ектаў. + +### У заключэнне + +Аператар `instanceof` мае быць выкарыстаны **толькі** для працы з аб'ектамі не +ўбудаваных тыпаў якія паходзяць з аднаго кантэкста JavaScript. Як і ў выпадку з +[аператарам `typeof`](#types.typeof), трэба **пазбягаць** любога іншага яго выкарыстання. diff --git a/doc/by/types/typeof.md b/doc/by/types/typeof.md new file mode 100644 index 00000000..7fb16ba9 --- /dev/null +++ b/doc/by/types/typeof.md @@ -0,0 +1,80 @@ +## Аператар `typeof` + +Аператар `typeof` (разам з [`instanceof`](#types.instanceof)) магчыма найбольшая +хіба мовы JavaScript, таму што ён амаль што **цалкам зламаны**. + +Хаця `instanceof` усё яшчэ мае абмежаванае ўжыванне, `typeof` можа быць выкарыстаны +толькі з адной мэтай, і гэта дарэчы **не** праверка тыпа. + +> **Заўвага:** Хаця для выкліка `typeof` можна выкарыстаць сінтаксіс функцыі, то бок +> `typeof(obj)`, гэта не выклік функцыі. Дужкі будуць апрацоўвацца нармальна +> і вернутае значэнне будзе выкарыстана як аперанд аператара `typeof`. +> **Не існуе** функцыі `typeof`. + +### Табліца тыпаў JavaScript + + Значэнне Клас Тып + ------------------------------------- + "foo" String string + new String("foo") String object + 1.2 Number number + new Number(1.2) Number object + true Boolean boolean + new Boolean(true) Boolean object + new Date() Date object + new Error() Error object + [1,2,3] Array object + new Array(1, 2, 3) Array object + new Function("") Function function + /abc/g RegExp object (function in Nitro/V8) + new RegExp("meow") RegExp object (function in Nitro/V8) + {} Object object + new Object() Object object + +У вышэй прыведзенай табыліцы, *Тып* паказвае значэнне вернутае аператарам `typeof`. +Як можна пабачыць, гэта значэнне абсалютна не кансістэнтнае. + +*Клас* паказвае значэнне ўнутраннай уласцівасці `[[Class]]` аб'екта. + +> **З спецыфікацыі:** значэнне `[[Class]]` можа быць быць адным з наступных +> радкоў. `Arguments`, `Array`, `Boolean`, `Date`, `Error`, +> `Function`, `JSON`, `Math`, `Number`, `Object`, `RegExp`, `String`. + +### Клас аб'екта + +Адзіны спосаб атрымаць значэнне `[[Class]]` аб'екта - выклікаць метад `Object.prototype.toString`. +Ён верне радок у наступным фармаце: `'[object ' + valueOfClass + ']'`, напрыклад +`[object String]` або `[object Array]`: + + function is(type, obj) { + var clas = Object.prototype.toString.call(obj).slice(8, -1); + return obj !== undefined && obj !== null && clas === type; + } + + is('String', 'test'); // true + is('String', new String('test')); // true + +У вышэйпрыведзеным прыкладзе, `Object.prototype.toString` выклікаецца са значэннем +[this](#function.this) пазначаным як аб'ект чыё значэнне `[[Class]]` мае быць +атрыманым. + +> **Заўвага для ES5:** у ECMAScript 5, для зручнасці, значэнне `Object.prototype.toString` +> для `null` і `undefined` было **зменена** з `Object` на `Null` і +> `Undefined` адпаведна. + +### Праверка вызначанасці пераменных + + typeof foo !== 'undefined' + +Вышэйпрыведзены код праверыць ці было вызначана `foo`; просты зварот да пераменнай +прывядзе да `ReferenceError`. Гэта адзінае для чаго карысны `typeof`. + +### У заключэнне + +Каб праверыць тып аб'екта, настойліва рэкамендуецца выкарыстоўваць +`Object.prototype.toString` - гэта адзіны надзейны спосаб. +Як паказана ў вышэйпрыведзенай табліцы, некаторыя значэнні вернутыя аператарам +`typeof` не вызначаныя ў спецыфікацыі; такім чынам, яны могуць быць рознымі ў +розных рэалізацыях. + +Акрамя як для праверкі вызначанасці пераменнай, `typeof` мае быць пазбегнуты. diff --git a/doc/en/array/general.md b/doc/en/array/general.md index 2e38b670..a78091d3 100644 --- a/doc/en/array/general.md +++ b/doc/en/array/general.md @@ -40,13 +40,13 @@ While the *getter* of the `length` property simply returns the number of elements that are contained in the array, the *setter* can be used to **truncate** the array. - var foo = [1, 2, 3, 4, 5, 6]; - foo.length = 3; - foo; // [1, 2, 3] + var arr = [1, 2, 3, 4, 5, 6]; + arr.length = 3; + arr; // [1, 2, 3] - foo.length = 6; - foo.push(4); - foo; // [1, 2, 3, undefined, undefined, undefined, 4] + arr.length = 6; + arr.push(4); + arr; // [1, 2, 3, undefined, undefined, undefined, 4] Assigning a smaller length truncates the array. Increasing it creates a sparse array. diff --git a/doc/en/core/delete.md b/doc/en/core/delete.md index 067fcfdb..8e712412 100644 --- a/doc/en/core/delete.md +++ b/doc/en/core/delete.md @@ -39,7 +39,7 @@ Explicitly set properties can be deleted normally. obj.y; // undefined In the example above, `obj.x` and `obj.y` can be deleted because they have no -`DontDelete` atribute. That's why the example below works too. +`DontDelete` attribute. That's why the example below works too. // this works fine, except for IE: var GLOBAL_OBJECT = this; diff --git a/doc/en/core/eval.md b/doc/en/core/eval.md index 2d929902..6fa000f9 100644 --- a/doc/en/core/eval.md +++ b/doc/en/core/eval.md @@ -2,27 +2,27 @@ The `eval` function will execute a string of JavaScript code in the local scope. - var foo = 1; + var number = 1; function test() { - var foo = 2; - eval('foo = 3'); - return foo; + var number = 2; + eval('number = 3'); + return number; } test(); // 3 - foo; // 1 + number; // 1 However, `eval` only executes in the local scope when it is being called directly *and* when the name of the called function is actually `eval`. - var foo = 1; + var number = 1; function test() { - var foo = 2; - var bar = eval; - bar('foo = 3'); - return foo; + var number = 2; + var copyOfEval = eval; + copyOfEval('number = 3'); + return number; } test(); // 2 - foo; // 3 + number; // 3 The use of `eval` should be avoided. 99.9% of its "uses" can be achieved **without** it. diff --git a/doc/en/function/arguments.md b/doc/en/function/arguments.md index 2394177d..fec3d8e4 100644 --- a/doc/en/function/arguments.md +++ b/doc/en/function/arguments.md @@ -38,23 +38,37 @@ another. // do stuff here } -Another trick is to use both `call` and `apply` together to create fast, unbound -wrappers. +Another trick is to use both `call` and `apply` together to turn methods - functions that use the +value of `this` as well as their arguments - into normal functions which only use their arguments. - function Foo() {} + function Person(first, last) { + this.first = first; + this.last = last; + } - Foo.prototype.method = function(a, b, c) { - console.log(this, a, b, c); + Person.prototype.fullname = function(joiner, options) { + options = options || { order: "western" }; + var first = options.order === "western" ? this.first : this.last; + var last = options.order === "western" ? this.last : this.first; + return first + (joiner || " ") + last; }; - // Create an unbound version of "method" - // It takes the parameters: this, arg1, arg2...argN - Foo.method = function() { - - // Result: Foo.prototype.method.call(this, arg1, arg2... argN) - Function.call.apply(Foo.prototype.method, arguments); + // Create an unbound version of "fullname", usable on any object with 'first' + // and 'last' properties passed as the first argument. This wrapper will + // not need to change if fullname changes in number or order of arguments. + Person.fullname = function() { + // Result: Person.prototype.fullname.call(this, joiner, ..., argN); + return Function.call.apply(Person.prototype.fullname, arguments); }; + var grace = new Person("Grace", "Hopper"); + + // 'Grace Hopper' + grace.fullname(); + + // 'Turing, Alan' + Person.fullname({ first: "Alan", last: "Turing" }, ", ", { order: "eastern" }); + ### Formal Parameters and Arguments Indices diff --git a/doc/en/function/closures.md b/doc/en/function/closures.md index f8061712..aef633b9 100644 --- a/doc/en/function/closures.md +++ b/doc/en/function/closures.md @@ -36,12 +36,12 @@ Since it is not possible to reference or assign scopes in JavaScript, there is interact with it is via the two closures. var foo = new Counter(4); - foo.hack = function() { + foo.hackFail = function() { count = 1337; }; The above code will **not** change the variable `count` in the scope of `Counter`, -since `foo.hack` was not defined in **that** scope. It will instead create - or +since `foo.hackFail` was not defined in **that** scope. It will instead create - or override - the *global* variable `count`. ### Closures Inside Loops @@ -96,6 +96,17 @@ above. })(i), 1000) } +The other popular way to achieve this is to add an additional argument to +the `setTimeout` function, which passes these arguments to the callback. + + for(var i = 0; i < 10; i++) { + setTimeout(function(e) { + console.log(e); + }, 1000, i); + } + +Some legacy JS environments (Internet Explorer 9 & below) do not support this. + There's yet another way to accomplish this by using `.bind`, which can bind a `this` context and arguments to function. It behaves identically to the code above diff --git a/doc/en/function/constructors.md b/doc/en/function/constructors.md index bf9771dc..e84a6cf8 100644 --- a/doc/en/function/constructors.md +++ b/doc/en/function/constructors.md @@ -11,45 +11,45 @@ constructor. If the function that was called has no explicit `return` statement, then it implicitly returns the value of `this` - the new object. - function Foo() { - this.bla = 1; + function Person(name) { + this.name = name; } - Foo.prototype.test = function() { - console.log(this.bla); + Person.prototype.logName = function() { + console.log(this.name); }; - var test = new Foo(); + var sean = new Person(); -The above calls `Foo` as constructor and sets the `prototype` of the newly -created object to `Foo.prototype`. +The above calls `Person` as constructor and sets the `prototype` of the newly +created object to `Person.prototype`. In case of an explicit `return` statement, the function returns the value specified by that statement, but **only** if the return value is an `Object`. - function Bar() { - return 2; + function Car() { + return 'ford'; } - new Bar(); // a new object + new Car(); // a new object, not 'ford' - function Test() { - this.value = 2; + function Person() { + this.someValue = 2; return { - foo: 1 + name: 'Charles' }; } - new Test(); // the returned object + new Person(); // the returned object ({name:'Charles'}), not including someValue When the `new` keyword is omitted, the function will **not** return a new object. - function Foo() { - this.bla = 1; // gets set on the global object + function Pirate() { + this.hasEyePatch = true; // gets set on the global object! } - Foo(); // undefined + var somePirate = Pirate(); // somePirate is undefined -While the above example might still appear to work in some cases, due to the -workings of [`this`](#function.this) in JavaScript, it will use the +While the above example might still appear to work in some cases, due to the +workings of [`this`](#function.this) in JavaScript, it will use the *global object* as the value of `this`. ### Factories @@ -57,28 +57,25 @@ workings of [`this`](#function.this) in JavaScript, it will use the In order to be able to omit the `new` keyword, the constructor function has to explicitly return a value. - function Bar() { - var value = 1; + function Robot() { + var color = 'gray'; return { - method: function() { - return value; + getColor: function() { + return color; } } } - Bar.prototype = { - foo: function() {} - }; - new Bar(); - Bar(); + new Robot(); + Robot(); -Both calls to `Bar` return the same thing, a newly create object that -has a property called `method`, which is a +Both calls to `Robot` return the same thing, a newly created object that +has a property called `getColor`, which is a [Closure](#function.closures). -It should also be noted that the call `new Bar()` does **not** affect the +It should also be noted that the call `new Robot()` does **not** affect the prototype of the returned object. While the prototype will be set on the newly -created object, `Bar` never returns that new object. +created object, `Robot` never returns that new object. In the above example, there is no functional difference between using and not using the `new` keyword. @@ -92,19 +89,21 @@ lead to bugs. In order to create a new object, one should rather use a factory and construct a new object inside of that factory. - function Foo() { - var obj = {}; - obj.value = 'blub'; + function CarFactory() { + var car = {}; + car.owner = 'nobody'; + + var milesPerGallon = 2; - var private = 2; - obj.someMethod = function(value) { - this.value = value; + car.setOwner = function(newOwner) { + this.owner = newOwner; } - obj.getPrivate = function() { - return private; + car.getMPG = function() { + return milesPerGallon; } - return obj; + + return car; } While the above is robust against a missing `new` keyword and certainly makes diff --git a/doc/en/function/scopes.md b/doc/en/function/scopes.md index 28caddbd..33d525e1 100644 --- a/doc/en/function/scopes.md +++ b/doc/en/function/scopes.md @@ -220,6 +220,7 @@ which, while different in syntax, behave the same way. !function(){}() +function(){}() (function(){}()); + void function(){}(); // and so on... ### In Conclusion diff --git a/doc/en/function/this.md b/doc/en/function/this.md index 48070d2e..f123f336 100644 --- a/doc/en/function/this.md +++ b/doc/en/function/this.md @@ -68,21 +68,30 @@ mis-design of the language because it **never** has any practical use. A common misconception is that `this` inside of `test` refers to `Foo`; while in fact, it **does not**. -In order to gain access to `Foo` from within `test`, it is necessary to create a +In order to gain access to `Foo` from within `test`, you can create a local variable inside of `method` that refers to `Foo`. Foo.method = function() { - var that = this; + var self = this; function test() { - // Use that instead of this here + // Use self instead of this here } test(); } -`that` is just a normal variable name, but it is commonly used for the reference to an +`self` is just a normal variable name, but it is commonly used for the reference to an outer `this`. In combination with [closures](#function.closures), it can also be used to pass `this` values around. +As of ECMAScript 5 you can use the `bind` method combined with an anonymous function to achieve the same result. + + Foo.method = function() { + var test = function() { + // this now refers to Foo + }.bind(this); + test(); + } + ### Assigning Methods Another thing that does **not** work in JavaScript is function aliasing, which is diff --git a/doc/en/object/forinloop.md b/doc/en/object/forinloop.md index 3d366f8c..28d586c4 100644 --- a/doc/en/object/forinloop.md +++ b/doc/en/object/forinloop.md @@ -3,10 +3,10 @@ Just like the `in` operator, the `for in` loop traverses the prototype chain when iterating over the properties of an object. -> **Note:** The `for in` loop will **not** iterate over any properties that -> have their `enumerable` attribute set to `false`; for example, the `length` +> **Note:** The `for in` loop will **not** iterate over any properties that +> have their `enumerable` attribute set to `false`; for example, the `length` > property of an array. - + // Poisoning Object.prototype Object.prototype.bar = 1; @@ -16,9 +16,18 @@ chain when iterating over the properties of an object. } Since it is not possible to change the behavior of the `for in` loop itself, it -is necessary to filter out the unwanted properties inside the loop body; -this is done using the [`hasOwnProperty`](#object.hasownproperty) method of -`Object.prototype`. +is necessary to filter out the unwanted properties inside the loop body. In +ECMAScript 3 and older, this is done using the [`hasOwnProperty`](#object.hasownproperty) +method of `Object.prototype`. + +Since ECMAScript 5, `Object.defineProperty` can be used with +`enumerable` set to `false` to add properties to objects (including `Object`) +without these properties being enumerated. In this case it is reasonable +to assume in application code that any enumerable properties have been added +for a reason and to omit `hasOwnProperty`, since it makes code more verbose and less +readable. In library code `hasOwnProperty` should still be used since +assumptions cannot be made about which enumerable properties might reside +on the prototype chain. > **Note:** Since `for in` always traverses the complete prototype chain, it > will get slower with each additional layer of inheritance added to an object. @@ -32,20 +41,26 @@ this is done using the [`hasOwnProperty`](#object.hasownproperty) method of } } -This version is the only correct one to use. Due to the use of `hasOwnProperty`, it -will **only** print out `moo`. When `hasOwnProperty` is left out, the code is -prone to errors in cases where the native prototypes - e.g. `Object.prototype` - +This version is the only correct one to use with older versions of ECMAScript. +Due to the use of `hasOwnProperty`, it will **only** print out `moo`. +When `hasOwnProperty` is left out, the code is prone to errors in cases where +the native prototypes - e.g. `Object.prototype` - have been extended. -One widely used framework that extends `Object.prototype` is [Prototype][1]. +In newer versions of ECMAScript, non-enumerable properties can be defined with +`Object.defineProperty`, reducing the risk of iterating over properties without +using `hasOwnProperty`. Nonetheless, care must be taken when using older +libraries like [Prototype][1], which does not yet take advantage of new ECMAScript features. When this framework is included, `for in` loops that do not use `hasOwnProperty` are guaranteed to break. ### In Conclusion -It is recommended to **always** use `hasOwnProperty`. Assumptions should never -be made about the environment the code is running in, or whether the native -prototypes have been extended or not. +It is recommended to **always** use `hasOwnProperty` in ECMAScript 3 or lower, as well as +in library code. Assumptions should never be made in these environments about whether +the native prototypes have been extended or not. Since ECMAScript 5, `Object.defineProperty` +makes it possible to define non-enumerable properties and to omit `hasOwnProperty` in +application code. [1]: http://www.prototypejs.org/ diff --git a/doc/en/object/general.md b/doc/en/object/general.md index 9300b18e..5ee2e0de 100644 --- a/doc/en/object/general.md +++ b/doc/en/object/general.md @@ -20,7 +20,7 @@ There are a couple of workarounds that can be used to make number literals act as objects too. 2..toString(); // the second point is correctly recognized - 2 .toString(); // note the space left to the dot + 2 .toString(); // note the space left of the dot (2).toString(); // 2 is evaluated first ### Objects as a Data Type diff --git a/doc/en/object/hasownproperty.md b/doc/en/object/hasownproperty.md index 1ba58f66..10423b00 100644 --- a/doc/en/object/hasownproperty.md +++ b/doc/en/object/hasownproperty.md @@ -21,10 +21,10 @@ does **not** traverse the prototype chain. foo.hasOwnProperty('bar'); // false foo.hasOwnProperty('goo'); // true -Only `hasOwnProperty` will give the correct and expected result; this is -essential when iterating over the properties of any object. There is **no** other -way to exclude properties that are not defined on the object itself, but -somewhere on its prototype chain. +Only `hasOwnProperty` will give the correct and expected result. See the section +on [`for in` loops](#object.forinloop) for more details on when to use +`hasOwnProperty` when iterating over object +properties. ### `hasOwnProperty` as a Property @@ -53,6 +53,6 @@ necessary to use an *external* `hasOwnProperty` to get correct results. Using `hasOwnProperty` is the **only** reliable method to check for the existence of a property on an object. It is recommended that `hasOwnProperty` -is used in **every** [`for in` loop](#object.forinloop) to avoid errors from -extended native [prototypes](#object.prototype). +be used in many cases when iterating over object properties as described +in the section on [`for in` loops](#object.forinloop). diff --git a/doc/en/object/prototype.md b/doc/en/object/prototype.md index cb053526..f63abaa9 100644 --- a/doc/en/object/prototype.md +++ b/doc/en/object/prototype.md @@ -41,7 +41,7 @@ chains*. // The resulting prototype chain test [instance of Bar] Bar.prototype [instance of Foo] - { foo: 'Hello World' } + { foo: 'Hello World', value: 42 } Foo.prototype { method: ... } Object.prototype diff --git a/doc/en/other/timeouts.md b/doc/en/other/timeouts.md index 8fe66d81..e27ccacf 100644 --- a/doc/en/other/timeouts.md +++ b/doc/en/other/timeouts.md @@ -55,7 +55,7 @@ intervals, result in function calls stacking up. function foo(){ // something that blocks for 1 second } - setInterval(foo, 100); + setInterval(foo, 1000); In the above code, `foo` will get called once and will then block for one second. @@ -70,7 +70,7 @@ the function itself. function foo(){ // something that blocks for 1 second - setTimeout(foo, 100); + setTimeout(foo, 1000); } foo(); diff --git a/doc/en/types/casting.md b/doc/en/types/casting.md index 0dcbc92b..f12aa811 100644 --- a/doc/en/types/casting.md +++ b/doc/en/types/casting.md @@ -4,8 +4,9 @@ JavaScript is a *weakly typed* language, so it will apply *type coercion* **wherever** possible. // These are true - new Number(10) == 10; // Number.toString() is converted - // back to a number + new Number(10) == 10; // Number object is converted + // to a number primitive via implicit call of + // Number.prototype.valueOf method 10 == '10'; // Strings gets converted to Number 10 == '+10 '; // More string madness @@ -57,7 +58,7 @@ Using the **unary** plus operator, it is possible to cast to a number. ### Casting to a Boolean -By using the **not** operator twice, a value can be converted a boolean. +By using the **not** operator twice, a value can be converted to a boolean. !!'foo'; // true !!''; // false diff --git a/doc/en/types/typeof.md b/doc/en/types/typeof.md index 637ea2bc..9eb3fbdc 100644 --- a/doc/en/types/typeof.md +++ b/doc/en/types/typeof.md @@ -42,13 +42,11 @@ The *Class* refers to the value of the internal `[[Class]]` property of an objec > following strings. `Arguments`, `Array`, `Boolean`, `Date`, `Error`, > `Function`, `JSON`, `Math`, `Number`, `Object`, `RegExp`, `String`. -In order to retrieve the value of `[[Class]]`, one has to make use of the -`toString` method of `Object.prototype`. - ### The Class of an Object -The specification gives exactly one way of accessing the `[[Class]]` value, -with the use of `Object.prototype.toString`. +The only way to determine an object's `[[Class]]` value is using `Object.prototype.toString`. It +returns a string in the following format: `'[object ' + valueOfClass + ']'`, e.g `[object String]` or +`[object Array]`: function is(type, obj) { var clas = Object.prototype.toString.call(obj).slice(8, -1); diff --git a/doc/es/index.json b/doc/es/index.json index 54d54e1c..1367f527 100644 --- a/doc/es/index.json +++ b/doc/es/index.json @@ -39,7 +39,7 @@ ] }, { - "title": "Types", + "title": "Tipos", "dir": "types", "articles": [ "equality", diff --git a/doc/es/object/general.md b/doc/es/object/general.md index 270bdc37..b06264ec 100644 --- a/doc/es/object/general.md +++ b/doc/es/object/general.md @@ -87,7 +87,7 @@ sido removido y por lo tanto no aparece en la salida. delete: 'Soy una palabra clave también' // lanza SyntaxError }; -Las propiedades de los objetos puede ser simbolizados como caracteres planos y como strings. Debido +Las propiedades de los objetos puede ser simbolizados como caracteres planos y como *strings*. Debido a otro mal diseño del parser de JavaScript, lo anterior es una excepción de `SyntaxError` antes de ECMAScript 5. diff --git a/doc/es/object/prototype.md b/doc/es/object/prototype.md index 363c4d48..0461d1ff 100644 --- a/doc/es/object/prototype.md +++ b/doc/es/object/prototype.md @@ -41,7 +41,7 @@ llamadas de *cadenas de prototipo* (*prototype chains*). // Resultado de cadena de prototipos (prototype chain) test [instance of Bar] Bar.prototype [instance of Foo] - { foo: 'Hello World' } + { foo: 'Hello World', value: 42 } Foo.prototype { method: ... } Object.prototype diff --git a/doc/es/types/equality.md b/doc/es/types/equality.md index 5665917f..f933d495 100644 --- a/doc/es/types/equality.md +++ b/doc/es/types/equality.md @@ -1,13 +1,13 @@ -## Equality and Comparisons +## Igualdad y Comparación -JavaScript has two different ways of comparing the values of objects for equality. +JavaScript posee 2 maneras diferentes para comparar valores entre objetos para comprobar igualdad. -### The Equality Operator +### El Operador de Igualdad -The equality operator consists of two equal signs: `==` +El operador de igualdad consiste en 2 signos es igual: `==` -JavaScript features *weak typing*. This means that the equality operator -**coerces** types in order to compare them. +JavaScript utiliza *tipado débil*. Esto significa que el operador de igualdad +**obliga** una conversión de tipos para poder compararlos. "" == "0" // false 0 == "" // true @@ -19,20 +19,20 @@ JavaScript features *weak typing*. This means that the equality operator null == undefined // true " \t\r\n" == 0 // true -The above table shows the results of the type coercion, and it is the main reason -why the use of `==` is widely regarded as bad practice. It introduces -hard-to-track-down bugs due to its complicated conversion rules. +La tabla anterior muestra los resultados de la conversión de tipos, éste es el motivo principal +de por qué el uso de `==` es ampliamente considerado una mala práctica. Introduce errores +difíciles de identificar debido a la complejidad de sus reglas de conversión. -Additionally, there is also a performance impact when type coercion is in play; -for example, a string has to be converted to a number before it can be compared -to another number. +Además, existe un impacto en el rendimiento cuando entra en juego la conversión de tipos; +por ejemplo, una cadena debe ser convertida a número antes de poder ser comparada +con otro número. -### The Strict Equality Operator +### El Operador de Igualdad Estricto -The strict equality operator consists of **three** equal signs: `===`. +El operador de igualdad estricto consiste en **tres** signos es igual: `===`: -It works exactly like the normal equality operator, except that strict equality -operator does **not** perform type coercion between its operands. +Funciona exactamente igual que el operador de igualdad, excepto que el operador de igualdad +estricto **no** utiliza conversión de tipos entre sus operandos. "" === "0" // false 0 === "" // false @@ -44,14 +44,14 @@ operator does **not** perform type coercion between its operands. null === undefined // false " \t\r\n" === 0 // false -The above results are a lot clearer and allow for early breakage of code. This -hardens code to a certain degree and also gives performance improvements in case -the operands are of different types. +Los resultados anteriores son mucho más claros y permiten una detección de errores temprana. +Esto permite un código más sólido en cierto grado y también mejora el rendimiento +en el caso que los operandos sean de tipos diferentes. -### Comparing Objects +### Comparando Objetos -While both `==` and `===` are stated as **equality** operators, they behave -differently when at least one of their operands happens to be an `Object`. +Aunque `==` como `===` son considerados operadores de **igualdad**, se comportan +de maneras diferentes cuando al menos uno de sus operandos es `Object`. {} === {}; // false new String('foo') === 'foo'; // false @@ -59,13 +59,13 @@ differently when at least one of their operands happens to be an `Object`. var foo = {}; foo === foo; // true -Here, both operators compare for **identity** and **not** equality; that is, they -will compare for the same **instance** of the object, much like `is` in Python -and pointer comparison in C. +En este caso, los dos operadores comparan por **referencia** y **no** por igualdad; esto es, +comparan por la misma **instancia** del objeto, parecido +al operador `is` en Python y la comparación entre punteros en C. -### In Conclusion +### En Conclusión -It is highly recommended to only use the **strict equality** operator. In cases -where types need to be coerced, it should be done [explicitly](#types.casting) -and not left to the language's complicated coercion rules. +Es altamente recomendable usar sólo el operador de **igualdad estricta**. En los casos +donde los tipos de datos necesitan ser convertidos, debe hacerse [explícitamente](#types.casting) +y no dejárselo a las complicadas reglas de conversión del lenguaje. diff --git a/doc/fi/object/prototype.md b/doc/fi/object/prototype.md index 4ecdae89..f2497e05 100644 --- a/doc/fi/object/prototype.md +++ b/doc/fi/object/prototype.md @@ -31,7 +31,7 @@ Ensimmäinen suuri ero liittyy siihen, kuinka perintä toimii. JavaScriptissä s // Prototyyppiketju test [Bar-olio] Bar.prototype [Foo-olio] - { foo: 'Terve maailma' } + { foo: 'Terve maailma', value: 42 } Foo.prototype { method: ... } Object.prototype diff --git a/doc/fr/array/constructor.md b/doc/fr/array/constructor.md new file mode 100644 index 00000000..76f9eda0 --- /dev/null +++ b/doc/fr/array/constructor.md @@ -0,0 +1,27 @@ +## Le constructeur `Array` + +Le constructeur `Array` traite ses paramètres de façon ambigu. +Il est fortement recommandé d'utiliser le littéral de tableau - notation `[]` - pour créer de nouveaux tableaux. + + [1, 2, 3]; // Résultat: [1, 2, 3] + new Array(1, 2, 3); // Résultat: [1, 2, 3] + + [3]; // Résultat: [3] + new Array(3); // Résultat: [] + new Array('3') // Résultat: ['3'] + +Dans les cas où il n'y a qu'un seul argument passé au constructeur `Array`, et quand cet argument est un nombre `Number`, le constructeur va retourner un nouveau tableau *clairsemé* avec la propriété `length` (longueur) fixée à la valeur de l'argument. +Il faut noter que de cette façon, **seulement** la propriété `length` du nouveau tableau sera mise en place, les indices réels du tableau ne seront pas initialisés. + + var arr = new Array(3); + arr[1]; // undefined + 1 in arr; // faux, l'indice n'existe pas + +Être en mesure de régler la longueur du tableau à l'avance n'est utile que dans quelques cas, comme la répétition d'une chaîne de caractères, dans lequel on évite l'utilisation d'une boucle. + + new Array(count + 1).join(chaineARepeter); + +### En conclusion + +Les littéraux sont préférés au constructeur `Array`. Ils sont plus courts, ont une syntaxe plus claire, et augmente la lisibilité du code. + diff --git a/doc/fr/array/general.md b/doc/fr/array/general.md new file mode 100644 index 00000000..aecec798 --- /dev/null +++ b/doc/fr/array/general.md @@ -0,0 +1,46 @@ +## Tableaux: iteration et propriétés + +Bien que les tableaux soient des objets en JavaScript, il n'y a pas de bonnes raisons d'utiliser la boucle [`for in`](#object.forinloop). +En fait, il y a un certain nombre de bonnes raisons **contre** l'utilisation de `for in` sur les tableaux. + +**Remarque:** Les tableaux JavaScript ne sont **pas** *associatifs*. JavaScript n'offre que les [objets](#object.general) pour associer des clés à des valeurs. Contrairement aux tableaux associatifs, les objets ne préservent **pas** l'ordre. + +La boucle `for in` énumère toutes les propriétés qui sont sur la chaîne de prototypes, et le seul moyen d'exclure ces propriétés consiste à utiliser +[`hasOwnProperty`](#object.hasownproperty), par conséquent la boucle `for in ` est **vingt fois** plus lente qu'une boucle `for` classique. + +### Itération + +Pour itérer sur les tableaux de façon performante, il est préférable d'utiliser la boucle `for` classique. + + var list = [1, 2, 3, 4, 5, ...... 100000000]; + for(var i = 0, l = list.length; i < l; i++) { + console.log(list[i]); + } + +Notez l'optimization supplémentaire dans l'exemple ci-dessus: la longueur du tableau est mise en mémoire "cached" via `l = list.length`. + +La propriété `length` est définie sur le tableau lui-même, mais la rechercher à chaque itération de la boucle à un coût. +Bien que les moteurs JavaScript récents **peuvent** appliquer l'optimisation, il n'y a aucun moyen de savoir si le code s'exécutera sur un de ces nouveaux moteurs. + +En effet, mettre la longueur du tableau en mémoire cache peut **doubler** la vitesse d'execution de la boucle. + +### La propriété `length` + +Le *getter* de la propriété `length` (longueur) renvoie simplement le nombre d'éléments contenus dans le tableau, mais le *setter* peut être utilisé pour +tronquer le tableau. + + var arr = [1, 2, 3, 4, 5, 6]; + arr.length = 3; + arr; // [1, 2, 3] + + arr.length = 6; + arr.push(4); + arr; // [1, 2, 3, undefined, undefined, undefined, 4] + +Attribuer une longueur inférieure tronque le tableau. Accroître la longueur crée un tableau clairsemé. + +### En conclusion + +Pour de meilleures performances, il est recommandé de toujours utiliser la boucle `for` classique et de mettre en mémoire la propriété `length`. +L'utilisation de la boucle `for in` sur un tableau est un signe de code mal écrit, de mauvaise performance, et sujet à des bogues. + diff --git a/doc/fr/core/delete.md b/doc/fr/core/delete.md new file mode 100644 index 00000000..5ef0b16b --- /dev/null +++ b/doc/fr/core/delete.md @@ -0,0 +1,76 @@ +## L'opérateur `delete` + +Il est *impossible* de supprimer les variables globales, fonctions et autres choses qui ont l'attribut `DontDelete` en JavaScript. + +### Le code global et le code de fonction + +Quand une variable ou une fonction est définie dans la portée globale ou une [portée de fonction](#function.scopes), c'est une propriété soit de l'objet d'activation, soit de l'objet global. +Ces propriétés ont un ensemble d'attributs, dont l'un est `DontDelete`. Les déclarations de variables et de fonctions dans le code global et le code de fonction vont toujours créer des propriétés avec `DontDelete`, elle ne peuvent donc pas être supprimées. + + // global variable: + var a = 1; // DontDelete est mis + delete a; // faux + a; // 1 + + // normal function: + function f() {} // DontDelete is mis + delete f; // faux + typeof f; // "function" + + // reassigner n'aide pas: + f = 1; + delete f; // faux + f; // 1 + +### Propriétés explicites + +Les propriétés crées explicitement peuvent être supprimées normalement. + + // propriété crée explicitement: + var obj = {x: 1}; + obj.y = 2; + delete obj.x; // vrai + delete obj.y; // vrai + obj.x; // undefined + obj.y; // undefined + +Dans l'exemple ci-dessus, les propriétés `obj.x` et `obj.y` peuvent être supprimées parce qu'elles n'ont pas l'attribut `DontDelete`. C'est aussi pourquoi l'exemple ci-dessous fonctionne également. + + // ceci fonctionne, sauf sur IE: + var GLOBAL_OBJECT = this; + GLOBAL_OBJECT.a = 1; + a === GLOBAL_OBJECT.a; // vrai - juste une var globale + delete GLOBAL_OBJECT.a; // vrai + GLOBAL_OBJECT.a; // undefined + +Ici, nous utilisons une astuce pour supprimer `a`. [`this`](#function.this) se réfère ici à l'objet global et nous déclarons explicitement la variable `a` comme sa propriété, ce qui nous permet de la supprimer. + +IE (au moins 6-8) a quelques bogues, le code ci-dessus n'y fonctionne pas. + +### Les arguments de fonction et built-ins + +Les arguments normaux de fonctions, [objets `arguments`](#Function.arguments) et les propriétés intégrées "built-in" ont aussi l'attribut `DontDelete`. + + // les arguments de fonction et les propriétés: + (function (x) { + + delete arguments; // faux + typeof arguments; // "object" + + delete x; // faux + x; // 1 + + function f(){} + delete f.length; // faux + typeof f.length; // "number" + + })(1); + +### Objets hôtes + +Le comportement de l'opérateur `delete` peut être imprévisible pour les objets hébergés "hosted". Dû à la spécification, les objets hôte sont autorisés à mettre en œuvre tout type de comportement. + +### En conclusion + +L'opérateur `delete` a souvent un comportement inattendu et ne peut être utilisé que pour supprimer les propriétés explicitement définies sur des objets normaux. + diff --git a/doc/fr/core/eval.md b/doc/fr/core/eval.md new file mode 100644 index 00000000..5b2cdcd1 --- /dev/null +++ b/doc/fr/core/eval.md @@ -0,0 +1,42 @@ +## Il ne faut pas utiliser `eval` + +La fonction `eval` exécute une chaîne de caractères représentant du code JavaScript dans la portée locale. + + var number = 1; + function test() { + var number = 2; + eval('number = 3'); + return number; + } + test(); // 3 + number; // 1 + +Cependant, `eval` n'exécute dans la portée locale que quand il est appelé directement *et* quand le nom de la fonction appelée est en fait `eval`. + + var number = 1; + function test() { + var number = 2; + var copyOfEval = eval; + copyOfEval('number = 3'); + return number; + } + test(); // 2 + number; // 3 + +L'utilisation de la fonction `eval` doit être évitée. 99,9% de ses "cas d'utilisation" peuvent être obtenues **sans** elle. + +### `eval` déguisé + +Les [fonctions timeout](#other.timeouts) `setTimeout` et `setInterval` acceptent une chaîne comme premier argument. +Cette chaîne sera **toujours** exécutée dans la portée globale car dans ce cas, `eval` n'est pas appelé directement. + +### Problèmes de sécurité + +`eval` est aussi un problème de sécurité, car il exécute **n'importe quel** code qu'on lui donne. +Il devrait **jamais** être utilisé avec des chaînes d'origines inconnues ou douteuses. + +### En conclusion + +`eval` ne devrait jamais être utilisé. Sa presence met en doute le fonctionnement, la performance, et la sécurité du code qui l'utilise. +Si quelque chose a besoin d'`eval` pour pouvoir fonctionner, il ne doit **pas** être utilisé en premier lieu. Un *meilleur design* qui n'utilise pas `eval` doit être trouvé et implementé. + diff --git a/doc/fr/core/semicolon.md b/doc/fr/core/semicolon.md new file mode 100644 index 00000000..75e4ac11 --- /dev/null +++ b/doc/fr/core/semicolon.md @@ -0,0 +1,100 @@ +## Insertion automatique du point-virgule + +Bien que JavaScript a une syntaxe de style C, il n'impose **pas** les points-virgules dans le code source. Il est donc possible de les omettre. + +JavaScript n'est pas un langage sans points-virgules. En fait, les points-virgules sont necessaires pour comprendre le code source. Par conséquent, l'analyseur JavaScript les insère **automatiquement** chaque fois qu'il rencontre une erreur d'analyse due à un point-virgule manquant. + + var foo = function() { + } // erreur d'analyse, point-virgule attendu + test() + +L'analyseur insère un point-virgule, puis tente à nouveau. + + var foo = function() { + }; // plus d'error, l'analyse continue + test() + +L'insertion automatique du point-virgule est considérée comme l'un des **plus gros** défauts de conception dans le langage parce que cela *peut* changer le comportement du code. + +### Comment cela marche + +Le code ci-dessous n'a pas de points-virgules, l'analyseur va donc décider où les insérer. + + (function(window, undefined) { + function test(options) { + log('testing!') + + (options.list || []).forEach(function(i) { + + }) + + options.value.test( + 'long string to pass here', + 'and another long string to pass' + ) + + return + { + foo: function() {} + } + } + window.test = test + + })(window) + + (function(window) { + window.someLibrary = {} + + })(window) + +Voici le résultat du jeu de devinette de l'analyseur. + + (function(window, undefined) { + function test(options) { + + // pas inséré, les lignes ont fusionné + log('testing!')(options.list || []).forEach(function(i) { + + }); // <- inséré + + options.value.test( + 'long string to pass here', + 'and another long string to pass' + ); // <- inséré + + return; // <- inséré, casse la déclaration return + { // traité comme un bloc + + // un label et une déclaration d'expression + foo: function() {} + }; // <- inséré + } + window.test = test; // <- inséré + + // les lignes ont fusionné ici encore + })(window)(function(window) { + window.someLibrary = {}; // <- inséré + + })(window); //<- inséré + +> **Remarque:** L'analyseur JavaScript ne manipule pas "correctement" les déclarations return suivies par une nouvelle ligne. + +L'analyseur a radicalement changé le comportement du code ci-dessus. Dans certains cas, il fait la **mauvaise chose**. + +### Parenthèse en tête + +En cas de parenthèse en tête, l'analyseur ne va **pas** insérer de point-virgule. + + log('testing!') + (options.list || []).forEach(function(i) {}) + +Ce code fusionne en une ligne. + + log('testing!')(options.list || []).forEach(function(i) {}) + +Il y a de **très** fortes chances que `log` ne retourne **pas** de fonction; par conséquent, le programme ci-dessus va produire une erreur de type `TypeError` indiquant que undefined n'est pas un function `undefined is not a function`. + +### En conclusion + +Il est fortement recommandé de ne **jamais** omettre les points-virgules. Il est également recommandé de garder les accolades sur la même ligne que leurs déclarations correspondantes et de ne jamais les omettre pour les déclaration en une ligne `if` / `else`. Ces mesures vont non seulement améliorer la cohérence du code, mais elles empêcheront également l'analyseur JavaScript de changer le comportement du code. + diff --git a/doc/fr/core/undefined.md b/doc/fr/core/undefined.md new file mode 100644 index 00000000..4736b5dc --- /dev/null +++ b/doc/fr/core/undefined.md @@ -0,0 +1,55 @@ +## `undefined` et `null` + +JavaScript a deux valeurs distinctes pour "rien": `null` et `undefined`, `undefined` étant la plus utile. + +### La valeur `undefined` + +`undefined` est un type avec exactement une valeur:` undefined`. + +Le langage définit également une variable globale qui a la valeur `undefined`. Cette variable est aussi appelée `undefined`. Cependant, cette variable n'est ni une constante, ni un mot clé du langage, ce que signifie que sa *valeur* peut être facilement écrasée. + +> **Remarque ES5:** `undefined` dans ECMAScript 5 n'est **plus** inscriptible dans le mode stricte, mais son nom peut toujours être outrepassé, par example par une fonction avec le nom `undefined`. + +Voici quelques exemples de cas où la valeur `undefined` est retournée: + + - Accès à la variable globale (non modifié) `undefined`. + - Accès à une variable déclarée, mais *pas encore* initialisée. + - Retours implicites de fonctions sans déclaration `return`. + - Déclarations `return` vides, qui ne renvoient rien. + - Recherches de propriétés inexistantes. + - Paramètres de fonction qui ne ont pas de valeur explicite passée. + - Tout ce qui a été mis à la valeur de `undefined`. + - Toute expression sous forme de `void(expression)`. + +### Changements à la valeur de `undefined` + +Puisque la variable globale `undefined` contient uniquement une copie de la *valeur* réelle `undefined`, l'attribution d'une nouvelle valeur à la variable ne modifie **pas** la valeur du *type* `undefined`. + +Pourtant, pour pouvoir comparer quelque chose contre la valeur de `undefined`, il est d'abord nécessaire pour récupérer la valeur de `undefined`. + +Afin de protéger le code contre une éventuelle variable `undefined` écrasée, une technique commune utilisée consiste à ajouter un paramètre supplémentaire à une [enveloppe anonyme](#function.scopes) et de lui passer aucun argument. + + var undefined = 123; + (function(something, foo, undefined) { + // undefined dans la portée locale + // réfère bien à la valeur `undefined` + + })('Hello World', 42); + +Une autre façon d'obtenir le même effet est d'utiliser une déclaration à l'intérieur de l'enveloppe. + + var undefined = 123; + (function(something, foo) { + var undefined; + ... + + })('Hello World', 42); + +La seule différence étant quelques caractères de plus pour écrire "var". + +### Utilisation de `null` + +Alors que `undefined` dans le contexte du langage JavaScript est utilisé dans la plupart des cas dans le d'un *null* traditionnel, le `null` réel (un littéral et un type) est juste un autre type de données. + +`null` est utilisé par JavaScript (comme signaler la fin de la chaîne de prototypes avec `Foo.prototype = null`), mais dans presque tous les cas, il peut être remplacé par `undefined`. + diff --git a/doc/fr/function/arguments.md b/doc/fr/function/arguments.md new file mode 100644 index 00000000..84a09ea1 --- /dev/null +++ b/doc/fr/function/arguments.md @@ -0,0 +1,118 @@ +## L'objet `arguments` + +Chaque portée "scope" de fonction en JavaScript peut accéder à la variable spéciale `arguments`. +Cette variable contient une liste de tous les arguments qui ont été passés à la fonction. + +> **Remarque:** Si `arguments` a déjà été définie soit par une déclaration `var` +> à l'intérieur de la fonction ou par un paramètre de fonction, l'objet `arguments` ne sera pas créé. + +L'objet `arguments` n'est **pas** un tableau `Array`. Même s'il a la sémantique d'un tableau - à savoir la propriété `length` (longueur) - il n'hérite pas de +`Array.prototype` mais est en fait un `Object`. + +Pour cette raison, il n'est **pas** possible d'utiliser les méthodes de tableau standards comme `push`, `pop` ou `slice` sur `arguments`. +Bien qu'itérer avec une boucle `for` fonctionne, il est nécessaire de convertir la variable `arguments` en un véritable `Array` pour pouvoir lui appliquer les fonctions de tableau `Array` standards. + +### Conversion à Array + +Le code ci-dessous va retourner un nouveau tableau `Array` contenant tous les éléments de l'objet `arguments`. + + Array.prototype.slice.call(arguments); + +Cette conversion est **lente**, il n'est donc **pas** recommandé de l'utiliser dans des sections de code où la performance est critique. + +### Passage d'arguments + +Voici la méthode recommandée pour passer des arguments d'une fonction à une autre. + + function foo() { + bar.apply(null, arguments); + } + function bar(a, b, c) { + // faire qqch ici + } + +Une autre astuce consiste à utiliser à la fois `call` et `apply` pour transformer des méthodes - fonctions qui utilisent la +valeur de `this` ainsi que leurs arguments - en des fonctions normales qui n'utilisent que leurs arguments. + + function Person(first, last) { + this.first = first; + this.last = last; + } + + Person.prototype.fullname = function(joiner, options) { + options = options || { order: "western" }; + var first = options.order === "western" ? this.first : this.last; + var last = options.order === "western" ? this.last : this.first; + return first + (joiner || " ") + last; + }; + + // Créer une version non liée de "fullname", utilisable sur n'importe quel + // objet avec les propriétés 'first' et 'last' passées comme premier + // argument. Cette enveloppe n'aura pas besoin de changer si fullname + // change le nombre ou l'ordre des ses arguments. + Person.fullname = function() { + // résultat: Person.prototype.fullname.call(this, joiner, ..., argN); + return Function.call.apply(Person.prototype.fullname, arguments); + }; + + var grace = new Person("Grace", "Hopper"); + + // 'Grace Hopper' + grace.fullname(); + + // 'Turing, Alan' + Person.fullname({ first: "Alan", last: "Turing" }, ", ", { order: "eastern" }); + + +### Paramètres formels et arguments indexés + +L'objet `arguments` crée des fonctions *getter* et *setter* à la fois pour ses propriétés et les paramètres formels de la fonction. + +Par conséquent, changer la valeur d'un paramètre formel va également modifier la valeur de la propriété correspondante sur l'objet `arguments`, et vice-versa. + + function foo(a, b, c) { + arguments[0] = 2; + a; // 2 + + b = 4; + arguments[1]; // 4 + + var d = c; + d = 9; + c; // 3 + } + foo(1, 2, 3); + +### Mythes et faits sur la performance + +Le seul moment où l'objet `arguments` n'est pas créé est quand il est déclaré comme un nom à l'intérieur d'une fonction ou l'un de ses paramètres formels. Le fait qu'il soit utilisé ou non n'est pas important. + +Les deux *getter* et *setter* sont toujours créé; et donc l'utilisation d'`arguments` n'a aucune incidence sur la performance. + +> **Remarque ES5:** Ces *getters* et *setters* ne sont pas créés en mode strict. + +Cependant, un cas va considérablement réduire la performance des moteurs JavaScript modernes. +C'est le cas de l'utilisation de `arguments.callee`. + + function foo() { + arguments.callee; // faire quelque chose avec cet objet de fonction + arguments.callee.caller; // et la fonction appelante + } + + function bigLoop() { + for(var i = 0; i < 100000; i++) { + foo(); // Seraient normalement inline... + } + } + +Dans le code ci-dessus, `foo` ne peut plus être [inline][1] car il a besoin de se connaitre lui-même et connaitre son appelant. +Cela défait les gains possibles de performance qui découleraient d'inline, mais cela casse également l'encapsulation +car la fonction peut maintenant être dépendante d'un contexte d'appel spécifique. + +Utiliser `arguments.callee` ou l'une de ses propriétés est **fortement déconseillé**. + +> **Remarque ES5:** En mode strict, `arguments.callee` jettera une erreur de type `TypeError` +> car son utilisation est marquée comme obsolète "deprecated". + +[1]: http://en.wikipedia.org/wiki/Inlining + diff --git a/doc/fr/function/closures.md b/doc/fr/function/closures.md new file mode 100644 index 00000000..50983db3 --- /dev/null +++ b/doc/fr/function/closures.md @@ -0,0 +1,97 @@ +## Fermetures et réferences + +Les *fermetures* "closures" sont une des fonctionnalités les plus puissantes de JavaScript. +Avec les fermetures, les portées gardent **toujours** l'accès à la portée externe, dans laquelle elles ont été définies. +Puisque la seule portée que JavaScript a est la [portée de fonction](#function.scopes), toutes les fonctions, par défaut, agissent comme des fermetures. + +### Simuler les variables privées + + function Counter(start) { // compteur + var count = start; // compte + return { + increment: function() { + count++; + }, + + get: function() { + return count; + } + } + } + + var foo = Counter(4); + foo.increment(); + foo.get(); // 5 + +Ici, `Counter` retourne **deux** fermetures: la fonction` increment` ainsi que la fonction `get`. Ces deux fonctions conservent une **référence** à la portée de `Counter` et, par conséquent, gardent toujours l'accès à la variable `count` qui a été définie dans cette portée. + +### Comment marchent les variables privées + +Comme il ne est pas possible de référencer ou assigner des portées en JavaScript, il n'y a **aucun** moyen d'accéder à la variable `count` de l'extérieur. +La seule façon d'interagir avec elle est par l'intermédiaire des deux fermetures. + + var foo = new Counter(4); + foo.hack = function() { + count = 1337; + }; + +Le code ci-dessus ne va **pas** changer la variable `count` dans la portée de `Counter`, car `foo.hack` n'a pas été défini dans cette portée. En fait, une nouvelle variable va etre crée - ou va remplacer - la variable *globale* `count`. + +### Fermetures dans les boucles + +Une erreur souvent commise est d'utiliser les fermetures à l'intérieur de boucles comme si elles copiaient la valeur de la variable d'indice de la boucle. + + for(var i = 0; i < 10; i++) { + setTimeout(function() { + console.log(i); + }, 1000); + } + +La programme ci-dessus ne vas **pas** produire les numéros `0` à `9`, il imprimera `10` dix fois. + +La fonction *anonyme* garde une **référence** à `i`. Au moment où `console.log` est appelée, la `boucle for` est déjà achevée, et donc la valeur de `i` est à `10`. + +Afin d'obtenir le comportement souhaité, il est nécessaire de créer une **copie** de la valeur de `i`. + +### Eviter le problème de référence + +Pour copier la valeur de la variable d'index de la boucle, il est préférable d'utiliser une [enveloppe anonyme](#function.scopes) "wrapper". + + for(var i = 0; i < 10; i++) { + (function(e) { + setTimeout(function() { + console.log(e); + }, 1000); + })(i); + } + +La fonction externe anonyme est appelée immédiatement avec `i` en tant que premier argument, et donc le paramètre `e` recevra une copie de la **valeur** de `i`. + +La fonction anonyme qui est passé à `setTimeout` a maintenant une référence à `e`, dont la valeur ne peut **pas** être changée par la boucle. + +Une autre façon de faire est de retourner une fonction de l'enveloppe anonyme qui aura alors le même comportement que le code ci-dessus. + + for(var i = 0; i < 10; i++) { + setTimeout((function(e) { + return function() { + console.log(e); + } + })(i), 1000) + } + +Une autre façon populaire d'achever le même comportement est d'ajouter un argument supplémentaire à la fonction `setTimeout`. La fonction passera ces arguments à la fonction de rappel "callback". + + for(var i = 0; i < 10; i++) { + setTimeout(function(e) { + console.log(e); + }, 1000, i); + } + +Sachez que certains environnements JS (Internet Explorer 9 et avant) ne supportent pas cette dernière approche. + +Enfin, une dernière façon de faire et d'utiliser `bind`, qui peut lier le contexte `this` et les arguments pour la fonction. + + for(var i = 0; i < 10; i++) { + setTimeout(console.log.bind(console, i), 1000); + } + diff --git a/doc/fr/function/constructors.md b/doc/fr/function/constructors.md new file mode 100644 index 00000000..e92dea93 --- /dev/null +++ b/doc/fr/function/constructors.md @@ -0,0 +1,109 @@ +## Constructeurs + +Les constructeurs en JavaScript diffèrent de beaucoup d'autres langages. +Tout appel de fonction précédé par le mot clé `new` agit comme un constructeur. + +Dans le constructeur - la fonction appelée - la valeur de `this` se réfère à un objet nouvellement créé. +Le [prototype](#Object.prototype) de ce **nouvel** objet pointe sur le `prototype` de l'objet de fonction qui a été invoqué comme constructeur. + +Si la fonction qui a été appelée n'a pas de déclaration `return` explicite, elle renvoira implicitement la valeur de `this` - le nouvel objet. + + function Person(name) { + this.name = name; + } + + Person.prototype.logName = function() { + console.log(this.name); + }; + + var sean = new Person(); + +Le code ci-dessus appelle `Person` en tant que constructeur et définit le `prototype` du nouvel objet créé à `Person.prototype`. + +En cas d'une déclaration `return` explicite, la fonction renvoie la valeur spécifiée par cette déclaration, mais **seulement** si cette valeur est un objet `Object`. + + function Car() { + return 'ford'; + } + new Car(); // un nouvel objet, pas 'ford' + + function Person() { + this.someValue = 2; + + return { + name: 'Charles' + }; + } + new Test(); // l'objet retourné ({name:'Charles'}) n'inclue pas someValue + +Lorsque le mot clé `new` est omis, la fonction ne retournera **pas** un nouvel objet. + + function Pirate() { + this.hasEyePatch = true; // this est l'object global! + } + var somePirate = Pirate(); // somePirate est undefined + +Bien que l'exemple ci-dessus a l'air de marcher, il utilisera l'*objet global* pour la valeur de `this`, en raison du fonctionnement particulier de [`this`](#function.this) en JavaScript. + +### Fabriques + +Pour pouvoir omettre le mot clé `new`, la fonction constructeur doit retourner explicitement une valeur. + + function Robot() { + var color = 'gray'; + return { + getColor: function() { + return color; + } + } + } + Robot.prototype = { + someFunction: function() {} + }; + + new Robot(); + Robot(); + +Les deux appels à `Robot` retournent la même chose, un objet nouvellement créé qui possède une propriété appelée `getColor`, qui est une [fermeture](#function.closures) "closure". + +Il convient également de noter que l'appel `new Robot()` n'affecte **pas** le prototype de l'objet retourné. +Bien que le prototype sera mis sur le nouvel objet créé, `Robot` ne retourne jamais cet objet. + +Dans l'exemple ci-dessus, il n'y a pas de différence fonctionnelle entre l'utilisation et la non-utilisation du mot clé `new`. + +### Creation de nouvels objects via fabriques + +Il est souvent recommandé de ne **pas** utiliser `new` car l'oublier peut conduire à des bugs. + +Pour créer un nouvel objet, il faut plutôt utiliser une fabrique qui va construire un nouvel objet. + + function CarFactory() { + var car = {}; + car.owner = 'nobody'; + + var milesPerGallon = 2; + + car.setOwner = function(newOwner) { + this.owner = newOwner; + } + + car.getMPG = function() { + return milesPerGallon; + } + + return car; + } + +Bien que le code qui précède est robuste contre un mot clé `new` manquant et rend certainement +l'utilisation de [variables privées](#function.closures) plus facile, il y a des inconvénients. + + 1. Il utilise plus de mémoire car les objets créés ne partagent **pas** leurs méthodes avec un prototype. + 2. Pour hériter, la fabrique a besoin de copier toutes les méthodes de l'autre objet ou mettre l'autre objet sur le prototype du nouvel objet. + 3. Abandonner la chaîne de prototype à cause d'un mot clé `new` laissé de côté est contraire à l'esprit du langage. + +### En Conclusion + +Omettre le mot clé `new` peut conduire à des bugs, mais ce n'est certainement **pas** une raison d'abandonner l'utilisation des prototypes. +En fin de compte il s'agit de savoir quelle solution est la mieux adaptée pour les besoins de l'application. +Il est particulièrement important de choisir un style spécifique de création d'objet et toujours l'utiliser afin de rester *cohérent*. + diff --git a/doc/fr/function/general.md b/doc/fr/function/general.md new file mode 100644 index 00000000..b6fe47ec --- /dev/null +++ b/doc/fr/function/general.md @@ -0,0 +1,38 @@ +## Déclaration des fonctions et expressions + +Les fonctions en JavaScript sont des objets de première classe. Cela signifie qu'elles peuvent être passées comme toute autre valeur. Une utilisation courante de cette caractéristique est de passer une *fonction anonyme* comme une fonction de rappel "callback" qui peut être asynchrone. + +### La déclaration `function` + + function foo() {} + +La fonction ci-dessus est [hissée](#function.scopes) "hoisted" avant le démarrage du programme; ainsi, elle est donc disponible partout dans la portée "scope" d'application où la fonction a été définie, même si appelé avant sa définition dans le code source. + + foo(); // Fonctionne car foo a été crée avant l'exécution de ce code + function foo() {} + +### L'expresssion `function` + + var foo = function() {}; + +Cet exemple attribue une fonction *anonyme* et sans nom à la variable `foo`. + + foo; // 'undefined' + foo(); // provoque un erreur de type TypeError + var foo = function() {}; + +En raison du fait que `var` est une déclaration qui hisse le nom de la variable `foo` avant que l'exécution réelle du code ne commence, `foo` est déjà déclarée lorsque le script est exécuté. + +Mais comme les assignements ne se produisent qu'au moment de l'exécution, la valeur de `foo` sera par défaut mise à [undefined](#core.undefined) avant l'exécution du code. + +### L'expression de fonction nommée + +Un autre cas est l'attribution de fonctions nommées. + + var foo = function bar() { + bar(); // Works + } + bar(); // erreur de reference ReferenceError + +Ici, `bar` n'est pas disponible dans la portée externe "outer scope", puisque la fonction est seulement assignée à `foo`, mais elle est disponible à l'intérieur de `bar`. Cela est dû à la méthode de [résolution de noms](#function.scopes) de JavaScript: le nom de la fonction est *toujours* disponible dans la portée locale "local scope" de la fonction elle-même. + diff --git a/doc/fr/function/scopes.md b/doc/fr/function/scopes.md new file mode 100644 index 00000000..7cd1d0b3 --- /dev/null +++ b/doc/fr/function/scopes.md @@ -0,0 +1,204 @@ +## Portées "scopes" et espaces de noms "namespaces" + +Bien que JavaScript utilise une syntaxe avec accolades pour les blocs, il ne crée **pas** de portée "scope" de bloc; par conséquent, la seule portée du langage est la portée de fonction. + + function test() { // une portée "scope" + for(var i = 0; i < 10; i++) { // pas une portée + // count + } + console.log(i); // 10 + } + +> **Remarque:** Lorsqu'elle n'est pas utilisé dans un assignement, une déclaration de retour, +> ou un argument de fonction, la notation `{...}` sera interprétée comme une déclaration +> de bloc et non **pas** comme un littéral d'objet. Ceci, quand combiné avec +> l'[insertion automatique des points-virgules](#de core.semicolon), peut conduire à des erreurs subtiles. + +Il n'existe pas d'espaces de noms "namespaces" en JavaScript, ce qui signifie que tout est défini dans un espace de noms commun partagé par tous. + +Chaque fois qu'une variable est référencée, JavaScript va traverser vers le haut toutes les portées jusqu'à ce qu'il la trouve. +S'il atteint la portée globale sans avoir trouvé le nom demandé, il va générer une erreur de référence `ReferenceError`. + +### Le fléau des variables globales + + // script A + foo = '42'; + + // script B + var foo = '42' + +Les deux scripts ci-dessus n'ont **pas** le même effet. Le script A définit une variable appelée `foo` dans la portée *globale*, le script B définit `foo` dans la portée actuelle. + +Ne pas utiliser `var` peut avoir des répercussions majeures. + + // portée globale + var foo = 42; + function test() { + // portée locale + foo = 21; + } + test(); + foo; // 21 + +En laissant de côté la déclaration `var` à l'intérieur de la fonction `test`, on remplace la valeur de `foo`. +Même si au premier abord cela ne semble pas être une grosse affaire, des milliers de lignes de JavaScript qui n'utilisent pas `var` créeront des bogues horribles qui seront très difficiles à dépister. + + // portée globale + var items = [/* some list */]; + for(var i = 0; i < 10; i++) { + subLoop(); + } + + function subLoop() { + // portée de subLoop + for(i = 0; i < 10; i++) { // var manquant + // ici, des choses incroyables! + } + } + +La boucle externe se terminera après le premier appel à `subLoop`, car `subLoop` écrase la valeur globale de `i`. +L'utilisation d'un `var` pour la deuxième boucle `for` aurait facilement évité cette erreur. +La déclaration de `var` devrait **jamais** être laissé de côté, sauf si l'*effet désiré* est d'affecter la portée externe. + +### Variables locales + +Seuls les paramètres de [fonction](#function.general) et les variables déclarées avec un `var` peuvent créer des variables locales en JavaScript. + + + // portée globale + var foo = 1; + var bar = 2; + var i = 2; + + function test(i) { + // portée locale de la fonction test + i = 5; + + var foo = 3; + bar = 4; + } + test(10); + +`foo` et `i` sont bien des variables locales à l'intérieur de la portée de la fonction `test`, mais l'assignment `bar` remplacera la variable globale portant le même nom. + +### Remontée "hoisting" + +JavaScript **hisse** les déclarations. Cela signifie que les déclarations de `var` et `function` seront déplacés vers le haut de leur portée englobante. + + bar(); + var bar = function() {}; + var someValue = 42; + + test(); + function test(data) { + if (false) { + goo = 1; + + } else { + var goo = 2; + } + for(var i = 0; i < 100; i++) { + var e = data[i]; + } + } + +Le code ci-dessus est transformé avant que l'exécution ne commence. JavaScript déplace les déclarations `var`, ainsi que les déclarations `function`, vers le haut de la portée la plus proche. + + // les déclarations var sont maintenant ici + var bar, someValue; // mis à 'undefined' par défaut + + // les déclarations de fonction aussi + function test(data) { + var goo, i, e; // pas de portée de bloc, + // donc déclarations var viennent ici + if (false) { + goo = 1; + + } else { + goo = 2; + } + for(i = 0; i < 100; i++) { + e = data[i]; + } + } + + bar(); // échoue avec TypeError puisque bar est toujours 'undefined' + someValue = 42; // les assignements ne sont pas concernés par la remontée + bar = function() {}; + + test(); + +L'inexistence des portées de bloc va non seulement déplacer les déclarations `var` en dehors du corps des boucles, mais va aussi rendre les résultats de certaines constructions de `if` non-intuitifs. + +Dans le code original, la déclaration `if` semblait modifier la *variable globale* `goo`, alors qu'en fait elle modifiait la *variable locale* - après la remontée appliquée. + +Sans la connaissance du concept de *remontée*, on pourrait soupçonner que le code ci-dessous produirait une erreur de référence `ReferenceError`. + + // verifie si SomeImportantThing a bien été initializé + if (!SomeImportantThing) { + var SomeImportantThing = {}; + } + +Le code fonctionne pourtant bien, car la déclaration de `var` est déplacé vers le haut de la *portée globale*. + + var SomeImportantThing; + + // du code peut, ou pas, initializer SomeImportantThing ici + + // soyons en sûr + if (!SomeImportantThing) { + SomeImportantThing = {}; + } + +### Ordre de la résolution de noms + +Toutes les portées en JavaScript, y compris la *portée globale*, ont le nom spécial [`this`](#function.this) défini qui se réfère à l'*objet courant*. + +Les portées de fonction ont aussi le nom [`arguments`](#Function.arguments) défini qui contient les arguments qui ont été transmis à la fonction. + +Par exemple, lorsque vous essayez d'accéder à une variable nommé `foo` l'intérieur de la portée d'une fonction, JavaScript va chercher le nom dans l'ordre suivant: + + 1. Si il y a une déclaration `var foo` var dans la portée courante, l'utiliser. + 2. Si l'un des paramètres de la fonction est nommé `foo`, l'utiliser. + 3. Si la fonction elle-même est appelée `foo`, l'utiliser. + 4. Sinon, accéder à la portée externe suivante, et recommencer à **#1** pour cette portée. + +**Remarque:** Avoir un paramètre appelé `arguments` va **empêcher** la création d'objet par défaut `arguments`. + +### Espaces de noms + +Le fait de n'avoir qu'un seul espace de noms global engendre un risque de conflit de noms de variables, un problème commun en JavaScript. +En JavaScript, ce problème peut facilement être évité grâces aux *enveloppes anonymes*. + + (function() { + // un "espace de nom" autonome + + window.foo = function() { + // une fermeture exposée + }; + + })(); // exécute la fonction immédiatement + +Les fonctions anonymes sont considérées comme des [expressions](#function.general); ainsi elles doivent d'abord être évaluées avant d'être appelées. + + ( // évaluer la fonction à l'intérieur des parenthèses + function() {} + ) // et retourner la fonction object + () // appeler le résultat de l'évaluation + +Il y a d'autres façons d'évaluer et d'appeler directement l'expression de fonction qui, bien que différentes dans la syntaxe, se comportent de la même manière. + + // Autres styles d'invocation directe + !function(){}() + +function(){}() + (function(){}()); + // etc. + +### En conclusion + +Il est recommandé de toujours utiliser une *enveloppe anonyme* pour encapsuler du code dans son propre espace de noms. +Non seulement cela protège des conflits de noms de code, cela permet également une meilleure modularisation des programmes. + +En outre, l'utilisation de variables globales est considéré comme une **mauvaise pratique**. +Leur utilisation indique un code mal écrit, sujet à des erreurs, et difficile à maintenir. + diff --git a/doc/fr/function/this.md b/doc/fr/function/this.md new file mode 100644 index 00000000..723c0255 --- /dev/null +++ b/doc/fr/function/this.md @@ -0,0 +1,100 @@ +## Comment marche `this` + +Pour JavaScript, ce que le nom spécial `this` réfère à diffère de la plupart des autres langages de programmation. Il y a exactement **cinq** façons différente de lier la valeur de `this` dans le langage. + +### Le contexte global "global scope" + + this; + +Lorsque vous utilisez `this` dans le contexte global, il va simplement référer à l'objet *global*. + +### Appel de fonction + + foo(); + +Ici, `this` va aussi référer à l'objet *global*. + +> **Remarque ES5:** En mode strict, le cas global **n'existe plus**: `this` aura la valeur `undefined`. + +### Appel de méthode + + test.foo(); + +Dans cet exemple, `this` va référer à `test`. + +### Appel de constructeur + + new foo(); + +Un appel de fonction qui est précédé par le mot clé `new` agit comme un [constructeur](#function.constructors). Dans la fonction, `this` va référer à un `Object` *nouvellement créé*. + +### Assignement direct de `this` + + function foo(a, b, c) {} + + var bar = {}; + foo.apply(bar, [1, 2, 3]); // table va s'étendre comme ci-dessous + foo.call(bar, 1, 2, 3); // mène à: a = 1, b = 2, c = 3 + +Lorsque vous utilisez les méthodes `call` (appeler) ou `apply` (appliquer) de `Function.prototype`, la valeur de `this` à l'intérieur de la fonction appelée est **directement définie** par le premier argument de l'appel correspondant. + +En conséquence, dans l'exemple ci-dessus le cas d'*appel de méthode* ne s'applique **pas**, et `this` à l'intérieur de `foo` va bien référer à `bar`. + +> **Remarque:** `this` ne peut **pas** être utilisé pour se référer à l'objet à l'intérieur d'un littéral `Object`. +> Donc dans `var obj = {moi: this}`, `moi` ne vas **pas** référer à `obj`, puisque `this` ne reçoit une valeur que dans l'un des cinq cas énumérés. + +### Pièges communs + +Bien que la plupart de ces cas ont du sens, le premier cas peut être considéré comme une autre faute de design du langage, car il n'est **jamais** d'aucune utilité pratique. + + Foo.method = function() { + function test() { + // this réfère à l'objet global + } + test(); + } + +Une autre erreur souvent commise est que `this` l'intérieur de `test` se réfère à `foo`; ce qui n'est **pas** du tout le cas. + +Pour accéder à `foo` de l'intérieur de `test`, vous pouvez créer une variable locale à intérieur de `method` qui fait référence à `foo`. + + Foo.method = function() { + var self = this; + function test() { + // Utilisez self au lieu de this ici + } + test(); + } + +`self` est juste une variable normale, couramment utilisée pour référencer un `this` extérieur. Combiné avec des [fermetures](# function.closures) "closures", on peut l'utiliser pour passer les valeurs de `this`. + +À partir d'ECMAScript 5, l'utilisation de la méthode `bind` avec une fonction anonyme mène au même resultat: + + Foo.method = function() { + var test = function() { + // maintenant, this réfère à Foo + }.bind(this); + test(); + } + +### Assignement de méthodes + +Une autre chose qui ne marche **pas** en JavaScript est l'alias de fonction, ou l'**assignement** d'une méthode à une variable. + + var test = someObject.methodTest; + test(); + +En raison du premier des cinq cas, `test` agit maintenant comme un appel de fonction normal; par conséquent, `this` à l'intérieur de la fonction ne va plus référer à `someObject`. + +Bien que la liaison tardive "late binding" de `this` pouvait sembler comme une mauvaise idée au premier abord, c'est en fait grâce à cela que l'[héritage prototypique](#Object.prototype) fonctionne. + + function Foo() {} + Foo.prototype.method = function() {}; + + function Bar() {} + Bar.prototype = Foo.prototype; + + new Bar().method(); + +Quand `method` est appelée d'une instance de `bar`, `this` va référer à cette même instance. + diff --git a/doc/fr/index.json b/doc/fr/index.json new file mode 100644 index 00000000..9f1bf373 --- /dev/null +++ b/doc/fr/index.json @@ -0,0 +1,69 @@ +{ + "title": "Le Jardin de JavaScript", + "langTitle": "JavaScript Garden en Français", + "description": "Un guide des defauts et excentricités de JavaScript", + "sections": [ + { + "title": "Introduction", + "dir": "intro", + "articles": ["index"] + }, + { + "title": "Objets", + "dir": "object", + "articles": [ + "general", + "prototype", + "hasownproperty", + "forinloop" + ] + }, + { + "title": "Fonctions", + "dir": "function", + "articles": [ + "general", + "this", + "closures", + "arguments", + "constructors", + "scopes" + ] + }, + { + "title": "Tableaux", + "dir": "array", + "articles": [ + "general", + "constructor" + ] + }, + { + "title": "Types", + "dir": "types", + "articles": [ + "equality", + "typeof", + "instanceof", + "casting" + ] + }, + { + "title": "Cœur", + "dir": "core", + "articles": [ + "eval", + "undefined", + "semicolon", + "delete" + ] + }, + { + "title": "Autres", + "dir": "other", + "articles": [ + "timeouts" + ] + } + ] +} diff --git a/doc/fr/intro/index.md b/doc/fr/intro/index.md new file mode 100644 index 00000000..71c6ac67 --- /dev/null +++ b/doc/fr/intro/index.md @@ -0,0 +1,36 @@ +## Introduction + +Le **Jardin de JavaScript** est une collection croissante de documentation liée aux aspects les plus excentriques du langage de programmation JavaScript. Il donne des conseils pour éviter les erreurs communes, les bugs subtils, ainsi que les problèmes de performance et de mauvaises pratiques, que les amateurs de JavaScript peuvent rencontrer dans leurs efforts d'apprentissage en profondeur du langage. + +Le Jardin de JavaScript ne cherche pas à vous enseigner JavaScript. Une connaissance préalable du langage est fortement recommandée afin de comprendre les sujets abordés dans ce guide. Veuillez vous référer à l'excellent [guide][1] du Mozilla Developer Network pour apprendre les rudiments du langage JavaScript. + +## Auteurs + +Ce guide est l'œuvre de deux charmants utilisateurs de [Stack Overflow][2]: [Ivo Wetzel][3] (écriture) et [Zhang Yi Jiang][4] (design). + +Actuellement maintenu par [Tim Ruffles](http://truffles.me.uk). + +## Collaborateurs + +- Trop nombreux pour être énumérés ici, [voir la liste des collaborateurs](https://github.com/BonsaiDen/JavaScript-Garden/graphs/contributors). + +## Hébergement + +Le Jardin de JavaScript est hébergé sur GitHub, mais [Cramer Développement][7] nous soutient avec un mirroir à [JavaScriptGarden.info][8]. + +## Licence + +Le Jardin de JavaScript est publié sous la [licence MIT][9] et hébergé sur [GitHub][10]. Si vous trouvez des erreurs ou fautes de frappe veuillez s'il vous plaît [déposer une question][11] ou une "pull request" sur le dépôt. Vous pouvez également nous trouver dans la [Salle JavaScript][12] sur Stack Overflow. + +[1]: https://developer.mozilla.org/en/JavaScript/Guide +[2]: http://stackoverflow.com/ +[3]: http://stackoverflow.com/users/170224/ivo-wetzel +[4]: http://stackoverflow.com/users/313758/yi-jiang +[5]: https://github.com/caio +[6]: https://github.com/blixt +[7]: http://cramerdev.com/ +[8]: http://javascriptgarden.info/ +[9]: https://github.com/BonsaiDen/JavaScript-Garden/blob/next/LICENSE +[10]: https://github.com/BonsaiDen/JavaScript-Garden +[11]: https://github.com/BonsaiDen/JavaScript-Garden/issues +[12]: http://chat.stackoverflow.com/rooms/17/javascript diff --git a/doc/fr/object/forinloop.md b/doc/fr/object/forinloop.md new file mode 100644 index 00000000..afc1a2d5 --- /dev/null +++ b/doc/fr/object/forinloop.md @@ -0,0 +1,44 @@ +## La boucle `for in` + +Tout comme l'opérateur `in`, la boucle `for in` traverse la chaîne de prototypes lors de l'itération sur les propriétés d'un objet. + +> **Remarque:** La boucle `for in` n'itérera **pas** sur les propriétés qui +> ont leur attribut `enumerable` à `false`; par exemple, la propriété `length` d'un tableau "array". + + // Empoisonnement d'Object.prototype + Object.prototype.bar = 1; + + var foo = {moo: 2}; + for(var i in foo) { + console.log(i); // imprime bar et moo + } + +Puisqu'il n'est pas possible de changer le comportement de la boucle `for in`, il est nécessaire de filtrer les propriétés indésirables à l'intérieur du corps de la boucle. Sous ECMAScript 3 et plus, cela se fait en utilisant la méthode [`hasOwnProperty`](#object.hasownproperty) de `Object.prototype`. + +Depuis ECMAScript 5, `Object.defineProperty` peut être utilisé avec `enumerable` mis à faux pour ajouter des propriétés à des objets (y compris `Object`) sans que ces propriétés soient énumérées. Il est raisonnable dans ce cas d'assumer que les propriétés énumérables ont été ajouté pour une raison, ce qui permet d'omettre les appels à `hasOwnProperty` qui réduisent la lisibilité du code. Dans du code de librairie, `hasOwnProperty` devrait toujours être utilisé car des propriétés énumérables pourraient résider sur la chaîne de prototypes sans qu'on le sache. + +> **Remarque:** Puisque la boucle `for in` traverse toujours la chaîne de prototypes complet, elle +> deviendra plus lente avec chaque couche supplémentaire d'héritage ajoutée à un objet. + +### Filtrer avec `hasOwnProperty` + + // le même foo qu'au dessus + for(var i in foo) { + if (foo.hasOwnProperty(i)) { + console.log(i); + } + } + +Cette version est la seule version correcte à utiliser avec les anciennes versions d'ECMAScript. +L'utilisation de `hasOwnProperty` nous garantie que seulement `moo` sera imprimé. +Quand `hasOwnProperty` n'est pas utilisé, les prototypes natifs - par exemple `Object.prototype` - qui ont peut-être été étendus, causeront probablement des erreurs. + +Avec les versions plus récentes d'ECMAScript, des propriétés non-dénombrables peuvent être définies avec `Object.defineProperty`, réduisant le risque d'itération sur les propriétés quand `hasOwnProperty` n'est pas utilisé. Néanmoins, il faut faire attention avec l'utilisation de vieilles librairies comme [Prototype][1] qui ne bénéficient pas des nouvelles fonctions d'ECMAScript. Dans ce cadre, écrire des boucles `for in` sans `hasOwnProperty` est garanti de causer des erreurs. + +### En conclusion + +Il est recommandé de **toujours** utiliser `hasOwnProperty` avec ECMAScript 3 ou moins, ou dans du code de librairie. Dans ces environnements, il ne faut jamais assumer que les prototypes natifs n'ont pas été étendus. Depuis ECMAScript 5, `Object.defineProperty` permet de définir les propriétés non-dénombrables et donc permet d'omettre les appels à `hasOwnProperty` dans le code de l'application. + + +[1]: http://www.prototypejs.org/ + diff --git a/doc/fr/object/general.md b/doc/fr/object/general.md new file mode 100644 index 00000000..afa2ea25 --- /dev/null +++ b/doc/fr/object/general.md @@ -0,0 +1,85 @@ +## Utilisation des objets et propriétés + + +En JavaScript, tout agit comme un objet, à part deux exceptions: [`null`](#core.undefined) et [`undefined`](#core.undefined). + + false.toString(); // 'false' + [1, 2, 3].toString(); // '1,2,3' + + function Foo(){} + Foo.bar = 1; + Foo.bar; // 1 + +Une méprise commune est que les littéraux numériques ne peuvent pas être utilisés comme objets, due à une imperfection de l'analyseur de JavaScript qui tente d'analyser la *notation à point* sur un nombre comme une virgule flottante. + + 2.toString(); // erreur de syntaxe SyntaxError + +Des solutions de contournement existent pour forcer les littéraux numériques à agir comme des objets. + + 2..toString(); // le second point est correctement reconnu + 2 .toString(); // notez l'espace à gauche du point + (2).toString(); // 2 est évalué en premier + +### Objets comme type de données + +Les objets en JavaScript peuvent également être utilisés comme [*HashMaps*][1]; essentiellement, des propriétés nommées pointant sur des valeurs. + +En utilisant un littéral d'objet - notation `{}` - il est possible de créer un objet vide. +Ce nouvel objet [hérite](#object.prototype) de `Object.prototype` et ne possède pas de [propriétés propres](#object.hasownproperty) définies. + + var foo = {}; // un nouvel objet vide + + // un nouvel objet avec une propriété 'test' à valeur 12 + var bar = {test: 12}; + +### Accéder aux propriétés + +Les propriétés d'un objet sont accessibles de deux façons, soit par la notation à point, soit par la notation à crochets. + + var foo = {name: 'kitten'} + foo.name; // kitten + foo['name']; // kitten + + var get = 'name'; + foo[get]; // kitten + + foo.1234; // SyntaxError + foo['1234']; // cela marche + +Les deux notations fonctionnent presque pareil, la seule différence étant que la notation à crochet permet l'écriture des propriétés et l'utilisation des noms de propriété qui autrement mèneraient à une erreur de syntaxe. + +### Supprimer des propriétés + +La seule façon de supprimer une propriété d'un objet est d'utiliser l'opérateur `delete`. +Mettre la propriété à `null` ou `undefined` ne supprime que la *valeur* associée à la propriété, et non pas la *propriété* elle-même. + + var obj = { + bar: 1, + foo: 2, + baz: 3 + }; + obj.bar = undefined; + obj.foo = null; + delete obj.baz; + + for(var i in obj) { + if (obj.hasOwnProperty(i)) { + console.log(i, '' + obj[i]); + } + } + +Les résultats du programme ci-dessus sont `bar undefined` et `foo null` - seul `baz` a été correctement supprimé. + +### Notation des clefs "keys" + + var test = { + 'case': 'Je suis un mot-clé, donc je dois etre écrit en tant que chaîne', + delete: 'Je suis un mot-clé, donc moi aussi' // erreur de syntaxe SyntaxError + }; + +Les propriétés d'objet peuvent être écrites simplement telles quelles ou comme des chaînes "string". Une autre imperfection de l'analyseur de JavaScript, avant ECMAScript 5, provoquera une erreur de syntaxe `SyntaxError` dans le programme qui précède. + +Cette erreur vient du fait que `delete` est un *mot-clé*; et par conséquent, il doit être écrit comme une *chaîne* littérale pour s'assurer qu'il sera correctement interprété par les vieux moteurs JavaScript. + +[1]: http://en.wikipedia.org/wiki/Hashmap + diff --git a/doc/fr/object/hasownproperty.md b/doc/fr/object/hasownproperty.md new file mode 100644 index 00000000..aa912107 --- /dev/null +++ b/doc/fr/object/hasownproperty.md @@ -0,0 +1,46 @@ +## `hasOwnProperty` + +Pour savoir si un objet possède une propriété définie, et non pas quelque part ailleurs sur sa [chaîne de prototype](#object.prototype), il est nécessaire d'utiliser la méthode `hasOwnProperty`, une méthode que tous les objets héritent d'`Object.prototype`. + +> **Remarque:** Il n'est **pas** suffisant de vérifier si une propriété est `undefined`, +> car la propriété peut très bien exister, mais avec une valeur `undefined`. + +`hasOwnProperty` est la seule chose en JavaScript qui traite des propriétés **sans** traverser la chaîne de prototypes. + + // Empoisonnement d'Object.prototype + Object.prototype.bar = 1; + var foo = {goo: undefined}; + + foo.bar; // 1 + 'bar' in foo; // vrai + + foo.hasOwnProperty('bar'); // faux + foo.hasOwnProperty('goo'); // vrai + +Seulement `hasOwnProperty` donnera le résultat attendu et correct. Voir la section sur [les boucles `for in`](#object.forinloop) pour plus de détails sur l'utilisation de `hasOwnProperty` pour traverser les propriétés d'un objet. + +### `hasOwnProperty` en tant que propriété + +JavaScript ne protège pas le nom de la propriété `hasOwnProperty`; ainsi, la possibilité existe qu'un objet peut avoir une propriété avec ce nom, et il est donc nécessaire d'utiliser une méthode `hasOwnProperty` *externe* pour obtenir des résultats corrects. + + var foo = { + hasOwnProperty: function() { + return false; + }, + bar: 'Here be dragons' + }; + + foo.hasOwnProperty('bar'); // toujours faux + + // Utiliser hasOwnProperty d'un autre object, + // et l'appeler avec foo assigné à 'this' + ({}).hasOwnProperty.call(foo, 'bar'); // vrai + + // Il est aussi possible d'utiliser hasOwnProperty + //du prototype d'Object + Object.prototype.hasOwnProperty.call(foo, 'bar'); // vrai + +### En conclusion + +Utiliser `hasOwnProperty` est la **seule** méthode fiable pour vérifier l'existence d'une propriété sur un objet. Il est recommandé d'utiliser `hasOwnProperty` pour itérer sur les propriétés des objets comme décrit dans la section sur [les boucles `for in`](#object.forinloop). + diff --git a/doc/fr/object/prototype.md b/doc/fr/object/prototype.md new file mode 100644 index 00000000..c1a471aa --- /dev/null +++ b/doc/fr/object/prototype.md @@ -0,0 +1,85 @@ +## Le prototype + +JavaScript n'utilise pas le modèle classique d'héritage, mais un modèle *prototypique*. + +Souvent considéré comme l'une des faiblesses de JavaScript, le modèle d'héritage prototypique est en fait plus puissant que le modèle classique. Par exemple, il est assez facile de construire un modèle classique à partir du modèle prototypique, tandis que l'inverse est une tâche beaucoup plus difficile à entreprendre. + +JavaScript étant le seul langage à héritage prototypique largement utilisé, s'adapter aux différences entre les deux modèles peut prendre du temps. + +La première différence majeure est que l'héritage en JavaScript utilise des *chaînes de prototypes*. + +> **Remarque:** Utiliser simplement `Bar.prototype = Foo.prototype` résultera aux deux objets +> partageant le **même** prototype. Par conséquent, le changement du prototype d'un objet aura une +> incidence sur le prototype de l'autre ce qui, dans la plupart des cas, n'est pas l'effet désiré. + + function Foo() { + this.value = 42; + } + Foo.prototype = { + method: function() {} + }; + + function Bar() {} + + // Assigner le prototype de Bar à une nouvelle instance de Foo + Bar.prototype = new Foo(); + Bar.prototype.foo = 'Hello World'; + + // S'assurer que Bar est le constructeur + Bar.prototype.constructor = Bar; + + var test = new Bar(); // crée une nouvelle instance de bar + + // La chaîne de prototypes qui en résulte + test [instance of Bar] + Bar.prototype [instance of Foo] + { foo: 'Hello World', value: 42 } + Foo.prototype + { method: ... } + Object.prototype + { toString: ... /* etc. */ } + +Dans le code ci-dessus, l'objet `test` va hériter à la fois de `Bar.prototype` et de `Foo.prototype`; par conséquent, il aura accès à la fonction `method` qui était définie sur `Foo`. Il aura également accès à la propriété `value` de la **seule** instance de `Foo` qui est son prototype. Il est important de noter que le `new Bar()` ne crée **pas** une nouvelle instance de `Foo`, mais réutilise celui attribué à son prototype; ainsi, toutes les instances de `Bar` se partageront la **même** propriété `value`. + +> **Remarque:** Ne **pas** utiliser `Bar.prototype = Foo`, car il ne pointera pas vers +> le prototype de `Foo` mais plutôt à l'objet-fonction `Foo`. donc, la +> chaîne de prototypes ira sur `Function.prototype` et non pas sur `Foo.prototype`; +> et donc, `method` ne sera pas disponible sur la chaîne de prototypes. + +### Recherche des propriétés + +Lors de l'accès aux propriétés d'un objet, JavaScript traversera la chaîne de prototypes **vers le haut** jusqu'à ce qu'il trouve une propriété avec le nom demandé. + +S'il atteint le sommet de la chaîne - à savoir `Object.prototype` - sans avoir trouvé la propriété spécifiée, la valeur [undefined](#core.undefined) sera retournée. + +### La propriété prototype + +Bien que la propriété prototype est utilisé par le langage pour construire la chaîne de prototypes, il est toujours possible de lui attribuer une valeur quelconque, mais les types primitifs seront simplement ignorés. + + function Foo() {} + Foo.prototype = 1; // aucun effet + +Assigner des objets, comme le montre l'exemple ci-dessus, va marcher, et permet la création dynamique de chaînes de prototypes. + +### Performance + +Les temps de recherche pour des propriétés qui sont en haut de la chaîne de prototypes peuvent avoir un impact négatif qui être significatif pour du code où la performance est critique. Essayer d'accéder à des propriétés inexistantes causera toujours la traversée complète de la chaîne de prototypes. + +De plus, [itérer](#object.forinloop) sur les propriétés d'un objet va causer l'énumération de **toutes** les propriétés qui se trouve sur la chaîne de prototype. + +### Extension des prototypes natifs + +Une mauvaise technique souvent utilisée est d'étendre `Object.prototype` ou un des prototypes intégrés. + +Cette technique est appelée [monkey patching][1] et casse l'*encapsulation*. Bien qu'utilisée par des cadriciels "frameworks" populaires tels que [Prototype][2], il n'existe aucune bonne raison pour encombrer les types intégrés avec des fonctionnalités supplémentaires *non standards*. + +La **seule** bonne raison d'étendre un prototype intégré est le rétroportage de caractéristiques des nouveaux moteurs JavaScript; par exemple, [`Array.forEach`][3]. + +### En conclusion + +Il est **essentiel** de comprendre le modèle d'héritage prototypique avant d'écrire du code complexe qui l'utilise. Soyez conscient de la longueur des chaînes de prototypes dans votre code; découpez les si nécessaire pour éviter de possible problèmes de performance. En outre, les prototypes natifs ne devraient **jamais** être étendus, sauf pour des raisons de compatibilité avec de nouvelles caractéristiques du langage JavaScript. + +[1]: http://en.wikipedia.org/wiki/Monkey_patch +[2]: http://prototypejs.org/ +[3]: https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/forEach + diff --git a/doc/fr/other/timeouts.md b/doc/fr/other/timeouts.md new file mode 100644 index 00000000..f06623e9 --- /dev/null +++ b/doc/fr/other/timeouts.md @@ -0,0 +1,130 @@ +### `setTimeout` et `setInterval` + +Puisque JavaScript est asynchrone, il est possible de programmer l'exécution future d'une fonction en utilisant les fonctions `setTimeout` et `setInterval`. + +> **Remarque:** Les temps d'attente "timeouts" ne font **pas** partie de la norme ECMAScript. Ils sont implémentés dans les [BOM ou DOM Niveau 0][1], qui ne ne sont ni définies ni documentés formellement. +> Aucune spécification recommandée n'a été publiée jusqu'à présent, cependant, ils sont en voie de normalisation par [HTML5][2]. +> En raison de cela, l'implémentation peut varier entre navigateurs et moteurs. + + function foo() {} + var id = setTimeout(foo, 1000); // retourne un nombre > 0 + +Quand `setTimeout` est appelé, il renvoie l'identifiant de la temporisation et fixe la date de d'exécution de `foo` **approximativement** mille millisecondes dans le future. `foo` sera exécuté **une seule** fois. + +La résolution de l'horloge du moteur JavaScript exécutant le code, le fait que JavaScript est mono-thread, et la possibilité qu'autre code en cours d'exécution peut bloquer le fil "thread", font qu'il n'est **pas** possible de déterminer le temps exact d'attente spécifié dans l'appel `setTimeout`. + +La fonction passée en tant que premier paramètre sera appelé par l'*objet global*, ce qui signifie que [`this`](#function.this) à l'intérieur de la fonction appelée fait référence à l'objet global. + + function Foo() { + this.value = 42; + this.method = function() { + // this réfère a l'boject global + console.log(this.value); // enregistre undefined + }; + setTimeout(this.method, 500); + } + new Foo(); + +> **Remarque:** Comme `setTimeout` prend un **objet fonction** comme premier paramètre, une erreur commune est d'écrire `setTimeout(foo(), 1000)`, qui utilisera la **valeur de retour** de l'appel `foo` et non **pas** `foo`. Cette erreur est, la plupart du temps, silencieuse, car lorsque la fonction retourne `undefined`, `setTimeout` ne produira **pas** d'erreur. + +### Empilement des appels avec `setInterval` + +`setTimeout` exécute la fonction une seule fois. `setInterval` - comme son nom le suggère - exécutera la fonction toutes les 'X' millisecondes, mais son utilisation est découragée. + +Lorsque que du code en cours d'exécution bloque la temporisation, `setInterval` continuera a émettre plusieurs appels à la fonction spécifiée. Cela peut, en particulier avec un petit intervalle, résulter à un empilement d'appels de fonction. + + function foo(){ + // qq chose qui bloque pendant 1 seconde + } + setInterval(foo, 100); + +Dans le code ci-dessus, `foo` sera appelé une fois et bloquera pendant une seconde. + +Pendant ce temps, `setInterval` va continuer à planifier les appels à la fonction. Quand `foo` se termine, il y aura déjà **dix** autres appels qui attendent pour s'exécuter. + +### Traiter le code bloquant éventuel + +La solution la plus simple et qui offre le plus de contrôle est d'utiliser `setTimeout` dans la fonction elle-même. + + function foo(){ + // qq chose qui bloque pendant 1 seconde + setTimeout(foo, 100); + } + foo(); + +Non seulement cela encapsule l'appel `setTimeout`, mais il empêche également l'empilement des appels et donne un contrôle supplémentaire. La fonction `foo` elle-même peut maintenant décider si elle veut s'exécuter à nouveau ou non. + +### Effacer un délais d'attente + +L'effacement des délais d'attente et des intervalles fonctionne en transmettant l'identifiant retourné par la fonction `setTimeout` ou `setInterval` à `clearTimeout` ou `clearInterval`, respectivement. + + var id = setTimeout(foo, 1000); + clearTimeout(id); + +### Effacer tous les délais d'attente + +Comme il n'existe pas de méthode intégrée pour effacer tous les délais d'attente et/ou intervalles, il est nécessaire d'utiliser la force brute pour obtenir cette fonctionnalité. + + // Effacement de "tous" les délais d'attente + for(var i = 1; i < 1000; i++) { + clearTimeout(i); + } + +Mais il pourrait encore y avoir des délais d'attente qui ne sont pas effacés par ce nombre arbitraire. +Une autre façon de faire découle du fait que l'identifiant donné à un délai d'attente est incrémenté à chaque fois que vous appelez `setTimeout`. + + // Effacement de "tous" les délais d'attente + var identifiantLePlusGrand = window.setTimeout(function(){}, 1), + i; + for(i = 1; i <= identifiantLePlusGrand; i++) { + clearTimeout(i); + } + +Même si cela fonctionne sur tous les principaux navigateurs d'aujourd'hui, il ne est pas précisé que les identifiants doivent être ordonnés de cette façon et cela peut changer. Par conséquent, il est plutôt recommandé de garder une trace de tous les identifiant crées, pour qu'ils puissent être effacées spécifiquement. + +### Utilisation cachée de `eval` + +`setTimeout` et `setInterval` peuvent également prendre une chaîne de caractères comme premier paramètre. +Cette fonctionnalité ne devrait **jamais** être utilisée car elle utilise `eval` en interne. + +> **Remarque:** Les mécanismes précis pour quand une chaîne est passée peuvent différer entre les diverses implémentations de JavaScript. +> Par exemple, JScript de Microsoft utilise le constructeur `Function` à la place de `eval`. + + function foo() { + // sera appelé + } + + function bar() { + function foo() { + // ne sera jamais appelé + } + setTimeout('foo()', 1000); + } + bar(); + +Puisque `eval` n'est pas appelé [directement](#core.eval), la chaîne passé à `setTimeout` sera exécutée dans la *portée globale*; ainsi, la variable `foo` locale à `bar` ne sera pas utilisée. + +Il est aussi recommandé de ne **pas** utiliser une chaîne pour passer des arguments à la fonction qui sera appelée par l'une des fonctions de temporisation. + + function foo(a, b, c) {} + + // ne JAMAIS faire cela + setTimeout('foo(1, 2, 3)', 1000) + + // utiliser plutôt une fonction anonyme + setTimeout(function() { + foo(1, 2, 3); + }, 1000) + +>**Remarque:** Bien qu'il soit également possible d'utiliser la syntaxe `setTimeout(foo, 1000, 1, 2, 3)`, elle n'est pas recommandée, car son utilisation peut entraîner des erreurs subtiles lorsqu'elle est utilisée avec des [méthodes](#function.this). +>En outre, la syntaxe peut ne pas fonctionner dans certaines implémentations de JavaScript. Par exemple, Internet Explorer de Microsoft [ne passe **pas** les arguments directement à la fonction de rappel][3]. + +### En conclusion + +Une chaîne ne devrait **jamais** être passée comme paramètre de `setTimeout` ou `setInterval` pour passer des arguments à la fonction appelée. C'est un clair signe de **mauvais** code. Il faut appeler une *fonction anonyme* qui se charge d'appeler la fonction réelle avec les arguments nécessaires. + +En outre, l'utilisation de `setInterval` doit être évitée car son programmateur n'est pas bloqué par le code en train de s'exécuter. + +[1]: http://www.nczonline.net/blog/2009/09/29/web-definitions-dom-ajax-and-more/ "Web definitions: DOM, Ajax, and more" +[2]: http://www.w3.org/TR/2014/WD-html5-20140617/webappapis.html#timers "6 Web application APIs - HTML5" +[3]: http://msdn.microsoft.com/en-us/library/ie/ms536753(v=vs.85).aspx "setTimeout method (Internet Explorer)" diff --git a/doc/fr/types/casting.md b/doc/fr/types/casting.md new file mode 100644 index 00000000..a0158f6b --- /dev/null +++ b/doc/fr/types/casting.md @@ -0,0 +1,62 @@ +## Changements de types + +JavaScript est un langage *faiblement typé*, il appliquera la *coercition de type* partout où c'est possible. + + // Ceux-ci sont vrais + new Number(10) == 10; // Objet Number est converti + // en un nombre primitif via un appel implicite + // à la méthode Number.prototype.valueOf + + 10 == '10'; // Strings est converti en Number + 10 == '+10 '; // Encore aussi fou + 10 == '010'; // Et encore + isNaN(null) == false; // null est converti en 0 + // ce qui, bien sûr, n'est pas NaN + + // Ceux-ci sont faux + 10 == 010; + 10 == '-10'; + +> **Remarque ES5:** Les nombres littéraux qui commencent avec un '0' sont interprétés comme octal (Base 8). L'octal a été **retiré** dans ECMAScript 5 en mode stricte. + +Pour éviter les problèmes ci-dessus, l'utilisation de l'[opérateur d'égalité stricte](# types.equality) est **fortement** recommandé. +Bien que cela évite beaucoup de pièges communs, il y en reste encore beaucoup. Tous ces pièges découlent de la faiblesse du système de typage de JavaScript. + +### Constructeurs de types internes + +Les constructeurs de types internes comme `Number` et `String` se comportent différemment suivant s'ils sont utilisés avec ou sans le mot clé `new`. + + new Number(10) === 10; // Faux, Object et Number + Number(10) === 10; // Vrai, Number et Number + new Number(10) + 0 === 10; // Vrai, due à la reconversion implicite + +L'utilisation d'un type intégré comme `Number` en tant que constructeur va créer une nouvel objet `Number`. Mais sans le mot clé `new`, `Number` se comportera comme un convertisseur. + +De plus, passer des valeurs littérales ou des non-objets se traduira par encore plus de coercition de type. + +La meilleure option est de forcer **explicitement** le type à l'un des trois types possibles . + +### Forcer à String + + '' + 10 === '10'; // vrai + +En faisant précéder une **chaîne vide**, une valeur peut facilement être converti en une chaîne. + +### Forcer à Number + + +'10' === 10; // vrai + +L'utilisation de l'opérateur **plus unaire** converti une valeur en nombre. + +### Forcer à Boolean + +L'utilisation double de l'opérateur **non** converti une valeur en booléen. + + !!'foo'; // vrai + !!''; // faux + !!'0'; // vrai + !!'1'; // vrai + !!'-1' // vrai + !!{}; // vrai + !!true; // vrai + diff --git a/doc/fr/types/equality.md b/doc/fr/types/equality.md new file mode 100644 index 00000000..3c1c09dd --- /dev/null +++ b/doc/fr/types/equality.md @@ -0,0 +1,58 @@ +## Égalité et comparaisons + +JavaScript a deux façons de comparer les valeurs des objets pour égalité. + +### L'opérateur d'égalité + +L'opérateur d'égalité se compose de deux signes égal: `==`. + +JavaScript est un langage au *typage faible* "weak typing". Cela signifie que l'opérateur d'égalité va convertir les deux opérandes en un même type afin de les comparer. + + "" == "0" // faux + 0 == "" // vrai + 0 == "0" // vrai + false == "false" // faux + false == "0" // vrai + false == undefined // faux + false == null // faux + null == undefined // vrai + " \t\r\n" == 0 // vrai + +Le tableau ci-dessus montre les résultats de la coercition de type, et c'est la raison principale pourquoi l'utilisation de `==` est largement considéré comme une mauvaise pratique. Les règles de conversion de types compliquées introduisent des bogues difficiles à dépister. + +### L'opérateur d'égalité stricte + +L'opérateur d'égalité stricte se compose de **trois** signes égal: `===`. + +Il fonctionne comme l'opérateur d'égalité normale, sauf que l'égalité stricte ne converti **pas** le types de ses opérandes. + + "" === "0" // faux + 0 === "" // faux + 0 === "0" // faux + false === "false" // faux + false === "0" // faux + false === undefined // faux + false === null // faux + null === undefined // faux + " \t\r\n" === 0 // faux + +Les résultats ci-dessus sont beaucoup plus clairs et permettent la rupture précoce de code. +Cela durcit le code jusqu'à un certain degré, et améliore la performance dans le cas où les opérandes sont de types différents. + +### Comparaison d'objets + +Bien que `==` et `===` sont appelés **opérateurs d'égalité**, ils se comportent différement quand au moins un des opérandes est un objet `Object`. + + {} === {}; // faux + new String('foo') === 'foo'; // faux + new Number(10) === 10; // faux + var foo = {}; + foo === foo; // vrai + +En effet, les deux opérateurs comparent l'**identité** et non pas l'**égalité**. Autrement dit, ils comparent pour la même **instance** de l'objet, tout comme `is` en Python, ou la comparaison de pointeur en C. + +### En conclusion + +Il est fortement recommandé de n'utiliser que l'opérateur d'**égalité stricte**. Dans les cas où les types ont à être convertis, cela devraient être fait [explicitement](#types.casting) et non pas laissé aux règles complexes de coercition de type du langage. + + diff --git a/doc/fr/types/instanceof.md b/doc/fr/types/instanceof.md new file mode 100644 index 00000000..ba733e43 --- /dev/null +++ b/doc/fr/types/instanceof.md @@ -0,0 +1,35 @@ +## L'opérateur `instanceof` + +L'opérateur `instanceof` (instance de) compare les constructeurs de ses deux opérandes. Il est seulement utile pour comparer des objets faits sur mesure. Utilisé sur les types intégrés, il est +aussi inutile que l'[opérateur typeof](# types.typeof). + +### Comparer des objets personnalisés + + function Foo() {} + function Bar() {} + Bar.prototype = new Foo(); + + new Bar() instanceof Bar; // vrai + new Bar() instanceof Foo; // vrai + + // Ceci définit simplement Bar.prototype à l'objet de fonction Foo, + // mais pas à une instance réelle de Foo + Bar.prototype = Foo; + new Bar() instanceof Foo; // faux + +### Utiliser `instanceof` avec des types natifs + + new String('foo') instanceof String; // vrai + new String('foo') instanceof Object; // vrai + + 'foo' instanceof String; // faux + 'foo' instanceof Object; // faux + +Une chose importante à noter ici est que `instanceof` ne fonctionne pas sur les objets qui proviennent de différents contextes JavaScript (par exemple, différents documents +dans un navigateur web), car leurs constructeurs ne seront pas exactement le même objet. + +### En conclusion + +L'opérateur `instanceof` devrait **seulement** être utilisé sur des objets crées sur mesure provenant du même contexte JavaScript. +Tout comme l'opérateur [`typeof`](#types.typeof), chaque autre utilisation de celui-ci devrait être **évitée**. + diff --git a/doc/fr/types/typeof.md b/doc/fr/types/typeof.md new file mode 100644 index 00000000..186bfb32 --- /dev/null +++ b/doc/fr/types/typeof.md @@ -0,0 +1,66 @@ +## L'opérateur `typeof` + +L'opérateur `typeof` (avec [`instanceof`](#types.instanceof)) est probablement le plus grand défaut de design de JavaScript, car il est presque **complètement cassé**. + +Bien que `instanceof` (instance de) a quelques utilisations limitées, `typeof` (type de) n'a qu'un seul cas pratique d'utilisation, et ce cas n'est **pas** la vérification du type d'un objet. + +> **Remarque:** Alors que `typeof` peut être appelé comme une fonction, i.e. `typeof(obj)`, ce n'est pas un appel de fonction. +> Les parenthèses se comportent comme d'habitude et la valeur de retour sera utilisé comme opérande de l'opérateur `typeof`. La *fonction* `typeof` n'existe pas. + +### table de types JavaScript + + Valeur Class Type + ------------------------------------- + "foo" String string + new String("foo") String object + 1.2 Number number + new Number(1.2) Number object + true Boolean boolean + new Boolean(true) Boolean object + new Date() Date object + new Error() Error object + [1,2,3] Array object + new Array(1, 2, 3) Array object + new Function("") Function function + /abc/g RegExp object (function pour Nitro/V8) + new RegExp("meow") RegExp object (function pour Nitro/V8) + {} Object object + new Object() Object object + +Dans la table ci-dessus, *Type* se réfère à la valeur retournée pas l'opérateur `typeof`, et comme on peut le voir clairement, cette valeur est incohérente. + +*Class* se réfère à la valeur de la propriété interne `[[Class]]` d'un objet. + +> **D'après la spécification:** La valeur de `[[Class]]` peut être l'une des chaînes suivantes: `Arguments`, `Array`, `Boolean`, `Date`, `Error`, `Function`, `JSON`, `Math`, `Number`, `Object`, `RegExp`, `String`. + +Pour récupérer la valeur de `[[Class]]`, on peut utiliser la méthode `toString` de `Object.prototype`. + +### La classe d'un objet + +La spécification donne exactement un moyen d'accéder à la valeur `[[Class]]`: via `Object.prototype.toString`. + + function is(type, obj) { + var clas = Object.prototype.toString.call(obj).slice(8, -1); + return obj !== undefined && obj !== null && clas === type; + } + + is('String', 'test'); // vrai + is('String', new String('test')); // vrai + +Dans l'exemple ci-dessus, `Object.prototype.toString` est appelé avec la valeur [this](#function.this) pointant sur l'objet dont on cherche a récupérer la valeur de `[[Class]]`. + +> **Remarque ES5:** Pour plus de commodité la valeur de retour de `Object.prototype.toString` de `null` et `undefined` a été **changée** de `Object` à `Null` et `Undefined` avec ECMAScript 5. + +### Test pour les variables indéfinies + + typeof foo !== 'undefined' + +Ce qui précède vérifie si `foo` a été effectivement déclarée. Juste référencer la variable résulterait en une erreur de référence `ReferenceError`. C'est la seule chose pour laquelle `typeof` est réellement utile. + +### En conclusion + +Pour vérifier le type d'un objet, il est fortement recommandé d'utiliser `Object.prototype.toString` parce que c'est le seul moyen fiable de le faire. +Comme représenté dans la table de type ci-dessus, certaines valeurs de retour de `typeof` ne sont pas définies dans la spécification; et donc, elles peuvent différer entre les implémentations. + +If faut éviter d'utiliser `typeof`, sauf pour vérifier si une variable est définie. + diff --git a/doc/hu/function/arguments.md b/doc/hu/function/arguments.md index 7ef9b59f..d7b77ec0 100644 --- a/doc/hu/function/arguments.md +++ b/doc/hu/function/arguments.md @@ -50,7 +50,7 @@ Egy másik trükk arra hogy teljesen független wrapper függvényeket gyártsun // Ezeket kapja paraméterül: this, arg1, arg2...argN Foo.method = function() { - // Eredmény: Foo.prototype.method.call(this, arg1, arg2... argN) + // Eredmény: Foo.prototype.method.call(this, arg1, ...argN) Function.call.apply(Foo.prototype.method, arguments); }; @@ -91,7 +91,8 @@ Habár, egyetlen eset van, amelynek komoly hatása lehet a kód teljesítményé JavaScript motorokban. Ez pedig az `arguments.callee` használata. function foo() { - arguments.callee; // csináljunk valamit ezzel a függvény objektummal + // ..csinálunk valamit + arguments.callee; // ezzel a függvény objektummal arguments.callee.caller; // és ennek a hívójával.. } diff --git a/doc/hu/function/constructors.md b/doc/hu/function/constructors.md index f1b460da..e48e0b60 100644 --- a/doc/hu/function/constructors.md +++ b/doc/hu/function/constructors.md @@ -38,12 +38,12 @@ visszatérített érték `Objektum` típusú. foo: 1 }; } - new Test(); // ez a returnben található objektumot fogja eredményezni + new Test(); // ez a { foo: 1 } objektumot fogja eredményezni Hogyha kihagyjuk a `new` kulcsszó használatát, a függvény **nem** egy új objektummal fog visszatérni. function Foo() { - this.bla = 1; // ez a globális objektumon állítja be a bla értékét 1-re + this.bla = 1; // ez a globális objektumon állít } Foo(); // undefined @@ -125,4 +125,4 @@ arra hogy ezért eldobjuk a prototípusok használatát. Végeredményben mindig az fog dönteni a különböző stílusok megválasztása között, hogy mire van szüksége éppen az aktuális programunknak. Egy dolog azért elengedhetetlenül fontos, ez pedig hogy megválasszuk melyik stílust fogjuk használni objektumok -létrehozásra, és ezt **konzisztensen** használjuk a teljes megoldáson keresztül. \ No newline at end of file +létrehozásra, és ezt **konzisztensen** használjuk a teljes megoldáson keresztül. diff --git a/doc/hu/function/general.md b/doc/hu/function/general.md index 92391ef4..4392060e 100644 --- a/doc/hu/function/general.md +++ b/doc/hu/function/general.md @@ -13,7 +13,7 @@ Ez a függvény felkerül a scope tetejére ([hoisting](#function.scopes)), miel még abban a trükkös esetben is, hogyha a kód azon pontján hívjuk ezt a függvényt, mielőtt definiáltuk volna (látszólag). - foo(); // Így is működik, mivel a foo fgv. létrejön mielőtt meghívnánk. + foo(); // Így is működik function foo() {} ### A `függvény` kifejezés (expression) diff --git a/doc/hu/function/scopes.md b/doc/hu/function/scopes.md index 9fa2e4b8..71c99902 100644 --- a/doc/hu/function/scopes.md +++ b/doc/hu/function/scopes.md @@ -124,7 +124,7 @@ hatókör tetejébe. // a függvény deklaráció is felkerül ide function test(data) { - var goo, i, e; // mivel nincs blokk hatókör, ezek is felkerülnek + var goo, i, e; // ezek is felkerülnek if (false) { goo = 1; @@ -163,7 +163,7 @@ tetejére lett mozgatva. var SomeImportantThing; - // más kódok még inicializálhatják a SomeImportantThing változót itt... + // más kódok még inicializálhatják az előbbi változót itt... // ellenőrizzük hogy létezik-e if (!SomeImportantThing) { @@ -231,4 +231,4 @@ névütközésektől, de jobb modularizációhoz is vezet. Emelett a globális változók használata **nem ajánlott**. **Bármilyen** fajta használata rosszul megírt kódról árulkodik, amelyik könnyen eltörik és nehezen -karbantartható. \ No newline at end of file +karbantartható. diff --git a/doc/hu/index.json b/doc/hu/index.json index 7456925a..c3a3c82e 100644 --- a/doc/hu/index.json +++ b/doc/hu/index.json @@ -6,7 +6,7 @@ { "title": "Bevezet\u0151", "dir": "intro", - "articles": [] + "articles": [ "index" ] }, { "title": "Objektumok", diff --git a/doc/hu/intro/index.md b/doc/hu/intro/index.md index d46378f8..911baf61 100644 --- a/doc/hu/intro/index.md +++ b/doc/hu/intro/index.md @@ -1,18 +1,21 @@ ## Bevezető -A **JavaScript Garden** egy kódgyűjtemény amely azért született, hogy tisztázza a JavaScript nyelv legsötétebb mélységeit. Itt tippeket találhatsz a gyakori hibák elkerüléséhez, teljesítmény javításhoz, rossz minták felismeréséhez, amelyeket a legtöbb kezdő JavaScript programozó már talán megtapasztalt, amikor a nyelv mélyére szeretett volna ásni. +A **JavaScript Garden** egy folytonosan növekvő kódgyűjtemény amely a nyelv kihívást okozó részeit hivatott tisztázni. Itt tanácsokat kaphatsz afelől, hogyan kerüld el a leggyakoribb programozási- valamint nyelvi hibákat, hogyan írj gyorsabb kódot, és mik a legsűrűbben elkövetett *bad practice*k amelyekkel egy átlagos JavaScript programozó (nem) mindennapi útján találkozhat a nyelv megismerése közben. -A JavaScript Gardennek **nem** célja hogy megtanítsa a JavaScript nyelv használatát! +A JavaScript Gardennek **nem** célja hogy megtanítsa a JavaScript nyelvet! Az itt felsorolt témák megértéséhez mindenképp szükséges némi tapasztalat. Ha a nyelv alapjait szeretnéd elsajátítani, először nézd át ezt a kiváló [tutorialt][1] a Mozilla Developer Networkön. ## Szerzők Ez a leírás két kiváló [Stack Overflow][2] felhasználó, [Ivo Wetzel][3] (szerző) és [Zhang Yi Jiang][4] (Design) tollából született. +A dokumentumot jelenleg [Tim Ruffles](http://truffles.me.uk) gondozza. + ## Hozzájárultak még - - [Caio Romão][5] (Helyesírási javítások) - - [Andreas Blixt][6] (Nyelvi javítások) + - Túl hosszú lenne itt mindenkit felsorolni, lásd a [közreműködők listáját](https://github.com/BonsaiDen/JavaScript-Garden/graphs/contributors). + + - A magyar fordítás [jozsefDevs](https://twitter.com/jozsefDevs) jóvoltából született. ## Hosting @@ -35,4 +38,4 @@ Ha bármilyen hibát vagy elírást veszel észre, kérlek [jelezd azt][11], vag [9]: https://github.com/BonsaiDen/JavaScript-Garden/blob/next/LICENSE [10]: https://github.com/BonsaiDen/JavaScript-Garden [11]: https://github.com/BonsaiDen/JavaScript-Garden/issues -[12]: http://chat.stackoverflow.com/rooms/17/javascript \ No newline at end of file +[12]: http://chat.stackoverflow.com/rooms/17/javascript diff --git a/doc/hu/object/prototype.md b/doc/hu/object/prototype.md index 2822188e..95e45b3c 100644 --- a/doc/hu/object/prototype.md +++ b/doc/hu/object/prototype.md @@ -40,7 +40,7 @@ használ. // A kapott prototípus lánc test [instance of Bar] Bar.prototype [instance of Foo] - { foo: 'Hello World' } + { foo: 'Hello World', value: 42 } Foo.prototype { method: ... } Object.prototype diff --git a/doc/it/array/general.md b/doc/it/array/general.md index 0b3e0c9c..453dc088 100644 --- a/doc/it/array/general.md +++ b/doc/it/array/general.md @@ -42,13 +42,13 @@ Mentre il *getter* della proprietà `length` ritorna semplicemente il numero di elementi che sono contenuti nell'array, il *setter* può essere usato per **troncare** l'array. - var foo = [1, 2, 3, 4, 5, 6]; - foo.length = 3; - foo; // [1, 2, 3] + var arr = [1, 2, 3, 4, 5, 6]; + arr.length = 3; + arr; // [1, 2, 3] - foo.length = 6; - foo.push(4); - foo; // [1, 2, 3, undefined, undefined, undefined, 4] + arr.length = 6; + arr.push(4); + arr; // [1, 2, 3, undefined, undefined, undefined, 4] Assegnando una lunghezza più piccola si tronca l'array. Incrementandola si crea un array frammentato. @@ -59,4 +59,3 @@ Per la miglior performance, si raccomanda di usare sempre il ciclo `for` classico e fare il caching della proprietà `length`. L'uso di `for in` su di un array è segno di un codice scritto male che è suscettibile a bug e pessima performance. - diff --git a/doc/it/core/eval.md b/doc/it/core/eval.md index 03af4c01..54cf4566 100644 --- a/doc/it/core/eval.md +++ b/doc/it/core/eval.md @@ -2,27 +2,27 @@ La funzione `eval` eseguirà una stringa di codice JavaScript nello scope locale. - var foo = 1; + var number = 1; function test() { - var foo = 2; - eval('foo = 3'); - return foo; + var number = 2; + eval('number = 3'); + return number; } test(); // 3 - foo; // 1 + number; // 1 Comunque, `eval` esegue solo nello scope locale quando viene chiamata direttamente *e* quando il nome della funzione chiamata è `eval`. - var foo = 1; + var number = 1; function test() { - var foo = 2; - var bar = eval; - bar('foo = 3'); - return foo; + var number = 2; + var copyOfEval = eval; + copyOfEval('number = 3'); + return number; } test(); // 2 - foo; // 3 + number; // 3 L'uso di `eval` dovrebbe essere evitato. Il 99.9% dei suoi "utilizzi" può essere ottenuto **senza** di essa. @@ -47,4 +47,3 @@ essere messo in discussione sotto l'aspetto della funzionalità, della performan e della sicurezza. Se qualcosa richiede `eval` per poter funzionare, allora **non** dovrebbe essere usato in primo luogo, ma si dovrebbe prevedere una *miglior progettazione* che non richieda l'uso di `eval`. - diff --git a/doc/it/function/constructors.md b/doc/it/function/constructors.md index a6f730c4..1273e87c 100644 --- a/doc/it/function/constructors.md +++ b/doc/it/function/constructors.md @@ -12,44 +12,44 @@ come costruttore. Se la funzione che è stata chiamata non ha un'istruzione `return` esplicita, allora essa ritorna implicitamente il valore di `this` (il nuovo oggetto). - function Foo() { - this.bla = 1; + function Person(name) { + this.name = name; } - Foo.prototype.test = function() { - console.log(this.bla); + Person.prototype.logName = function() { + console.log(this.name); }; - var test = new Foo(); + var sean = new Person(); -Questo esempio chiama `Foo` come costruttore ed imposta il `prototype` del -nuovo oggetto creato a `Foo.prototype`. +Questo esempio chiama `Person` come costruttore ed imposta il `prototype` del +nuovo oggetto creato a `Person.prototype`. In caso di istruzione `return` esplicita, la funzione ritorna il valore specificato da quell'istruzione, ma **solo** se il valore di ritorno è un `Object`. - function Bar() { - return 2; + function Car() { + return 'ford'; } - new Bar(); // un nuovo oggetto + new Car(); // un nuovo oggetto, non 'ford' - function Test() { - this.value = 2; + function Person() { + this.someValue = 2; return { - foo: 1 + name: 'Charles' }; } - new Test(); // l'oggetto ritornato + new Person(); // l'oggetto ritornato ({name: 'Charles'}), escluso someValue Quando la parola chiave `new` viene omessa, la funzione **non** ritornerà un nuovo oggetto. - function Foo() { - this.bla = 1; // imposta la proprietà dell'oggetto globale + function Pirate() { + this.hasEyePatch = true; // imposta la proprietà nell'oggetto globale! } - Foo(); // undefined + var somePirate = Pirate(); // somePirate è undefined Mentre l'esempio precedente potrebbe sembrare essere funzionante in alcuni casi, a causa del modo in cui lavora [`this`](#function.this) in JavaScript, @@ -60,27 +60,27 @@ esso userà l'*oggetto globale* come valore di `this`. Per poter omettere la parola chiave `new`, la funzione costruttore deve esplicitamente ritornare un valore. - function Bar() { - var value = 1; + function Robot() { + var color = 'gray'; return { - method: function() { - return value; + getColor: function() { + return color; } } } - Bar.prototype = { - foo: function() {} + Robot.prototype = { + someFunction: function() {} }; - new Bar(); - Bar(); + new Robot(); + Robot(); -Entrambe le chiamate a `Bar` ritornano lo stesso risultato, un nuovo oggetto +Entrambe le chiamate a `Robot` ritornano lo stesso risultato, un nuovo oggetto creato con una proprietà chiamata `method`, che è una [Closure](#function.closures). -Bisogna anche notare che la chiamata `new Bar()` **non** influisce sul prototipo +Bisogna anche notare che la chiamata `new Robot()` **non** influisce sul prototipo dell'oggetto ritornato. Mentre il prototipo sarà impostato con il nuovo oggetto -creato, `Bar` non ritornerà mai quel nuovo oggetto. +creato, `Robot` non ritornerà mai quel nuovo oggetto. Nell'esempio sopra, non c'è differenza funzionale nell'usare o meno la parola chiave `new`. @@ -93,19 +93,20 @@ può portare a bug potenzialmente insidiosi da risolvere. Per poter creare un nuovo oggetto, si dovrebbe invece usare una factory e costruire un nuovo oggetto all'interno di quella factory. - function Foo() { - var obj = {}; - obj.value = 'blub'; + function CarFactory() { + var car = {}; + car.owner = 'nobody'; - var private = 2; - obj.someMethod = function(value) { - this.value = value; + var milesPerGallon = 2; + + car.setOwner = function(newOwner) { + this.owner = newOwner; } - obj.getPrivate = function() { - return private; + car.getMPG = function() { + return milesPerGallon; } - return obj; + return car; } Sebbene questo esempio sia a prova di omissione della parola chiave `new` e @@ -115,7 +116,7 @@ esso ha alcuni aspetti negativi. 1. Usa più memoria dal momento che gli oggetti creati **non** condividono i metodi di un prototipo. 2. Per poter ereditare, la factory deve copiare tutti i metodi da un altro - oggetto oppure mettere quell'oggetto nel proptotipo del nuovo oggetto. + oggetto oppure mettere quell'oggetto nel prototipo del nuovo oggetto. 3. Perdere la catena di prototipi solo perché si vuole tralasciare la parola chiave `new` è contrario allo spirito del linguaggio. @@ -126,4 +127,3 @@ bug, **non** è certo un motivo per privarsi completamente dell'uso dei prototip Alla fine si tratta di decidere quale sia la soluzione più adatta per l'applicazione. È specialmente importante scegliere uno specifico stile di creazione degli oggetti ed usarlo in maniera **consistente**. - diff --git a/doc/it/function/general.md b/doc/it/function/general.md index f78ef846..9181ad88 100644 --- a/doc/it/function/general.md +++ b/doc/it/function/general.md @@ -3,7 +3,7 @@ Le funzioni in JavaScript sono oggetti di prima classe. Ciò significa che possono essere usate come ogni altro valore. Un uso comune di questa caratteristica è quello di passare una *funzione anonima* come funzione di -callback ad un'altra, possibilmente asincrona, funzione. +callback ad un'altra funzione, possibilmente asincrona. ### La dichiarazione di `function` diff --git a/doc/it/function/scopes.md b/doc/it/function/scopes.md index 812e4fbd..24f6d250 100644 --- a/doc/it/function/scopes.md +++ b/doc/it/function/scopes.md @@ -127,7 +127,7 @@ vicino scope che le racchiude. // le istruzioni var vengono spostate qui var bar, someValue; // di default a 'undefined' - // la dichiarazione function viene spostate qui + // la dichiarazione function viene spostata qui function test(data) { var goo, i, e; // il blocco scope mancante sposta qui queste istruzioni if (false) { diff --git a/doc/it/function/this.md b/doc/it/function/this.md index 8f405d09..5bee4398 100644 --- a/doc/it/function/this.md +++ b/doc/it/function/this.md @@ -71,21 +71,31 @@ uso pratico. Una comune credenza è che `this` all'interno di `test` faccia riferimento a `Foo` mentre, invece, **non** è così. -Per poter ottenere l'accesso a `Foo` dall'interno di `test`, è necessario creare +Per poter ottenere l'accesso a `Foo` dall'interno di `test`, si può creare una variabile locale all'interno di `method` che faccia riferimento a `Foo`. Foo.method = function() { - var that = this; + var self = this; function test() { - // Qui viene usato that invece di this + // Qui viene usato self invece di this } test(); } -`that` è solo un normale nome di variabile, ma viene comunemente usato come +`self` è solo un normale nome di variabile, ma viene comunemente usato come riferimento ad un `this` più esterno. Abbinato alle [closures](#function.closures) può anche essere usato per passare il valore di `this`. +Con l'introduzione di ECMAScript 5 è possibile usare il metodo `bind` combinato +con una funziona anonima + + Foo.method = function() { + var test = function() { + // this ora fa riferimento a Foo + }.bind(this); + test(); + } + ### Metodi di asseganzione Un'altra cosa che **non** funziona in JavaScript è la creazione di un alias ad @@ -112,4 +122,3 @@ l'[ereditarietà prototipale](#object.prototype). Quando `method` viene chiamato da un'istanza di `Bar`, `this` farà riferimento a quell'istanza. - diff --git a/doc/it/object/forinloop.md b/doc/it/object/forinloop.md index b77ab1ce..96fc2d24 100644 --- a/doc/it/object/forinloop.md +++ b/doc/it/object/forinloop.md @@ -17,8 +17,19 @@ prototipi quando itera tra le proprietà di un oggetto. Dato che non è possibile modificare il comportamento del ciclo `for in`, è necessario filtrare le proprietà indesiderate all'interno del ciclo stesso. -Questo può essere fatto usando il metodo [`hasOwnProperty`](#object.hasownproperty) -di `Object.prototype`. +In ECMAScript 3 o precedente, questo può essere fatto usando il metodo +[`hasOwnProperty`](#object.hasownproperty) di `Object.prototype`. + +A partire da ECMAScript 5, `Object.defineProperty` può essere utilizzato con +`enumerbale` impostato a `false` per aggiungere proprietà agli oggetti (incluso +`Object`) senza che queste proprietà vengano enumerate. In questo caso è +ragionevole assumere che, nel codice di un'applicazione, ogni proprietà +enumerabile sia stata aggiunta per un motivo, ed quindi omettere `hasOwnProperty` +in quanto rende il codice più prolisso e meno leggibile. Nel codice delle +librerie `hasOwnProperty` dovrebbe essere ancora utilizzato, dato che non è +possibile presumere quali proprietà enumerabili siano presenti nella catena dei +prototipi. + > **Nota:** dato che `for in` attraversa sempre tutta la catena di prototipi, > esso rallenterà per ogni strato aggiuntivo di ereditarietà aggiunto ad un @@ -33,20 +44,25 @@ di `Object.prototype`. } } -Questa è la sola versione corretta da usare. Proprio a causa dell'utilizzo di -`hasOwnProperty`, **soltanto** `moo` verrà stampato; mentre omettendone l'uso, -il codice sarà soggetto ad errori nei casi dove i prototipi nativi (ad esempio -`Object.prototype`) sono stati estesi. +Questa è la sola versione corretta da usare con le vecchie versioni di ECMAScript. +Proprio a causa dell'utilizzo di `hasOwnProperty`, **soltanto** `moo` verrà +stampato; mentre omettendone l'uso, il codice sarà soggetto ad errori nei casi +dove i prototipi nativi (ad esempio `Object.prototype`) sono stati estesi. -Un framework ampiamente usato che estende `Object.prototype` è [Prototype][1]. +Nelle nuove versioni di ECMAScript, le proprietà non enumerabili possono essere +definite con `Object.defineProperty`, riducendo il rischio di iterare sulle +proprietà non usando `hasOwnProperty`. È altresì importante stare attenti +quando si usano librerie come [Prototype][1], che ancora non sfruttano le nuove +funzionalità di ECMAScript. Quando questo framework viene incluso, è sicuro che i cicli `for in` che non utilizzano `hasOwnProperty` non funzioneranno. ### In conclusione -Si raccomanda di usare **sempre** `hasOwnProperty`. Non si dovrebbe mai dare -per scontato l'ambiente in cui il codice sta girando, o se i prototipi -nativi sono stati estesi o meno. +Si raccomanda di usare **sempre** `hasOwnProperty` in ECMAScript 3 o precedenti, +e nel codice delle librerie. Non si dovrebbe mai dare per scontato nell'ambiente +in cui il codice sta girando, se i prototipi nativi sono stati estesi o meno. A +partire da ECMAScript 5 `Object.defineProperty` rende possibile definire proprietà +non enumerabili ed omettere `hasOwnProperty` nel codice dell'applicazione. [1]: http://www.prototypejs.org/ - diff --git a/doc/it/object/hasownproperty.md b/doc/it/object/hasownproperty.md index a0ffa052..71226c10 100644 --- a/doc/it/object/hasownproperty.md +++ b/doc/it/object/hasownproperty.md @@ -22,10 +22,9 @@ Per verificare se un oggetto ha (possiede) una proprietà definita dentro foo.hasOwnProperty('bar'); // false foo.hasOwnProperty('goo'); // true -Solo `hasOwnProperty` darà il risultato atteso e corretto. Questo è essenziale -quando si itera tra le proprietà di un qualsiasi oggetto. **Non** c'è altro -modo per escludere proprietà che non sono definite all'interno dell'oggetto -stesso, ma da qualche altra parte nella sua catena di prototipi. +Solo `hasOwnProperty` darà il risultato atteso e corretto. Guarda la sezione +[cicli `for in`][#object.forinloop] per maggiori dettagli riguardo a quando +usare `hasOwnProperty` per iterare le proprietà di un oggetto. ### `hasOwnProperty` come proprietà @@ -54,7 +53,6 @@ risultato corretto. ### In conclusione Usare `hasOwnProperty` è l'**unico** metodo affidabile per verificare -l'esistenza di una proprietà in un oggetto. È raccomandabile usare -`hasOwnProperty` in **ogni** [ciclo `for in`](#object.forinloop) per -evitare errori con i [prototipi](#object.prototype) nativi estesi. - +l'esistenza di una proprietà in un oggetto. È raccomandabile che +`hasOwnProperty` venga usata in molti casi in cui è necessario iterare le +proprietà di un oggetto, come descritto nella sezione [cicli `for in`](#object.forinloop). diff --git a/doc/it/object/prototype.md b/doc/it/object/prototype.md index 4c34fada..8f8111d1 100644 --- a/doc/it/object/prototype.md +++ b/doc/it/object/prototype.md @@ -43,7 +43,7 @@ La prima grande differenza è che l'ereditarietà in JavaScript utilizza le // La catena di prototipi finale test [istanza di Bar] Bar.prototype [istanza di Foo] - { foo: 'Hello World' } + { foo: 'Hello World', value: 42 } Foo.prototype { method: ... } Object.prototype diff --git a/doc/it/other/timeouts.md b/doc/it/other/timeouts.md index 4bf1757e..da216d54 100644 --- a/doc/it/other/timeouts.md +++ b/doc/it/other/timeouts.md @@ -3,8 +3,12 @@ Dato che JavaScript è asincrono, è possibile programmare l'esecuzione di una funzione usando le funzioni `setTimeout` e `setInterval`. -> **Nota:** i timeout **non** sono parte dello standard ECMAScript. Essi -> vengono implementati come parte del [DOM][1]. +> **Nota:** i timeout **non** sono parte dello standard ECMAScript. Erano stati +> implementati in [BOM, o DOM Level 0][1], i quali non sono mai stati definiti +> o documentati formalmente. Nessuna specifica raccomandazione è mai stata +> pubblicata, tuttavia, la loro standardizzazione è in via di ultimazione con +> [HTML5][2]. Per loro stessa natura, quindi, l'implementazione può essere +> differente nei vari browser e motori di rendering. function foo() {} var id = setTimeout(foo, 1000); // ritorna un Number > 0 @@ -52,7 +56,7 @@ con intervalli molto brevi, tradursi in chiamate a funzione che si sovrappongono function foo(){ // qualcosa che blocca per 1 secondo } - setInterval(foo, 100); + setInterval(foo, 1000); Nel codice precedente, `foo` verrà chiamato una volta e quindi bloccherà per un secondo. @@ -68,7 +72,7 @@ La soluzione più semplice, come anche la più controllabile, è quella di usare function foo(){ // qualcosa che blocca per 1 secondo - setTimeout(foo, 100); + setTimeout(foo, 1000); } foo(); @@ -119,8 +123,7 @@ gli ID dei timeout, così che possano essere puliti in modo specifico. primo parametro. Questa caratteristica non dovrebbe essere **mai** usata perché internamente fa uso di `eval`. -> **Nota:** dato che le funzioni di timeout **non** sono specificate dallo -> standard ECMAScript, l'esatto funzionamento quando viene passata una stringa +> **Nota:** L'esatto funzionamento quando viene passata una stringa > potrebbe differire nelle varie implementazioni di JavaScript. Per esempio, > JScript di Microsoft usa il costruttore `Function` al posto di `eval`. @@ -157,6 +160,9 @@ funzione che verrà chiamata da una delle funzioni di timeout. > `setTimeout(foo, 1000, 1, 2, 3)`, non la si raccomanda, dato che il suo > utilizzo potrebbe portare ad errori subdoli quando usata con i > [metodi](#function.this). +> Inoltre, la sintassi potrebbe non funzionare in alcune implementazioni di +> JavaScript. +> Ad esempio, Internet Explorer di Microsoft [**non** passa direttamente gli argomenti al callback](3). ### In conclusione @@ -169,5 +175,6 @@ di gestire l'effettiva chiamata. Inoltre, l'uso di `setInterval` dovrebbe essere evitato perché il suo schedulatore non viene bloccato dall'esecuzione di JavaScript. -[1]: http://en.wikipedia.org/wiki/Document_Object_Model "Document Object Model" - +[1]: http://www.nczonline.net/blog/2009/09/29/web-definitions-dom-ajax-and-more/ "Web definitions: DOM, Ajax, and more" +[2]: http://www.w3.org/TR/2014/WD-html5-20140617/webappapis.html#timers "6 Web application APIs - HTML5" +[3]: http://msdn.microsoft.com/en-us/library/ie/ms536753(v=vs.85).aspx "setTimeout method (Internet Explorer)" diff --git a/doc/it/types/casting.md b/doc/it/types/casting.md index 7c9f4a60..5da767f0 100644 --- a/doc/it/types/casting.md +++ b/doc/it/types/casting.md @@ -4,8 +4,9 @@ JavaScript è un linguaggio **debolmente tipizzato**, perciò esso applicherà una *conversione di tipo* **ovunque** sia possibile. // Queste sono vere - new Number(10) == 10; // Number.toString() viene convertito - // nuovamente in un numero + new Number(10) == 10; // l'oggetto Number viene convertito + // in una primitiva numero tramite chiamata implicita + // al metodo Number.prototype.valueOf 10 == '10'; // String viene convertita in Number 10 == '+10 '; // Stringa più assurda @@ -24,7 +25,7 @@ una *conversione di tipo* **ovunque** sia possibile. Per evitare i problemi appena visti, l'uso dell'[operatore di uguaglianza stretta](#types.equality) è **altamente** raccomandato. Sebbene questo eviti molti dei comuni problemi, ci sono ancora -molti ulteriori problemi che possono essere generati dal sistema debolemente +molti ulteriori problemi che possono essere generati dal sistema debolmente tipizzato di JavaScript. ### Costruttori di tipi interni @@ -72,5 +73,3 @@ booleano. !!'-1' // true !!{}; // true !!true; // true - - diff --git a/doc/it/types/instanceof.md b/doc/it/types/instanceof.md index 04ba1e93..8ff454f4 100644 --- a/doc/it/types/instanceof.md +++ b/doc/it/types/instanceof.md @@ -34,7 +34,7 @@ esattamente lo stesso oggetto. ### In conclusione -L'operatore `instanceof` dovrebbe essere usto **solo** quando si ha a che fare +L'operatore `instanceof` dovrebbe essere usato **solo** quando si ha a che fare con oggetti personalizzati creati dal programmatore, che provengono dallo stesso contesto JavaScript. Proprio come per l'operatore [`typeof`](#types.typeof), ogni altro tipo di utilizzo dovrebbe essere **evitato**. diff --git a/doc/ja/object/prototype.md b/doc/ja/object/prototype.md index 4a5ad300..a38ff3f5 100644 --- a/doc/ja/object/prototype.md +++ b/doc/ja/object/prototype.md @@ -33,7 +33,7 @@ JavaScriptはプロトタイプベースが採用されている唯一の広範 // プロトタイプチェーンの結果 test [instance of Bar] Bar.prototype [instance of Foo] - { foo: 'Hello World' } + { foo: 'Hello World', value: 42 } Foo.prototype { method: ... } Object.prototype diff --git a/doc/ko/array/general.md b/doc/ko/array/general.md index 1a665fa3..12f66100 100644 --- a/doc/ko/array/general.md +++ b/doc/ko/array/general.md @@ -25,14 +25,15 @@ JavaScript에서는 배열(Array)도 객체(Object)지만 객체 순회(Iterate) `length` 프로퍼티의 *getter*는 단순히 Array 안에 있는 엘리먼트의 개수를 반환하고 *setter*는 배열을 할당한 수만큼 잘라 버린다. - var foo = [1, 2, 3, 4, 5, 6]; - foo.length = 3; - foo; // [1, 2, 3] + var arr = [1, 2, 3, 4, 5, 6]; + arr.length = 3; + arr; // [1, 2, 3] - foo.length = 6; - foo; // [1, 2, 3] + arr.length = 6; + arr.push(4); + arr; // [1, 2, 3, undefined, undefined, undefined, 4] -현재 크기보다 더 작은 값을 할당하면 배열을 자르지만, 현재 크기보다 더 큰 값을 할당한다고 해서 배열을 늘리진 않는다. +현재 크기보다 더 작은 값을 할당하면 배열을 자른다. 배열의 크기를 증가시키면 드문드문(sparse)한 배열을 생성한다. ### 결론 diff --git a/doc/ko/core/eval.md b/doc/ko/core/eval.md index 528b1883..2a97ebea 100644 --- a/doc/ko/core/eval.md +++ b/doc/ko/core/eval.md @@ -2,26 +2,26 @@ `eval` 함수는 JavaScript 문자열을 지역 스코프에서 실행한다. - var foo = 1; + var number = 1; function test() { - var foo = 2; - eval('foo = 3'); - return foo; + var number = 2; + eval('number = 3'); + return number; } test(); // 3 - foo; // 1 + number; // 1 `eval`함수는 `eval`이라는 이름으로 **직접** 실행할 때에만 지역 스코프에서 실행된다. 그리고 `eval`이라는 이름에 걸맞게 악명또한 높다. - var foo = 1; + var number = 1; function test() { - var foo = 2; - var bar = eval; - bar('foo = 3'); - return foo; + var number = 2; + var copyOfEval = eval; + copyOfEval('number = 3'); + return number; } test(); // 2 - foo; // 3 + number; // 3 어쨌든 `eval`은 사용하지 말아야 한다. eval을 사용하는 99.9%는 사실 eval 없이도 만들수있다. diff --git a/doc/ko/function/arguments.md b/doc/ko/function/arguments.md index 5ea383cb..288928f5 100644 --- a/doc/ko/function/arguments.md +++ b/doc/ko/function/arguments.md @@ -27,22 +27,37 @@ JavaScript의 모든 함수 스코프에는 `arguments`라는 특별한 변수 // 내곡동에 땅이라도 산다. } -또 다른 방법으로는 함수를 랩핑하지 않고, 풀어서 `call`과 `apply`를 함께 사용하는 방법이 있다. (역주: 프로토타입에 있는 method를 호출하기 전에 Foo 객체 안에 있는 method로 한번더 필터링하는 효과가 있다. ) +또 다른 트릭은 `call`과 `apply`를 함께 사용하여 메소드(`this`의 값과 인자들을 사용하는 함수)를 +단지 인자들만 사용하는 일반 함수로 바꾸는 것이다. - function Foo() {} + function Person(first, last) { + this.first = first; + this.last = last; + } - Foo.prototype.method = function(a, b, c) { - console.log(this, a, b, c); + Person.prototype.fullname = function(joiner, options) { + options = options || { order: "western" }; + var first = options.order === "western" ? this.first : this.last; + var last = options.order === "western" ? this.last : this.first; + return first + (joiner || " ") + last; }; - // "method"를 풀어 쓴(unbound) 버전 - // 이 Function의 인자: this, arg1, arg2...argN - Foo.method = function() { - - // 결과: Foo.prototype.method.call(this, arg1, arg2... argN) - Function.call.apply(Foo.prototype.method, arguments); + // "fullname" 메소드의 비결합(unbound) 버전을 생성한다. + // 첫번째 인자로 'first'와 'last' 속성을 가지고 있는 어떤 객체도 사용 가능하다. + // "fullname"의 인자 개수나 순서가 변경되더라도 이 랩퍼를 변경할 필요는 없을 것이다. + Person.fullname = function() { + // 결과: Person.prototype.fullname.call(this, joiner, ..., argN); + return Function.call.apply(Person.prototype.fullname, arguments); }; + var grace = new Person("Grace", "Hopper"); + + // 'Grace Hopper' + grace.fullname(); + + // 'Turing, Alan' + Person.fullname({ first: "Alan", last: "Turing" }, ", ", { order: "eastern" }); + ### 일반 파라미터와 arguments 객체의 인덱스 일반 파라미터와 `arguments` 객체의 프로퍼티는 모두 *getter*와 *setter*를 가진다. diff --git a/doc/ko/function/closures.md b/doc/ko/function/closures.md index 4d7463a6..4e5631fa 100644 --- a/doc/ko/function/closures.md +++ b/doc/ko/function/closures.md @@ -75,3 +75,21 @@ JavaScript에서는 스코프(Scope)를 어딘가에 할당해두거나 참조 } })(i), 1000) } + +즐겨 쓰이는 또 하나의 방법은 `setTimeout` 함수에 세번째 인자를 추가하는 방법이다. +추가된 인자는 콜백 함수에 전달된다. + + for(var i = 0; i < 10; i++) { + setTimeout(function(e) { + console.log(e); + }, 1000, i); + } + +레거시 JS 환경(Internet Explorer 9 이하)은 이 방법을 지원하지 않는다. + +`.bind`를 사용하는 방법도 있다. `.bind`는 `this` 컨텍스트와 인자들을 함수에 결속(bind)시킨다. +아래 코드는 위 코드와 동일하게 동작한다. + + for(var i = 0; i < 10; i++) { + setTimeout(console.log.bind(console, i), 1000); + } diff --git a/doc/ko/function/constructors.md b/doc/ko/function/constructors.md index 1aa6de4a..2b26dc24 100644 --- a/doc/ko/function/constructors.md +++ b/doc/ko/function/constructors.md @@ -6,40 +6,40 @@ JavaScript의 생성자는 다른 언어들과 다르게 `new` 키워드로 호 그리고 생성자에 명시적인 `return` 구문이 없으면 this가 가리키는 객체를 반환한다. - function Foo() { - this.bla = 1; + function Person(name) { + this.name = name; } - Foo.prototype.test = function() { - console.log(this.bla); + Person.prototype.logName = function() { + console.log(this.name); }; - var test = new Foo(); + var sean = new Person(); -위 코드는 `new` 키워드가 실행되는 시점에 `Foo`를 생성자로 호출하고 `Foo.prototype`을 새 객체의 prototype에 할당한다. +위 코드는 `Person`을 생성자로 호출하고 새로 생성된 객체의 `prototype`을 `Person.prototype`으로 설정한다. 아래 코드와 같이 생성자에 명시적인 `return` 문이 있는 경우에는 반환하는 값이 객체인 경우에만 그 값을 반환한다. - function Bar() { - return 2; + function Car() { + return 'ford'; } - new Bar(); // 새 객체를 만들어 반환 + new Car(); // 'ford'가 아닌 새로운 객체를 반환 - function Test() { - this.value = 2; + function Person() { + this.someValue = 2; return { - foo: 1 + name: 'Charles' }; } - new Test(); // 명시한 객체를 반환 + new Person(); // someValue가 포함되지 않은 ({name:'Charles'}) 객체 반환 new 키워드가 없으면 그 함수는 객체를 반환하지 않는다. - function Foo() { - this.bla = 1; // 전역객체에 할당된다. + function Pirate() { + this.hasEyePatch = true; // 전역 객체를 준비! } - Foo(); // undefined + var somePirate = Pirate(); // somePirate = undefined 위 예제는 그때그때 다르게 동작한다. 그리고 [`this`](#function.this) 객체의 동작 원리에 따라서 Foo 함수안의 `this`의 값은 *Global 객체*를 가리키게된다. (역주: 결국 new 키워드를 빼고, 코드를 작성할 경우 원치 않은 this 참조 오류가 발생할 수 있다.) @@ -48,24 +48,24 @@ new 키워드가 없으면 그 함수는 객체를 반환하지 않는다. 생성자가 객체를 반환하면 `new` 키워드를 생략할 수 있다. - function Bar() { - var value = 1; + function Robot() { + var color = 'gray'; return { - method: function() { - return value; + getColor: function() { + return color; } } } - Bar.prototype = { - foo: function() {} + Robot.prototype = { + someFunction: function() {} }; - new Bar(); - Bar(); + new Robot(); + Robot(); -new 키워드의 유무과 관계없이 `Bar` 생성자의 동작은 동일한다. 즉 [클로저](#function.closures)가 할당된 method 프로퍼티가 있는 새로운 객체를 만들어 반환한다. +new 키워드의 유무과 관계없이 `Robot` 생성자의 동작은 동일하다. 즉 [클로저](#function.closures)가 할당된 method 프로퍼티가 있는 새로운 객체를 만들어 반환한다. -`new Bar()`로 호출되는 생성자는 반환되는 객체의 prototype 프로퍼티에 아무런 영향을 주지 않는다. 객체를 반환하지 않는 생성자로 만들어지는 경우에만 객체의 prototype이 생성자의 것으로 할당된다. +`new Robot()`으로 호출되는 생성자는 반환되는 객체의 prototype 프로퍼티에 아무런 영향을 주지 않는다. 객체를 반환하지 않는 생성자로 만들어지는 경우에만 객체의 prototype이 생성자의 것으로 할당된다. 그러니까 이 예제에서 `new` 키워드의 유무는 아무런 차이가 없다. (역주: 생성자에 객체를 만들어 명시적으로 반환하면 new 키워드에 관계없이 잘 동작하는 생성자를 만들수있다. 즉, new 키워드가 빠졌을때 발생하는 this 참조 오류를 방어해준다.) @@ -76,19 +76,21 @@ new 키워드의 유무과 관계없이 `Bar` 생성자의 동작은 동일한 객체를 만들고 반환해주는 팩토리를 사용하여 `new` 키워드 문제를 회피할 수 있다. - function Foo() { - var obj = {}; - obj.value = 'blub'; + function CarFactory() { + var car = {}; + car.owner = 'nobody'; - var private = 2; - obj.someMethod = function(value) { - this.value = value; + var milesPerGallon = 2; + + car.setOwner = function(newOwner) { + this.owner = newOwner; } - obj.getPrivate = function() { - return private; + car.getMPG = function() { + return milesPerGallon; } - return obj; + + return car; } `new` 키워드가 없어도 잘 동작하고 [private 변수](#function.closures)를 사용하기도 쉽다. 그렇지만, 단점도 있다. diff --git a/doc/ko/function/this.md b/doc/ko/function/this.md index b6d57aa6..019b4458 100644 --- a/doc/ko/function/this.md +++ b/doc/ko/function/this.md @@ -58,16 +58,26 @@ Global Scope에서도 this가 사용될 수 있고 이때에는 *Global* 객체 `test`에서 `Foo`에 접근하려면 method에 Local 변수를 하나 만들고 `Foo`를 가리키게 하여야 한다. Foo.method = function() { - var that = this; + var self = this; function test() { - // 여기에서 this 대신에 that을 사용하여 Foo에 접근한다. + // 여기에서 this 대신에 self를 사용하여 Foo에 접근한다 } test(); } -`that`은 this에 접근하기 위해 만든 변수다. [closures](#function.closures)와 함께 `this`의 값을 넘기는 데 사용할 수 있다. +`self`는 통상적인 변수 이름이지만, 바깥쪽의 `this`를 참조하기 위해 일반적으로 사용된다. +또한 [클로저](#function.closures)와 결합하여 `this`의 값을 주고 받는 용도로 사용할 수도 있다. -### Method할당 하기 +ECMAScript 5부터는 익명 함수와 결합된 `bind` 메소드를 사용하여 같은 결과를 얻을 수 있다. + + Foo.method = function() { + var test = function() { + // this는 이제 Foo를 참조한다 + }.bind(this); + test(); + } + +### Method 할당하기 JavaScript의 또다른 함정은 바로 함수의 별칭을 만들수 없다는 점이다. 별칭을 만들기 위해 메소드를 변수에 넣으면 자바스크립트는 별칭을 만들지 않고 바로 *할당*해 버린다. diff --git a/doc/ko/object/prototype.md b/doc/ko/object/prototype.md index 9e8ffb2a..606d8105 100644 --- a/doc/ko/object/prototype.md +++ b/doc/ko/object/prototype.md @@ -31,7 +31,7 @@ Javascript는 클래스 스타일의 상속 모델을 사용하지 않고 *프 // 결과적으로 만들어진 프로토타입 체인은 다음과 같다. test [instance of Bar] Bar.prototype [instance of Foo] - { foo: 'Hello World' } + { foo: 'Hello World', value: 42 } Foo.prototype { method: ... } Object.prototype diff --git a/doc/language.json b/doc/language.json index dc45c11f..df12ab7d 100644 --- a/doc/language.json +++ b/doc/language.json @@ -1,5 +1,4 @@ { "default": "en", - "listed": ["en", "fi", "ru", "zhtw", "zh", "tr", "pl", "ko", "ja", "es", "it", "hu"] + "listed": ["by","en","es","fi","fr","hu","it","ja","ko","pl","ptbr","ru","tr","zh","zhtw"] } - diff --git a/doc/pl/array/constructor.md b/doc/pl/array/constructor.md index 7df61c1d..e715c840 100644 --- a/doc/pl/array/constructor.md +++ b/doc/pl/array/constructor.md @@ -11,9 +11,9 @@ przekazane do niego parametry. new Array(3); // Rezultat: [] new Array('3') // Rezultat: ['3'] -W przypadku gdy tylko jeden argument zostanie przekazany do kostruktora `Array` i +W przypadku, gdy tylko jeden argument zostanie przekazany do kostruktora `Array` i ten argument jest typu `Number`, konstruktor zwróci nową *dziwną* tablicę -z ustawioną właściwością `length` na wartość przekazaną jako argument. Należy +z właściwością `length` ustawioną na wartość przekazaną jako argument. Należy zauważyć, że **tylko** właściwość `length` zostanie ustawiona w ten sposób. Rzeczywiste indeksy w tej tablicy nie zostaną zainicjalizowane. diff --git a/doc/pl/array/general.md b/doc/pl/array/general.md index 6bd89bae..499e0d62 100644 --- a/doc/pl/array/general.md +++ b/doc/pl/array/general.md @@ -1,6 +1,6 @@ ## Iterowanie po tablicach oraz właściwościach tablic -Mimo że tablice w JavaScript są obiektami, nie ma dobrych powodów aby używać +Mimo, że tablice w JavaScript są obiektami, nie ma dobrych powodów, aby używać [`pętli for in`](#object.forinloop) do iteracji po nich. W rzeczywstości istnieje wiele dobrych powodów **przeciwko** wykorzystaniu `for in` na tablicach. @@ -9,9 +9,9 @@ wiele dobrych powodów **przeciwko** wykorzystaniu `for in` na tablicach. > tablice asocjacyjne **zachowują** porządek, natomiast obiekty **nie zachowują**. Ponieważ pętla `for in` wylicza wszystkie właściwości, które są wewnątrz -łańcucha prototypów i jedynym sposobem aby wykluczyć te właściwości jest użycie -[`hasOwnProperty`](#object.hasownproperty), ale wówczas pętla staje się -**dwadzieście razy** wolniejsza od normalnej pętli `for`. +łańcucha prototypów, jedynym sposobem, aby wykluczyć te właściwości, jest użycie +[`hasOwnProperty`](#object.hasownproperty). Wówczas pętla staje się jednak +**dwadzieścia razy** wolniejsza od normalnej pętli `for`. ### Iteracja @@ -26,10 +26,10 @@ użyć klasycznej pętli `for`. W powyższym przykładzie jest jeszcze jeden dodatkowy haczyk. Jest to zbuforowanie długości tablicy poprzez `l = list.length`. -Mimo że właściwość `length` jest zdefiniowana wewnątrz tablicy, istnieje nadal -dodatkowy koszt na wyszukiwanie tej właściwości przy każdej iteracji w pętli. -Chociaż najnowsze silniki JavaScript **mogą** zastosować w tym -przypadku optymalizację. Nie ma jednak możliwość ustalenia czy kod będzie wykonywany w jednym +Mimo, że właściwość `length` jest zdefiniowana wewnątrz tablicy, istnieje nadal +dodatkowy koszt wyszukiwania tej właściwości przy każdej iteracji w pętli. +Najnowsze silniki JavaScript **mogą** zastosować w tym +przypadku optymalizację. Nie ma jednak możliwości ustalenia, czy kod będzie wykonywany w jednym z tych nowych silników, czy też nie. W rzeczywistości pominięcie buforowania długości tablicy może spowodować, że pętla diff --git a/doc/pl/core/eval.md b/doc/pl/core/eval.md index 1da5c812..9a0ae0d6 100644 --- a/doc/pl/core/eval.md +++ b/doc/pl/core/eval.md @@ -12,7 +12,7 @@ Funkcja `eval` uruchomi podany string jako kod JavaScript w lokalnym zasięgu (s foo; // 1 Niestaty, `eval` zostanie wykonana w lokalnym zasięgu tylko wtedy, gdy zostanie wywołana -**bezpośrednio** *i* nazwa wywoływanej funkcji równa sie `eval`. +**bezpośrednio** *i* nazwa wywoływanej funkcji równa się `eval`. var foo = 1; function test() { diff --git a/doc/pl/function/closures.md b/doc/pl/function/closures.md index 2c72db1b..df782104 100644 --- a/doc/pl/function/closures.md +++ b/doc/pl/function/closures.md @@ -47,7 +47,7 @@ Zamiast tego funkcja utworzy lub nadpisze *globalną* zmienną `count`. ### Domknięcia wewnątrz pętli -Jednym z częstrzych błędów jest wykorzystywanie domknięć wewnątrz pętli, +Jednym z częstszych błędów jest wykorzystywanie domknięć wewnątrz pętli, aby wartość zmiennej po której odbywa się iteracja była kopiowana do wewnętrznej funkcji. diff --git a/doc/pl/function/general.md b/doc/pl/function/general.md index c960c9b5..f9c3247c 100644 --- a/doc/pl/function/general.md +++ b/doc/pl/function/general.md @@ -1,6 +1,6 @@ ## Deklaracje funkcji i wyrażenia funkcyjne -Funcje w języku JavaScript są [typami pierwszoklasowymi][1], co oznacza, że mogą +Funkcje w języku JavaScript są [typami pierwszoklasowymi][1], co oznacza, że mogą być przekazywane jak każda inna wartość. Jednym z typowych zastosowań tej cechy jest przekazywanie *anonimowej funkcji* jako callback do innej, prawdopodobnie asynchronicznej funkcji. diff --git a/doc/pl/function/scopes.md b/doc/pl/function/scopes.md index 52126570..bb43387b 100644 --- a/doc/pl/function/scopes.md +++ b/doc/pl/function/scopes.md @@ -21,7 +21,7 @@ definiowane w jednej *globalnie współdzielonej* przestrzeni nazw. Z każdym odwołaniem do zmiennej, JavaScript przeszukuje w górę wszystkie zasięgi dopóki nie znajdzie tej zmiennej. W przypadku, gdy przeszukiwanie dotrze do globalnego -zasięgu i nadal nie znajdzie żądanej nazwy, to wyrzuca błąd `ReferenceError`. +zasięgu i nadal nie znajdzie żądanej nazwy, wyrzuca błąd `ReferenceError`. ### Zmora globalnych zmiennych @@ -35,7 +35,7 @@ Powyższe dwa skrypty **nie** dają tego samego efektu. Skrypt A definiuje zmien nazwaną `foo` w *globalnym* zasięgu, natomiast skrypt B definiuje `foo` w *aktualnym* zasięgu. -Jeszcze raz, to wcale nie daje *tego samego efektu*. Nie użycie `var` może mieć +Jeszcze raz, to wcale nie daje *tego samego efektu*. Brak użycia `var` może mieć poważne konsekwencje. // globalny zasięg @@ -48,8 +48,8 @@ poważne konsekwencje. foo; // 21 Pominięcie słowa `var` w deklaracji wewnątrz funkcji `test` nadpisze wartość -zmiennej globalnej `foo`. Mimo że nie wygląda to na początku na duży problem, -posiadanie wielu tysięcy linii kodu w JavaScript i nie korzystanie z `var` +zmiennej globalnej `foo`. Mimo, że nie wygląda to na początku na duży problem, +w przypadku kodu, który posiada wielu tysięcy linii, brak `var` wprowadzi straszne i trudne do wyśledzenia błędy. // globalny zasięg @@ -68,8 +68,8 @@ wprowadzi straszne i trudne do wyśledzenia błędy. Zewnętrzna pętla zakończy działanie po pierwszym wywołaniu `subLoop`, ponieważ `subLoop` nadpisuje wartość globalnej zmiennej `i`. Użycie `var` w drugiej pętli `for` pozwoliłoby łatwo uniknąć problemu. Słowo kluczowe `var` nie powinno być -**nigdy** pominięte w deklaracji, chyba że *pożądanym skutkiem* jest wpłynięcie na -zewnętrzny zasięg. +**nigdy** pominięte w deklaracji, chyba że *pożądanym skutkiem* jest modyfikacja +zewnętrznego zasięgu. ### Lokalne zmienne @@ -90,7 +90,7 @@ oraz zmienne zadeklarowane poprzez deklaracje `var` wewnątrz funkcji. } test(10); -Zmienne `foo` oraz `i` są lokalnymi zmiennymi wewnątrz zasiegu funkcji `test`, +Zmienne `foo` oraz `i` są lokalnymi zmiennymi wewnątrz zasięgu funkcji `test`, natomiast przypisanie wartości do `bar` nadpisze zmienną globalną o tej samej nazwie. ### "Hoisting" - wywindowanie, podnoszenie @@ -150,10 +150,10 @@ W oryginalnym kodzie instrukcja warunkowa `if` zdaje się modyfikować *zmienną globalną* `goo`, podczas gdy faktycznie modyfikuje ona *zmienną lokalną* - po tym jak zostało zastosowane windowanie (hoisting). -Bez wiedzy na temat podnoszenia (hoistingu), poniższy kod może sprawiać wrażenie, +Analizując poniższy kod bez wiedzy na temat hoistingu możemy odnieść wrażenie, że zobaczymy błąd `ReferenceError`. - // sprawdz czy SomeImportantThing zostało zainicjalizowane + // sprawdź, czy SomeImportantThing zostało zainicjalizowane if (!SomeImportantThing) { var SomeImportantThing = {}; } @@ -163,9 +163,9 @@ przeniesiona na początek *globalnego zasięgu*. var SomeImportantThing; - // inny kod który może ale nie musi zainicjalizować SomeImportantThing + // inny kod, który może, ale nie musi zainicjalizować SomeImportantThing - // upewnienie sie, że SomeImportantThing zostało zainicjalizowane + // upewnij się, że SomeImportantThing zostało zainicjalizowane if (!SomeImportantThing) { SomeImportantThing = {}; } @@ -182,19 +182,21 @@ funkcji. Na przykład, kiedy próbujemy odczytać zmienną `foo` wewnątrz zasięgu funkcji, JavaScript będzie szukać nazwy w określonej kolejności: - 1. Jeżeli wewnątrz aktualnego zasięgu znajduje się deklaracja `var foo` skorzystaj z niej. - 2. Jeżeli jeden z parametrów fukcji został nazwany `foo` użyj go. - 3. Jeżeli fukcja została nazwana `foo` skorzystaj z tego. - 4. Przejdz do zewnętrznego zasięgu i przejdz do kroku **#1**. -> **Uwaga:** Jeżeli jeden z parametrów fukcji został nazwany `arguments`, zapobiegnie -> to utworzeniu domyślnego obiektu `arguments`. + 1. Jeżeli wewnątrz aktualnego zasięgu znajduje się deklaracja `var foo`, skorzystaj z niej. + 2. Jeżeli jeden z parametrów fukcji został nazwany `foo`, użyj go. + 3. Jeżeli funkcja została nazwana `foo`, skorzystaj z tego. + 4. Przejdź do zewnętrznego zasięgu i przejdź do kroku **#1**. + +> **Uwaga:** Jeżeli jeden z parametrów fukcji został nazwany `arguments`, +> nie zostanie utworzony domyślny obiekt `arguments`. ### Przestrzenie nazw Powszechnym problemem posiadania tylko jednej globalnej przestrzeni nazw jest prawdopodobieństwo wystąpienia kolizji nazw. W JavaScripcie, można łatwo uniknąć -tego problemu korzystając z *anonimowych wrapperów*. +tego problemu korzystając z *anonimowych wrapperów* (inaczej: Immediately-Invoked +Function Expression - IIFE). (function() { // autonomiczna "przestrzeń nazw" diff --git a/doc/pl/function/this.md b/doc/pl/function/this.md index 3fa2d477..3819cac7 100644 --- a/doc/pl/function/this.md +++ b/doc/pl/function/this.md @@ -14,7 +14,7 @@ Używanie `this` w globalnym zasięgu, zwróci po prostu referencję do obiektu foo(); -Tutaj `this` również będzie wkazywało na obiekt *global* +Tutaj `this` również będzie wskazywało na obiekt *global* > **Uwaga ES5:** W trybie strict mode, przypadki z globalnym zasięgiem nie mają miejsca. > W tym przypadku `this` zwróci `undefined` zamiast wartości. @@ -55,7 +55,7 @@ miejsca i `this` wewnątrz `foo` będzie wskazywać na `bar`. ### Częste pułapki Mimo iż Większość z tych przypadków ma sens, to pierwszy przypadek powinien być -traktorany jako błąd podczas projektowania języka i **nigdy** nie wykorzystywany +traktowany jako błąd podczas projektowania języka i **nigdy** nie wykorzystywany w praktyce. Foo.method = function() { diff --git a/doc/pl/object/general.md b/doc/pl/object/general.md index 54346ab0..b3b05e5c 100644 --- a/doc/pl/object/general.md +++ b/doc/pl/object/general.md @@ -1,6 +1,6 @@ ## Wykorzystanie obiektów i ich właściwości -Wszystko w JavaScripcie zachowuje sie jak obiekt, z dwoma wyjątkami +Wszystko w JavaScripcie zachowuje się jak obiekt, z dwoma wyjątkami [`null`](#core.undefined) oraz [`undefined`](#core.undefined). false.toString(); // 'false' @@ -17,7 +17,7 @@ liczby. 2.toString(); // wyrzuca błąd SyntaxError -Istnieje kilka rozwiązań, dzieki którym literał liczbowy będzie zachowywał się +Istnieje kilka rozwiązań, dzięki którym literał liczbowy będzie zachowywał się jak obiekt. 2..toString(); // druga kropka jest poprawnie rozpoznana @@ -31,8 +31,8 @@ ponieważ obiekty składają się głównie z mapowań pomiędzy nazwanymi wła a wartościami dla tych atrybutów. Używając literału obiektu - notacji `{}` - istnieje możliwość stworzenia obiektu prostego. -Ten nowy obiekt bedzie [dziedziczył](#object.prototype) z `Object.prototype` oraz -nie bedzie posiadał żadnych [własnych właściwości](#object.hasownproperty). +Ten nowy obiekt będzie [dziedziczył](#object.prototype) z `Object.prototype` oraz +nie będzie posiadał żadnych [własnych właściwości](#object.hasownproperty). var foo = {}; // nowy, pusty obiekt @@ -60,7 +60,7 @@ błędu podczas odczytu nieistniejącej właściwości. ### Usuwanie właściwości -Jedynym sposobem na faktycze usunięcie własności z obiektu jest użycie operatora +Jedynym sposobem na faktyczne usunięcie własności z obiektu jest użycie operatora `delete`. Ustawienie własności na `undefined` lub `null` usunie tylko *wartość* związaną z własnością, ale nie usunie to *klucza* (nazwy własności) z obiektu. @@ -90,9 +90,9 @@ została usunięta i dlatego nie została wypisana. }; Nazwy właściwości obiektu mogą być zarówno zapisane jako tekst (bez cudzysłowów -lub apostrofów) lub jako string (w cudzisłowach lub apostrofach). +lub apostrofów) lub jako string (w cudzysłowach lub apostrofach). Ze względu na kolejne niedociągnięcie w parserze JavaScript, -powyższy kod wyrzuci błąd `SyntaxError` dla implementacji JavaScript ponizej ECMAScript 5. +powyższy kod wyrzuci błąd `SyntaxError` dla implementacji JavaScript poniżej ECMAScript 5. Ten błąd wynika z faktu, że `delete` jest *słowem kluczowym*, dlatego musi zostać zapisany jako *string* (z cudzysłowami lub apostrofami), aby zapewnić, że zostanie diff --git a/doc/pl/object/hasownproperty.md b/doc/pl/object/hasownproperty.md index d9366447..59ae744a 100644 --- a/doc/pl/object/hasownproperty.md +++ b/doc/pl/object/hasownproperty.md @@ -40,7 +40,7 @@ możliwość, że obiekt będzie posiadać tak nazwaną właściwość. Konieczn foo.hasOwnProperty('bar'); // zawsze zwraca false - // Została użyta metoda innego obiektu i wywołana z konkekstem + // Została użyta metoda innego obiektu i wywołana z kontekstem // `this` ustawionym na foo ({}).hasOwnProperty.call(foo, 'bar'); // true diff --git a/doc/pl/object/prototype.md b/doc/pl/object/prototype.md index 85dbdfb7..3cabc20e 100644 --- a/doc/pl/object/prototype.md +++ b/doc/pl/object/prototype.md @@ -9,7 +9,7 @@ modelu. Na przykład stworzenia klasycznego modelu na podstawie modelu prototypo jest dość proste, podczas gdy zrobienie odwrotnego przekształcenie to o wiele trudniejsze zadanie. Ze względu na fakt, że w JavaScript jest w zasadzie jedynym powszechnie stosowanym -językiem, któy posiada prototypowy model dziedziczenia, dostosowanie się do różnic pomiędzy +językiem, który posiada prototypowy model dziedziczenia, dostosowanie się do różnic pomiędzy tymi dwoma modelami wymaga trochę czasu. Pierwszą znaczącą różnicą jest to, że dziedziczenie w JavaScript odbywa się za pomocą @@ -17,7 +17,7 @@ tak zwanych *łańcuchów prototypów*. > **Uwaga:** Używanie po prostu `Bar.prototype = Foo.prototype` spowoduje, że oba obiekty > będą korzystały z **tego samego** prototypu. W związku z tym zmiany w prototypie jednego -> obiektu będą również zmieniały prototyp drugiego obiektu, co jest ,w wiekszości przypadków, +> obiektu będą również zmieniały prototyp drugiego obiektu, co jest ,w większości przypadków, > niepożądanym efektem. function Foo() { @@ -41,23 +41,23 @@ tak zwanych *łańcuchów prototypów*. // The resulting prototype chain test [instance of Bar] Bar.prototype [instance of Foo] - { foo: 'Hello World' } + { foo: 'Hello World', value: 42 } Foo.prototype { method: ... } Object.prototype { toString: ... /* etc. */ } W powyższym przykładzie obiekt `test` będzie dziedziczył z obydwu, tj. -`Bar.prototyp` i `Foo.prototyp`, stąd będzie miał dostęp do funkcji `method`, +`Bar.prototype` i `Foo.prototype`, stąd będzie miał dostęp do funkcji `method`, która była zdefiniowana w `Foo`. Ponadto obiekt będzie miał dostęp do -właściwości `value`, która jest jednyną instancją `Foo` i stała się jego prototypem. +właściwości `value`, która jest jedyną instancją `Foo` i stała się jego prototypem. Należy pamiętać, że `new Bar` **nie** tworzy nowej instancji `Foo`, tylko wykorzystuje instancję, która jest przypisana do własności `prototype`. Zatem Wszystkie instancje `Bar` będą dzieliły tą samą własność `value`. > **Uwaga:** **Nie** należy używać konstrukcji `Bar.prototype = Foo`, > ponieważ nie spowoduje ona przypisania prototypu `Foo` tylko obiektu -> funckji `Foo`. Zatem łańcuch prototypów nie bedzie zawierał `Foo.prototype`, +> funckji `Foo`. Zatem łańcuch prototypów nie będzie zawierał `Foo.prototype`, > tylko `Function.prototype`, więc metoda `method` nie będzie w łańcuchu prototypów. ### Wyszukiwanie własności @@ -102,11 +102,11 @@ Nie ma jednak dobrego powodu, aby zaśmiecać wbudowane typy poprzez wzbogacanie *niestandardowe* funkcjonalności. **Jedynym** dobrym powodem do rozszerzania wbudowanych prototypów jest portowanie -funkcjonalności znajdujących sie w nowszych silnikach JavaScript, np. [`Array.forEach`][3] +funkcjonalności znajdujących się w nowszych silnikach JavaScript, np. [`Array.forEach`][3] ### Wnioski -Zanim przystąpi się do pisania skomplikowanego kodu korzystającego z dziedziczania, +Zanim przystąpi się do pisania skomplikowanego kodu korzystającego z dziedziczenia, należy **całkowicie** zrozumieć prototypowy model dziedziczenia. Ponadto trzeba uważać na długość łańcucha prototypów i w razie potrzeby zmniejszać ilość dziedziczeń, aby uniknąć problemów z wydajnością. Natywne prototypy **nigdy** nie powinny być diff --git a/doc/pl/other/timeouts.md b/doc/pl/other/timeouts.md index ad59fc50..97a47745 100644 --- a/doc/pl/other/timeouts.md +++ b/doc/pl/other/timeouts.md @@ -47,7 +47,7 @@ milisekund. Jednakże korzystanie z tej funkcji jest odradzane. Kiedy wykonywany kod zablokuje możliwość uruchomienia zaplanowanej funkcji, `setInterval` będzie próbować uruchamiać daną funkcję, co będzie powodować -kolejkowanie wykonania tej samej funkcji kilkukrotnie. Może się to zdażyć +kolejkowanie wykonania tej samej funkcji kilkukrotnie. Może się to zdarzyć szczególnie przy krótkim interwale. function foo(){ diff --git a/doc/pl/types/casting.md b/doc/pl/types/casting.md index 7c676ee1..099ac0c9 100644 --- a/doc/pl/types/casting.md +++ b/doc/pl/types/casting.md @@ -17,7 +17,7 @@ typów **gdziekolwiek** jest to możliwe. 10 == 010; 10 == '-10'; -> **Uwaga ES5: Literały liczbowe zaczynające sie od `0` są interpretowane jako +> **Uwaga ES5: Literały liczbowe zaczynające się od `0` są interpretowane jako > liczby w systemie ósemkowym. W trybie strict mode w ECMAScript 5 wsparcie dla > liczb ósemkowych zostało porzucone. diff --git a/doc/pl/types/typeof.md b/doc/pl/types/typeof.md index ccbc21d1..666d9b52 100644 --- a/doc/pl/types/typeof.md +++ b/doc/pl/types/typeof.md @@ -36,7 +36,7 @@ natomiast `typeof` ma tylko jeden praktyczny przypadek użycia, który na dodate W powyższej tabeli *Typ* odnosi się do wartości zwracanej przez operator `typeof`. Wyraźnie widać, że zwracane wartości w ogóle nie są spójne. -*Klasa* odnosi sie do wartości wewnętrznej właściwości `[[Class]]` obiektu. +*Klasa* odnosi się do wartości wewnętrznej właściwości `[[Class]]` obiektu. > **Fragment Specyfikacji:** Wartość `[[Class]]` może być jednym z poniższych > stringów. `Arguments`, `Array`, `Boolean`, `Date`, `Error`, diff --git a/doc/ptbr/array/constructor.md b/doc/ptbr/array/constructor.md new file mode 100644 index 00000000..eaaf1c20 --- /dev/null +++ b/doc/ptbr/array/constructor.md @@ -0,0 +1,29 @@ +## O construtor `Array` + +Uma vez que o construtor `Array` é ambíguo na forma como ele lida com seus parâmetros, +o uso da notação `[]` é fortemente recomendado ao criar novo arrays. + + [1, 2, 3]; // Resultado: [1, 2, 3] + new Array(1, 2, 3); // Resultado: [1, 2, 3] + + [3]; // Resultado: [3] + new Array(3); // Resultado: [] + new Array('3') // Resultado: ['3'] + +Nos casos onde somente um argumento é passado para o construtor `Array` e quando o argumento é +um `Number`, o construtor retornará um novo array *sem elementos* com a propriedade `length` configurada de acordo com o valor do argumento. +É importante perceber que **somente** a propriedade `length` do novo array será configurada desta maneira; os índices do array não serão inicializados. + + var arr = new Array(3); + arr[1]; // undefined + 1 in arr; // false, o índice não foi definida + +Ser capaz de definir o comprimento de um array antecipadamente é útil em poucos casos, +como ao replicar uma string, em que se evita o uso de um loop. + + new Array(count + 1).join(stringToRepeat); + +### Conclusão + +O uso de literais é preferencial na inicialição de Arrays. São curtos, possuem uma sintaxe limpa, e contribuem para a legibilidade do código. + diff --git a/doc/ptbr/array/general.md b/doc/ptbr/array/general.md new file mode 100644 index 00000000..10543a84 --- /dev/null +++ b/doc/ptbr/array/general.md @@ -0,0 +1,59 @@ +## Iteração com Arrays e propriedades + +Embora arrays em JavaScript sejam objetos, não existem boas razões para utilizar +o [`for in`](#object.forinloop) loop. De fato, existem muitas boas razões para +**evitar** o uso de `for in` com arrays. + +> **Nota:** JavaScript arrays **não** são *arrays associativos*. JavaScript utiliza +> [objects](#object.general) apenas para mapear chaves com valores. Enquanto arrays associativos +> **preservam** a ordem, objetos **não preservam**. + +Uma vez que o `for in` loop enumera todas as propriedades que estão na cadeia +prototype e visto que o único modo de excluir tais propriedades é por meio do uso +do [`hasOwnProperty`](#object.hasownproperty), ele chega a ser **vinte vezes** +mais custoso que o uso normal do `for` loop. + +### Iteração + +A fim de atingir a melhor performance ao interagir sobre arrays, +a melhor opção é utilizar o clássico `for` loop. + + var list = [1, 2, 3, 4, 5, ...... 100000000]; + for(var i = 0, l = list.length; i < l; i++) { + console.log(list[i]); + } + +Existe um detalhe importante no exemplo acima , que é o caching +do comprimento do array via `l = list.length`. + +Embora a propriedade `length` esteja definida no próprio array, ainda existe +um trabalho extra ao executar a busca em cada iteração do array. +Enquanto que recentes engines JavaScript **talvez** implementem um otimização +para este caso, não existe uma maneira de saber quando o código será executado em uma +dessas novas engines. + +De fato, deixando de lado o armazenamento em caching pode resultar em um loop **duas vezes mais rápido** +do que com o armazenamento em caching. + +### A propriedade `length` + +Enquanto que o *getter* da propriedade `length` retorna o total de elementos +que estão contidos no array, o *setter* pode ser usado para **truncar** o array. + + var foo = [1, 2, 3, 4, 5, 6]; + foo.length = 3; + foo; // [1, 2, 3] + + foo.length = 6; + foo.push(4); + foo; // [1, 2, 3, undefined, undefined, undefined, 4] + +Atribuir um valor de menor para length trunca o array. Por outro lado, incrementando +o valor de length cria um array esparso. + +### Conclusão + +Para melhor performance, é recomendado o uso do `for` loop e o cache da propriedade +`length`. O uso do `for in` loop na iteração com array é um sinal de código mal escrito +e tendencioso a apresentar defeitos, além de ter performance ruim. + diff --git a/doc/ptbr/core/delete.md b/doc/ptbr/core/delete.md new file mode 100644 index 00000000..949c24d8 --- /dev/null +++ b/doc/ptbr/core/delete.md @@ -0,0 +1,85 @@ +## O operador `delete` + +Em resumo, é *impossível* remover variáveis globais, funções e outras coisas em JavaScript +que tenham o atributo `DontDelete` definido. + +### Código global e código de função + +Quando uma variável ou função é definida no escopo global ou em +um [escopo de função](#function.scopes) ela passa a ser uma propriedade de ambos +objeto Activation e do objeto Global. Tais propriedades possuem um conjunto de atributos, um dos quais é o `DontDelete`. +Declarações de funções e variáveis em código global e em código de função +sempre criam propriedades com `DontDelete`, e portanto não podem ser removidas. + + // variável global: + var a = 1; // DontDelete está definido + delete a; // false + a; // 1 + + // função comum: + function f() {} // DontDelete está definido + delete f; // false + typeof f; // "function" + + // mudar o valor do atributo não ajuda: + f = 1; + delete f; // false + f; // 1 + +### Propriedades explícitas + +Propriedades definidas explicitamente podem ser apagadas normalmente. + + // definição explícita de propriedade: + var obj = {x: 1}; + obj.y = 2; + delete obj.x; // true + delete obj.y; // true + obj.x; // undefined + obj.y; // undefined + +No exemplo acima, `obj.x` e `obj.y` podem ser removidos por que eles não possuem o +atributo `DontDelete`. Este é o motivo pelo qual o exemplo abaixo também funciona. + + // Desconsiderando o IE, isto funciona bem: + var GLOBAL_OBJECT = this; + GLOBAL_OBJECT.a = 1; + a === GLOBAL_OBJECT.a; // true - apenas uma variável global + delete GLOBAL_OBJECT.a; // true + GLOBAL_OBJECT.a; // undefined + +Aqui nós utilizamos um truque para remover `a`. Aqui o [`this`](#function.this) +faz referência ao objeto Global e declara explicitamente a variável `a` como +sua propriedade a qual nos permite removê-la. + +O IE (pelo menos 6-8) possui defeitos, então o código acima não funciona. + +### Argumentos de função e propriedades nativas + +Argumentos de função, [objetos `arguments`](#function.arguments) e +propriedades nativas tambêm possuem o `DontDelete` definido. + + // argumentos de funções e propriedades: + (function (x) { + + delete arguments; // false + typeof arguments; // "object" + + delete x; // false + x; // 1 + + function f(){} + delete f.length; // false + typeof f.length; // "number" + + })(1); + +### Objetos hosts + +O comportamento do operador `delete` pode ser imprevisível para objetos hosts. +Devido a especificação, objetos hosts têm permissão para implementar qualquer tipo de comportamento. + +### Conclusão + +O operador `delete` freqüentemente apresenta um comportamento inesperado e só +pode ser usado com segurança para remover propriedades definidas explicitamente em objetos normais. diff --git a/doc/ptbr/core/eval.md b/doc/ptbr/core/eval.md new file mode 100644 index 00000000..0579953d --- /dev/null +++ b/doc/ptbr/core/eval.md @@ -0,0 +1,45 @@ +## Por que não utilizar `eval` + +A função `eval` executará uma string de código JavaScript no escopo local. + + var foo = 1; + function test() { + var foo = 2; + eval('foo = 3'); + return foo; + } + test(); // 3 + foo; // 1 + +Entreranto, `eval` somente é executado no escopo local quando é chamado diretamente +*e* quanto o nome da função chamada é `eval`. + + var foo = 1; + function test() { + var foo = 2; + var bar = eval; + bar('foo = 3'); + return foo; + } + test(); // 2 + foo; // 3 + +O uso de `eval` deve ser evitado. 99.9% de seu "uso" pode ser alcançado **sem** ele. + +### `eval` dissimulado + +As [funções timeout](#other.timeouts) `setTimeout` e `setInterval` podem ambas receberem uma string +como primeiro argumento. Tais strings **sempre** serão executadas no escopo global uma vez que +`eval` não é chamado diretamente, naquele caso. + +### Problemas de segurança + +`eval` também é considerado um problema de segurança, por que executa **qualquer** código dado. +Ele **nunca** deve ser utilizado com strings de origens duvidosas ou desconhecidas. + +### Conclusão + +`eval` nunca deve ser utilizado. Qualquer código que faça uso de `eval` seve ser questionado +em sua utilizade, performance e segurança. Se algo necessita de `eval` para funcionar, então **não** deve ser utilizado. +Um *design melhor* deve ser utilizado, um que não faça uso de `eval`. + diff --git a/doc/ptbr/core/semicolon.md b/doc/ptbr/core/semicolon.md new file mode 100644 index 00000000..38375017 --- /dev/null +++ b/doc/ptbr/core/semicolon.md @@ -0,0 +1,106 @@ +## Inserção automática do ponto e vírgula + +Apesar do JavaScript possuir uma sintaxe no estilo C, o uso do ponto e vírgula **não** é obrigatório. + +JavaScript não é uma linguagem 'semicolon-less'. De fato, o ponto e vírgula é necessário para o interpretação do código. Entretanto, o parser do JavaScript insere o **automaticamente** ponto e vírgula sempre que ocorrer um error de parser, decorrente da falta do ponto e vírgula. + + var foo = function() { + } // parse error, semicolon expected + test() + +A inserção acontece e o parser realiza uma nova tentativa. + + var foo = function() { + }; // no error, parser continues + test() + +A inseção automática de ponto e vírgula é considerada um dos **maiores** equívocos no design da linguagem pois pode influenciar no comportamento do código. + +### Como funciona + +O código abaixo não possui ponto e vírgula, então fica à cargo do parser inserir o ponto e vírgula onde julgar necessário. + + (function(window, undefined) { + function test(options) { + log('testing!') + + (options.list || []).forEach(function(i) { + + }) + + options.value.test( + 'long string to pass here', + 'and another long string to pass' + ) + + return + { + foo: function() {} + } + } + window.test = test + + })(window) + + (function(window) { + window.someLibrary = {} + + })(window) + +Abaixo está o resultado do processamento do parser. + + (function(window, undefined) { + function test(options) { + + // Not inserted, lines got merged + log('testing!')(options.list || []).forEach(function(i) { + + }); // <- inserted + + options.value.test( + 'long string to pass here', + 'and another long string to pass' + ); // <- inserted + + return; // <- inserted, breaks the return statement + { // treated as a block + + // a label and a single expression statement + foo: function() {} + }; // <- inserted + } + window.test = test; // <- inserted + + // The lines got merged again + })(window)(function(window) { + window.someLibrary = {}; // <- inserted + + })(window); //<- inserted + +> **Nota:** O parser do JavaScript não manipula corretamente 'return statements' que são seguidos de uma nova linha. Apesar de não ser necessariamente uma > > > falha da inserção automática do ponto e vírgula, ainda pode gerar efeitos colaterais não-esperados. + +O parser mudou o comportamento do código acima drásticamente. Em determinados casos, o parser **não procede** como o esperado. + +### Parênteses + +No caso de parênteses, o parser **não** insere o ponto e vírgula. + + log('testing!') + (options.list || []).forEach(function(i) {}) + +Este código é interpretado em uma só linha. + + log('testing!')(options.list || []).forEach(function(i) {}) + +As chances de `log` não retornar uma função são **muito** altas; portanto, o código acima irá produzir um `TypeError` informando que `undefined is not a function`. + +### Conclusão + +It is highly recommended to **never** omit semicolons. It is also recommended +that braces be kept on the same line as their corresponding statements and to +never omit them for single-line `if` / `else` statements. These measures will +not only improve the consistency of the code, but they will also prevent the +JavaScript parser from changing code behavior. + +É **fortemente** recomendado que nunca se omita o ponto e vírgula. Também é recomendado que chaves sejam mantidas na mesma linha que seus statements e que nunca sejam omitadas em declações de uma só linha como `if` / `else` statements. Tais medidas não somente melhorarão a consistência do código, como também irão previnir alteração no comportamento do código por má interpretação do parser do JavaScript. + diff --git a/doc/ptbr/core/undefined.md b/doc/ptbr/core/undefined.md new file mode 100644 index 00000000..463a9618 --- /dev/null +++ b/doc/ptbr/core/undefined.md @@ -0,0 +1,68 @@ +## `undefined` e `null` + +JavaScript tem duas formas distintas para representar o nada, `null` e `undefined`, com +o último sendo o mais útil. + +### O valor `undefined` + +`undefined` é um tipo com um valor exato : `undefined`. + +A linguagem também define uma variável global que tem como valor `undefined`; +esta variável também é chamada `undefined`. Entretanto tal variável *não é nem* uma constante +*muito menos* uma palavra-chave da linguagem. Isto significa que seu *valor* pode ser facilmente +sobrescrito. + +> **Nota ES5:** `undefined` em ECMAScript 5 **não dispõe** mais de permissão para escrita no modo estrito, porém +> sua denominação ainda pode ser confundida com, por exemplo, uma função com o nome `undefined`. + +Aqui estão alguns exemplos de quando o valor `undefined` é retornado: + + - Acessando uma variável global (não-modificada) `undefined`. + - Acessando uma variável declarada *mas não* ainda inicializada. + - Retornos implícitos de funções devido ao esquecimento do `return` statement. + - `return` statements que explicimente retornam o nada. + - Busca por propriedades não-existentes. + - Parâmetros de funções que não têm um valor explícito definido. + - Qualquer coisa que tenha sido definida como `undefined`. + - Qualquer expressão no formato `void(expressão)` + +### Manipulando mudanças no valor de `undefined` + +Uma que a variável global `undefined` apenas mantém uma cópia do valor *atual* de `undefined`, atribuir-lhe +um novo valor **não** muda o valor do tipo `undefined`. + +Ainda, a fim de comparar alguma coisa com o valor de `undefined`, é ncessário que +primeiro se retorne o `undefined`. + +A fim de proteger o código contra uma possível sobrescrtia da variável `undefined`, uma +técnica comum utilizada é a de adicionar um parâmetro adicional em um [wrapper anônimo](#function.scopes) + que não recebe argumentos. + + var undefined = 123; + (function(something, foo, undefined) { + // undefined no escopo local agora + // refer-se ao valor `undefined` + + })('Hello World', 42); + +Outra maneira de atingir o mesmo efeito seria utilizar uma declaração dentro do wrapper. + + var undefined = 123; + (function(something, foo) { + var undefined; + ... + + })('Hello World', 42); + +A única diferença aqui é a que a última versão resulta na redução de 4 bytes, e nã existe +outro `var` statement dentro do wrapper anônimo. + +### Usos do `null` + +Enquanto que `undefined` no contexto da linguagem JavaScript é normalmente utilizado +como um *null*, o atual `null` (ambos o tipo e o literal) é mais ou menos um outro tipo de dado. + +Ele é utilizado internamente pelo JavaScript (como na declaração no fim da cadeia prototype +ao definir `Foo.prototype = null`), porém na maioria dos casos, pode ser substituido por `undefined`. + + diff --git a/doc/ptbr/function/arguments.md b/doc/ptbr/function/arguments.md new file mode 100644 index 00000000..099ecf02 --- /dev/null +++ b/doc/ptbr/function/arguments.md @@ -0,0 +1,113 @@ +## O objeto `arguments` + +Todo escopo de uma função em JavaScript em acesso à variável especial `arguments`. +Esta variável armazena uma lista de todos os argumentos que foram passados para a função. + +> **Nota:** No caso em que `arguments` tenha sido definido dentro do escopo da função por meio +> de `var` statement ou que este seja o nome de um parâmetro formal, o objeto `arguments` não será criado. + +O objeto `arguments` **não** é um `Array`. Enquanto que ele possui uma semântica +parecida com a de um array - a saber a propriedade `length` - ele não herda de `Array.prototype` +e é de fato um `Object`. + +Devido a isto, **não** é possível usar os métodos padrões de array como `push`, +`pop` ou `slice` no `arguments`. Enquanto que a iteração com um simples `for` loop funciona bem, +é necessário convertê-lo para um `Array` a fim de usar os métodos padrões de `Array`. + +### Convertendo em um Array + +O código abaixo irá retornar um novo `Array` contendo todos os elementos do +objeto `arguments`. + + Array.prototype.slice.call(arguments); + +Por este tipo de conversão ser **lenta**, seu uso em porções de código que apresentam performance crítica **não é recomendado**. + +### Passando argumentos + +O código abaixo é a maneira recomendada de se passar argumentos de uma função para outra. + + function foo() { + bar.apply(null, arguments); + } + function bar(a, b, c) { + // do stuff here + } + +Outro truque é o de usar ambos `call` e `apply` juntos para criar wrappers. + + function Foo() {} + + Foo.prototype.method = function(a, b, c) { + console.log(this, a, b, c); + }; + + // Create an unbound version of "method" + // It takes the parameters: this, arg1, arg2...argN + Foo.method = function() { + + // Result: Foo.prototype.method.call(this, arg1, arg2... argN) + Function.call.apply(Foo.prototype.method, arguments); + }; + + +### Parâmetros formais Formal Parameters and Arguments Indices + +O objeto `arguments` cria funções *getter* e *setter* para suas propriedades, +bem como os parâmetros formais da função. + +Como resultado, alterando o valor de um parâmetro formal também mudará o valor +da propriedade correspondente no objeto `arguments`, e vice versa. + + function foo(a, b, c) { + arguments[0] = 2; + a; // 2 + + b = 4; + arguments[1]; // 4 + + var d = c; + d = 9; + c; // 3 + } + foo(1, 2, 3); + +### Mitos e verdades sobre performance + +A única vez em que o objeto `arguments` não é criado é quando é declarado como um nome dentro de uma função +ou declarado como um de seus parâmetros formais. Não importa se ele é usado ou não. + +Ambos *getters* e *setters* são *sempre* criados; desta maneira, usá-los não causa impacto +de performance, especialmente não em código do mundo real, onde existe mais de um simples +acesso às propriedades do objeto `arguments`. + +> **Nota ES5:** Estes *getters* e *setters* não são criados no strict mode. + +Entretando, existe um caso em que a performance é drasticamente reduzida +em engines modernas de JavaScript. Este caso é o uso de `arguments.callee` + + function foo() { + arguments.callee; // Faça alguma coisa com os objeto deta função + arguments.callee.caller; // e o calling do objeto da função + } + + function bigLoop() { + for(var i = 0; i < 100000; i++) { + foo(); // Would normally be inlined... + } + } + +No código acima, `foo` +In the above code, `foo` can no longer be a subject to [inlining][1] since it +needs to know about both itself and its caller. +Isto não somente acaba com possíveis ganhos de performance que resultariam de inlining, +mas também quebram o encapsulamento pois a função agora depende de uma chamada específica de contexto. + +O uso de `arguments.callee` é **fortemente desencorajado**. + +> **Nota ES5:** No strict mode, `arguments.callee` lança `TypeError` uma vez que +> se tornou obsoleto. + +[1]: http://en.wikipedia.org/wiki/Inlining + + diff --git a/doc/ptbr/function/closures.md b/doc/ptbr/function/closures.md new file mode 100644 index 00000000..cdf8fd30 --- /dev/null +++ b/doc/ptbr/function/closures.md @@ -0,0 +1,83 @@ +## Closures e Referências + +Uma das caracterísricas mais poderosas do JavaScript é a possibilidade de usar *closures*. Quando usamos closures, definimos que um escopo **sempre** poderá acessar o escopo externo no qual foi definido. Uma vez que a única concepção de escopo em JavaScripe é [function scope](#function.scopes), todas as funções, por default, agem como closures. + +### Emulando variáveis privadas + + function Counter(start) { + var count = start; + return { + increment: function() { + count++; + }, + + get: function() { + return count; + } + } + } + + var foo = Counter(4); + foo.increment(); + foo.get(); // 5 + +Aqui, `Counter` retorna **duas** closures: a função 'increment' bem como a função 'get'. Ambas as funções mantêm uma **referência** ao escopo de 'Counter' e, portanto, sempre mantêm o acesso à variável 'count' definida naquele escopo. + +### Por que variáveis privadas funcionam + +Uma vez que não é possível referenciar ou atribuir escopos em JavaScript, **não** existe uma maneira de acessar a variável 'count' por fora. A única maneira de interagir com a variável é através das duas closures. + + var foo = new Counter(4); + foo.hack = function() { + count = 1337; + }; + +O código acima **não** irá mudar a variável 'count' no escopo de 'Counter', uma vez que 'foo.hack' não foi definido **naquele** escopo. Neste caso, uma variável 'global' 'count' será criada ou substituida. + +### Closures dentro de laços + +Um erro comum é utilizar closures dentro de laços, como se elas copiassem o valor da variável de indexação do laço. + + for(var i = 0; i < 10; i++) { + setTimeout(function() { + console.log(i); + }, 1000); + } + +O exemplo acima **não** retornará os números '0' até '9', mas os número '10' dez vezes. + +A função *anônima* mantêm uma **referência** para 'i'. No momento em que 'console.log' é chamado, 'o laço for' já encerrou a execução, e o valor '10' está atrbuído em 'i'. + +Com a finalidade de se obter o comportamento esperado, é necessário criar uma **cópia** do valor de 'i'. + +### Evitando problemas de referência + +Com a finalidade de copiar o valor da variável de indexação do laço, a melhor opção é utilizar um [wrapper anônimo](#function.scopes). + + for(var i = 0; i < 10; i++) { + (function(e) { + setTimeout(function() { + console.log(e); + }, 1000); + })(i); + } + +A função anônima será chamada imediatamente com 'i' como seu primeiro argumento e receberá uma cópia do **valor** de 'i' como parâmetro de 'e'. + +A função anônima que é passada para o 'setTimeout' agora possui uma referência a 'e', cujo os valores **não** são modificados pelo laço. + +Não existe outra maneira de se obter este resultado, que não seja retornando uma função do wrapper anônimo que terá, então, o mesmo comportamento que o código acima. + + for(var i = 0; i < 10; i++) { + setTimeout((function(e) { + return function() { + console.log(e); + } + })(i), 1000) + } + +Há ainda uma outra maneira, usando .bind, que pode ligar argumentos e um contexto'this' a uma função. Isto se comporta como o código acima + + for(var i = 0; i < 10; i++) { + setTimeout(console.log.bind(console, i), 1000); + } diff --git a/doc/ptbr/function/constructors.md b/doc/ptbr/function/constructors.md new file mode 100644 index 00000000..26abfedf --- /dev/null +++ b/doc/ptbr/function/constructors.md @@ -0,0 +1,115 @@ +## Construtores + +Construtores em JavaScript ainda são diferentes de muitas outras linguagens. +Qualquer chamada a uma função que seja precedida pela palavra-chave `new` age como um cosntrutor. + +Dentro do construtor - a função chamada - o valor de `this` se refere ao objeto recém criado. +O [prototype](#object.prototype) deste **novo** objeto é definido como o `prototype` do objeto da função que foi +invocada como construtor. + +Se a função chamada não possui um `return` statement explícito, então implicitamente +retornará o valor de `this` - o novo objeto. + + function Foo() { + this.bla = 1; + } + + Foo.prototype.test = function() { + console.log(this.bla); + }; + + var test = new Foo(); + +O código acima chama `Foo` como construtor e define o `prototype` do objeto recém criado +como `Foo.prototype`. + +No caso de um `return` statement explícito, a função retorna o valor +especificado pelo statement, mas **somente** se o valor de retorno for um `Object`. + + function Bar() { + return 2; + } + new Bar(); // um novo objeto + + function Test() { + this.value = 2; + + return { + foo: 1 + }; + } + new Test(); // o objeto retornado + +Quando a palavra-chave `new` é omitida, a função **não** retornará o novo objeto. + + function Foo() { + this.bla = 1; // esta definida no escopo global do objeto + } + Foo(); // undefined + +Enquanto que o exemplo acima pareça funcionar em alguns casos, devido +a maneira como [`this`](#function.this) funciona em JavaScript, o *objeto global* +será usado como valor do `this`. + +### Fábricas + +A fim de omitir a palavra-chave `new`, o construtor da função deve retornar um valor explicitamente. + + function Bar() { + var value = 1; + return { + method: function() { + return value; + } + } + } + Bar.prototype = { + foo: function() {} + }; + + new Bar(); + Bar(); + +Ambas as chamadas a `Bar` retornam a mesma coisa, um objeto recém criado +que tem a propriedade chamada `method`, que é uma [Closure](#function.closures). + +Deve-se perceber que a chamada `new Bar()` **não** afeta o prototype do objeto retornado. +Enquanto o prototype é definido no objeto recém criado, `Bar` nunca retornará um novo objeto. + +No exemplo acima, não existe diferença funcional entre o uso ou não de `new`. + +### Criando novos objetos por fábricas + +É recomendado **não** usar `new` pois eventual o esquecimento de seu uso +pode levar à defeitos. + +A fim de criar um novo objeto, deve-se utilizar uma fábrica e construir o novo objeto dentro desta fábrica. + + function Foo() { + var obj = {}; + obj.value = 'blub'; + + var private = 2; + obj.someMethod = function(value) { + this.value = value; + } + + obj.getPrivate = function() { + return private; + } + return obj; + } + +Enquanto que o código acima previne defeitos decorrentes do esquecimnto da palavra-chave `new` +e certamente utiliza-se de [private variables](#function.closures) de forma mais fácil, este apresenta algumas desvantagens: + + 1. Utiliza mais memória desde que os objetos criados **não** compartilham métodos em um prototype. + 2. A fim de implementar herença, a fábrica precisa copiar todos os métodos de um outro objeto ou colocar o outro objeto no prototype do novo objeto. + 3. Quebrar a cadeia prototype somente por causa de esquecer eventualmente o `new` vai contra o que é proposto pela linguagem. + +### Conclusão + +Enquanto que a omissão do `new` origine defeitos, **não** é certamente uma razão para +quebrar a estrura prototype como um todo. No final, a melhor solução é sempre a que se adequa às necessidades de cada projeto. +O importante é utilizar de forma **consistente** o modelo de criação de objetos escolhido. + diff --git a/doc/ptbr/function/general.md b/doc/ptbr/function/general.md new file mode 100644 index 00000000..dc002e8f --- /dev/null +++ b/doc/ptbr/function/general.md @@ -0,0 +1,46 @@ +## Declaração de funções e expressões + +Funções em JavaScript são objetos de primeira classe. Isto significa que elas +podem ser tratadas como qualquer outro tipo. Um uso muito comum desta característica é +o de passar uma *função anônima* como uma callback para outra, talvez uma função assíncrona. + +### A declaração `function` + + function foo() {} + +A função acima sofrerá [hoisting](#function.scopes) antes que a execução do programa se inicie; assim, +ela estará disponível em *todo* o escopo em que foi *definida*, até mesmo se for chamada antes de ter +sido definida no código. + + foo(); // Funciona pois foo foi elevada para o topo do escopo + function foo() {} + +### A expressão `function` + + var foo = function() {}; + +Este exemplo atribui uma função sem nome e *anônima* à variável `foo`. + + foo; // 'undefined' + foo(); // dispara TypeError + var foo = function() {}; + +Devido ao fato de que `var` é uma declaração que eleva a definição da variável `foo` ao topo do escopo, esta sofrerá hoist e `foo` estará declarado logo que o script for executado. + +Como atribuições só ocorrem em tempo de execução, o valor default de `foo` +será [undefined](#core.undefined) antes que o código seja executado. + +### Expressão de uma função nomeada + +Outro caso especial é a atribuição de funções nomeadas. + + var foo = function bar() { + bar(); // Funciona + } + bar(); // ReferenceError + +Aqui, `bar` não está disponível fora do escopo, uma vez que a função se encontra atribuída +em `foo`; no entanto, dentro de `bar`, ela esta disponível. Isto ocorre devido ao fato de +como o [name resolution](#function.scopes) funciona em JavaScript, o nome da função está *sempre* +disponível no escopo local da própria função. + diff --git a/doc/ptbr/function/scopes.md b/doc/ptbr/function/scopes.md new file mode 100644 index 00000000..0bcd99d6 --- /dev/null +++ b/doc/ptbr/function/scopes.md @@ -0,0 +1,225 @@ +## Escopos e Namespaces + +Embora o JavaScript lide bem com a sintaxe de duas chaves para definir blocos, ele **não** oferece suporte a escopos em blocos; por isso, +todo o restante da linguagem é definido em *escopo de função*. + + function test() { // define escopo + for(var i = 0; i < 10; i++) { // não define escopo + // count + } + console.log(i); // 10 + } + +> **Nota:** Quando não usado em um assignment, em um statement return ou como um argumento de função, +> a notação `{...}` será interpretada como um block statement e **não** como um objeto literal. +> Isto, em conjunto com a [inserção automática de ponto-e-vírgula](#core.semicolon), pode levar à erros sutis. + +Também não existem namespaces distintos em JavaScript, o que significa que tudo é +automaticamente definido em um namespace *globalmente compartilhado*. + +Cada vez que uma variável é referenciada, o JavaScript vai percorrer toda a hierarquia +de escopos até encontrá-la. Caso ele alcance o escopo global e ainda não tenha encontrado +a variável, ele lançará um `ReferenceError`. + +### A queda das variáveis globais + + // script A + foo = '42'; + + // script B + var foo = '42' + +O dois scripts acima **não** têm o mesmo efeito. O Script A define uma +variável chamada `foo` no escopo *global*, e o Script B define `foo` no +escopo *atual*. + +Novamente, isto **não** é *mesma coisa*: emitir o uso de `var` tem várias implicações. + + // escopo global + var foo = 42; + function test() { + // escopo local + foo = 21; + } + test(); + foo; // 21 + +Deixando o statement `var` de fora da função `test` faz com que o valor de `test` seja sobrescrito. +Enquanto que à primeira vista isto não pareça um problema, um script com milhares de linhas de código +que não utiliza `var` apresenta erros horríveis e bugs difíceis de serem detectados. + + // escopo global + var items = [/* uma lista qualquer */]; + for(var i = 0; i < 10; i++) { + subLoop(); + } + + function subLoop() { + // escopo de subLoop + for(i = 0; i < 10; i++) { // esquecendo do var statement + // faça algo incrível! + } + } + +O loop externo terminará depois da primeira chamada para `subLoop`, uma vez que `subLoop` +sobrescreve o valor global `i`. Utilizar `var` no segundo `for` loop evitaria facilmente este problema. +O `var` statement **nunca** pode ser esquecido a não ser que o *efeito desejado* seja afetar o escopo externo. + +### Variáveis locais + +A única fonte de variáveis locais em JavaScript são parâmetros de [função](#function.general) +e variáveis declaradas via `var` statement. + + // escopo global + var foo = 1; + var bar = 2; + var i = 2; + + function test(i) { + // escopo local da função test + i = 5; + + var foo = 3; + bar = 4; + } + test(10); + +Enquanto que `foo` e `i` são variáveis locais dentro do escopo da função `test`, +a atribuição de `bar` irá substituir a variável global com o mesmo nome. + +### Hoisting + +Javascript **eleva** declarações. Isto quer dizer que ambas declarações `var` +e `function` serão movidas para o topo do escopo ao qual pertencem. + + bar(); + var bar = function() {}; + var someValue = 42; + + test(); + function test(data) { + if (false) { + goo = 1; + + } else { + var goo = 2; + } + for(var i = 0; i < 100; i++) { + var e = data[i]; + } + } + +O código acima é modificado antes mesmo que seja executado. O JavaScript move + todos as declarações `var` assim como as de `function`, para o topo +do escopo mais próximo. + + // declarações var são movidas aqui + var bar, someValue; // default para 'undefined' + + // as declarações de função também são movidas + function test(data) { + var goo, i, e; // escopo de bloco ausente move essas variáveis p/ cá + if (false) { + goo = 1; + + } else { + goo = 2; + } + for(i = 0; i < 100; i++) { + e = data[i]; + } + } + + bar(); // falha com um TypeError uma vez que bar continua 'undefined' + someValue = 42; // atribuições não são afetadas pelo hoisting + bar = function() {}; + + test(); + +A falta de delimitação de um escopo não somente moverá `var` statements para fora de loops + e seus blocos, isto também fará com que os testes de determinados `if` se tornem não-intuitivos. + + No código original, embora o `if` statement pareça modificar a *variável global* + `goo`, ele modifica a *variável local* - depois que hoisting foi aplicado. + +Por desconhecer o *hoisting*, pode-se suspeitar que o código abaixo lançaria um +`ReferenceError`. + + // verifique se SomeImportantThing já foi inicializado + if (!SomeImportantThing) { + var SomeImportantThing = {}; + } + +Mas é claro, isto funciona devido ao fato de que `var` statement é movido para o topo +do *escopo global*. + + var SomeImportantThing; + + // outro código pode inicializar SomeImportantThing aqui, ou não + + // tenha certeza de que isto foi inicializado + if (!SomeImportantThing) { + SomeImportantThing = {}; + } + +### Ordem da Resolução de Nomes + +Todos os escopos em JavaScript, incluindo o *escopo global*, possuem o [`this`](#function.this) + o qual faz referência ao *objeto atual*. + +Escopos de funções também possuem o [`arguments`](#function.arguments), o qual contêm +os argumentos que foram passados para a função. + +Por exemplo, ao tentar acessar a variável denominada `foo` dentro do escopo de uma função, JavaScript irá +procurar pela variável na seguinte ordem: + + 1. No caso de haver `var foo` statement no escopo atual, use-a. + 2. Se um dos parâmetros é denominado `foo`, use-o. + 3. Se a própria função é denominada `foo`, use-a. + 4. Vá para o escopo externo mais próximo e inicie do **#1**. + +> **Nota:** Dispor de um parâmetro denominado `arguments` irá **previnir** a criação +> do objeto default `arguments`. + +### Namespaces + +Um problema comum relacionado ao fato de dispor de apenas um namespace global é +a probabilidade de esbarrar com problemas onde nomes de variáveis coincidem. Em JavaScript, +este problema pode ser facilmente evitado com a ajuda de *wrappers anônimos*. + + (function() { + // um "namespace" autocontido + + window.foo = function() { + // closure exposta + }; + + })(); // execute a função imediatamente + + +Funções sem nome são consideradas [expressões](#function.general); a fim de ser referênciável, +elas devem ser avaliadas. + + ( // avalie a função dentro dos parênteses + function() {} + ) // e retorne o objeto de função + () // chama o resultado da avaliação + +Existem outras maneiras para avaliar e chamar diretamente a expressão da função a qual, +enquanto que diferentes em sintaxe, comportam-se da mesma maneira. + + // Alguns outros estilos para invocar diretamente ... + !function(){}() + +function(){}() + (function(){}()); + // e assim por diante... + +### Conclusão + +É recomendado sempre utilizar um *wrapper anônimo* para encapsular código em seu +próprio namespace. Isto não é somente uma maneira de se proteger contra conflitos de nomes, +como também contribui para melhor modularização de programas. + +Adicionalmente, o uso de variáveis globais é considerado **uma prática ruim**. **Qualquer** +uso delas indica código mal escrito que tende à apresentar erros e apresenta manutenção complexa. + diff --git a/doc/ptbr/function/this.md b/doc/ptbr/function/this.md new file mode 100644 index 00000000..6f8c45d9 --- /dev/null +++ b/doc/ptbr/function/this.md @@ -0,0 +1,108 @@ +## Como funciona o `this` + +JavaScript tem uma concepção diferente sobre a que a palavra reservada `this` se refere da maioria das outras linguagens de programação. Existem exatamente **cinco** diferentes maneiras as quais os valores de `this` podem ser referenciados na linguagem. + +### O escopo Global + + this; + +Quando usando `this` no escopo global, ele simplesmente estará apontando para o objeto *global*. + + +### Chamando uma função + + foo(); + +Aqui, `this` irá referenciar novamente o objeto *global*. + +> **Nota ES5:** No strict mode, global **não existe**. +> neste caso, `this` receberá como valor `undefined`. + +### Chamando um método + + test.foo(); + +Neste exemplo, `this` irá referenciar `test`. + +### Chamando um construtor + + new foo(); + +Uma chamada de função que é precedida pela palavra chave `new` age como +um [construtor](#function.constructors). Dentro da função, `this` irá se referir +a um objeto *recém criado*. + +### Referência explícita do `this` + + function foo(a, b, c) {} + + var bar = {}; + foo.apply(bar, [1, 2, 3]); // array will expand to the below + foo.call(bar, 1, 2, 3); // results in a = 1, b = 2, c = 3 + +Quando utiliza-se os métodos `call` ou `apply` de `Function.prototype`, o valor de +`this` dentro da função chamada irá referenciar **explicitamente** o primeiro argumento +correspondente na chamada da função. + +Como resultado, no exemplo anterior o *escopo original do método* **não** é aplicado, e `this` +dentro de `foo` irá referenciar `bar`. + +> **Nota:** `this` **não** pode ser utilizado para referenciar o objeto dentro de um `Object` lietral. +> Logo `var obj = {me: this}` **não** irá resultar em `me` apontando para +> `obj`, uma vez que `this` só pode ser referenciado em dos cinco casos aqui apresentados. + +### Erros comuns + +Embora a maioria destes casos façam sentido, o primeiro pode ser considerado +como um engano de concepção da linguagem, já que **nunca** se mostrou útil. + + Foo.method = function() { + function test() { + // this referencia o objeto global + } + test(); + } + +Um erro comum é achar que `this` dentro de `test` referencia `Foo`; enquanto que, na realidade + **não é isto que acontece**. + +Com a finalidade de acessar `Foo` de dentro de `test`, é necessário instanciar +uma variável global dentro do método para se referir à `Foo`. + + Foo.method = function() { + var that = this; + function test() { + // Utilize that no lugar de this aqui + } + test(); + } + +`that` trata-se de uma variável normal, porém é normalmente utilizada para referências externas de `this`. +Quando combinadas com [closures](#function.closures), também podem ser utilizadas para repassar `this` como valor. + +### Atribuindo métodos + +Outra coisa que **não** funciona em JavaScript é function aliasing, ou seja, +**atribuir** um método a uma variável. + + var test = someObject.methodTest; + test(); + +Devido ao primeiro caso, `test` se comportará como uma chamada de função; como consequencia, +o `this` dentro do método não apontará para `someObject`. + +Enquanto que realizar binding do `this` pareça uma idéia ruim, no fundo, é o que faz a +[herança prototypal](#object.prototype) funcionar. + + function Foo() {} + Foo.prototype.method = function() {}; + + function Bar() {} + Bar.prototype = Foo.prototype; + + new Bar().method(); + +Quando os métodos da instância de `Bar` são chamados, o `this` faz referência +àquela mesma instância. + + diff --git a/doc/ptbr/index.json b/doc/ptbr/index.json new file mode 100644 index 00000000..e7b22d3f --- /dev/null +++ b/doc/ptbr/index.json @@ -0,0 +1,69 @@ +{ + "title": "JavaScript Garden", + "langTitle": "JavaScript Garden em Português", + "description": "Um guia pelas vantagens e desvantagens do JavaScript.", + "sections": [ + { + "title": "Introdução", + "dir": "intro", + "articles": ["index"] + }, + { + "title": "Objetos", + "dir": "object", + "articles": [ + "general", + "prototype", + "hasownproperty", + "forinloop" + ] + }, + { + "title": "Funções", + "dir": "function", + "articles": [ + "general", + "this", + "closures", + "arguments", + "constructors", + "scopes" + ] + }, + { + "title": "Arrays", + "dir": "array", + "articles": [ + "general", + "constructor" + ] + }, + { + "title": "Tipos", + "dir": "types", + "articles": [ + "equality", + "typeof", + "instanceof", + "casting" + ] + }, + { + "title": "Core", + "dir": "core", + "articles": [ + "eval", + "undefined", + "semicolon", + "delete" + ] + }, + { + "title": "Outros assuntos", + "dir": "other", + "articles": [ + "timeouts" + ] + } + ] +} diff --git a/doc/ptbr/intro/index.md b/doc/ptbr/intro/index.md new file mode 100644 index 00000000..ecba225b --- /dev/null +++ b/doc/ptbr/intro/index.md @@ -0,0 +1,38 @@ +## Introdução + +**JavaScript Garden** é uma coletânea crescente que documenta as peculiaridades da linguagem de programação JavaScript. Nela você encontra recomendações para escapar dos erros comuns aos mais sutís, bem como de problemas de desempenho e práticas ruins, que programadores novatos podem acabar encontrando enquanto se aprofundam na linguagem. + +JavaScript Garden **não** tem como propósito te ensinar à programar em JavaScript. Conhecimento prévio da linguagem é fortemente recomendado para que você entenda o conteúdo dos tópicos abordados neste guia. A fim de aprender as noções básicas da linguagem, por favor, consulte o excelente [guia][1] disponível na Mozilla Developer Network. + +## Os autores + +Este guia é fruto do trabalho de dois excelentes usuários do [Stack Overflow][2], [Ivo Wetzel][3] +(Conteúdo) e [Zhang Yi Jiang][4] (Design). + +É mantido atualmente por [Tim Ruffles](http://truffles.me.uk). + +## Contribuidores + +- São muitos para serem listados, [veja a lista completa clicando aqui](https://github.com/BonsaiDen/JavaScript-Garden/graphs/contributors). + + +## Hospedagem + +JavaScript Garden está hospedado no GitHub, porém [Cramer Development][7] nos apoia com um espelho em [JavaScriptGarden.info][8]. + +## Licença + +JavaScript Garden está publicado sob a [licença MIT][9] e hospedado no [GitHub][10]. Caso você encontre defeitos ou erros de digitação, por favor [registre o problema][11] ou realize um pull request no repositório. Você também pode nos encontrar na [sala de JavaScript][12] no chat do Stack Overflow. + +[1]: https://developer.mozilla.org/en/JavaScript/Guide +[2]: http://stackoverflow.com/ +[3]: http://stackoverflow.com/users/170224/ivo-wetzel +[4]: http://stackoverflow.com/users/313758/yi-jiang +[5]: https://github.com/caio +[6]: https://github.com/blixt +[7]: http://cramerdev.com/ +[8]: http://javascriptgarden.info/ +[9]: https://github.com/BonsaiDen/JavaScript-Garden/blob/next/LICENSE +[10]: https://github.com/BonsaiDen/JavaScript-Garden +[11]: https://github.com/BonsaiDen/JavaScript-Garden/issues +[12]: http://chat.stackoverflow.com/rooms/17/javascript diff --git a/doc/ptbr/object/forinloop.md b/doc/ptbr/object/forinloop.md new file mode 100644 index 00000000..e3e09efa --- /dev/null +++ b/doc/ptbr/object/forinloop.md @@ -0,0 +1,41 @@ +## O laço `for in` + +Assim como o operador `in`, o laço `for in` percorre a cadeia prototype quando interage sobre as propriedades de um objeto. + +> **Nota:** O laço `for in` **não** interage sobre propriedades que +> que tenham o atributo `enumerable` configurado como `false`; por exemplo, a propriedade `length` de um array. + + // Poluindo o Object.prototype + Object.prototype.bar = 1; + + var foo = {moo: 2}; + for(var i in foo) { + console.log(i); // retorna ambos bar e moo + } + +Uma vez que não é possível alterar o comportamento do laço `for in` por si só, faz-se necessário filtrar as propriedades do objeto durante o ciclo de repetição do laço; isso é feito usando o método [`hasOwnProperty`](#object.hasownproperty) do `Object.prototype`. + +> **Nota:** Uma vez que o `for in` percorre toda a cadeia prototype, +> cada camada a mais na herança do objeto deixa a execução do laço mais lenta. + +### Utilizando `hasOwnProperty` como filtro + + // o mesmo foo utilizado anteriormente + for(var i in foo) { + if (foo.hasOwnProperty(i)) { + console.log(i); + } + } + +Esta é única forma correta de usar. Devido ao uso de `hasOwnProperty`, o exemplo **só** irá retornar `moo`. Quando `hasOwnProperty` é deixado de lado, o código fica propenso a erros nos casos em que o prototype - por exemplo `Object.prototype`- tenha sido estendido. + +Um framework largamente utilizado que estende o `Object.prototype` é [Prototype][1]. +Quando este framework é utilizado, laços `for in` que não utilizam +`hasOwnProperty` ficam desprotegidos contra erros. + +### Conclusão + +Recomenda-se utilizar `hasOwnProperty` **sempre**. Nunca faça pressuposições sobre o ambiente em que o código está sendo executado, ou se os prototypes nativos foram estendidos ou não. + +[1]: http://www.prototypejs.org/ + diff --git a/doc/ptbr/object/general.md b/doc/ptbr/object/general.md new file mode 100644 index 00000000..a5e88626 --- /dev/null +++ b/doc/ptbr/object/general.md @@ -0,0 +1,83 @@ +## Propriedades e manipulação de objetos + +Tudo em JavaScript se comporta como um objeto, com apenas duas exceções que são +[`null`](#core.undefined) e [`undefined`](#core.undefined). + + false.toString(); // 'false' + [1, 2, 3].toString(); // '1,2,3' + + function Foo(){} + Foo.bar = 1; + Foo.bar; // 1 + +Um equívoco muito comum é a idéia de que números não podem ser manipulados como objetos. O parser do JavaScript analisa a *notação de ponto* como ponto flutuante de um número. + + 2.toString(); // raises SyntaxError + +Existem duas soluções para contornar este problema e permtir que números se comportem como objetos. + + 2..toString(); // o segundo ponto é reconhecido corretamente + 2 .toString(); // perceba o espaço deixado à esquerda do ponto + (2).toString(); // 2 é interpretado primeiro + +### Objetos como tipo de dados + +Em JavaScript, Objetos podem também ser utilizados como [*Hashmaps*][1]; eles consistem principalmente de propriedades nomeadas, que apontam para valores. + +Usando um objeto literal - notação do tipo `{}`- é possível criar um objeto simples. Este novo objeto [herda](#object.prototype) de `Object.prototype` e não possui [propriedades próprias](#object.hasownproperty) definidas. + + var foo = {}; // um novo objeto vazio + + // um novo objeto com uma propriedade 'test' populada com o valor 12 + var bar = {test: 12}; + +### Acessando propriedades + +As propriedades de um objeto podem ser acessadas de duas maneiras, através da notação de ponto ou da notação de colchete. + + var foo = {name: 'kitten'} + foo.name; // kitten + foo['name']; // kitten + + var get = 'name'; + foo[get]; // kitten + + foo.1234; // Erro de sintaxe + foo['1234']; // funciona + +Ambas as notações trabalham de forma quase idêntica, com a única diferença de que o colchete permite configuração dinâmica de propriedades e uso de propriedades nomeadas que de outra maneira levaria à erros de sintaxe. + +### Removendo propriedades + +A única maneira de remover uma propriedade de um objeto é através do operador `delete`; definir uma propriedade como `undefined` ou `null` somente apaga o valor associado com tal propriedade, mas não remove a *key*. + + var obj = { + bar: 1, + foo: 2, + baz: 3 + }; + obj.bar = undefined; + obj.foo = null; + delete obj.baz; + + for(var i in obj) { + if (obj.hasOwnProperty(i)) { + console.log(i, '' + obj[i]); + } + } + +O código acima retorna tanto `bar undefined` quanto`foo null` - somente `baz` foi removido e, portanto, não saiu no output. + +### Notações de Keys + + var test = { + 'case': 'I am a keyword, so I must be notated as a string', + delete: 'I am a keyword, so me too' // dispara SyntaxError + }; + +Propriedades de objetos podem ser tanto representadas como caracteres simples bem como strings. Devido a outro engano do parser do JavaScript, o exemplo acima irá retornar `SyntaxError` remetendo ao ECMAScript 5. + +Este erro decorre do fato de que 'apagar' é uma *palavra reservada*; por consequencia, deve ser representada como uma *string literal* a fim de garantir a interpretação correta pelas antigas engines de JavaScript. + +[1]: http://en.wikipedia.org/wiki/Hashmap + diff --git a/doc/ptbr/object/hasownproperty.md b/doc/ptbr/object/hasownproperty.md new file mode 100644 index 00000000..2ff0589f --- /dev/null +++ b/doc/ptbr/object/hasownproperty.md @@ -0,0 +1,56 @@ +## `hasOwnProperty` + +Para verificar se uma propriedade está definida no **próprio** objeto e não em outro lugar +da sua [cadeia prototype](#object.prototype), é necessário utilizar o método +`hasOwnProperty` o qual todos os objetos herdam de `Object.prototype`. + +> **Nota:** **Não** é sufuciente verificar se uma propriedade é `undefined`. +> A propriedade pode muito bem existir, porém acontece de seu valor só ser +> `undefined`. + +`hasOwnProperty` é a única coisa em JavaScript a qual lida com propriedades e **não** percorre a cadeia prototype. + + // Poluindo Object.prototype + Object.prototype.bar = 1; + var foo = {goo: undefined}; + + foo.bar; // 1 + 'bar' in foo; // true + + foo.hasOwnProperty('bar'); // false + foo.hasOwnProperty('goo'); // true + +Somente `hasOwnProperty` irá retornar o resultado correto e esperado; isto é +essencial quando se interage sobre propriedades de qualquer objeto. **Não** existe +outra maneira de verificar propriedades que não estejam definidas no próprio objeto, mas +em outro lugar na cadeia prototype. + +### `hasOwnProperty` como propriedade + +JavaScript não protege o nome do propriedade `hasOwnProperty`; assim, se +existe a possibilidade de algum objeto possuir uma propriedade com este mesmo nome, +torna-se necessário utilizar um `hasOwnProperty` **externo** a fim de obter resultados corretos. + + var foo = { + hasOwnProperty: function() { + return false; + }, + bar: 'Here be dragons' + }; + + foo.hasOwnProperty('bar'); // sempre retorna false + + // Utiliza hasOwnProperty de outro objeto e o instancia com 'this' apontado para foo + ({}).hasOwnProperty.call(foo, 'bar'); // true + + // Também é possível utilizar hasOwnProperty do Object + // prototype para este fim + Object.prototype.hasOwnProperty.call(foo, 'bar'); // true + + +### Conclusão + +O método é a **única** maneira confiável `hasOwnProperty` para verificar a existência da propriedade em um objeto. +É recomendado que `hasOwnProperty` seja utilizado em **cada** interação de um [laço `for in`](#object.forinloop) +a fim de evitar erros de extensão do [prototype](#object.prototype). + diff --git a/doc/ptbr/object/prototype.md b/doc/ptbr/object/prototype.md new file mode 100644 index 00000000..c9411640 --- /dev/null +++ b/doc/ptbr/object/prototype.md @@ -0,0 +1,109 @@ +## Prototype + +JavaScript não dispõe de nenhum modelo clássico de herança; em vez disso, ele +faz uso do modelo *prototypal*. + +Enquanto isto é considerado muitas vezes como sendo um dos pontos fracos do JavaScript, o modelo de herança prototypal é de fato muito mais poderoso do que o modelo clássico. +Por exemplo, isto torna relativamente trivial construir um modelo clássico +com base no modelo prototypal, enquanto que o contrário se verifica como uma tarefa mais difícil. + +JavaScript é a única linguagem amplamente utilizada que apresenta um modelo de herança do tipo prototypal, +por isso pode levar algum tempo até que você se ajuste às diferenças entre os dois modelos. + +A primeira grande diferença é que herança em JavaScript utiliza o conceito de *cadeias prototype*. + +> **Nota:** Usando simplesmente `Bar.prototype = Foo.prototype` resultará em ambos os objetos +> compartilhando **o mesmo** prototype. Portanto, as alterações no prototype de um dos objetos +> também irá afetar o prototype do outro, o que na maioria dos casos não é o esperado. + + function Foo() { + this.value = 42; + } + Foo.prototype = { + method: function() {} + }; + + function Bar() {} + + // Apontar Bar's prototype para uma nava instância de Foo + Bar.prototype = new Foo(); + Bar.prototype.foo = 'Hello World'; + + // Tenha certeza de que Bar é o construtor atual + Bar.prototype.constructor = Bar; + + var test = new Bar(); // criar uma nova instância de bar + + // A cadeia prototype resultante + test [instance of Bar] + Bar.prototype [instance of Foo] + { foo: 'Hello World', value: 42 } + Foo.prototype + { method: ... } + Object.prototype + { toString: ... /* etc. */ } + +No código acima, o objeto `test` irá herdar de ambos `Bar.prototype` e +`Foo.prototype`; portanto, ele terá acesso à função `method` que foi definida em Foo. +Ele também terá acesso à propriedade `value` da **única** instância de Foo que é seu próprio prototype. +É importante perceber que `new Bar()` não cria uma nova instância de `Foo`, mas +reutiliza aquela associada ao prototype; assim, todas as intâncias `Bar` dividirão a +**mesma** propriedade `value`. + +> **Nota:** **Não** utilize `Bar.prototype = Foo`, uma vez que isto não aponta para o prototype de `Foo`, mas sim para o objeto função `Foo`. +> Assim a cadeia prototype irá percorrer `Function.prototype` e não `Foo.prototype`; +> desse modo, `method` não estará na cadeia prototype. + +### Buscando propriedades + +Ao acessar as propriedades de um objeto, JavaScript irá percorre a cadeia prototype +**até o topo** para encontrar a propriedade solicitada. + +Caso atinja o topo da cadeia - denominada `Object.prototype` - e não encontre +a propriedade especificada, o valor [undefined](#core.undefined) será retornado. + +### A propriedade Prototype + +Enquanto a propriedade prototype é utilizada pela linguagem na contrução de cadeia de prototype, +ainda é possível associar **qualquer** valor dado a ele. No entanto, tipos primitivos serão +ignorados quando associados como prototype. + + function Foo() {} + Foo.prototype = 1; // sem efeito + +Atribuindo objetos, como demonstrado no exemplo anterior, irá funcionar, e permite +a criação dinâmica de cadeias prototype. + +### Performance + +O tempo de pesquisa por propriedades que estão no topo da cadeia prototype +pode ter um impacto negativo na performance, principalmente em código +onde a performance é um fator crítico. Além disso, a busca por propriedades que não existem +também atravessa a cadeia prototype. + +Além disso, ao [interagir](#object.forinloop) com propriedades de um objeto +**cada** propriedade na cadeia prototype será enumerada. + +### Estendendo Prototypes nativos + +Uma prática ruim que é normalmente utilizada é a de estender `Object.prototype` ou qualquer outro prototype construído. + +Esta técnica é denominada [monkey patching][1] e quebra o *encapsulamento*. +Mesmo utilizada por frameworks populars como [Prototype][2], não existe mais razão +para poluir tipos built-in com funcionalidades adicionais *fora de padrão*. + +A **única** boa razão existente para continuar estendendo um built-in prototype +é a de assegurar as novas funcionalidade de engines JavaScript modernas; por exemplo, [`Array.forEach`][3]. + +### Conclusão + +É **essencial** entender o modelo de herança prototypal antes de escrever código complexo +que faço uso do mesmo. Além disso, tome cuidado com o tamanho da cadeia prototype em seu código +e a refatore caso necessário a fim de evitar futuros problemas de performance. A respeito do prototypes nativos, +estes **nunca** devem ser estendidos ao menos que seja para manter a compatibilidade com novas +características do JavaScript. + +[1]: http://en.wikipedia.org/wiki/Monkey_patch +[2]: http://prototypejs.org/ +[3]: https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/forEach + diff --git a/doc/ptbr/other/timeouts.md b/doc/ptbr/other/timeouts.md new file mode 100644 index 00000000..8d522c4e --- /dev/null +++ b/doc/ptbr/other/timeouts.md @@ -0,0 +1,161 @@ +### `setTimeout` e `setInterval` + +Uma vez que JavaScript é assíncrono, é possível agendar a execução de uma função +usando as funções `setTimeout` e `setInterval`. + +> **Nota:** Timeouts **não** fazem parte do Padrão ECMAScript. Eles são +> implementados como parte do [DOM][1]. + + function foo() {} + var id = setTimeout(foo, 1000); // retorna um Number > 0 + +Quando `setTimeout` é chamado, ele retorna o ID do timeout e agenda a execução de `foo` +para **aproximadamente** mil milissegundos no futuro. +`foo` será executado uma **única** vez. + +Dependendo de como a enine JavaScript que está rodando o código resolve o timer, bem como +o fato de que o JavaScript é single threaded e outro código que é executado pode bloquear a +thread, **não há como** garantir a precisão dos intervalos especificados nas chamadas `setTimeout`. + +A função que foi passada como primeiro parâmetro será chamada pelo *objeto global*, o que +significa que o [`this`](#function.this) dentro da função chamada se refere ao objeto global. + + function Foo() { + this.value = 42; + this.method = function() { + // this faz referência ao objeto global + console.log(this.value); // log undefined + }; + setTimeout(this.method, 500); + } + new Foo(); + + +> **Nota:** Como o `setTimeout` espera um **objeto de função** para primeiro parâmetro, um +> erro comum é usar `setTimeout(foo(), 1000)`, que irá usar o +> **o valor retornado** por `foo` e **não** `foo`. Isto é, na maioria das vezes, +> um erro silencioso, visto que neste caso a função retorna `undefined`, logo `setTimeout` **não** +> lançará erro algum. + +### Acumulando chamadas com o `setInterval` + +Enquanto que `setTimeout` somente executa a função uma vez, `setInterval` - como +o nome sugere - irá executar a função a **cada** `X` milisegundos, porém seu uso é +desencorajado. + +Quando um código em execução bloqueia a chamada do timeout, `setInterval` continuará +emitindo chamads para a função em questão. Isto pode, especialmente com intervalos curtos, +resultar em uma pilha de chamadas de função. + + function foo(){ + // algo que bloqueie por 1 segundo + } + setInterval(foo, 1000); + +No código acima, `foo` será chamada uma vez e irá então bloquear a execução por um segundo. + +Enquanto `foo` bloqueia a execução, `setInterval` irá programar mais chamadas para ela. +Em seguida, quando `foo` completar sua execução, existirão **dez** chamadas programadas +para ela aguardando por execução. + +### Lidando com possíveis bloqueios de código + +A solução mais fácil, bem como a mais controlável, é usar `setTimeout` dentro da +própria função. + + function foo(){ + // Algo que bloqueia por um segundo + setTimeout(foo, 1000); + } + foo(); + +Isto não somente encapsula a chamada para `setTimeout`, mas também previne +o acumulo de chamadas e dá controle adicional. `foo` por si só pode decidir +quando rodar novamente ou não. + +### Limpando Timeouts manualmente + +A limpeza de intervalos e timeouts funciona passando o respectivo ID +para `clearTimeout` ou `clearInterval`, dependendo onde a função `set` foi usada primeiro. + + var id = setTimeout(foo, 1000); + clearTimeout(id); + +### Limpando todos os Timeouts + +Como não existe métodos próprios para limpar todos os timeouts e/ou intervalos, +é necessário usar a força bruta para chegar a esta funcionalidade. + + // limpe "todos" os timeouts + for(var i = 1; i < 1000; i++) { + clearTimeout(i); + } + +Mas ainda podem haver timeouts que não serão afetados por este número arbitrário. +Uma outra maneira de fazer isto é considerar que o ID dado a um timeout é +incrementado um a um cada vez que você chama `setTimeout`. + + // limpe "todos" os timeouts + var biggestTimeoutId = window.setTimeout(function(){}, 1), + i; + for(i = 1; i <= biggestTimeoutId; i++) { + clearTimeout(i); + } + +Apesar desta maneira funcionar nos principais navegadores hoje em dia, não está especificado +que os IDs respeitem uma ordem como este, logo esta ordem pode ser variada. Por este motivo, em vez disso +é recomendade manter o controle de todos os IDs de timeouts, de forma que possam ser apagados precisamente. + +### O uso oculto do `eval` + +`setTimeout` e `setInterval` aceitam uma string como primeiro argumento. +Esta funcionalidade **nunca** deve ser utilizada pois internamente faz uso de `eval`. + +> **Nota:** Uma vez que funções timeout **não** são especificadas pelo padrão ECMAScript, a maneira como +> eles interpretam uma string passada pode variar de acordo com a implementação do JavaScript. Por exemplo, JScript +> da Microsoft faz uso do construtor `Function` no lugar do `eval`. + + function foo() { + // será chamada + } + + function bar() { + function foo() { + // nunca será chamada + } + setTimeout('foo()', 1000); + } + bar(); + +Uma vez que `eval` não é chamado [diretamente](#core.eval) neste caso, a string +passada como argumento para `setTimeout` será executada no *escopo global*; assim, ela +não usará a variávle local `foo` do escopo de `bar`. + +Também é recomendado **não** usar uma string para passar argumentos +para a função que será chamada por qualquer uma das funções de timeout. + + function foo(a, b, c) {} + + // NUNCA use isto + setTimeout('foo(1, 2, 3)', 1000) + + // Utilize uma função anônima do lugar + setTimeout(function() { + foo(a, b, c); + }, 1000) + +> **Nota:** Enquanto que é possivel utilizar a sintaxe +> `setTimeout(foo, 1000, a, b, c)`, não é recomendada, pois sua utilização pode levar +> a erros sútis quando utilizadas com [métodos](#function.this). + +### Conclusão + +Uma string **nunca** deve ser usada como parâmetro `setTimeout` ou +`setInterval`. Esta prática é um sinal **claro** de código ruim, quando argumentos precisam ser fornecido para a função que é chamada. +Uma *função anônima* é que deve ser passada para que, em seguida, cuide da chamada. + +Além disso, o uso de `setInterval` deve ser evitado pois seu scheduler não é +bloqueado pela execução do JavaScript. + +[1]: http://en.wikipedia.org/wiki/Document_Object_Model "Document Object Model" + diff --git a/doc/ptbr/types/casting.md b/doc/ptbr/types/casting.md new file mode 100644 index 00000000..d7dc9b3f --- /dev/null +++ b/doc/ptbr/types/casting.md @@ -0,0 +1,67 @@ +## Conversão de tipos + +JavaScript é *fracamente tipado*, logo ele aplica a *coerção de tipos* +**sempre** que possível. + + // Estes retornam true + new Number(10) == 10; // Number.toString() é convertido + // de volta a um número + + 10 == '10'; // Strings são convertidas em Number + 10 == '+10 '; // Mais loucuras com strings + 10 == '010'; // E mais + isNaN(null) == false; // null é convertido em 0 + // que claro não é NaN + + // Estes retornam false + 10 == 010; + 10 == '-10'; + +> **Nota ES5:** Literais Number que começam com um `0` são interpretados como octais +> (Base 8). Suporte à octais para estes literais foi **removido** no modo estrito do ECMAScript. + +A fim de evitar os problemas acima, o uso do [operador de igualdade estrito](#types.equality) +é **fortemente** recomendado. Embora ele evite uma série de problemas comuns, +existem ainda muitas outras questões que surgem do fraco sistema de tipagem do JavaScript. + +### Construtores de tipos nativos + +Os construtores de tipos nativos como `Number` e `String` comportam-se +diferentemente quando utilizados com ou sem a palavra-chave `new`. + + new Number(10) === 10; // False, Object e Number + Number(10) === 10; // True, Number e Number + new Number(10) + 0 === 10; // True, devido à conversão implícita + +Utilizar um tipo nativo como `Number` como construtor iré criar um novo objeto `Number`, +porém omitir a palavra-chave `new` fará com que a função `Number` se comporte como +um conversor. + +Além, passando valores literais ou não-objetos irá resultar em mais coerções +de tipos. + +A melhor opção é converter para um dos três possíveis tipos **de forma explícita**. + +### Convertendo para String + + '' + 10 === '10'; // true + +Prefixando uma string vazia, qualquer valor pode ser facilmente convertido em uma string. + +### Convertendo para Number + + +'10' === 10; // true + +Ao utilizar o operador de soma **unário**, é possível converter um valor para Number. + +### Convertendo para Boolean + +Ao utilizar duas vezes o operador **not**, é possível converter um valor para Boolean. + + !!'foo'; // true + !!''; // false + !!'0'; // true + !!'1'; // true + !!'-1' // true + !!{}; // true + !!true; // true \ No newline at end of file diff --git a/doc/ptbr/types/equality.md b/doc/ptbr/types/equality.md new file mode 100644 index 00000000..709b1186 --- /dev/null +++ b/doc/ptbr/types/equality.md @@ -0,0 +1,70 @@ +## Igualdades e comparações + +JavaScript tem duas maneiras diferentes de comparar a igualdades entre valores de objetos. + +### O operador de igualdade + +O operador de igualdade consiste de dois sinais de igual : `==` + +JavaScript é *fracamente tipado*. Isto que dizer que o operador de igualdade +**induz** tipos ao invés de compará-los. + + "" == "0" // false + 0 == "" // true + 0 == "0" // true + false == "false" // false + false == "0" // true + false == undefined // false + false == null // false + null == undefined // true + " \t\r\n" == 0 // true + +A tabela acima mostra o resultado da coerção de tipos, e isto é principal razão +para que o uso `==` seja amplamente considerado uma má prática. Seu uso introduz defeitos +difíceis de serem rastreados devido às suas complicadas regras de conversão. + +Adicionalmente, também existe um impacto em performance quando a coerção acontece; +por exemplo, é necessário que uma string seja convertida em um número antes que seja comparada +com outro número. + +### O operador de igualdade estrito + +O operador de igualdade estrito consiste de **três** sinais de igual : `===`. + +Ele funciona como o operador de igualdade normal, salvo que o operador de igualdade estrito +**não** realiza coerção de tipos entre seus operandos. + + "" === "0" // false + 0 === "" // false + 0 === "0" // false + false === "false" // false + false === "0" // false + false === undefined // false + false === null // false + null === undefined // false + " \t\r\n" === 0 // false + +Os resultados acima são bastante claros e permitem uma análise objetiva do código. Pode parecer complicar o código até um certo ponto + mas também traz ganhos de performance em casos em que os operandos são de tipos diferentes. + +### Comparando Objetos + +Enquanto que ambos `==` e `===` são denominados operadores de **igualdade**, eles se comportam de +formas diferentes quando pelo menos um de seus operandos é um `Object`. + + {} === {}; // false + new String('foo') === 'foo'; // false + new Number(10) === 10; // false + var foo = {}; + foo === foo; // true + +Aqui, ambos os operadores comparam em função da **identidade** e **não** da igualdade; isto é, +eles vão comparar em função da mesma **instância** do objeto, muito parecido com o `is` do Python +e a comparação de ponteiros em C. + +### Conclusão + +E fortemente recomendado que só se use o operador de ** igualdade estrito**. +Em casos onde a coerção de tipos seja necessária, isto deve ser feito [explicitamente](#types.casting) +e não deve ser deixado para as complicadas regras de coerção da linguagem. + diff --git a/doc/ptbr/types/instanceof.md b/doc/ptbr/types/instanceof.md new file mode 100644 index 00000000..9cbd7561 --- /dev/null +++ b/doc/ptbr/types/instanceof.md @@ -0,0 +1,38 @@ +## O operador `instanceof` + +O operador `instanceof` compara os construtores de seus dois operandos. +Ele é útil somente quando estamos comparando objetos personalizados. Quando utilizado em tipos nativos, +ele é tão inútil quanto [o operador typeof](#types.typeof). + +### Comparando objetos personalizados + + function Foo() {} + function Bar() {} + Bar.prototype = new Foo(); + + new Bar() instanceof Bar; // true + new Bar() instanceof Foo; // true + + // Isto somente define Bar.prototype ao objeto de função Foo, + // mas não à instância atual de Foo + Bar.prototype = Foo; + new Bar() instanceof Foo; // false + +### Utilizando `instanceof` com tipos nativos + + new String('foo') instanceof String; // true + new String('foo') instanceof Object; // true + + 'foo' instanceof String; // false + 'foo' instanceof Object; // false + +Uma coisa importante para perceber aqui é que `instanceof` não funciona em objetos +originados de diferentes contextos de JavaScript (isto é, de diferentes documentos em um +navegador web), uma vez que seus construtores não irão representar exatamente o mesmo objeto. + +### Conclusão + +O operador `instanceof` deve **somente** ser utilizado quando estive lidando +com objetos customizados originados de um mesmo contexto JavaScript. Bem como o operador +[`typeof`](#types.typeof), qualquer outro uso de `instanceof` deve ser **evitado**. + diff --git a/doc/ptbr/types/typeof.md b/doc/ptbr/types/typeof.md new file mode 100644 index 00000000..3f499ee5 --- /dev/null +++ b/doc/ptbr/types/typeof.md @@ -0,0 +1,83 @@ +## O operador `typeof` + +O operador `typeof`(em conjunto com +[`instanceof`](#types.instanceof) é provavelmente a maior falha de design do JavaScript, +por estar **complemente mal implementado**. + +Embora `instanceof` ainda tenha seu uso limitado, `typeof` realmente só possui uma utilidade, +a qual **não** acaba por ser a de verificar o tipo de um objeto. + +> **Nota:** Enquanto que `typeof` possa também ser invocado com uma sintaxe parecida com a de chamada de função, i.e. +> `typeof(obj)`, não se trata de uma chamada de função. Os parênteses se comportam normalmente +> e o valor retornado será usado como o operando do operador `typeof`. +> **Não** existe a função `typeof`. + +### A tabela de tipos em JavaScript + + Value Class Type + ------------------------------------- + "foo" String string + new String("foo") String object + 1.2 Number number + new Number(1.2) Number object + true Boolean boolean + new Boolean(true) Boolean object + new Date() Date object + new Error() Error object + [1,2,3] Array object + new Array(1, 2, 3) Array object + new Function("") Function function + /abc/g RegExp object (function in Nitro/V8) + new RegExp("meow") RegExp object (function in Nitro/V8) + {} Object object + new Object() Object object + +Na tabela acima, *Type* se refere ao valor de retorno do operador `typeof`. +Como pode ser facilmente observado, este valor não é nada consistente. + +O *Class* se refere ao valor interno da propriedade `[[Class]]` de um objeto. + +> **Da especificação:** O valor de `[[Class]]` pode ser +> das seguintes strings. `Arguments`, `Array`, `Boolean`, `Date`, `Error`, +> `Function`, `JSON`, `Math`, `Number`, `Object`, `RegExp`, `String`. + +A fim de se obeter o valor de `[[Class]]`, deve-se utilizar o método +`toString` de `Object.prototype`. + +### A classe de um objeto + +A especificação fornece exatamente uma maneira de acessar o valor de `[[Class]]`, +com o uso de `Object.prototype.toString`. + + function is(type, obj) { + var clas = Object.prototype.toString.call(obj).slice(8, -1); + return obj !== undefined && obj !== null && clas === type; + } + + is('String', 'test'); // true + is('String', new String('test')); // true + +No exemplo acima, `Object.prototype.toString` é chamado enquanto que o valor de [this](#function.this) +é definido como o objeto o qual o valor `[[Class]]` deva ser retornado. + +> **Nota ES5:** Por conveniência o retorno do valor de `Object.prototype.toString` +> para ambos `null` e `undefined` foi **modificado** de `Object` para `Null` e +> `Undefined` no ECMAScript 5. + +### Teste para variáveis não-definidas + + typeof foo !== 'undefined' + +O exemplo acima irá verificar se `foo` foi declarado ou não; apenas +o fato de referênciá-lo poderia resultar em `ReferenceError`. Esta é a única utilidade +real de `typeof`. + +### Conclusão + +A fim de verificar o tipo de um objeto, é fortemente recomendade o uso de +`Object.prototype.toString` pelo motivo de que esta é a única maneira confiável de ser feita. +Como demonstrado na tabela anterior, alguns valores retornados de `typeof` não estão definidos na +especificação; assim, eles podem variar entre implementações. +O uso de `typeof` deve ser evitado, a menos que não se esteja testando se uma variável está ou não definida. + + diff --git a/doc/ru/array/constructor.md b/doc/ru/array/constructor.md index 0bfec314..13f58846 100644 --- a/doc/ru/array/constructor.md +++ b/doc/ru/array/constructor.md @@ -15,7 +15,7 @@ arr[1]; // не определён, undefined 1 in arr; // false, индекс не был установлен -Поведение, которое позволяет изначально установить только размер массива, может пригодиться лишь в нескольких случаях, таких как повторение строк, за счёт чего избегается использование цикла `for loop`. +Поведение, которое позволяет изначально установить только размер массива, может пригодиться лишь в нескольких случаях, таких как повторение строк, за счёт чего избегается использование цикла `for`. new Array(count + 1).join(stringToRepeat); diff --git a/doc/ru/core/delete.md b/doc/ru/core/delete.md new file mode 100644 index 00000000..7db3010b --- /dev/null +++ b/doc/ru/core/delete.md @@ -0,0 +1,88 @@ +## Оператор `delete` + +Если говорить коротко, то JavaScript *невозможно* удалить глобальную переменную, функцию или любой другой объект, которому задан атрибут `DontDelete` . + +### Глобальный код и код функции + +Если переменная или функция определена в глобальной области видимости (scope) или в +[области видимости функции](#function.scopes), это значит что она является +свойством (property) глобального или же Activation объекта. +Подобные свойства имеют набор атрибутов, одним из которых и является +упомянутый ранее `DontDelete`. Объявление переменных и функций в коде +функции или глобально всегда создает свойство с атрибутом `DontDelete`, и поэтому +не может быть удалено. + + // глобальная переменная: + var a = 1; // задается DontDelete + delete a; // false + a; // 1 + + // обычная функция: + function f() {} // задается DontDelete + delete f; // false + typeof f; // "function" + + // переназначение не поможет: + f = 1; + delete f; // false + f; // 1 + +### Явные свойства + +Явно заданные свойство могут быть удалены обычным способом. + + // явно заданные свойства: + var obj = {x: 1}; + obj.y = 2; + delete obj.x; // true + delete obj.y; // true + obj.x; // undefined + obj.y; // undefined + +В примере выше, `obj.x` и `obj.y` могут быть удалены потому что у них не задан +атрибут `DontDelete`. Именно поэтому следующий пример тоже сработает. + + // работает хорошо везде, кроме IE: + var GLOBAL_OBJECT = this; + GLOBAL_OBJECT.a = 1; + a === GLOBAL_OBJECT.a; // true - просто глобальная переменная + delete GLOBAL_OBJECT.a; // true + GLOBAL_OBJECT.a; // undefined + +Здесь мы используем небольшой трюк, чтобы удалить `a`. [`this`](#function.this) здесь +относится к глобальному объекту и мы явно указали удаление переменной `a` как свойства +глобального объекта, что и позволи нам ее удалить. + +Из-за нескольких багов в IE (как минимум 6-8) предыдущий код работать в нем не будет. + +### Аргументы функций и встроенные модули (built-ins) + +Обычным аргументам функций [`arguments` objects](#function.arguments) и +встроенным свойствам также задан атрибут `DontDelete`. + + // аргументы функции и свойства: + (function (x) { + + delete arguments; // false + typeof arguments; // "object" + + delete x; // false + x; // 1 + + function f(){} + delete f.length; // false + typeof f.length; // "number" + + })(1); + +### Host объекты + +Host объект - это объект, предоставляемый окружением. К таким объектам относятся `window`, +`document`, `location` и так далее. +Для host объектов поведение оператора `delete` может быть непредсказуемым. +Согласно спецификации, таким объектам позволено реализовывать любой вид поведения. + +### Заключение + +Оператор `delete` часто обладает непредсказуемым поведением и безопасно использовать +его можно лишь для удаления явно заданных свойств обычных объектов. \ No newline at end of file diff --git a/doc/ru/object/forinloop.md b/doc/ru/object/forinloop.md index 0b097259..3bc5c8d4 100644 --- a/doc/ru/object/forinloop.md +++ b/doc/ru/object/forinloop.md @@ -25,7 +25,7 @@ } } -Это единственная версия правильного использования цикла. Благодаря использованию `hasOwnPropery` будет выведено **только** свойство `moo`. Если же убрать `hasOwnProperty`, код становится нестабилен и могут возникнуть ошибки, особенно если кто-то изменил встроенные прототипы, такие как `Object.prototype`. +Это единственная версия правильного использования цикла. Благодаря использованию `hasOwnProperty` будет выведено **только** свойство `moo`. Если же убрать `hasOwnProperty`, код становится нестабилен и могут возникнуть ошибки, особенно если кто-то изменил встроенные прототипы, такие как `Object.prototype`. Один из самых популярных фреймворков [Prototype][1] как раз этим и славится, и если вы его подключаете, то не забудьте использовать `hasOwnProperty` внутри цикла `for in`, иначе у вас гарантированно возникнут проблемы. diff --git a/doc/ru/object/general.md b/doc/ru/object/general.md index 9490570f..aa5ad534 100644 --- a/doc/ru/object/general.md +++ b/doc/ru/object/general.md @@ -73,7 +73,7 @@ var test = { 'case': 'Я — ключевое слово, поэтому меня надо записывать строкой', - delete: 'Я тоже ключевое слово, так что я' // бросаю SyntaxError + delete: 'Я тоже ключевое слово, так что я' // не является ошибкой, бросает SyntaxError только в версиях ECMAScript ниже 5ой версии }; Свойства объектов могут записываться как явно символами, так и в виде закавыченных строк. В связи с другим упущением в парсере JavaScript, этот код выбросит `SyntaxError` во всех версиях ранее ECMAScript 5. diff --git a/doc/ru/object/hasownproperty.md b/doc/ru/object/hasownproperty.md index d46d7f10..89b950ca 100644 --- a/doc/ru/object/hasownproperty.md +++ b/doc/ru/object/hasownproperty.md @@ -16,7 +16,7 @@ foo.hasOwnProperty('bar'); // false foo.hasOwnProperty('goo'); // true -Только используя `hasOwnProperty` можно гарантировать правильный результат при переборе свойств объекта. И **нет** иного способа для определения свойств, которые определены в *самом* объекте, а не где-то в цепочке его прототипов. +Только используя `hasOwnProperty` можно гарантировать правильный результат при переборе свойств объекта. И **нет** иного способа для определения свойств, которые определены в *самом* объекте, а не где-то в цепочке его прототипов. ### `hasOwnProperty` как свойство @@ -38,4 +38,3 @@ JavaScript **не** резервирует свойство с именем `has ### Заключение **Единственным** способом проверить существование свойства у объекта является использование метода `hasOwnProperty`. При этом рекомендуется использовать этот метод в **каждом** [цикле `for in`](#object.forinloop) вашего проекта, чтобы избежать возможных ошибок с ошибочным заимствованием свойств из [прототипов](#object.prototype) родительских объектов. Также вы можете использовать конструкцию `{}.hasOwnProperty.call(...)` на случай, если кто-то вздумает расширить [прототипы](#object.prototype) встроенных объектов. - diff --git a/doc/ru/object/prototype.md b/doc/ru/object/prototype.md index 7ae8ed99..a8e75129 100644 --- a/doc/ru/object/prototype.md +++ b/doc/ru/object/prototype.md @@ -10,17 +10,19 @@ > **Замечание:** В результате выполнения конструкции `Bar.prototype = Foo.prototype` оба объекта будут делить друг с другом **один и тот же** прототип. Так что изменение прототипа одного из объектов повлечёт за собой изменение прототипа другого и наоборот — вряд ли это окажется тем, чего вы ожидали. +> **Замечание:** Для объявления наследования вместо `Bar.prototype = Object.create(Foo.prototype)` можно воспользоваться конструкций `Bar.prototype = new Foo()`, но у нее есть пару недостатков: 1) как правило требуется унаследовать только методы и свойства прототипа, а не создавать для этого новый объект; 2) создание объекта может требовать обязательные аргументы. + +> **Примечание:** Метод `Object.create` отсутствует в IE8 и ниже, но его легко реализовать созданием своей такой функции или же можно подключить библиотеку для поддержки старых IE [*es5-shim*][5] + function Foo() { this.value = 42; } - Foo.prototype = { - method: function() {} - }; + Foo.prototype.method = function() {} function Bar() {} - // Установим значением прототипа Bar новый экземпляр Foo - Bar.prototype = new Foo(); + // Зададим наследование от Foo + Bar.prototype = Object.create(Foo.prototype); Bar.prototype.foo = 'Hello World'; // Убедимся, что Bar является действующим конструктором @@ -31,7 +33,7 @@ // Цепочка прототипов, которая получится в результате test [instance of Bar] Bar.prototype [instance of Foo] - { foo: 'Hello World' } + { foo: 'Hello World', value: 42 } Foo.prototype { method: ... } Object.prototype @@ -81,4 +83,5 @@ [2]: http://en.wikipedia.org/wiki/Monkey_patch [3]: http://prototypejs.org/ [4]: https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/forEach +[5]: https://github.com/es-shims/es5-shim diff --git a/doc/ru/types/casting.md b/doc/ru/types/casting.md index 89749e48..8e77c79d 100644 --- a/doc/ru/types/casting.md +++ b/doc/ru/types/casting.md @@ -3,8 +3,9 @@ JavaScript — *слабо типизированный* язык, поэтому *преобразование типов* будет применяться **везде**, где возможно. // Эти равенства — истинны - new Number(10) == 10; // Number.toString() преобразуется - // обратно в число + new Number(10) == 10; // объект типа Number преобразуется + // в числовой примитив в результате неявного вызова + // метода Number.prototype.valueOf 10 == '10'; // Strings преобразуется в Number 10 == '+10 '; // Ещё чуток строко-безумия diff --git a/doc/tr/function/scopes.md b/doc/tr/function/scopes.md index d826f1aa..211c45f7 100644 --- a/doc/tr/function/scopes.md +++ b/doc/tr/function/scopes.md @@ -178,7 +178,7 @@ adında bir özel değişken tanımlanmıştır, bu değişken *geçerli nesneyi Fonksiyon kapsamlarında aynı zamanda [`arguments`](#function.arguments) adında bir değişken tanımlanmıştır ve fonksiyonun argümanlarını içerir. -Örnek olarak bir fonksiyon kapsamında `foo` değişkenine eriğildiğinde JavaScript +Örnek olarak bir fonksiyon kapsamında `foo` değişkenine erişildiğinde JavaScript isim çözümlemeyi aşağıdaki sıra ile yapacaktır: 1. Geçerli kapsamda bir `var foo` ifadesi mevcutsa bu kullanılır. diff --git a/doc/tr/object/prototype.md b/doc/tr/object/prototype.md index 1a2d09a1..d8b8522a 100644 --- a/doc/tr/object/prototype.md +++ b/doc/tr/object/prototype.md @@ -39,7 +39,7 @@ yapılmasıdır. // Sonuçta ortaya çıkan prototip zinciri test [bir Bar sınıfı nesnesi] Bar.prototype [bir Foo sınıfı nesnesi] - { foo: 'Hello World' } + { foo: 'Hello World', value: 42 } Foo.prototype { method: ... } Object.prototype diff --git a/doc/zh/function/arguments.md b/doc/zh/function/arguments.md index d6f7f9db..ac6967eb 100755 --- a/doc/zh/function/arguments.md +++ b/doc/zh/function/arguments.md @@ -9,7 +9,7 @@ JavaScript 中每个函数内都能访问一个特别变量 `arguments`。这个 `arguments` 变量**不是**一个数组(`Array`)。 尽管在语法上它有数组相关的属性 `length`,但它不从 `Array.prototype` 继承,实际上它是一个对象(`Object`)。 -因此,无法对 `arguments` 变量使用标准的数组方法,比如 `push`, `pop` 或者 `slice`。 +因此,无法对 `arguments` 变量使用标准的数组方法,比如 `push`、`pop` 或者 `slice`。 虽然使用 `for` 循环遍历也是可以的,但是为了更好的使用数组方法,最好把它转化为一个真正的数组。 ###转化为数组 @@ -93,19 +93,19 @@ JavaScript 中每个函数内都能访问一个特别变量 `arguments`。这个 return [a, arguments[0]]; } var pair = f(17); - assert(pair[0] === 42); - assert(pair[1] === 17); + console.assert(pair[0] === 42); + console.assert(pair[1] === 17); 然而,的确有一种情况会显著的影响现代 JavaScript 引擎的性能。这就是使用 `arguments.callee`。 function foo() { - arguments.callee; // do something with this function object - arguments.callee.caller; // and the calling function object + arguments.callee; // 使用这个函数对象 + arguments.callee.caller; // 以及这个函数对象的调用者 } function bigLoop() { for(var i = 0; i < 100000; i++) { - foo(); // Would normally be inlined... + foo(); // 通常情况会作为内联函数... } } diff --git a/doc/zh/function/closures.md b/doc/zh/function/closures.md index 77f69e4c..df474a65 100755 --- a/doc/zh/function/closures.md +++ b/doc/zh/function/closures.md @@ -3,6 +3,8 @@ 闭包是 JavaScript 一个非常重要的特性,这意味着当前作用域**总是**能够访问外部作用域中的变量。 因为 [函数](#function.scopes) 是 JavaScript 中唯一拥有自身作用域的结构,因此闭包的创建依赖于函数。 +> 译者注:ES2015 中增加了块级作用域。 + ###模拟私有变量 function Counter(start) { @@ -23,7 +25,7 @@ foo.get(); // 5 这里,`Counter` 函数返回两个闭包,函数 `increment` 和函数 `get`。 这两个函数都维持着 -对外部作用域 `Counter` 的引用,因此总可以访问此作用域内定义的变量 `count`. +对外部作用域 `Counter` 的引用,因此总可以访问此作用域内定义的变量 `count`。 ###为什么不可以在外部访问私有变量 @@ -44,13 +46,13 @@ for(var i = 0; i < 10; i++) { setTimeout(function() { - console.log(i); + console.log(i); }, 1000); } 上面的代码不会输出数字 `0` 到 `9`,而是会输出数字 `10` 十次。 -当 `console.log` 被调用的时候,*匿名*函数保持对外部变量 `i` 的引用,此时 `for`循环已经结束, `i` 的值被修改成了 `10`. +当 `console.log` 被调用的时候,*匿名*函数保持对外部变量 `i` 的引用,此时 `for`循环已经结束, `i` 的值被修改成了 `10`。 为了得到想要的结果,需要在每次循环中创建变量 `i` 的**拷贝**。 @@ -61,7 +63,7 @@ for(var i = 0; i < 10; i++) { (function(e) { setTimeout(function() { - console.log(e); + console.log(e); }, 1000); })(i); } @@ -76,8 +78,8 @@ setTimeout((function(e) { return function() { console.log(e); - } - })(i), 1000) + }; + })(i), 1000); } diff --git a/doc/zh/function/general.md b/doc/zh/function/general.md index 964ce094..04414900 100755 --- a/doc/zh/function/general.md +++ b/doc/zh/function/general.md @@ -1,6 +1,6 @@ ##函数声明与表达式 -函数是JavaScript中的一等对象,这意味着可以把函数像其它值一样传递。 +函数是 JavaScript 中的一等对象,这意味着可以把函数像其它值一样传递。 一个常见的用法是把*匿名函数*作为回调函数传递到异步函数中。 ###函数声明 @@ -8,9 +8,9 @@ function foo() {} 上面的方法会在执行前被 [解析(hoisted)](#function.scopes),因此它存在于当前上下文的*任意*一个地方, -即使在函数定义体的上面被调用也是对的。 +即使在函数定义体的上面被调用也是对的。 - foo(); // 正常运行,因为foo在代码运行前已经被创建 + foo(); // 正常运行,因为 foo 在代码运行前已经被创建 function foo() {} ### 函数赋值表达式 @@ -39,5 +39,6 @@ `bar` 函数声明外是不可见的,这是因为我们已经把函数赋值给了 `foo`; 然而在 `bar` 内部依然可见。这是由于 JavaScript 的 [命名处理](#function.scopes) 所致, 函数名在函数内*总是*可见的。 +> **注意: **在 IE8 及 IE8 以下版本浏览器 bar 在外部也是可见的,是因为浏览器对命名函数赋值表达式进行了错误的解析, +> 解析成两个函数 `foo` 和 `bar` -[30]: http://cnblogs.com/sanshi/ diff --git a/doc/zh/function/scopes.md b/doc/zh/function/scopes.md index 898c0574..32fe9370 100755 --- a/doc/zh/function/scopes.md +++ b/doc/zh/function/scopes.md @@ -136,7 +136,7 @@ JavaScript 会**提升**变量声明。这意味着 `var` 表达式和 `function 没有块级作用域不仅导致 `var` 表达式被从循环内移到外部,而且使一些 `if` 表达式更难看懂。 -在原来代码中,`if` 表达式看起来修改了*全部变量* `goo`,实际上在提升规则被应用后,却是在修改*局部变量*。 +在原来代码中,`if` 表达式看起来修改了*全局变量* `goo`,实际上在提升规则被应用后,却是在修改*局部变量*。 如果没有提升规则(hoisting)的知识,下面的代码看起来会抛出异常 `ReferenceError`。 diff --git a/doc/zh/function/this.md b/doc/zh/function/this.md index 0930ef26..eac3ddef 100755 --- a/doc/zh/function/this.md +++ b/doc/zh/function/this.md @@ -9,7 +9,8 @@ JavaScript 有一套完全不同于其它语言的对 `this` 的处理机制。 当在全部范围内使用 `this`,它将会指向*全局*对象。 -> **[译者注][30]:**浏览器中运行的 JavaScript 脚本,这个全局对象是 `window`。 +> **[译者注][30]:**浏览器中运行的 JavaScript 脚本,这个全局对象是 `window`; +> 在 nodejs 环境中运行的 Javascript 脚本,这个全局对象是 `global`。 ###函数调用 @@ -22,13 +23,13 @@ JavaScript 有一套完全不同于其它语言的对 `this` 的处理机制。 ###方法调用 - test.foo(); + test.foo(); 这个例子中,`this` 指向 `test` 对象。 ###调用构造函数 - new foo(); + new foo(); 如果函数倾向于和 `new` 关键词一块使用,则我们称这个函数是 [构造函数](#function.constructors)。 在函数内部,`this` 指向*新创建*的对象。 @@ -39,7 +40,7 @@ JavaScript 有一套完全不同于其它语言的对 `this` 的处理机制。 var bar = {}; foo.apply(bar, [1, 2, 3]); // 数组将会被扩展,如下所示 - foo.call(bar, 1, 2, 3); // 传递到foo的参数是:a = 1, b = 2, c = 3 + foo.call(bar, 1, 2, 3); // 传递到 foo 的参数是:a = 1, b = 2, c = 3 当使用 `Function.prototype` 上的 `call` 或者 `apply` 方法时,函数内的 `this` 将会被 **显式设置**为函数调用的第一个参数。 @@ -53,7 +54,7 @@ JavaScript 有一套完全不同于其它语言的对 `this` 的处理机制。 ###常见误解 尽管大部分的情况都说的过去,不过第一个规则(**[译者注][30]:**这里指的应该是第二个规则,也就是直接调用函数时,`this` 指向全局对象) -被认为是JavaScript语言另一个错误设计的地方,因为它**从来**就没有实际的用途。 +被认为是 JavaScript 语言另一个错误设计的地方,因为它**从来**就没有实际的用途。 Foo.method = function() { function test() { diff --git a/doc/zh/intro/license.md b/doc/zh/intro/license.md index 33aa7406..057dd8a6 100755 --- a/doc/zh/intro/license.md +++ b/doc/zh/intro/license.md @@ -1,7 +1,7 @@ ##许可 JavaScript 秘密花园在 [MIT license][1] 许可协议下发布,并存放在 [GitHub][2] 开源社区。 -如果你发现错误或者打字错误,请[新建一个任务单][3]或者发一个抓取请求。 +如果你发现错误,请[新建一个任务单][3]或者发一个抓取请求(Pull Request)。 你也可以在 Stack Overflow 的 [JavaScript 聊天室][4]找到我们。 [1]: https://github.com/BonsaiDen/JavaScript-Garden/blob/next/LICENSE diff --git a/doc/zh/object/forinloop.md b/doc/zh/object/forinloop.md index a0360e7e..16f9faaa 100755 --- a/doc/zh/object/forinloop.md +++ b/doc/zh/object/forinloop.md @@ -37,5 +37,4 @@ 推荐**总是**使用 `hasOwnProperty`。不要对代码运行的环境做任何假设,不要假设原生对象是否已经被扩展了。 [1]: http://www.prototypejs.org/ -[30]: http://cnblogs.com/sanshi/ diff --git a/doc/zh/object/general.md b/doc/zh/object/general.md index 58f20810..3ada17fa 100755 --- a/doc/zh/object/general.md +++ b/doc/zh/object/general.md @@ -1,6 +1,6 @@ ##对象使用和属性 -JavaScript 中所有变量都是对象,除了两个例外 [`null`](#core.undefined) 和 [`undefined`](#core.undefined)。 +JavaScript 中所有变量都可以当作对象使用,除了两个例外 [`null`](#core.undefined) 和 [`undefined`](#core.undefined)。 false.toString(); // 'false' [1, 2, 3].toString(); // '1,2,3' @@ -9,7 +9,7 @@ JavaScript 中所有变量都是对象,除了两个例外 [`null`](#core.undef Foo.bar = 1; Foo.bar; // 1 -一个常见的误解是数字的字面值(literal)不是对象。这是因为 JavaScript 解析器的一个错误, +一个常见的误解是数字的字面值(literal)不能当作对象使用。这是因为 JavaScript 解析器的一个错误, 它试图将*点操作符*解析为浮点数字面值的一部分。 2.toString(); // 出错:SyntaxError @@ -25,7 +25,7 @@ JavaScript 中所有变量都是对象,除了两个例外 [`null`](#core.undef JavaScript 的对象可以作为[*哈希表*][1]使用,主要用来保存命名的键与值的对应关系。 使用对象的字面语法 - `{}` - 可以创建一个简单对象。这个新创建的对象从 `Object.prototype` -[继承](#object.prototype)下面,没有任何[自定义属性](#object.hasownproperty)。 +[继承](#object.prototype)下来,没有任何[自定义属性](#object.hasownproperty)。 var foo = {}; // 一个空对象 @@ -34,7 +34,7 @@ JavaScript 的对象可以作为[*哈希表*][1]使用,主要用来保存命 ### 访问属性 -有两种方式来访问对象的属性,点操作符或者中括号操作符。 +有两种方式来访问对象的属性,点操作符和中括号操作符。 var foo = {name: 'kitten'} foo.name; // kitten diff --git a/doc/zh/object/hasownproperty.md b/doc/zh/object/hasownproperty.md index 2466f8c5..c9b3fc21 100755 --- a/doc/zh/object/hasownproperty.md +++ b/doc/zh/object/hasownproperty.md @@ -8,8 +8,8 @@ `hasOwnProperty` 是 JavaScript 中唯一一个处理属性但是**不**查找原型链的函数。 - // 修改Object.prototype - Object.prototype.bar = 1; + // 修改 Object.prototype + Object.prototype.bar = 1; var foo = {goo: undefined}; foo.bar; // 1 @@ -18,8 +18,8 @@ foo.hasOwnProperty('bar'); // false foo.hasOwnProperty('goo'); // true -只有 `hasOwnProperty` 可以给出正确和期望的结果,这在遍历对象的属性时会很有用。 -**没有**其它方法可以用来排除原型链上的属性,而不是定义在对象*自身*上的属性。 +只有 `hasOwnProperty` 可以给出正确和期望的结果。可以查看 [`for in` 循环](#object.forinloop) +章节来获取关于在迭代遍历对象属性的时候,何时使用 `hasOwnProperty` 的更多信息。 ###`hasOwnProperty` 作为属性 @@ -35,7 +35,7 @@ JavaScript **不会**保护 `hasOwnProperty` 被非法占用,因此如果一 foo.hasOwnProperty('bar'); // 总是返回 false - // 使用其它对象的 hasOwnProperty,并将其上下文设置为foo + // 使用其它对象的 hasOwnProperty,并将其上下文设置为 foo ({}).hasOwnProperty.call(foo, 'bar'); // true ###结论 @@ -44,4 +44,3 @@ JavaScript **不会**保护 `hasOwnProperty` 被非法占用,因此如果一 同时在使用 [`for in` loop](#object.forinloop) 遍历对象时,推荐**总是**使用 `hasOwnProperty` 方法, 这将会避免[原型](#object.prototype)对象扩展带来的干扰。 -[30]: http://cnblogs.com/sanshi/ diff --git a/doc/zh/object/prototype.md b/doc/zh/object/prototype.md index a9e09841..a8f08448 100755 --- a/doc/zh/object/prototype.md +++ b/doc/zh/object/prototype.md @@ -1,9 +1,9 @@ ##原型 -JavaScript 不包含传统的类继承模型,而是使用 *prototypal* 原型模型。 +JavaScript 不包含传统的类继承模型,而是使用 *prototype* 原型模型。 虽然这经常被当作是 JavaScript 的缺点被提及,其实基于原型的继承模型比传统的类继承还要强大。 -实现传统的类继承模型是很简单,但是实现 JavaScript 中的原型继承则要困难的多。 +例如,很容易通过原型继承实现传统的类继承模型,但是反过来,通过传统的类继承模型来实现原型继承模型就困难得多。 (It is for example fairly trivial to build a classic model on top of it, while the other way around is a far more difficult task.) @@ -23,19 +23,19 @@ other way around is a far more difficult task.) function Bar() {} - // 设置Bar的prototype属性为Foo的实例对象 + // 设置 Bar 的 prototype 属性为 Foo 的实例对象 Bar.prototype = new Foo(); Bar.prototype.foo = 'Hello World'; - // 修正Bar.prototype.constructor为Bar本身 + // 修正 Bar.prototype.constructor 为 Bar 本身 Bar.prototype.constructor = Bar; - var test = new Bar() // 创建Bar的一个新实例 + var test = new Bar(); // 创建Bar的一个新实例 // 原型链 test [Bar的实例] Bar.prototype [Foo的实例] - { foo: 'Hello World' } + { foo: 'Hello World', value: 42 } Foo.prototype {method: ...}; Object.prototype @@ -58,7 +58,7 @@ other way around is a far more difficult task.) ###原型属性 当原型属性用来创建原型链时,可以把**任何**类型的值赋给它(prototype)。 -然而将原子类型赋给 prototype 的操作将会被忽略。 +然而将原子类型(primitives)赋给 prototype 的操作将会被忽略。 function Foo() {} Foo.prototype = 1; // 无效 @@ -67,16 +67,16 @@ other way around is a far more difficult task.) ###性能 -如果一个属性在原型链的上端,则对于查找时间将带来不利影响。特别的,试图获取一个不存在的属性将会遍历整个原型链。 +如果一个属性在原型链的上端,则对于查找时间将带来不利影响。注意,试图获取一个不存在的属性将会遍历整个原型链。 并且,当使用 [`for in`](#object.forinloop) 循环遍历对象的属性时,原型链上的**所有**属性都将被访问。 ###扩展内置类型的原型 -一个错误特性被经常使用,那就是扩展 `Object.prototype` 或者其他内置类型的原型对象。 +扩展 `Object.prototype` 或者其他内置类型的原型对象,作为一个错误特性,经常被使用。 这种技术被称之为 [monkey patching][1] 并且会破坏*封装*。虽然它被广泛的应用到一些 JavaScript 类库中比如 [Prototype][2], -但是我仍然不认为为内置类型添加一些*非标准*的函数是个好主意。 +但是我仍然不赞同为内置类型添加一些*非标准*的函数。 扩展内置类型的**唯一**理由是为了和新的 JavaScript 保持一致,比如 [`Array.forEach`][3]。 diff --git a/doc/zh/types/equality.md b/doc/zh/types/equality.md index c3bb8002..006c02bf 100755 --- a/doc/zh/types/equality.md +++ b/doc/zh/types/equality.md @@ -53,6 +53,7 @@ JavaScript 是*弱类型*语言,这就意味着,等于操作符会为了比 这里等于操作符比较的**不是**值是否相等,而是是否属于同一个**身份**;也就是说,只有对象的同一个实例才被认为是相等的。 这有点像 Python 中的 `is` 和 C 中的指针比较。 +> **注意:**为了更直观的看到`==`和`===`的区别,可以参见[JavaScript Equality Table](http://dorey.github.io/JavaScript-Equality-Table/) ###结论 diff --git a/doc/zh/types/typeof.md b/doc/zh/types/typeof.md index 8a322b2f..f7a6cc1e 100755 --- a/doc/zh/types/typeof.md +++ b/doc/zh/types/typeof.md @@ -6,7 +6,7 @@ 尽管 `instanceof` 还有一些极少数的应用场景,`typeof` 只有一个实际的应用(**[译者注][30]:**这个实际应用是用来检测一个对象是否已经定义或者是否已经赋值), 而这个应用却**不是**用来检查对象的类型。 -> **注意:** 由于 `typeof` 也可以像函数的语法被调用,比如 `typeof(obj)`,但这并是一个函数调用。 +> **注意:** 由于 `typeof` 也可以像函数的语法被调用,比如 `typeof(obj)`,但这并不是一个函数调用。 > 那两个小括号只是用来计算一个表达式的值,这个返回值会作为 `typeof` 操作符的一个操作数。 > 实际上**不存在**名为 `typeof` 的函数。 diff --git a/doc/zhtw/core/eval.md b/doc/zhtw/core/eval.md index fb9e36bb..26b7d332 100644 --- a/doc/zhtw/core/eval.md +++ b/doc/zhtw/core/eval.md @@ -32,7 +32,7 @@ ### 安全上的顧慮 `eval` 同樣有安全上的問題,因為所有的程式碼都可以被直接執行。 -而他不應去執行一串未知的字串或是來自不幸任的來源。 +而他不應去執行一串未知的字串或是來自不信任的來源。 ### 結語 diff --git a/doc/zhtw/function/general.md b/doc/zhtw/function/general.md index 84a2bb3c..fe400880 100644 --- a/doc/zhtw/function/general.md +++ b/doc/zhtw/function/general.md @@ -25,19 +25,19 @@ 由於 `var` 已經宣告變數 `foo` 在所有的程式碼執行之前。 所以 `foo`已經在程式運行前就已經被定義過了。 -但是因為賦值只會在運行時去職情,所以在程式碼執行前,`foo` 的值還沒被宣告所以為 [undefined](#core.undefined)。 +但是因為賦值只會在運行時去執行,所以在程式碼執行前,`foo` 的值還沒被宣告所以為 [undefined](#core.undefined)。 ### 命名函式的賦值表達式 -另一個特殊狀況就勢將一個命名函式賦值給一個變數。 +另一個特殊狀況是將一個命名函式賦值給一個變數。 var foo = function bar() { bar(); // 可以運行 } bar(); // 錯誤:ReferenceError -`bar` 不可以在外部的區域被執行,因為它只有在 `foo` 的函式內才可以去執行。 +`bar` 不可以在外部的區域被執行,因為它只有在 `foo` 的函式內才可以執行。 然而在 `bar` 內部還是可以看見。這是由於 JavaScript的 [命名處理](#function.scopes)所致。 -函式名在函式內 *都* 可以去使用。 +函式名在函式內 *都* 可以使用。 diff --git a/doc/zhtw/function/scopes.md b/doc/zhtw/function/scopes.md index 76a84a6c..3e151282 100644 --- a/doc/zhtw/function/scopes.md +++ b/doc/zhtw/function/scopes.md @@ -10,7 +10,7 @@ console.log(i); // 10 } -> **注意:** 如果不是在賦值語句中,而是在 return 表達式或者函數參數中, `{...}` 將會作為程式碼中的解析,而不是作為物件的字面語法解析。 +> **注意:** 如果不是用在變數賦予值的宣告中、return 的回傳值中或者函數的參數中, `{...}` 將會被解析為一個程式區塊(block scope),而不是被解析為物件實體語法(object literal)。 > 如果考慮到 [自動分號插入](#core.semicolon),可能會造成一些不易察覺的錯誤。 JavaScript 中沒有寫示的命名空間定義,這代表著它所有定義的東西都是 *全域共享* 在同一個命名空間下。 @@ -196,4 +196,4 @@ JavaScript 中所有的作用區,包括 *全域作用域*,都有一個特殊 建議最好是都用 *匿名包裝器* 來封裝你的程式碼在自己的命名區間內。這不僅是要防止命名衝突也可以使得程序更有模組化。 -另外,全域變數是個 **不好的** 習慣,因為它會帶來錯誤和更難去維護。 \ No newline at end of file +另外,全域變數是個 **不好的** 習慣,因為它會帶來錯誤和更難去維護。 diff --git a/doc/zhtw/function/this.md b/doc/zhtw/function/this.md index d919c228..c5bf8d60 100644 --- a/doc/zhtw/function/this.md +++ b/doc/zhtw/function/this.md @@ -1,7 +1,7 @@ ## `this` 的工作原理 JavaScript 有移到完全部屬於其他語言處理 `this` 的處理機制。 -在 **五** 種物同的情況下, `this` 指向的個不相同 +在 **五** 種不同的情況下, `this` 指向的各不相同 ### 全域變數 @@ -14,12 +14,12 @@ JavaScript 有移到完全部屬於其他語言處理 `this` 的處理機制。 foo(); -這裡 `this` 也會指向 *全域* 對象。 +這裡 `this` 也會指向 *全域* 物件。 > **ES5 注意:** 在嚴格模式下,不存在全域變數。 > `this` 將會是 `undefined`。 -### 方法調用 +### 呼叫一個方法 test.foo(); diff --git a/doc/zhtw/object/forinloop.md b/doc/zhtw/object/forinloop.md index 67fa8915..06b248a6 100644 --- a/doc/zhtw/object/forinloop.md +++ b/doc/zhtw/object/forinloop.md @@ -27,10 +27,10 @@ } 這個版本的程式碼是唯一正確的寫法。由於我們使用了 `hasOwnProperty`,這次 **只** 輸出 `moo`。 -如果不只用這個程式碼在原型物件中(比如 `Object.prototype`)被擴展可能會出錯。 +如果不使用這個程式碼在原型物件中(比如 `Object.prototype`)被擴展可能會出錯。 -一個廣泛的模組 [Prototype][1]就礦展了圓型的 JavaScript 物件。 -因此,但這模組包含在頁面中時,不使用 `hasOwnProperty` 過濾的 `for in` 尋難免會出問題。 +一個廣泛使用的舊函式庫 [Prototype][1]就擴展了原型的 JavaScript 物件。 +因此,當這個函式庫包含在頁面中時,不使用 `hasOwnProperty` 過濾的 `for in` 迴圈難免會出問題。 ### 總結 diff --git a/doc/zhtw/object/general.md b/doc/zhtw/object/general.md index 01c98bc5..aee1885c 100644 --- a/doc/zhtw/object/general.md +++ b/doc/zhtw/object/general.md @@ -1,6 +1,6 @@ ## 物件的使用和屬性 -每個變數可以表現像 JavaScript 物件,除了 [`null`](#core.undefined) 和 [`undefined`](#core.undefined)。 +在 Javascript 中全部都是物件,除了 [`null`](#core.undefined) 和 [`undefined`](#core.undefined)。 false.toString(); // 'false' [1, 2, 3].toString(); // '1,2,3' @@ -23,7 +23,7 @@ JavaScript 的物件可以作為 [*Hashmaps*][1]使用,主要用來保存命名的鍵與值的對應關係。 -使用物件的字面語法 - `{}` - 可以創建一個簡單的物件。 這個新創建的物件從 `Object.prototype` [繼承](#object.prototype),下面,沒有任何 [自定義屬性](#object.hasownproperty)。 +使用物件的字面語法 - `{}` - 可以創建一個簡單的物件。 這個新創建的物件[繼承](#object.prototype) 自 `Object.prototype` ,沒有任何 [自定義屬性](#object.hasownproperty)。 var foo = {}; // 一個空的物件 @@ -32,7 +32,7 @@ JavaScript 的物件可以作為 [*Hashmaps*][1]使用,主要用來保存命 ### 訪問屬性 -有兩種訪問物件的屬性,點操作或是中括號操作。 +有兩種方式來訪問物件的屬性,點操作或是中括號操作。 var foo = {name: 'kitten'} foo.name; // kitten @@ -76,7 +76,7 @@ JavaScript 的物件可以作為 [*Hashmaps*][1]使用,主要用來保存命 delete: 'I am a keyword, so me too' // raises SyntaxError }; -物件的屬性名可以使用字符串或是普通的宣告。但是由於 JavaScript 編譯器有個另外一個錯誤設計。 +物件的屬性名可以使用字符串或是普通的宣告。但是由於 JavaScript 編譯器存在一個錯誤設計。 上面的兩種方式在 ECMAScript 5之前都會拋出 `SyntaxError` 的錯誤。 這個錯誤的原因是 `delete` 是 JavaScript 語言的一個 *關鍵字* 因此為了在更低的版本能執行最好用 *string literal* diff --git a/doc/zhtw/object/hasownproperty.md b/doc/zhtw/object/hasownproperty.md index d35d49e2..5d8403b4 100644 --- a/doc/zhtw/object/hasownproperty.md +++ b/doc/zhtw/object/hasownproperty.md @@ -1,6 +1,6 @@ ## `hasOwnProperty` -為了判斷一個物件是否包含 *自定義* 屬性而 *不是* [原形](#object.prototype)上的屬性,我們需要使用繼承 `Object.prototype` 的 `hasOwnProperty` 方法。 +為了判斷一個物件是否包含 *自定義* 屬性而 *不是* [原型](#object.prototype)上的屬性,我們需要使用繼承 `Object.prototype` 的 `hasOwnProperty` 方法。 > **注意:** 判斷一個屬性是否 `undefined` 是 **不夠的**。 > 因為一個屬性可能存在,但是它的值被設成 `undefined`。 @@ -42,4 +42,4 @@ JavaScript **不會** 保護 `hasOwnProperty`被占用,因此如果碰到存 當檢查一個物件是否存在的時候, `hasOwnProperty` 是 **唯一** 可用的方法。 同時在使用 [`for in loop`](#object.forinloop) -建議使用 `hasOwnProperty` 避免 [原型](#object.prototype)所帶來的干擾。 \ No newline at end of file +建議使用 `hasOwnProperty` 避免 [原型](#object.prototype)所帶來的干擾。 diff --git a/doc/zhtw/object/prototype.md b/doc/zhtw/object/prototype.md index f2bcaff3..83ad784a 100644 --- a/doc/zhtw/object/prototype.md +++ b/doc/zhtw/object/prototype.md @@ -1,9 +1,9 @@ ## Prototype -JavaScript 不包含原本繼承的模型。然而它使用的是*原型*模型。 +JavaScript 不包含傳統繼承的模型,它使用的是*原型*模型。 -然而常常有人提及 JavaScript 的缺點,就是基於原本繼承模型比類繼承更強大。 -現實傳統的類繼承模型是很簡單。但是在 JavaScript 中實現元繼承則要困難很多。 +儘管常常有人提及 JavaScript 的缺點,但基於原型的繼承模型比傳統繼承更強大。 +實現傳統的類繼承模型是很簡單。但是在 JavaScript 中實現原型的繼承模型則要困難很多。 由於 JavaScript 是唯一一個被廣泛使用的基於原型繼承的語言,所以我們必須要花時間來理解這兩者的不同。 @@ -33,7 +33,7 @@ JavaScript 不包含原本繼承的模型。然而它使用的是*原型*模型 // 原型鏈 test [instance of Bar] Bar.prototype [instance of Foo] - { foo: 'Hello World' } + { foo: 'Hello World', value: 42 } Foo.prototype { method: ... } Object.prototype @@ -72,14 +72,14 @@ JavaScript 不包含原本繼承的模型。然而它使用的是*原型*模型 一個經常發生的錯誤,那就是擴展 `Object.prototype` 或者是其他內建類型的原型物件。 -這種技術叫做 [monkey patching][1] 並且會破壞 *封裝*。雖然被廣泛的應用到一些 Javascript 的架構,像是 [Prototype](http://prototypejs.org) , 但仍然沒有好的理由新增一個 *非標準* 的功能去搞亂內建型別 +這種技術叫做 [monkey patching][1] 並且會破壞 *封裝*。雖然被廣泛的應用到一些 Javascript 的架構,像是 [Prototype](http://prototypejs.org) , 但仍然沒有好的理由新增一個 *非標準* 的功能去搞亂內建型別。 擴展內置類型的 **唯一** 理由是為了和新的 JavaScript 保持一致,比如說 [`Array.forEach`][3] ### 總結 在寫複雜的程式碼的時候,要 **充分理解** 所有程式繼承的屬性還有原型鏈。 -還要堤防原型鏈過長帶來的性能問題,並知道如何通過縮短原型鏈來提高性能。 +還要提防原型鏈過長帶來的性能問題,並知道如何通過縮短原型鏈來提高性能。 絕對 **不要使用** `native prototype` 除非是為了和新的 JavaScript 引擎作兼容。 [1]: http://en.wikipedia.org/wiki/Monkey_patch diff --git a/doc/zhtw/other/timeouts.md b/doc/zhtw/other/timeouts.md index 3fe9a6da..d717a81e 100644 --- a/doc/zhtw/other/timeouts.md +++ b/doc/zhtw/other/timeouts.md @@ -1,13 +1,13 @@ ### `setTimeout` 和 `setInterval` -由於 Javascript 是一個非同步傳輸的系統,因此可以執行一個函式用 `setTimeout` 和 `setInterval`。 +由於 Javascript 具有非同步的特性,因此可以用 `setTimeout` 和 `setInterval` 來執行一個函式。 > **注意:** Timeouts 不在 ECMAScript 的標準中。它們是 [DOM][1] 其中的一部分 function foo() {} var id = setTimeout(foo, 1000); // returns a Number > 0 -當 `setTimeout` 被呼叫,它會回傳一個 ID 標準並是計畫在將來 **大約** 1000 毫秒後在在去呼叫 `foo` 函式。 +當 `setTimeout` 被呼叫,它會回傳一個 ID 標準並且 **大約** 1000 毫秒後在在去呼叫 `foo` 函式。 `foo` 函式只會被執行 **一次**。 基於 JavaScript 引擎的計時策略,以及基本的單線程運行的方式,所以其他的程式碼可以被阻塞。 @@ -85,13 +85,15 @@ ### 隱藏使用 `eval` -`setTimeout` and `setInterval` can also take a string as their first parameter. -This feature should **never** be used because it internally makes use of `eval`. +`setTimeout` and `setInterval` 也可以使用字串當作他們的第一個參數. +不過這個特性 **絕對** 不要使用, 因為在內部他將利用 `eval` 來實作。 + +> **注意:** 由於 timeout 函式 **並未** 被列入 ECMAScript +> 標準中,當你將字串當成參數傳入時,在不同的 Javscript +> 實作中很有可能會造成不一樣的行為。比如說:在 Microsoft 的 JScript 中,就使用 `Function` +> 建構子來取代 `eval`。 + -> **Note:** Since the timeout functions are **not** specified by the ECMAScript -> standard, the exact workings when a string is passed to them might differ in -> various JavaScript implementations. For example, Microsoft's JScript uses -> the `Function` constructor in place of `eval`. function foo() { // will get called @@ -105,12 +107,10 @@ This feature should **never** be used because it internally makes use of `eval`. } bar(); -Since `eval` is not getting called [directly](#core.eval) in this case, the string -passed to `setTimeout` will be executed in the *global scope*; thus, it will -not use the local variable `foo` from the scope of `bar`. +在這個範例中,由於 `eval` 沒有被[直接](#core.eval)呼叫,在 `setTimeout` 中被傳入的字串將會在 *全域* 範圍中被執行,因此,他將不會使用在 `bar` 區域的 `foo`。 + +我們進一步建議 **不要** 用字串當作參數傳到會被 timeout 呼叫的函式中。 -It is further recommended to **not** use a string to pass arguments to the -function that will get called by either of the timeout functions. function foo(a, b, c) {} @@ -122,18 +122,14 @@ function that will get called by either of the timeout functions. foo(1, 2, 3); }, 1000) -> **Note:** While it is also possible to use the syntax -> `setTimeout(foo, 1000, 1, 2, 3)`, it is not recommended, as its use may lead -> to subtle errors when used with [methods](#function.this). +> **注意** 儘管使用 `setTimeout(foo, 1000, 1, 2, 3)` +> 這樣的文法是可能的,但我們卻不建議這樣做,因為這和 [方法](#function.this) +> 一起使用時可能會導致微妙的錯誤。 -### In Conclusion +### 結論 -A string should **never** be used as the parameter of `setTimeout` or -`setInterval`. It is a clear sign of **really** bad code, when arguments need -to be supplied to the function that gets called. An *anonymous function* should -be passed that then takes care of the actual call. +**絕對** 不要使用字串當作 `setTimeout` 或 `setInterval` 參數。當參數要被當成呼叫的函式時,這絕對是 **不好** 的程式碼,相反的,利用 *匿名函式* 來完成這樣的行為。 -Furthermore, the use of `setInterval` should be avoided because its scheduler is not -blocked by executing JavaScript. +此外,應該避免使用 `setInterval`,因為他將不會被 Javascript 給中斷。 [1]: http://en.wikipedia.org/wiki/Document_Object_Model "Document Object Model" diff --git a/garden.jade b/garden.jade index 88bba318..bd191d39 100644 --- a/garden.jade +++ b/garden.jade @@ -1,4 +1,4 @@ -!!! 5 +doctype html html(lang=language) head title #{title} @@ -24,7 +24,7 @@ html(lang=language) // Navigation nav(id='nav_main') div - ul + ul - each lang in languages li(class=lang.id === language ? 'active' : '') - if (lang.id === baseLanguage) @@ -54,7 +54,7 @@ html(lang=language) a(id='nav_next_section', href='#') next section span(class='nav_section_name') section name - + a(id='show_menu') show menu // Sections @@ -77,25 +77,19 @@ html(lang=language) // Footer footer - p Copyright © 2011. Built with - | - a(href='http://nodejs.org/') Node.js + p Copyright ©. Built with + | + a(href='http://nodejs.org/') Node.js | using a - a(href='https://github.com/visionmedia/jade/') jade - | template. - | Hosted by - a(href='http://cramerdev.com/') Cramer Development - . - - script(src='http://ajax.googleapis.com/ajax/libs/jquery/1.5.1/jquery.min.js') - + a(href='https://github.com/visionmedia/jade/') jade + | template. + + script(src='http://ajax.googleapis.com/ajax/libs/jquery/1.5.1/jquery.min.js') + - if (language === baseLanguage) script(src='http://github.com/javascript/prettify.js') - script(src='http://github.com/javascript/plugin.js') script(src='http://github.com/javascript/garden.js') - + - else script(src='http://github.com/javascript/prettify.js') - script(src='http://github.com/javascript/plugin.js') script(src='http://github.com/javascript/garden.js') - diff --git a/package.json b/package.json index ea637eb1..a9662f9f 100644 --- a/package.json +++ b/package.json @@ -2,6 +2,9 @@ "name": "javascript-garden", "description": "A collection of documentation about the most quirky parts of the JavaScript language.", "version": "0.0.0", + "scripts": { + "build": "node build.js" + }, "dependencies": { "fomatto": "0.5.0", "forever": "0.10.8", diff --git a/site/javascript/garden.js b/site/javascript/garden.js index c55a970b..3939a2c7 100644 --- a/site/javascript/garden.js +++ b/site/javascript/garden.js @@ -18,10 +18,10 @@ Sections.prototype = { }, map: function() { - this.names = $('section [id]').map(function(idx, ele) { + this.names = $('section>[id]').map(function(idx, ele) { return { id: this.id.replace('.intro', ''), - offset: $(this).offset().top - 20, + offset: $(this).offset().top - 100, title: $(this).find(':header:first').html() }; @@ -33,7 +33,7 @@ Sections.prototype = { articleID = this.names[this.names.length - 1].id; for(var i = 0, l = this.names.length; i < l; i++) { - if (scroll > 0 && this.names[i].offset > scroll) { + if (scroll >= 0 && this.names[i].offset > scroll) { articleID = this.names[i - 1].id; break; } @@ -60,18 +60,18 @@ Sections.prototype = { } }, - expand: function (sectionName) { + expand: function(sectionName) { var nav = this.page.nav, index = nav.find('a[href=#' + sectionName + ']') .closest('nav > ul > li').index(); var height = this.page.window.height() - $('nav > div').height() - - (33 * this.heights.length), + - (33 * this.heights.length); - sections = [], - currentHeight = 0, - distance = 0; + var sections = [], + currentHeight = 0, + distance = 0; while ((currentHeight + this.heights[index]) < height) { sections.push(index); @@ -135,7 +135,7 @@ function Page() { section: null, articule: null }); - + this.sections = new Sections(this); this.init(); } @@ -143,48 +143,35 @@ function Page() { Page.prototype = { init: function() { var that = this, - mainNav = $('#nav_main'); + $mainNav = $('#nav_main'); $.extend(this, { scrollLast: 0, resizeTimeout: null }); - + this.window.scroll(function() { that.onScroll(); }); - + this.window.resize(function() { that.onResize(); }); - that.sections.map(); + this.sections.map(); setTimeout(function() { that.sections.highlight(); }, 10); - // Mobile, for position: fixed - if ($.mobile) { - var navs = $('#nav_mobile, #nav_main'); - navs.css('position', 'absolute'); - this.window.scroll(function(){ - navs.offset({ - top: that.window.scrollTop() - }); - }); - } - - // Show menu for tablets - $('#show_menu').click(function (){ - var scrollTop = $.mobile ? that.window.scrollTop() : 0; - - mainNav.slideDown(300).css('top', scrollTop); + // Show menu for tablets and smart phones + $('#show_menu').click(function() { + $mainNav.slideDown(300); return false; }); - - $('#nav_main').click(function(){ + + $mainNav.click(function() { if(that.window.width() < 1000) - mainNav.slideUp(300); + $mainNav.slideUp(300, function() { $mainNav.removeAttr('style'); }); }); }, diff --git a/site/javascript/plugin.js b/site/javascript/plugin.js deleted file mode 100644 index 9461358a..00000000 --- a/site/javascript/plugin.js +++ /dev/null @@ -1,12 +0,0 @@ -/** - * jQuery.browser.mobile (http://detectmobilebrowser.com/) - * - * Copyright (c) 2010 Chad Smith (http://twitter.com/chadsmith) - * Dual licensed under the MIT and GPL licenses. - * http://www.opensource.org/licenses/mit-license.php - * http://www.opensource.org/licenses/gpl-license.php - * - * jQuery.browser.mobile will be true if the browser is a mobile device - * - **/ -(function(a){jQuery.browser.mobile=/android|avantgo|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|symbian|treo|up\.(browser|link)|vodafone|wap|windows (ce|phone)|xda|xiino/i.test(a)||/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|e\-|e\/|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(di|rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|xda(\-|2|g)|yas\-|your|zeto|zte\-/i.test(a.substr(0,4))})(navigator.userAgent||navigator.vendor||window.opera); \ No newline at end of file diff --git a/site/style/garden.css b/site/style/garden.css index 8b1896fb..9c95ff95 100644 --- a/site/style/garden.css +++ b/site/style/garden.css @@ -74,16 +74,16 @@ nav { position: fixed; margin-left: 750px; top: 0; - padding-bottom: 20px; + padding-bottom: 20px; height: 100%; - + text-shadow: none; width: 240px; } nav > div li { - float: left; - margin-right: 1px; + float: left; + margin-right: 1px; } nav > div li a, #top, #hide_menu { @@ -96,7 +96,7 @@ nav > div li a, #top, #hide_menu { nav > div li.active a { border-top: 4px solid #0D2E4C; padding-top: 4px; - color: #FFC76D; + color: #FFC76D; } #hide_menu { @@ -117,10 +117,15 @@ nav > div li.active a { width: 200px; } +#nav_main > ul { + height: calc(100% - 4em); + overflow-y: auto; +} + nav li { font-size: 16px; - margin: 0px; - list-style: none; + margin: 0px; + list-style: none; } nav > ul li:last-child a { @@ -182,10 +187,10 @@ nav li a.active:hover { nav a:hover, nav ul.active a:hover, nav a, nav li { -moz-transition-property: background-color, color; -moz-transition-duration: 0.3s; - + -webkit-transition-property: background-color, color; -webkit-transition-duration: 0.3s; - + -o-transition-property: background-color, color; -o-transition-duration: 0.3s; @@ -243,9 +248,9 @@ code { section pre code { font-size: 0.8125em; line-height: 1.4em; - padding: 0px; - margin-top: 3px; - margin-bottom: 1px; + padding: 0px; + margin-top: 3px; + margin-bottom: 1px; background: #0F192A; } @@ -267,7 +272,7 @@ section h1 { } section header + section h1 { - + } /* Adding 'icon' to the side of sections */ @@ -336,7 +341,7 @@ aside { width: 180px; right: -190px; opacity: 0.7; - + -moz-transition: opacity 0.3s; -webkit-transition: opacity 0.3s; -o-transition: opacity 0.3s; @@ -369,7 +374,7 @@ aside.es5:after { font-style: italic; top: -18px; right: -3px; - + -ms-filter: “progid:DXImageTransform.Microsoft.Alpha(Opacity=25)”; /* Just kill me already... */ opacity: 0.25; } @@ -377,7 +382,7 @@ aside.es5:after { /* Article elements */ section ol { - margin-bottom: 2em; + margin-bottom: 2em; list-style: decimal; } @@ -438,10 +443,10 @@ a abbr { /* "Tablet" Styles */ -@media screen and (max-width: 1000px) { +@media screen and (max-width: 999px) { body { width: 100%; - max-width: 1000px; + max-width: 999px; overflow-x: hidden; } @@ -463,7 +468,7 @@ a abbr { nav > div li.active a { padding-top: 8px; } - + #nav_main { display: none; height: auto; @@ -471,29 +476,29 @@ a abbr { width: 100%; z-index: 100; padding: 0; - + -moz-box-shadow: 0 3px 3px rgba(0, 0, 0, 0.3); -webkit-box-shadow: 0 3px 3px rgba(0, 0, 0, 0.3); box-shadow: 0 3px 3px rgba(0, 0, 0, 0.3); } - + #nav_main ul ul { display: none !important; } - + #nav_main > ul > li { float: left; text-align: center; width: 14.28%; border-bottom: 0; } - + #nav_main li h1 a { background-image: none; height: 5em; padding: 1.5em 0 2em; } - + #nav_main li h1 a:after { display: block; font-family: Georgia; @@ -501,21 +506,21 @@ a abbr { font-weight: normal; margin-top: 10px; } - + #nav_main > div ul { height: auto; } - + nav a:hover, nav li.active, nav li.active a { background-color: #0D2E4C; } - + #hide_menu { display: block; } - + #nav_mobile { position: fixed; width: 24%; @@ -524,7 +529,7 @@ a abbr { display: block; z-index: 50; } - + #nav_mobile a { display: block; background-color: #556C81; @@ -532,12 +537,12 @@ a abbr { margin-bottom: 1px; text-align: right; } - + #nav_next_section, #nav_prev_section { font-size: 0.55em; text-transform: uppercase; } - + #nav_next_section .nav_section_name, #nav_prev_section .nav_section_name { display: block; @@ -547,12 +552,12 @@ a abbr { line-height: 1.3em; text-transform: none; } - + #show_menu { font-weight: bold; cursor: pointer; } - + pre { border-left: 0; padding-left: 12px; @@ -567,7 +572,7 @@ a abbr { right: -33%; width: 30%; } - + section:after { display: none; } @@ -575,17 +580,16 @@ a abbr { /* "Smartphone" styles */ -@media screen and (max-width: 600px), -screen and (-webkit-min-device-pixel-ratio: 2) { +@media screen and (max-width: 600px) { body { max-width: 600px; } - + section { margin-right: 30px; width: auto; } - + section:after { right: 0; font-size: 60px; @@ -599,16 +603,30 @@ screen and (-webkit-min-device-pixel-ratio: 2) { border-top: 1px solid #9eabb7; opacity: 0.85; } - + #nav_main > ul > li { - width: 100%; + float: left; + text-align: center; + width: 25%; + border-bottom: 0; } - + #nav_mobile { width: 160px; } - + aside.es5:after { display: none; } } + +/* Small Screen "Smarphone" Vertical Mode */ + +@media screen and (max-width: 360px) { + #nav_main > ul > li { + float: left; + text-align: center; + width: 33.33%; + border-bottom: 0; + } +} From 8f9a8a56c532b6fa4d787e1dd7f4c74fd13ec8e4 Mon Sep 17 00:00:00 2001 From: SnailSword Date: Thu, 21 Jul 2016 10:05:18 +0800 Subject: [PATCH 078/105] =?UTF-8?q?=E6=8A=8A=E2=80=9C=E6=89=A7=E8=A1=8C?= =?UTF-8?q?=E2=80=9D=E6=94=B9=E4=B8=BA=E2=80=9C=E6=8C=87=E5=90=91=E2=80=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- doc/zh/object/prototype.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/zh/object/prototype.md b/doc/zh/object/prototype.md index a8f08448..25a1d89d 100755 --- a/doc/zh/object/prototype.md +++ b/doc/zh/object/prototype.md @@ -46,7 +46,7 @@ other way around is a far more difficult task.) 需要注意的是 `new Bar()` **不会**创造出一个新的 `Foo` 实例,而是 重复使用它原型上的那个实例;因此,所有的 `Bar` 实例都会共享**相同**的 `value` 属性。 -> **注意:** **不要**使用 `Bar.prototype = Foo`,因为这不会执行 `Foo` 的原型,而是指向函数 `Foo`。 +> **注意:** **不要**使用 `Bar.prototype = Foo`,因为这不会指向 `Foo` 的原型,而是指向函数 `Foo`。 > 因此原型链将会回溯到 `Function.prototype` 而不是 `Foo.prototype`,因此 `method` 将不会在 Bar 的原型链上。 ###属性查找 From 3f9826e5e362343401b57d7694d2edca4daa8427 Mon Sep 17 00:00:00 2001 From: Lee Sun-Hyoup Date: Thu, 25 Aug 2016 15:55:25 +0900 Subject: [PATCH 079/105] Fix markdown grammer --- doc/ko/function/scopes.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/ko/function/scopes.md b/doc/ko/function/scopes.md index 7792ee65..b94dc10e 100644 --- a/doc/ko/function/scopes.md +++ b/doc/ko/function/scopes.md @@ -1,4 +1,4 @@ - ## 스코프와 네임스페이스 +## 스코프와 네임스페이스 JavaScript는 '{}' Block이 배배 꼬여 있어도 문법적으로는 잘 처리하지만, Block Scope은 지원하지 않는다. 그래서 JavaScript에서는 항상 *함수 스코프*를 사용한다. From c49045c4027d72d3a9f2860ce20a386dd072aa9a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maksim=20=C5=81abovi=C4=8D?= Date: Thu, 10 Nov 2016 17:19:31 +0300 Subject: [PATCH 080/105] Some punctuation and spelling fixes Made some punctuation and spelling fixes in Russian translation --- doc/ru/function/constructors.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/doc/ru/function/constructors.md b/doc/ru/function/constructors.md index 33f62bf2..7a322aff 100644 --- a/doc/ru/function/constructors.md +++ b/doc/ru/function/constructors.md @@ -70,7 +70,7 @@ ### Создание объектов с использованием фабрик -Часто рекомендуют **не** использовать `new`, поскольку если вы его забудете, это может привести к ошибкам. +Часто **не** рекомендуют использовать `new`, поскольку если вы его забудете, это может привести к ошибкам. Чтобы создать новый объект, лучше использовать фабрику и создать новый объект *внутри* этой фабрики. @@ -89,13 +89,13 @@ return obj; } -Хотя данный пример и сработает, если вы забыли ключевое слово `new` и благодаря ему легче работать с [приватными переменными](#function.closures), у него есть несколько недостатков +Хотя данный пример и сработает, если вы забыли ключевое слово `new`, и благодаря ему легче работать с [приватными переменными](#function.closures), у него есть несколько недостатков 1. Он использует больше памяти, поскольку созданные объекты **не** хранят методы в прототипе и соответственно для каждого нового объекта создаётся копия каждого метода. 2. Чтобы эмулировать наследование, фабрике нужно скопировать все методы из другого объекта или установить прототипом нового объекта старый. - 3. Разрыв цепочки прототипов просто по причине забытого ключевого слова `new` идёт в разрез с духом языка. + 3. Разрыв цепочки прототипов просто по причине забытого ключевого слова `new` идёт вразрез с духом языка. ### Заключение -Хотя забытое ключевое слово `new` и может привести к багам, это точно **не** причина отказываться от использования прототипов. В конце концов, полезнее решить какой из способов лучше совпадает с требованиями приложения: очень важно выбрать один из стилей создания объектов и после этого **не изменять** ему. +Хотя забытое ключевое слово `new` и может привести к багам, это точно **не** причина отказываться от использования прототипов. В конце концов, полезнее решить, какой из способов лучше совпадает с требованиями приложения: очень важно выбрать один из стилей создания объектов и после этого **не изменять** ему. From 1b8c8c0035de4d556cc839721e36286a3ebeb7ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maksim=20=C5=81abovi=C4=8D?= Date: Thu, 10 Nov 2016 17:39:34 +0300 Subject: [PATCH 081/105] Some changes in Russian translation --- doc/ru/function/scopes.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/doc/ru/function/scopes.md b/doc/ru/function/scopes.md index 8883e3f7..81f82847 100644 --- a/doc/ru/function/scopes.md +++ b/doc/ru/function/scopes.md @@ -75,7 +75,7 @@ ### Высасывание -JavaScript **высасывает** определения. Это значит, что оба определения с использованием `var` и определение `function` будут перенесены наверх заключающей их области видимости. +В JavaScript действует механизм **всплытия** определения. Это значит, что оба определения с использованием `var` и определение `function` будут перенесены наверх заключающей их области видимости. bar(); var bar = function() {}; @@ -116,16 +116,16 @@ JavaScript **высасывает** определения. Это значит, bar(); // вылетает с ошибкой TypeError, // поскольку bar всё ещё 'undefined' - someValue = 42; // присвоения не подвержены высасыванию + someValue = 42; // присвоения не подвержены поднятию bar = function() {}; test(); Потерянная область видимости блока не только переместит операторы `var` вовне циклов и их тел, но и сделает результаты некоторых конструкций с `if` неинтуитивными. -В исходном коде оператор `if` изменял *глобальную переменную* `goo`, когда, как оказалось, он изменяет *локальную переменную* — в результате работы высасывания. +В исходном коде оператор `if` изменял *глобальную переменную* `goo`, когда, как оказалось, он изменяет *локальную переменную* — в результате работы всплытия. -Если вы не знакомы с *высасываниями*, то можете посчитать, что нижеприведённый код должен породить +Если вы не знакомы со *всплытием*, то можете посчитать, что нижеприведённый код должен породить `ReferenceError`. // проверить, проинициализована ли SomeImportantThing @@ -162,7 +162,7 @@ JavaScript **высасывает** определения. Это значит, ### Пространства имён -Нередкое последствие наличия только одного глобального пространства имён — проблемы с перекрытием имён переменных. В JavaScript эту проблему легко избежать, используя *анонимные обёртки*. +Нередкое последствие наличия только одного глобального пространства имён — проблема с перекрытием имён переменных. В JavaScript эту проблему легко избежать, используя *анонимные обёртки*. (function() { // самостоятельно созданное "пространство имён" From f0358fd6a2e8c0454368df28cb1eb18411eb0e32 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maksim=20=C5=81abovi=C4=8D?= Date: Thu, 10 Nov 2016 17:51:48 +0300 Subject: [PATCH 082/105] =?UTF-8?q?Changed=20=E2=80=9Choisting=E2=80=9D=20?= =?UTF-8?q?translation=20in=20Russian?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Changed “hoisting” translation in Russian from «высасывание/всасывание» to more widely spread «Всплытие/поднятие» articles using this translation: https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Statements/var https://webref.ru/dev/jqfundamentals/javascript-basics http://jsraccoon.ru/es6-block-scoped-declarations https://habrahabr.ru/post/127482/ https://habrahabr.ru/post/239863/ official Russian translations of popular JavaScript books: ”Single Page Web Applications“ https://books.google.by/books?id=XVUHCgAAQBAJ&lpg=PA58&ots=PBfFs9YqTj&dq=%D0%BF%D0%BE%D0%B4%D0%BD%D1%8F%D1%82%D0%B8%D0%B5%20%D0%BF%D0%B5%D1%80%D0%B5%D0%BC%D0%B5%D0%BD%D0%BD%D1%8B%D1%85%20javascript&pg=PA58#v=onepage&q=hoisting&f=false --- doc/ru/function/scopes.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/ru/function/scopes.md b/doc/ru/function/scopes.md index 81f82847..323db6a5 100644 --- a/doc/ru/function/scopes.md +++ b/doc/ru/function/scopes.md @@ -73,7 +73,7 @@ В то время как `foo` и `i` — локальные переменные в области видимости функции `test`, присвоение `bar` переопределит значение одноимённой глобальной переменной. -### Высасывание +### Всплытие В JavaScript действует механизм **всплытия** определения. Это значит, что оба определения с использованием `var` и определение `function` будут перенесены наверх заключающей их области видимости. From 7f86b6e366d9eef5492c22615343e53a79c595f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maksim=20=C5=81abovi=C4=8D?= Date: Thu, 10 Nov 2016 17:53:29 +0300 Subject: [PATCH 083/105] Update scopes.md --- doc/ru/function/scopes.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/ru/function/scopes.md b/doc/ru/function/scopes.md index 323db6a5..0cf88caa 100644 --- a/doc/ru/function/scopes.md +++ b/doc/ru/function/scopes.md @@ -116,7 +116,7 @@ bar(); // вылетает с ошибкой TypeError, // поскольку bar всё ещё 'undefined' - someValue = 42; // присвоения не подвержены поднятию + someValue = 42; // присвоения не подвержены всплытию bar = function() {}; test(); From 86e9af5c8f0252a910394780d6cbb9c0432f51f9 Mon Sep 17 00:00:00 2001 From: Rafael Lima Date: Sat, 19 Nov 2016 19:25:20 -0300 Subject: [PATCH 084/105] Fix some words. --- doc/ptbr/core/eval.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/ptbr/core/eval.md b/doc/ptbr/core/eval.md index 0579953d..e7608cd9 100644 --- a/doc/ptbr/core/eval.md +++ b/doc/ptbr/core/eval.md @@ -11,8 +11,8 @@ A função `eval` executará uma string de código JavaScript no escopo local. test(); // 3 foo; // 1 -Entreranto, `eval` somente é executado no escopo local quando é chamado diretamente -*e* quanto o nome da função chamada é `eval`. +Entretanto, `eval` somente é executado no escopo local quando é chamado diretamente +*e* quando o nome da função chamada é `eval`. var foo = 1; function test() { @@ -40,6 +40,6 @@ Ele **nunca** deve ser utilizado com strings de origens duvidosas ou desconhecid ### Conclusão `eval` nunca deve ser utilizado. Qualquer código que faça uso de `eval` seve ser questionado -em sua utilizade, performance e segurança. Se algo necessita de `eval` para funcionar, então **não** deve ser utilizado. +em sua utilidade, performance e segurança. Se algo necessita de `eval` para funcionar, então **não** deve ser utilizado. Um *design melhor* deve ser utilizado, um que não faça uso de `eval`. From f5998d381123e4536d8b3fd8715c26b8d37a99e9 Mon Sep 17 00:00:00 2001 From: Rafael Lima Date: Sat, 19 Nov 2016 19:29:25 -0300 Subject: [PATCH 085/105] Remove duplicate paragraph. --- doc/ptbr/core/semicolon.md | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/doc/ptbr/core/semicolon.md b/doc/ptbr/core/semicolon.md index 38375017..843d7db4 100644 --- a/doc/ptbr/core/semicolon.md +++ b/doc/ptbr/core/semicolon.md @@ -2,7 +2,7 @@ Apesar do JavaScript possuir uma sintaxe no estilo C, o uso do ponto e vírgula **não** é obrigatório. -JavaScript não é uma linguagem 'semicolon-less'. De fato, o ponto e vírgula é necessário para o interpretação do código. Entretanto, o parser do JavaScript insere o **automaticamente** ponto e vírgula sempre que ocorrer um error de parser, decorrente da falta do ponto e vírgula. +JavaScript não é uma linguagem 'semicolon-less'. De fato, o ponto e vírgula é necessário para o interpretação do código. Entretanto, o parser do JavaScript insere o **ponto e vírgula** automaticamente sempre que ocorrer um error de parser, decorrente da falta do ponto e vírgula. var foo = function() { } // parse error, semicolon expected @@ -96,11 +96,5 @@ As chances de `log` não retornar uma função são **muito** altas; portanto, o ### Conclusão -It is highly recommended to **never** omit semicolons. It is also recommended -that braces be kept on the same line as their corresponding statements and to -never omit them for single-line `if` / `else` statements. These measures will -not only improve the consistency of the code, but they will also prevent the -JavaScript parser from changing code behavior. - É **fortemente** recomendado que nunca se omita o ponto e vírgula. Também é recomendado que chaves sejam mantidas na mesma linha que seus statements e que nunca sejam omitadas em declações de uma só linha como `if` / `else` statements. Tais medidas não somente melhorarão a consistência do código, como também irão previnir alteração no comportamento do código por má interpretação do parser do JavaScript. From 079506fb4bc4eeb279509a3103079fdb9e6e015f Mon Sep 17 00:00:00 2001 From: Rafael Lima Date: Sat, 19 Nov 2016 19:33:07 -0300 Subject: [PATCH 086/105] More fixes. --- doc/ptbr/core/undefined.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/ptbr/core/undefined.md b/doc/ptbr/core/undefined.md index 463a9618..cbaedcc6 100644 --- a/doc/ptbr/core/undefined.md +++ b/doc/ptbr/core/undefined.md @@ -28,10 +28,10 @@ Aqui estão alguns exemplos de quando o valor `undefined` é retornado: ### Manipulando mudanças no valor de `undefined` -Uma que a variável global `undefined` apenas mantém uma cópia do valor *atual* de `undefined`, atribuir-lhe +Uma vez que a variável global `undefined` apenas mantém uma cópia do valor *atual* de `undefined`, atribuir-lhe um novo valor **não** muda o valor do tipo `undefined`. -Ainda, a fim de comparar alguma coisa com o valor de `undefined`, é ncessário que +Ainda, a fim de comparar alguma coisa com o valor de `undefined`, é necessário que primeiro se retorne o `undefined`. A fim de proteger o código contra uma possível sobrescrtia da variável `undefined`, uma @@ -54,7 +54,7 @@ Outra maneira de atingir o mesmo efeito seria utilizar uma declaração dentro d })('Hello World', 42); -A única diferença aqui é a que a última versão resulta na redução de 4 bytes, e nã existe +A única diferença aqui é a que a última versão resulta na redução de 4 bytes, e não existe outro `var` statement dentro do wrapper anônimo. ### Usos do `null` From 12f9e559ada86205b1bc657c60dab715dc924a61 Mon Sep 17 00:00:00 2001 From: Rafael Lima Date: Sat, 19 Nov 2016 19:38:28 -0300 Subject: [PATCH 087/105] Remove duplicate paragraph. --- doc/ptbr/function/arguments.md | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/doc/ptbr/function/arguments.md b/doc/ptbr/function/arguments.md index 099ecf02..33c3214f 100644 --- a/doc/ptbr/function/arguments.md +++ b/doc/ptbr/function/arguments.md @@ -1,6 +1,6 @@ ## O objeto `arguments` -Todo escopo de uma função em JavaScript em acesso à variável especial `arguments`. +Todo escopo de uma função em JavaScript tem acesso à variável especial `arguments`. Esta variável armazena uma lista de todos os argumentos que foram passados para a função. > **Nota:** No caso em que `arguments` tenha sido definido dentro do escopo da função por meio @@ -12,7 +12,7 @@ e é de fato um `Object`. Devido a isto, **não** é possível usar os métodos padrões de array como `push`, `pop` ou `slice` no `arguments`. Enquanto que a iteração com um simples `for` loop funciona bem, -é necessário convertê-lo para um `Array` a fim de usar os métodos padrões de `Array`. +é necessário convertê-lo para um `Array` a fim de usar os métodos padrões de `Array`. ### Convertendo em um Array @@ -96,10 +96,7 @@ em engines modernas de JavaScript. Este caso é o uso de `arguments.callee` foo(); // Would normally be inlined... } } - -No código acima, `foo` -In the above code, `foo` can no longer be a subject to [inlining][1] since it -needs to know about both itself and its caller. + Isto não somente acaba com possíveis ganhos de performance que resultariam de inlining, mas também quebram o encapsulamento pois a função agora depende de uma chamada específica de contexto. From 3af1ad1f50e131927819e7b77ae75e25e68ef98a Mon Sep 17 00:00:00 2001 From: Rafael Lima Date: Sat, 19 Nov 2016 19:52:51 -0300 Subject: [PATCH 088/105] Update general.md --- doc/ptbr/object/general.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/ptbr/object/general.md b/doc/ptbr/object/general.md index a5e88626..12452e7f 100644 --- a/doc/ptbr/object/general.md +++ b/doc/ptbr/object/general.md @@ -14,7 +14,7 @@ Um equívoco muito comum é a idéia de que números não podem ser manipulados 2.toString(); // raises SyntaxError -Existem duas soluções para contornar este problema e permtir que números se comportem como objetos. +Existem três soluções para contornar este problema e permtir que números se comportem como objetos. 2..toString(); // o segundo ponto é reconhecido corretamente 2 .toString(); // perceba o espaço deixado à esquerda do ponto From 6dca90445415102f94b0f33d07927bd6eb3a8b5f Mon Sep 17 00:00:00 2001 From: Rafael Lima Date: Sat, 19 Nov 2016 19:57:16 -0300 Subject: [PATCH 089/105] Some fixes. --- doc/ptbr/object/hasownproperty.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/ptbr/object/hasownproperty.md b/doc/ptbr/object/hasownproperty.md index 2ff0589f..858e052c 100644 --- a/doc/ptbr/object/hasownproperty.md +++ b/doc/ptbr/object/hasownproperty.md @@ -27,7 +27,7 @@ em outro lugar na cadeia prototype. ### `hasOwnProperty` como propriedade -JavaScript não protege o nome do propriedade `hasOwnProperty`; assim, se +JavaScript não protege o nome da propriedade `hasOwnProperty`; assim, se existe a possibilidade de algum objeto possuir uma propriedade com este mesmo nome, torna-se necessário utilizar um `hasOwnProperty` **externo** a fim de obter resultados corretos. @@ -50,7 +50,7 @@ torna-se necessário utilizar um `hasOwnProperty` **externo** a fim de obter res ### Conclusão -O método é a **única** maneira confiável `hasOwnProperty` para verificar a existência da propriedade em um objeto. +O método `hasOwnProperty` é a **única** maneira confiável para verificar a existência da propriedade em um objeto. É recomendado que `hasOwnProperty` seja utilizado em **cada** interação de um [laço `for in`](#object.forinloop) a fim de evitar erros de extensão do [prototype](#object.prototype). From e508a7f61365ba97dcd3651306bf11b90a0d7c73 Mon Sep 17 00:00:00 2001 From: Rafael Lima Date: Sat, 19 Nov 2016 20:01:20 -0300 Subject: [PATCH 090/105] Some fixes. --- doc/ptbr/other/timeouts.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/ptbr/other/timeouts.md b/doc/ptbr/other/timeouts.md index 8d522c4e..74ec2081 100644 --- a/doc/ptbr/other/timeouts.md +++ b/doc/ptbr/other/timeouts.md @@ -13,7 +13,7 @@ Quando `setTimeout` é chamado, ele retorna o ID do timeout e agenda a execuçã para **aproximadamente** mil milissegundos no futuro. `foo` será executado uma **única** vez. -Dependendo de como a enine JavaScript que está rodando o código resolve o timer, bem como +Dependendo de como a engine JavaScript que está rodando o código resolve o timer, bem como o fato de que o JavaScript é single threaded e outro código que é executado pode bloquear a thread, **não há como** garantir a precisão dos intervalos especificados nas chamadas `setTimeout`. @@ -44,7 +44,7 @@ o nome sugere - irá executar a função a **cada** `X` milisegundos, porém se desencorajado. Quando um código em execução bloqueia a chamada do timeout, `setInterval` continuará -emitindo chamads para a função em questão. Isto pode, especialmente com intervalos curtos, +emitindo chamadas para a função em questão. Isto pode, especialmente com intervalos curtos, resultar em uma pilha de chamadas de função. function foo(){ @@ -129,7 +129,7 @@ Esta funcionalidade **nunca** deve ser utilizada pois internamente faz uso de `e Uma vez que `eval` não é chamado [diretamente](#core.eval) neste caso, a string passada como argumento para `setTimeout` será executada no *escopo global*; assim, ela -não usará a variávle local `foo` do escopo de `bar`. +não usará a variável local `foo` do escopo de `bar`. Também é recomendado **não** usar uma string para passar argumentos para a função que será chamada por qualquer uma das funções de timeout. From add9f23c9bf77efcfb956361a0e2648cc1aaf203 Mon Sep 17 00:00:00 2001 From: Jesus Urrabieta Date: Thu, 12 Jan 2017 19:25:53 +0100 Subject: [PATCH 091/105] Minor translation Fix. This edit solves the Issue: ES translation issue in "Notation of Keys" section. #361 (https://github.com/BonsaiDen/JavaScript-Garden/issues/361) Original Issue Text:ES translation issue in "Notation of Keys" section. #361 There is a translation error (into Spanish) in the "Notation of Keys" section of the "JavaScript Garden", just before "The prototype" section. The original English text reads: "This error arises from the fact that delete is a keyword;" And the translation reads: "Este error se debe al eliminar una keyword;" that means "The error is due to deleting a keyword". Also it translates a language keyword, and that I think is wrong. A better translation might be (just a suggestion): "Este error se produce porque delete es una palabra clave;" Thanks for your time and al the great work put into the garden... It's green and beautiful. --- doc/es/object/general.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/es/object/general.md b/doc/es/object/general.md index b06264ec..da48e138 100644 --- a/doc/es/object/general.md +++ b/doc/es/object/general.md @@ -91,7 +91,7 @@ Las propiedades de los objetos puede ser simbolizados como caracteres planos y c a otro mal diseño del parser de JavaScript, lo anterior es una excepción de `SyntaxError` antes de ECMAScript 5. -Este error se debe al `eliminar` una *keyword*; por lo tanto, debe ser +Este error se produce porque `delete` es una *keyword*; por lo tanto, debe ser anotado como un *string literal* para asegurarse que será interpretado correctamente por diversos motores de JavaScript. From 3ba3f9a7cd7a595ab24e4423405bf4df6c827727 Mon Sep 17 00:00:00 2001 From: Zoltan Sebestyen Date: Sat, 21 Jan 2017 16:39:07 +0100 Subject: [PATCH 092/105] various typo fixes --- doc/hu/function/general.md | 4 ++-- doc/hu/function/this.md | 14 +++++++------- doc/hu/object/forinloop.md | 8 ++++---- doc/hu/object/general.md | 8 ++++---- doc/hu/object/prototype.md | 2 +- 5 files changed, 18 insertions(+), 18 deletions(-) diff --git a/doc/hu/function/general.md b/doc/hu/function/general.md index 4392060e..4921d83e 100644 --- a/doc/hu/function/general.md +++ b/doc/hu/function/general.md @@ -9,7 +9,7 @@ egy másik -aszinkron- függvény paramétereként. function foo() {} -Ez a függvény felkerül a scope tetejére ([hoisting](#function.scopes)), mielőtt a kód végrehajtása megtörténne. Így abban a scopeban ahol *definiálták*, *mindenhol* elérhető, +Ez a függvény felkerül a scope tetejére ([hoisting](#function.scopes)), mielőtt a kód végrehajtása megtörténne. Így abban a scope-ban, ahol *definiálták*, *mindenhol* elérhető, még abban a trükkös esetben is, hogyha a kód azon pontján hívjuk ezt a függvényt, mielőtt definiáltuk volna (látszólag). @@ -41,7 +41,7 @@ Egy másik érdekes eset, amikor névvel ellátott függvényeket adunk érték } bar(); // ReferenceError -Ebben a példában a `bar`t önmagában nem lehet elérni egy külső scopeból (utolsó sor), +Ebben a példában a `bar`t önmagában nem lehet elérni egy külső scope-ból (utolsó sor), mivel egyből értékül adtuk a `foo` változónak. Ennek ellenére a `bar`on belül elérhető a `bar` név. A tanulság az, hogy a függvény önmagát *mindig* eléri a saját scopeján belül, és ez a JavaScriptben található [névfeloldásnak](#function.scopes) köszönhető. diff --git a/doc/hu/function/this.md b/doc/hu/function/this.md index 4b2efd74..b85a1819 100644 --- a/doc/hu/function/this.md +++ b/doc/hu/function/this.md @@ -1,20 +1,20 @@ ## A `this` mágikus működése -A `this` kicsit másképp működik a JavaScriptben mint ahogy azt megszokhattuk -más nyelvekben. Ugyanis pontosan **ötféle** módja lehet annak hogy a `this` +A `this` kicsit másképp működik a JavaScriptben, mint ahogy azt megszokhattuk +más nyelvekben. Ugyanis pontosan **ötféle** módja lehet annak, hogy a `this` éppen mire utal a nyelvben. ### A Globális hatókör this; -Amikor globális hatókörben van használva a this, akkor pontosan a *globális* objektumra utal. +Amikor globális hatókörben van használva a `this`, akkor pontosan a *globális* objektumra utal. ### Függvény híváskor foo(); -Itt, a `this` megint a *globális* objektumra fog utalni. +Itt a `this` megint a *globális* objektumra fog utalni. > **ES5 Megjegyzés:** Strict módban a globális eset **nem létezik** többé. > Ezekben az esetekben a `this` értéke undefined lesz. @@ -80,8 +80,8 @@ lokálisan elhelyezni a `method`-on belül, ami már valóban a kívánt `this`- }; A `that` tuladjonképpen egy mezei változónév (nem kulcsszó), de sokszor használják arra, -hogy egy másik `this`-re hivatkozzanak vele. A [colsureökkel](#function.closures) kombinálva -ez a módszer arra is használható hogy `this`-eket passzolgassunk a vakvilágban és mégtovább. +hogy egy másik `this`-re hivatkozzanak vele. A [closure-ökkel](#function.closures) kombinálva +ez a módszer arra is használható, hogy `this`-eket passzolgassunk a vakvilágban és még tovább. ### Eljárások értékül adása @@ -107,4 +107,4 @@ ami a nyelv egyik fő erőssége. new Bar().method(); Amikor a `method` meghívódik a `Bar` példányaként, a `this` pontosan a `Bar` -megfelelő példányára fog mutatni. \ No newline at end of file +megfelelő példányára fog mutatni. diff --git a/doc/hu/object/forinloop.md b/doc/hu/object/forinloop.md index b004e557..642dc265 100644 --- a/doc/hu/object/forinloop.md +++ b/doc/hu/object/forinloop.md @@ -1,13 +1,13 @@ ## A `for in` ciklus -Csak úgy mint a jó öreg `in` operátor, a `for in` is bejárja az egész +Csak úgy, mint a jó öreg `in` operátor, a `for in` is bejárja az egész prototípus láncot, amikor egy objektum mezőin próbálnánk iterálni. > **Megjegyzés:** A `for in` ciklus **nem** fog iterálni azokon a mezőkön, > amelyeknek az `enumerable` tulajdonsága `false`-ra van állítva. Például a > `length` mező nem kerül az iterációba amikor egy tömbön iterálnánk végig. - // Mérgezzük Object.prototypeot! + // Mérgezzük Object.prototype-ot! Object.prototype.bar = 1; var foo = {moo: 2}; @@ -32,10 +32,10 @@ lakó [`hasOwnProperty`](#object.hasownproperty) függvény használatával érh } } -Ez az egyetlen helyes útja annak hogy az objektum saját mezőin iteráljunk csak végig. +Ez az egyetlen helyes útja annak, hogy az objektum saját mezőin iteráljunk csak végig. Mivel a `hasOwnProperty`-t használjuk, így csak a várt `moo`-t fogja kiírni. Tehén jó kódunk van! Hogyha a `hasOwnProperty`-t kihagynánk, a kódunk ki lenne téve nem várt -hibáknak, amik pl. abból fakadnak hogy valaki ocsmányul kiterjesztette az +hibáknak, amik pl. abból fakadnak, hogy valaki ocsmányul kiterjesztette az `Object.prototype`-t. Például, ha a [Prototype][1] frameworköt használjuk, és nem ilyen stílusban írjuk a diff --git a/doc/hu/object/general.md b/doc/hu/object/general.md index 8f396de4..296ddf3c 100644 --- a/doc/hu/object/general.md +++ b/doc/hu/object/general.md @@ -1,6 +1,6 @@ ## Objektumok és mezők használata -A JavaSciprtben minden objektumként működik, a [`null`](#core.undefined) és az [`undefined`](#core.undefined) kivételével. +A JavaScriptben minden objektumként működik, a [`null`](#core.undefined) és az [`undefined`](#core.undefined) kivételével. false.toString(); // 'hamis' [1, 2, 3].toString(); // '1,2,3' @@ -47,11 +47,11 @@ Egy objektum mezői kétféle módon érhetőek el, vagy az 'objektum.mezőnév' foo.1234; // SyntaxError foo['1234']; // működik -A két jelölés majdnem egyenértékűen használható, kivéve, hogy a szögletes zárójelekkel dinamkusan állíthatunk be mezőket és olyan neveket is választhatunk, amik amúgy szintaxis hibához vezetnének (Fordító: mivel a neveket stringbe kell rakni, megadhatunk a JS által "lefoglalt" kulcsszavakat is mezőnévként, habár ennek használata erősen kerülendő). +A két jelölés majdnem egyenértékűen használható, kivéve, hogy a szögletes zárójelekkel dinamikusan állíthatunk be mezőket és olyan neveket is választhatunk, amik amúgy szintaxis hibához vezetnének (Fordító: mivel a neveket stringbe kell rakni, megadhatunk a JS által "lefoglalt" kulcsszavakat is mezőnévként, habár ennek használata erősen kerülendő). ### Mezők törlése -Egyetlen módon lehet mezőt törölni egy objektumból ez pedig a `delete` operátor +Egyetlen módon lehet mezőt törölni egy objektumból, ez pedig a `delete` operátor használata; a mező értékének `undefined`-ra vagy `null`-ra való állítása csak magára az értékre van kihatással, de a kulcs ugyanúgy megmarad az objektumban. @@ -84,7 +84,7 @@ Az objektumok mezőnevei mind stringként, mind egyszerű szövegként (Ford.: a leírhatóak. A JavaScript értelmező hibája miatt, a fenti kód azonban `SyntaxErrort` eredményez ECMAScript 5 előtti verzió esetén. Ez a hiba onnan ered, hogy a `delete` egy *kulcsszó*, viszont érdemes *string literálként* -leírni hogy helyesen megértsék a régebbi JavaScript motorok is. +leírni, hogy helyesen megértsék a régebbi JavaScript motorok is. [1]: http://en.wikipedia.org/wiki/Hashmap diff --git a/doc/hu/object/prototype.md b/doc/hu/object/prototype.md index 95e45b3c..8d86f42a 100644 --- a/doc/hu/object/prototype.md +++ b/doc/hu/object/prototype.md @@ -4,7 +4,7 @@ A JavaScript nem a klasszikus öröklődést használja, hanem egy ún. *protot származtatást használ. Míg ezt gyakran a JavaScript legnagyobb hibái között tartják számon, valójában -ez a származtatási modell jóval kifejezőbb mint klasszikus barátja. +ez a származtatási modell jóval kifejezőbb, mint klasszikus barátja. Ezt jelzi, hogy például sokkal könnyebb megépíteni a klasszikus modellt, alapul véve a prototípusos modellt, míg a fordított irány kivitelezése igencsak nehézkes lenne. From cdfd71d8659010f9b8cbbf7bad1d369f2b71d999 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=92=9F=E6=99=93=E4=BB=95?= Date: Mon, 13 Feb 2017 21:16:27 -0600 Subject: [PATCH 093/105] fix typo MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 这里应该是 “未”,而不是 “为” --- doc/zh/types/typeof.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/zh/types/typeof.md b/doc/zh/types/typeof.md index f7a6cc1e..fec6fcf7 100755 --- a/doc/zh/types/typeof.md +++ b/doc/zh/types/typeof.md @@ -75,7 +75,7 @@ JavaScript 标准文档只给出了一种获取 `[[Class]]` 值的方法,那 Object.prototype.toString.call(undefined) // "[object Undefined]" -###测试为定义变量 +###测试未定义变量 typeof foo !== 'undefined' From ea285dafe028fcccb3f77d0b225c46b4d522a1ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=92=9F=E6=99=93=E4=BB=95?= Date: Tue, 14 Feb 2017 02:43:24 -0600 Subject: [PATCH 094/105] fix typo MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 这里应该用 “到” 更加准确 --- doc/zh/other/timeouts.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/zh/other/timeouts.md b/doc/zh/other/timeouts.md index 7810b39f..4b2cc5d0 100755 --- a/doc/zh/other/timeouts.md +++ b/doc/zh/other/timeouts.md @@ -101,7 +101,7 @@ } bar(); -由于 `eval` 在这种情况下不是被[直接](#core.eval)调用,因此传递到 `setTimeout` 的字符串会自*全局作用域*中执行; +由于 `eval` 在这种情况下不是被[直接](#core.eval)调用,因此传递到 `setTimeout` 的字符串会到*全局作用域*中执行; 因此,上面的回调函数使用的不是定义在 `bar` 作用域中的局部变量 `foo`。 建议**不要**在调用定时器函数时,为了向回调函数传递参数而使用字符串的形式。 From cf30742b4df6274aebbc2f2073480619c7b244de Mon Sep 17 00:00:00 2001 From: ivanov-v Date: Tue, 28 Mar 2017 16:56:54 +0300 Subject: [PATCH 095/105] Fix desktop nav --- site/style/garden.css | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/site/style/garden.css b/site/style/garden.css index 9c95ff95..b6d29302 100644 --- a/site/style/garden.css +++ b/site/style/garden.css @@ -72,13 +72,12 @@ body { nav { position: fixed; - margin-left: 750px; top: 0; + right: 0; padding-bottom: 20px; height: 100%; - text-shadow: none; - width: 240px; + width: 225px; } nav > div li { @@ -607,7 +606,6 @@ a abbr { #nav_main > ul > li { float: left; text-align: center; - width: 25%; border-bottom: 0; } From dc21512f72fe664d1b96d502eaa70f81aaf6d0df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Munk=C3=A1csi=20M=C3=A1rk?= Date: Thu, 27 Jul 2017 17:31:40 +0200 Subject: [PATCH 096/105] hungarian typos fixed --- doc/hu/array/constructor.md | 2 +- doc/hu/array/general.md | 4 ++-- doc/hu/core/delete.md | 6 +++--- doc/hu/core/eval.md | 2 +- doc/hu/core/semicolon.md | 2 +- doc/hu/function/arguments.md | 8 ++++---- doc/hu/function/closures.md | 8 ++++---- doc/hu/function/constructors.md | 8 ++++---- doc/hu/function/general.md | 4 ++-- doc/hu/function/scopes.md | 4 ++-- doc/hu/function/this.md | 4 ++-- doc/hu/intro/index.md | 2 +- doc/hu/object/general.md | 2 +- doc/hu/object/hasownproperty.md | 6 +++--- doc/hu/object/prototype.md | 8 ++++---- doc/hu/other/timeouts.md | 24 ++++++++++++------------ doc/hu/types/casting.md | 6 +++--- doc/hu/types/equality.md | 12 ++++++------ doc/hu/types/instanceof.md | 4 ++-- doc/hu/types/typeof.md | 2 +- 20 files changed, 59 insertions(+), 59 deletions(-) diff --git a/doc/hu/array/constructor.md b/doc/hu/array/constructor.md index 444644a0..57a5a9ca 100644 --- a/doc/hu/array/constructor.md +++ b/doc/hu/array/constructor.md @@ -10,7 +10,7 @@ ajánlott mindig a tömb literált - `[]` jelölés - használni új tömbök l new Array(3); // Eredmény: [] new Array('3') // Eredmény: ['3'] -Abban az esetben, hogyha ez a konstruktor csak egy `szám` paramétert kap, akkor +Abban az esetben, ha ez a konstruktor csak egy `szám` paramétert kap, akkor visszatérési értékül egy olyan tömböt fog létrehozni amelynek a `length` mezője akkorára van beállítva, ahogy azt megadtuk az argumentumban. Megjegyzendő hogy **csak** a `length` tulajdonság lesz ekkor beállítva; az egyes indexek külön-külön diff --git a/doc/hu/array/general.md b/doc/hu/array/general.md index 660bb3b3..f7fa98e4 100644 --- a/doc/hu/array/general.md +++ b/doc/hu/array/general.md @@ -13,7 +13,7 @@ lassabb mint egy sima `for` ciklus. ### Iteráció -Annak érdekébern hogy a legjobb teljesítményt érjük el a tömbökön való iteráció során, +Annak érdekében, hogy a legjobb teljesítményt érjük el a tömbökön való iteráció során, a legjobb hogyha a klasszikus `for` ciklust használjuk. var list = [1, 2, 3, 4, 5, ...... 100000000]; @@ -27,7 +27,7 @@ a `l = list.length` kifejezés használatával. Habár a `length` tulajdonság mindig magán a tömbön van definiálva, még mindig lehet egy kis teljesítmény kiesés amiatt hogy minden iterációban újra meg kell keresni ezt a tulajdonságot. Persze a legújabb JavaScript motorok **talán** -használnak erre optimalizációt, de nem lehet biztosan megmondani hogy ahol a kódunk +használnak erre optimalizációt, de nem lehet biztosan megmondani, hogy ahol a kódunk futni fog, az egy ilyen motor-e vagy sem. Valójában, a cachelés kihagyása azt eredményezheti, hogy a ciklusunk csak diff --git a/doc/hu/core/delete.md b/doc/hu/core/delete.md index 859a3537..89b95b41 100644 --- a/doc/hu/core/delete.md +++ b/doc/hu/core/delete.md @@ -41,7 +41,7 @@ Az expliciten beállított mezőket persze normálisan lehet törölni. obj.y; // undefined -A fenti példábna az `obj.x` és `obj.y` törölhető, mivel nincs `DontDelete` +A fenti példában az `obj.x` és `obj.y` törölhető, mivel nincs `DontDelete` attribútuma egyik mezőnek sem. Ezért működik az alábbi példa is. // működik, kivéve IE-ben @@ -52,7 +52,7 @@ attribútuma egyik mezőnek sem. Ezért működik az alábbi példa is. GLOBAL_OBJECT.a; // undefined Itt egy trükköt használunk az `a` törlésére. A [`this`](#function.this) itt -a Globális objektumra mutat, és expliciten bezetjük rajta az `a` változót, mint +a Globális objektumra mutat, és expliciten bevezetjük rajta az `a` változót, mint egy mezőjét, így törölni is tudjuk. Mint az szokás, a fenti kód egy kicsit bugos IE-ben (legalábbis 6-8-ig). @@ -88,4 +88,4 @@ meghatározva az ES aktuális verziójú specifikációjában, pl. a window) ### Összegzésképp A `delete` működése helyenként megjósolhatatlan, így biztonsággal csak olyan -objektumok mezőin használhatjuk amelyeket expliciten mi állítottunk be. \ No newline at end of file +objektumok mezőin használhatjuk, amelyeket expliciten mi állítottunk be. \ No newline at end of file diff --git a/doc/hu/core/eval.md b/doc/hu/core/eval.md index b2c83d45..9de5d3b3 100644 --- a/doc/hu/core/eval.md +++ b/doc/hu/core/eval.md @@ -44,6 +44,6 @@ nem megbízható/ismeretlen. ### Összegzésül Soha ne használjunk `eval`t. Bármilyen kód működése, teljesítménye, ill. biztonsága -megkérdőjelezhető amely használja ezt a nyelvi elemet. Semmilyen megoldás +megkérdőjelezhető, amely használja ezt a nyelvi elemet. Semmilyen megoldás használata **nem ajánlott** amely első sorban `eval`ra épül. Ekkor egy *jobb megoldás* szükségeltetik, amely nem függ az `eval`tól. \ No newline at end of file diff --git a/doc/hu/core/semicolon.md b/doc/hu/core/semicolon.md index 0241234f..fddd1acf 100644 --- a/doc/hu/core/semicolon.md +++ b/doc/hu/core/semicolon.md @@ -93,7 +93,7 @@ Az értelmező drasztikusan megváltoztatta a fenti kódot. A legtöbb esetben a beillesztő **rosszul** tippel. (A ford.: Semmilyen nyelvben sem jó, hogyha hagyjuk hogy a gép találja ki mit -szerettünk volna írni. Néma gyereknek az anyja sem érti a kódját ugye) +szerettünk volna írni. Néma gyereknek az anyja sem érti a kódját ugye.) ### Kezdő Zárójelek diff --git a/doc/hu/function/arguments.md b/doc/hu/function/arguments.md index d7b77ec0..0a0a1e6f 100644 --- a/doc/hu/function/arguments.md +++ b/doc/hu/function/arguments.md @@ -22,12 +22,12 @@ Ez a kódrészlet egy új `Array` objektummá varázsolja az emlegetett `argumen Array.prototype.slice.call(arguments); -De, ez a konverzió meglehetősen **lassú** így egyáltalán **nem ajánlott** teljesítmény kirtikus +De, ez a konverzió meglehetősen **lassú**, így egyáltalán **nem ajánlott** teljesítmény kirtikus alkalmazások írásakor. ### Argumentumok kezelése -A következő módszer ajánlott arra az esetre hogyha az egyik függvény paramétereit egy-az-egyben +A következő módszer ajánlott arra az esetre, hogy ha az egyik függvény paramétereit egy-az-egyben át szeretnénk adni egy másik függvény számára. function foo() { @@ -37,7 +37,7 @@ A következő módszer ajánlott arra az esetre hogyha az egyik függvény param // sok okos kód ide } -Egy másik trükk arra hogy teljesen független wrapper függvényeket gyártsunk, a `call` +Egy másik trükk arra, hogy teljesen független wrapper függvényeket gyártsunk, a `call` és `apply` együttes használata. function Foo() {} @@ -83,7 +83,7 @@ egyik paraméterének ezt a nevet választjuk. Azonban a *getterek* és *setterek* mindig létrejönnek, de ez ne zavarjon meg minket, mert semmiféle befolyása nincs a teljesítményre, pláne olyan kódban ahol sokkal több mindennel -is foglalkozunk mint az `arguments` objetkumhoz való hozzáférés. +is foglalkozunk, mint az `arguments` objetkumhoz való hozzáférés. > **ES5 Megjegyzés:** Ezek a **getterek** és **setterek** nem jönnek létre strict módban. diff --git a/doc/hu/function/closures.md b/doc/hu/function/closures.md index 436f58e2..33d4e3bd 100644 --- a/doc/hu/function/closures.md +++ b/doc/hu/function/closures.md @@ -3,7 +3,7 @@ A JavaScript nyelv egyik legerőteljesebb tulajdonsága a *closure*-ök használatában rejlik. Ezek használatával a hatókörök egymásba ágyazhatóak, és egy belső hatókör mindig hozzáfér az őt körülvevő, külső hatókör változóihoz. Miután JavaScriptben egyetlen dologgal lehet -hatóköröket kifejezni, és ez a [funkció](#function.scopes) (bizony az if, try/catch és hasonló blokkok **nem** jelentenek új hatókört, mint pl. a Javaban), az összes funkció closure-ként szerepel. +hatóköröket kifejezni, és ez a [függvény](#function.scopes) (bizony az if, try/catch és hasonló blokkok **nem** jelentenek új hatókört, mint pl. a Javaban), az összes funkció closure-ként szerepel. ### Privát változók emulálása @@ -25,7 +25,7 @@ hatóköröket kifejezni, és ez a [funkció](#function.scopes) (bizony az if, t foo.get(); // 5 Ebben a példában a `Counter` **két** closure-rel tér vissza: az `increment` és -a `get` funkcióval. Mind a két funkció **referenciát** tárol a `Counter` hatókörre, +a `get` függvénnyel. Mind a két függvény **referenciát** tárol a `Counter` hatókörre, és így mindketten hozzáférnek a `count` változóhoz, ami ebben a hatókörben lett definiálva. @@ -46,7 +46,7 @@ létre fogja hozni, vagy felül fogja írni a *globális* `count` változót (wi ### Closure-ök használata ciklusokban -Az egyik leggyakoribb hiba amit el lehet követni, az a closure-ök ciklusokban való használata. +Az egyik leggyakoribb hiba, amit el lehet követni, az a closure-ök ciklusokban való használata. Annak is azon speciális esete amikor a ciklus indexváltozóját szeretnénk lemásolni a closure-ön belül. for(var i = 0; i < 10; i++) { @@ -82,7 +82,7 @@ függvénnyel](#function.scopes). A külső (wrapper) névtelen függvény így azonnal meghívódik az `i` ciklusváltozóval, mint paraméterrel, és így mindig egy másolatot fog kapni az `i` változó **értékéről**, amit ő `e` néven emészt tovább. -Így a `setTimeout`ban lévő névtelen fgv. mindig az `e` nevű referenciára fog mutatni, aminek az értéke így már **nem** változik meg a ciklus futása során. +Így a `setTimeout`ban lévő névtelen függvény mindig az `e` nevű referenciára fog mutatni, aminek az értéke így már **nem** változik meg a ciklus futása során. Egy másik lehetséges út a megoldáshoz az, hogy egy wrapper függvényt visszatérítünk a setTimeoutból, aminek ugyanaz lesz a hatása, mint a fentebbi példának. diff --git a/doc/hu/function/constructors.md b/doc/hu/function/constructors.md index e48e0b60..c955cce1 100644 --- a/doc/hu/function/constructors.md +++ b/doc/hu/function/constructors.md @@ -1,6 +1,6 @@ ## Konstruktorok -Csak úgy mint minden más, a konstruktorok működése szintén különbözik +Csak úgy, mint minden más, a konstruktorok működése szintén különbözik a megszokottól. Itt minden függvényhívás amelyet a `new` kulcsszó előz meg, konstruktor hívásnak számít. @@ -19,7 +19,7 @@ Ha a konstruktor függvényben nincs `return` utasítás, akkor automatikusan a var test = new Foo(); -A fenti kódban a `Foo` függvényt mint konstruktort hívjuk meg, ami a test változóban +A fenti kódban a `Foo` függvényt, mint konstruktort hívjuk meg, ami a test változóban egy új objektumot fog eredményezni. Ennek az objektumnak a `prototípusa` a Foo prototípusa lesz. Trükkös ugyan, de ha mégis van `return` utasítás az éppen konstruált függvényben, akkor @@ -47,12 +47,12 @@ Hogyha kihagyjuk a `new` kulcsszó használatát, a függvény **nem** egy új o } Foo(); // undefined -A [`this`](#function.this) JavaScript beli működésének köszönhetően, mégha le is +A [`this`](#function.this) JavaScript beli működésének köszönhetően, még ha le is fut az előbbi kód, akkor a `this` helyére a *globális objektumot* képzeljük. ### Gyárak (Factory-k) -Ahhoz, hogy teljesen eltudjuk hagyni a `new` kulcsszó használatát, a konstruktor +Ahhoz, hogy teljesen el tudjuk hagyni a `new` kulcsszó használatát, a konstruktor függvény explicit értékkel kell visszatérjen. function Bar() { diff --git a/doc/hu/function/general.md b/doc/hu/function/general.md index 4921d83e..9b62b0ee 100644 --- a/doc/hu/function/general.md +++ b/doc/hu/function/general.md @@ -1,7 +1,7 @@ ## Függvény deklarációk és kifejezések A függvények JavaScriptben egyben objektumok is. Ez azt jelenti, hogy -ugyanúgy lehet őket passzolgatni mint bármelyik más értékeket. Ezt a featuret +ugyanúgy lehet őket passzolgatni, mint bármelyik más értékeket. Ezt a featuret gyakran használják arra, hogy egy *névtelen (callback) függvényt* átadjunk egy másik -aszinkron- függvény paramétereként. @@ -30,7 +30,7 @@ Habár ebben a példában a `var` deklaráció futás előtt a kód tetejére k ettől függetlenül a foo mint függvény meghívásakor hibát fogunk kapni. Ugyanis a deklaráció felkúszott, azonban az értékadás csak futásidőben fog megtörténni, -addig is a foo változó értéke [undefined](#core.undefined) marad. Az undefinedet pedig hiába hívjuk függvényként, TypeErrort kapunk végeredményül. +addig is a foo változó értéke [undefined](#core.undefined) marad. Az undefinedot pedig hiába hívjuk függvényként, TypeErrort kapunk végeredményül. ### Névvel ellátott függvény kifejezés diff --git a/doc/hu/function/scopes.md b/doc/hu/function/scopes.md index 71c99902..7e75a0b5 100644 --- a/doc/hu/function/scopes.md +++ b/doc/hu/function/scopes.md @@ -214,8 +214,8 @@ ahhoz hogy meghívhatóak legyenek, először ki kell értékelni őket. ) // a függvény objektum visszatérítése () // az eredmény meghívása -Persze más kifejezések is használhatóak arra hogy kiértékeljük és meghívjuk -a függvény kifejezést, amelyek habár szintaxisukban eltérnek, ugyanazt eredményezik. +Persze más kifejezések is használhatóak arra, hogy kiértékeljük és meghívjuk +a függvény kifejezést, amelyek habár szintaxisukban eltérnek, ugyan azt eredményezik. // Még több stílus anonymus függvények azonnali hívásához... !function(){}() diff --git a/doc/hu/function/this.md b/doc/hu/function/this.md index b85a1819..8c363873 100644 --- a/doc/hu/function/this.md +++ b/doc/hu/function/this.md @@ -1,7 +1,7 @@ ## A `this` mágikus működése A `this` kicsit másképp működik a JavaScriptben, mint ahogy azt megszokhattuk -más nyelvekben. Ugyanis pontosan **ötféle** módja lehet annak, hogy a `this` +más nyelvekben. Ugyanis pontosan **öt féle** módja lehet annak, hogy a `this` éppen mire utal a nyelvben. ### A Globális hatókör @@ -40,7 +40,7 @@ az *újonnan létrehozott* `Objektumra` fog hivatkozni. foo.apply(bar, [1, 2, 3]); // ugyanaz mint egy sorral lejjebb foo.call(bar, 1, 2, 3); // argumentumok: a = 1, b = 2, c = 3 -A `Function.prototype`-ban levő `call` vagy `apply` használatakor aztán elszabadul a pokol :). +A `Function.prototype`-ban levő `call` vagy `apply` használatakor aztán elszabadul a pokol 😀. Ezekben az esetekben ugyanis a this a foo hívásakor **egzaktan** be lesz állítva az apply/call első argumentumára. diff --git a/doc/hu/intro/index.md b/doc/hu/intro/index.md index 911baf61..83bb9b94 100644 --- a/doc/hu/intro/index.md +++ b/doc/hu/intro/index.md @@ -2,7 +2,7 @@ A **JavaScript Garden** egy folytonosan növekvő kódgyűjtemény amely a nyelv kihívást okozó részeit hivatott tisztázni. Itt tanácsokat kaphatsz afelől, hogyan kerüld el a leggyakoribb programozási- valamint nyelvi hibákat, hogyan írj gyorsabb kódot, és mik a legsűrűbben elkövetett *bad practice*k amelyekkel egy átlagos JavaScript programozó (nem) mindennapi útján találkozhat a nyelv megismerése közben. -A JavaScript Gardennek **nem** célja hogy megtanítsa a JavaScript nyelvet! +A JavaScript Gardennek **nem** célja, hogy megtanítsa a JavaScript nyelvet! Az itt felsorolt témák megértéséhez mindenképp szükséges némi tapasztalat. Ha a nyelv alapjait szeretnéd elsajátítani, először nézd át ezt a kiváló [tutorialt][1] a Mozilla Developer Networkön. ## Szerzők diff --git a/doc/hu/object/general.md b/doc/hu/object/general.md index 296ddf3c..0032e735 100644 --- a/doc/hu/object/general.md +++ b/doc/hu/object/general.md @@ -2,7 +2,7 @@ A JavaScriptben minden objektumként működik, a [`null`](#core.undefined) és az [`undefined`](#core.undefined) kivételével. - false.toString(); // 'hamis' + false.toString(); // 'false' [1, 2, 3].toString(); // '1,2,3' function Foo(){} diff --git a/doc/hu/object/hasownproperty.md b/doc/hu/object/hasownproperty.md index 46d713e8..245a3287 100644 --- a/doc/hu/object/hasownproperty.md +++ b/doc/hu/object/hasownproperty.md @@ -1,8 +1,8 @@ ## `hasOwnProperty` -Hogy megtudjuk nézni egy adott objektum saját mezőit - azokat a mezőket amelyek +Hogy meg tudjuk nézni egy adott objektum saját mezőit - azokat a mezőket, amelyek az objektumon *közvetlenül* vannak definiálva, és nem valahol a -[prototípus láncon](#object.prototype) -, a `hasOwnProperty` függvényt használata +[prototípus láncon](#object.prototype) -, a `hasOwnProperty` függvény használata ajánlott, amelyet az összes objektum amúgy is örököl az `Object.prototype`-ból. > **Megj.:** Vicces programozók miatt, **nem** biztos hogy elég lesz megnézni hogy @@ -58,4 +58,4 @@ A `hasOwnProperty` használata az **egyetlen** megbízható módszer annak eldö hogy egy mező közvetlenül az objektumon lett-e létrehozva. Melegen ajánlott a `hasOwnProperty`-t **minden** [`for in` ciklusban](#object.forinloop) használni. Használatával ugyanis elkerülhetjük a kontár módon kiegészített natív prototípusokból -fakadó esetleges hibákat, amire példát az imént láttunk. \ No newline at end of file +fakadó esetleges hibákat, amire az imént láttunk példát. \ No newline at end of file diff --git a/doc/hu/object/prototype.md b/doc/hu/object/prototype.md index 8d86f42a..27a533b4 100644 --- a/doc/hu/object/prototype.md +++ b/doc/hu/object/prototype.md @@ -73,7 +73,7 @@ visszatérni. Alapjáraton, a JavaScript a prototype nevű mezőt használja a prototípus láncok kialakításához, de ettől függetlenül ez is ugyanolyan mező mint a többi, és -**bármilyen** értéket belehet neki állítani. Viszont a primitív típusokat egyszerűen +**bármilyen** értéket be lehet neki állítani. Viszont a primitív típusokat egyszerűen figyelmen kívül fogja hagyni a feldolgozó. function Foo() {} @@ -84,9 +84,9 @@ mezőkre és ezeknek az átállításával bele lehet szólni a prototípus lán ### Teljesítmény -Értelemszerűen, minnél nagyobb a prototípus lánc, annál tovább tart egy-egy mező +Értelemszerűen, minél nagyobb a prototípus lánc, annál tovább tart egy-egy mező felkeresése, és ez rossz hatással lehet a kód teljesítményére. Emellett, ha egy -olyan mezőt próbálunk elérni amely nincs az adott objektum példányban, az mindig +olyan mezőt próbálunk elérni, amely nincs az adott objektum példányban, az mindig a teljes lánc bejárását fogja eredményezni. Vigyázat! Akkor is bejárjuk a teljes láncot, amikor egy objektum mezőin próbálunk [iterálni](#object.forinloop). @@ -98,7 +98,7 @@ definiált prototípust próbálunk kiegészíteni új kóddal. Ezt [monkey patching][1]-nek is hívják, és aktívan kerülendő, mivel megtöri az *egységbe zárás* elvét. Habár ezt a technikát olyan népszerű framework-ök -is használják mint a [Prototype][2], ettől függetlenül ne hagyjuk magunkat csőbe húzni; +is használják, mint a [Prototype][2], ettől függetlenül ne hagyjuk magunkat csőbe húzni; nincs ésszerű indok arra, hogy összezavarjuk a beépített típusokat, további *nem standard* saját funkcionalitással. diff --git a/doc/hu/other/timeouts.md b/doc/hu/other/timeouts.md index 36c17e56..7ad37665 100644 --- a/doc/hu/other/timeouts.md +++ b/doc/hu/other/timeouts.md @@ -3,16 +3,16 @@ Mivel a JavaScript aszinkron, a `setTimeout` és `setInterval` használatával lehetséges késleltetni a kódok lefutási idejét. -> **Megjegyzés:** A timeout fv.-ek **nem** részei az ECMAScript Standardnek. +> **Megjegyzés:** A timeout függvények **nem** részei az ECMAScript Standardnek. > Mivel a [DOM][1] részeként lettek implementálva. function foo() {} var id = setTimeout(foo, 1000); // Egy számmal (> 0) tér vissza -Amikor a `setTimeout` függvényt meghívjuk, válaszul egy timeout ID-t kapunk +Amikor a `setTimeout` függvényt meghívjuk, válaszul egy timeout ID-t kapunk, valamint be lesz ütemezve a `foo` függvényhívás, hogy **körülbelül** 1000 miliszekundum múlva fusson le a jövőben. A `foo` **egyszer** lesz végrehajtva. -Az aktuális JavaScript motor időzítésétől függően, és annak figyelembe vételével +Az aktuális JavaScript motor időzítésétől függően, és annak figyelembe vételével, hogy a JavaScript mindig egyszálú, tehát a megelőző kódok blokkolhatják a szálat, **soha** nem lehet biztonságosan meghatározni hogy valóban a kért időzítéssel fog lefutni a kód amit megadtunk a `setTimeout`ban. Erre semmilyen biztosíték nincs. @@ -40,8 +40,8 @@ utal. ### Híváshalmozás a `setInterval`al -Míg a `setTimeout` csak egyszer futtatja le a megadott függvényt, a `setInterval` -- ahogy a neve is mutatja - **minden** `X` miliszekundumban végrehajtja a +Míg a `setTimeout` csak egyszer futtatja le a megadott függvényt, a `setInterval` - +ahogy a neve is mutatja - **minden** `X` miliszekundumban végrehajtja a neki átadott kódot, használata pedig erősen kerülendő. Nagy hátulütője, hogy még akkor is ütemezi az újabb és újabb @@ -62,7 +62,7 @@ futtatása először végzett. ### Hogyan Bánjunk El a Blokkolással -A legkönnyebb és kontrollálhatóbb megoldásnak az bizonyul, hogyha a `setTimeout` +A legkönnyebb és kontrollálhatóbb megoldásnak az bizonyul, ha a `setTimeout` függvényt a rögtön a foo-n belül használjuk. function foo(){ @@ -72,13 +72,13 @@ függvényt a rögtön a foo-n belül használjuk. foo(); Ez nem csak egységbe zárja a `setTimeout` hívást, de meggátolja a felesleges hívások -felhalmozását, és több irányítást ad a kezünkbe. A `foo` így magától eltudja +felhalmozását, és több irányítást ad a kezünkbe. A `foo` így magától el tudja dönteni, hogy akarja-e újra futtatni önmagát vagy sem. ### Timeout Tisztogatás Kézzel A `clearTimeout` vagy `clearInterval` hívással tudjuk a timeoutjainkat -megszüntetni, természetesen attól függ hogy melyiket használjuk, +megszüntetni, természetesen attól függ, hogy melyiket használjuk, hogy melyik `set` függvénnyel indítottuk útjára a timeoutunkat. var id = setTimeout(foo, 1000); @@ -94,7 +94,7 @@ hívás törlésére, ezért bruteforce módszerekhez kell folyamodjunk. clearTimeout(i); } -Persze ez csak véletlenszerű lövöldözés, semmi sem garantálja hogy a fenti +Persze ez csak véletlenszerű lövöldözés, semmi sem garantálja, hogy a fenti módszerrel nem marad timeout a rendszerben (A ford.: például az ezredik timeout vagy afelett). Szóval egy másik módszer ennek megoldására, hogy feltételezzük hogy minden `setTimeout` hívással az azonosítók száma egyel növekszik. @@ -106,8 +106,8 @@ minden `setTimeout` hívással az azonosítók száma egyel növekszik. clearTimeout(i); } -Habár ez a megoldás minden böngészőben megy (egyenlőre), ez az azonosítókról született mondás nincs specifikációban rögzítve, és ennek megfelelően változhat. -Az ajánlott módszer továbbra is az, hogy kövessük nyomon az összes timeout azonosítót amit generáltunk, és így ki is tudjuk őket rendesen törölni. +Habár ez a megoldás minden böngészőben megy (egyelőre), ez az azonosítókról született mondás nincs specifikációban rögzítve, és ennek megfelelően változhat. +Az ajánlott módszer továbbra is az, hogy kövessük nyomon az összes timeout azonosítót, amit generáltunk, és így ki is tudjuk őket rendesen törölni. ### `eval` A Színfalak Mögött @@ -158,7 +158,7 @@ a timeout függvények által meg lesz hívva a későbbiekben. **Soha** ne használjunk stringeket a `setTimeout` vagy `setInterval` első paramétereiként. Ha argumentumokat kell átadni a meghívandó függvénynek, az egyértelműen **rossz** kódra utal. Ebben az esetben a függvényhívás -lebonyolításához egy *anoním* függvény használata ajánlott. +lebonyolításához egy *anonim* függvény használata ajánlott. Továbbá, mivel az ütemező kódja nem blokkolódik a JavaScript futás által, a `setInterval` használata úgy általában kerülendő. diff --git a/doc/hu/types/casting.md b/doc/hu/types/casting.md index b5066ca5..ee604410 100644 --- a/doc/hu/types/casting.md +++ b/doc/hu/types/casting.md @@ -26,14 +26,14 @@ meglepetéseket. ### Natív típusok konstruktorai -A jó hír az, hogy a natív típusok mint a `Number` és a `String` különféle -módon viselkednek hogyha a `new` kulcsszóval avagy anélkül vannak inicializálva. +A jó hír az, hogy a natív típusok, mint a `Number` és a `String` különféle +módon viselkednek, hogy ha a `new` kulcsszóval avagy anélkül vannak inicializálva. new Number(10) === 10; // Hamis, Objektum vs. Szám Number(10) === 10; // Igaz, Szám vs. szám new Number(10) + 0 === 10; // Igaz, az implicit konverziónak hála -Ha egy natív típust mint a `Number` konstruktorként kezelünk, akkor egy új +Ha egy natív típust, mint a `Number` konstruktorként kezelünk, akkor egy új `Number` objektumot kapunk. De ha kihagyjuk a `new` kulcsszót akkor a `Number` egy egyszerű konverter függvényként fog viselkedni. diff --git a/doc/hu/types/equality.md b/doc/hu/types/equality.md index 0b503294..d627e86c 100644 --- a/doc/hu/types/equality.md +++ b/doc/hu/types/equality.md @@ -7,7 +7,7 @@ vizsgálatára Az egyenlőség vizsgálatot végző (egyik) operátort így jelöljük: `==` -A JavaScript egy *gyengén típusos* nyelv. Ez azt jelenti hogy az egyenlőség +A JavaScript egy *gyengén típusos* nyelv. Ez azt jelenti, hogy az egyenlőség operátor **típuskényszerítést** alkalmaz ahhoz, hogy össze tudjon hasonlítani két értéket. @@ -21,9 +21,9 @@ két értéket. null == undefined // igaz " \t\r\n" == 0 // igaz -A fenti táblázat szépen mutatja hogy mi a típuskényszerítés eredménye, és egyben +A fenti táblázat szépen mutatja, hogy mi a típuskényszerítés eredménye, és egyben azt is, hogy miért rossz szokás a `==` használata. Szokás szerint, ez megint -olyan fícsör ami nehezen követhető kódhoz vezethet a komplikált konverziós +olyan fícsör, ami nehezen követhető kódhoz vezethet a komplikált konverziós szabályai miatt. Pláne, hogy a kényszerítés teljesítmény problémákhoz is vezet; ugyanis, mielőtt @@ -34,7 +34,7 @@ a megfelelő típusra. Ez az operátor már **három** egyenlőségjelből áll: `===`. -Ugyanúgy működik mint az előbbi, kivéve hogy ez a változat **nem** alkalmaz +Ugyanúgy működik, mint az előbbi, kivéve hogy ez a változat **nem** alkalmaz típuskényszerítést az operandusai között. "" === "0" // hamis @@ -49,12 +49,12 @@ típuskényszerítést az operandusai között. A felső eredmények sokkal egyértelműbbek és ennek köszönhetően sokkal hamarabb eltörik a kód egy-egy ellenőrzésen. Ettől sokkal hibatűrőbb lesz -a produktumunk, és ráadásul teljesítménybeli gondjaink sem lesznek. +a produktumunk, ráadásul teljesítménybeli gondjaink sem lesznek. ### Objektumok összehasonlítása Habár mind a `==`-t és a `===`-t is egyenlőség operátornak hívjuk, eltérően -viselkednek hogyha legalább az egyik operandusuk egy objektum. +viselkednek, hogy ha legalább az egyik operandusuk egy objektum. {} === {}; // hamis new String('foo') === 'foo'; // hamis diff --git a/doc/hu/types/instanceof.md b/doc/hu/types/instanceof.md index 82f5942d..50dbd489 100644 --- a/doc/hu/types/instanceof.md +++ b/doc/hu/types/instanceof.md @@ -2,7 +2,7 @@ Az `instanceof` operátor a két operandusának konstruktorait hasonlítja össze. Csak akkor bizonyul hasznosnak, amikor saját készítésű objektumokon alkalmazzuk. -Beépített típusokon ugyanolyan hasztalan alkalmazni mint a [typeof operátort](#types.typeof). +Beépített típusokon ugyanolyan hasztalan alkalmazni, mint a [typeof operátort](#types.typeof). ### Saját objektumok összehasonlítása @@ -32,4 +32,4 @@ a böngészőn belül), mivel a konstruktoruk nem pontosan ugyanaz az objektum l ### Összegzésül -Az `instanceof`-ot tehát **csak** megegyező JS kontextusból származó, saját készítésű objektumoknál használjuk. Minden más felhasználása kerülendő, csak úgy mint a [`typeof`](#types.typeof) operátor esetén. \ No newline at end of file +Az `instanceof`-ot tehát **csak** megegyező JS kontextusból származó, saját készítésű objektumoknál használjuk. Minden más felhasználása kerülendő, csak úgy, mint a [`typeof`](#types.typeof) operátor esetén. \ No newline at end of file diff --git a/doc/hu/types/typeof.md b/doc/hu/types/typeof.md index b39070fd..556543dc 100644 --- a/doc/hu/types/typeof.md +++ b/doc/hu/types/typeof.md @@ -5,7 +5,7 @@ lehetőség szerint a JavaScript nyelv egyik legnagyobb buktatója, mivel majdne teljesen **rosszul működik**. Habár az `instanceof`-nak korlátozottan még lehet értelme, a `typeof` operátor -tényleg csak egyetlen praktikus use case-zel rendelkezik és ez **nem** az hogy egy +tényleg csak egyetlen praktikus use case-el rendelkezik és ez **nem** az, hogy egy objektum típusvizsgálatát elvégezzük. > **Megjegyzés:** Mivel a `typeof` vizsgálatot ravaszul úgy is le lehet írni, From 0fa71491cfd2142152913f50edae94a42981802f Mon Sep 17 00:00:00 2001 From: Siddharth Kshetrapal Date: Mon, 9 Oct 2017 15:47:03 +0530 Subject: [PATCH 097/105] Change foobar to slightly better variables --- doc/en/object/general.md | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/doc/en/object/general.md b/doc/en/object/general.md index 5ee2e0de..864dda5a 100644 --- a/doc/en/object/general.md +++ b/doc/en/object/general.md @@ -6,9 +6,9 @@ Everything in JavaScript acts like an object, with the only two exceptions being false.toString(); // 'false' [1, 2, 3].toString(); // '1,2,3' - function Foo(){} - Foo.bar = 1; - Foo.bar; // 1 + function sayHello(){} + sayHello.bar = 1; + sayHello.bar; // 1 A common misconception is that number literals cannot be used as objects. That is because a flaw in JavaScript's parser tries to parse the *dot @@ -32,25 +32,25 @@ Using an object literal - `{}` notation - it is possible to create a plain object. This new object [inherits](#object.prototype) from `Object.prototype` and does not have [own properties](#object.hasownproperty) defined. - var foo = {}; // a new empty object + var names = {}; // a new empty object - // a new object with a 'test' property with value 12 - var bar = {test: 12}; + // a new object with a 'name' property with value 'Rob' + var rob = {name: 'Rob'}; ### Accessing Properties The properties of an object can be accessed in two ways, via either the dot notation or the square bracket notation. - var foo = {name: 'kitten'} - foo.name; // kitten - foo['name']; // kitten + var pet = {name: 'kitten'} + pet.name; // kitten + pet['name']; // kitten var get = 'name'; - foo[get]; // kitten + pet[get]; // kitten - foo.1234; // SyntaxError - foo['1234']; // works + pet.1234; // SyntaxError + pet['1234']; // works The notations work almost identically, with the only difference being that the square bracket notation allows for dynamic setting of properties and @@ -63,13 +63,13 @@ operator; setting the property to `undefined` or `null` only removes the *value* associated with the property, but not the *key*. var obj = { - bar: 1, - foo: 2, - baz: 3 + a: 1, + b: 2, + c: 3 }; - obj.bar = undefined; - obj.foo = null; - delete obj.baz; + obj.a = undefined; + obj.b = null; + delete obj.c; for(var i in obj) { if (obj.hasOwnProperty(i)) { @@ -77,7 +77,7 @@ operator; setting the property to `undefined` or `null` only removes the } } -The above outputs both `bar undefined` and `foo null` - only `baz` was +The above outputs both `a undefined` and `b null` - only `c` was removed and is therefore missing from the output. ### Notation of Keys From ebcf110edcbaffe2febe2be9fe0e51b0138400f2 Mon Sep 17 00:00:00 2001 From: Siddharth Kshetrapal Date: Mon, 9 Oct 2017 20:25:27 +0530 Subject: [PATCH 098/105] Missed a bar --- doc/en/object/general.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/en/object/general.md b/doc/en/object/general.md index 864dda5a..41450da2 100644 --- a/doc/en/object/general.md +++ b/doc/en/object/general.md @@ -7,8 +7,8 @@ Everything in JavaScript acts like an object, with the only two exceptions being [1, 2, 3].toString(); // '1,2,3' function sayHello(){} - sayHello.bar = 1; - sayHello.bar; // 1 + sayHello.numberOfTimes = 1; + sayHello.numberOfTimes; // 1 A common misconception is that number literals cannot be used as objects. That is because a flaw in JavaScript's parser tries to parse the *dot From 624a9e62d649ab9b0fed39ed7f78c350316b6cf4 Mon Sep 17 00:00:00 2001 From: Siddharth Kshetrapal Date: Mon, 9 Oct 2017 23:00:58 +0530 Subject: [PATCH 099/105] replace numberOfTimes to count --- doc/en/object/general.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/en/object/general.md b/doc/en/object/general.md index 41450da2..89589229 100644 --- a/doc/en/object/general.md +++ b/doc/en/object/general.md @@ -7,8 +7,8 @@ Everything in JavaScript acts like an object, with the only two exceptions being [1, 2, 3].toString(); // '1,2,3' function sayHello(){} - sayHello.numberOfTimes = 1; - sayHello.numberOfTimes; // 1 + sayHello.count = 1; + sayHello.count; // 1 A common misconception is that number literals cannot be used as objects. That is because a flaw in JavaScript's parser tries to parse the *dot From ee3407cd3b38e06c7f2bad1b61c3c0feb744cf7f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my=20Mouzin?= Date: Fri, 30 Mar 2018 17:57:56 +0200 Subject: [PATCH 100/105] Fix missing spaces in the footer --- garden.jade | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/garden.jade b/garden.jade index bd191d39..bb67c1d1 100644 --- a/garden.jade +++ b/garden.jade @@ -79,10 +79,10 @@ html(lang=language) footer p Copyright ©. Built with | - a(href='http://nodejs.org/') Node.js - | using a - a(href='https://github.com/visionmedia/jade/') jade - | template. + a(href='http://nodejs.org/') Node.js + | using a + a(href='https://github.com/visionmedia/jade/') jade + | template. script(src='http://ajax.googleapis.com/ajax/libs/jquery/1.5.1/jquery.min.js') From 2c7a3a61148c2d41ed07c76b12b410880e22883a Mon Sep 17 00:00:00 2001 From: a90100 Date: Sat, 14 Mar 2020 15:32:50 +0800 Subject: [PATCH 101/105] Fixed zhtw typo & translated chapter this into zhtw --- doc/zhtw/array/constructor.md | 2 +- doc/zhtw/array/general.md | 6 ++--- doc/zhtw/core/undefined.md | 2 +- doc/zhtw/function/arguments.md | 4 ++-- doc/zhtw/function/scopes.md | 2 +- doc/zhtw/function/this.md | 41 +++++++++++++--------------------- doc/zhtw/object/general.md | 2 +- doc/zhtw/types/instanceof.md | 4 ++-- doc/zhtw/types/typeof.md | 6 ++--- 9 files changed, 29 insertions(+), 40 deletions(-) diff --git a/doc/zhtw/array/constructor.md b/doc/zhtw/array/constructor.md index 6c66656d..fd952497 100644 --- a/doc/zhtw/array/constructor.md +++ b/doc/zhtw/array/constructor.md @@ -10,7 +10,7 @@ new Array('3') // 結果: ['3'] 在上面的範例 `new Array(3)` 當只有一個參數傳入到 `Array` 的建構函數 -且那個參數事宜個數字,建構函數會回傳空值 +且那個參數是一個數字,建構函數會回傳空值 但是 `Array` 長度的屬性會變成跟那個參數一樣(以此範例來看他回傳的長度為 3) **注意** 只有他長度的屬性會被設定,整個 Array裡面的數值都不會初始化 diff --git a/doc/zhtw/array/general.md b/doc/zhtw/array/general.md index e9de8782..1a59d72e 100644 --- a/doc/zhtw/array/general.md +++ b/doc/zhtw/array/general.md @@ -7,7 +7,7 @@ > 只有 [objects](#object.general) 來管理建值的相對應關係 > Arrays 是**保持** 順序的,Objects **則沒有** -因為 `for in` 迴圈會列舉所有在原型 Array 上的屬性因為他會使用[`hasOwnProperty`](#object.hasownproperty), 這會使得 Array 比原本的 `for` 迴圈慢上二十幾倍 +因為 `for in` 迴圈會使用[`hasOwnProperty`](#object.hasownproperty),所以它會列舉所有在原型 Array 上的屬性,這會使得 Array 比原本的 `for` 迴圈慢上二十幾倍 ### 迴圈 @@ -20,8 +20,8 @@ 在上面的例子中利用 `l = list.length` 來處理 Array 的長度問題。 -雖然 `length` 屬性是屬於 Array 中其中一個屬性,但是他還使有一定的性能消耗在每次循環的訪問。 -近期 Javascript 使用 **may** 來解決在這上面的效率問題,但是在現在的引擎上還不一定有支援。 +雖然 `length` 屬性是屬於 Array 中其中一個屬性,但是他在每次循環還是有一定的性能消耗。 +近期 Javascript **可能**使用來解決在這上面的效率問題,但是在現在的引擎上還不一定有支援。 實際上,不使用暫存 Array 長度的方式比使用暫存的版本還要慢很多。 diff --git a/doc/zhtw/core/undefined.md b/doc/zhtw/core/undefined.md index 491f8528..501dfb95 100644 --- a/doc/zhtw/core/undefined.md +++ b/doc/zhtw/core/undefined.md @@ -1,6 +1,6 @@ ## `undefined` 和 `null` -JavaScript 中有兩個表示空值的方式, `null` 和 `undefined` , `undefined`式比較常用的一種。 +JavaScript 中有兩個表示空值的方式, `null` 和 `undefined` , `undefined`是比較常用的一種。 ### `undefined` 的值 diff --git a/doc/zhtw/function/arguments.md b/doc/zhtw/function/arguments.md index 7cb76032..39aa58f0 100644 --- a/doc/zhtw/function/arguments.md +++ b/doc/zhtw/function/arguments.md @@ -18,7 +18,7 @@ Array.prototype.slice.call(arguments); -這種轉化方式比較 **慢** ,不建議使用這種作法如果再追求效率的程式中。 +這種轉化方式比較 **慢** ,如果在追求效率的程式中,不建議使用這種作法。 ### 傳遞參數 @@ -53,7 +53,7 @@ 在 `Arguments` 物件創造的 *getter* 和 *setter* 的函數方法,可以被視為原本函數的變數。 -因此,改變了一個變數會跟著改變它的值而且也間接的改變稻香對應的 `arguments` 的物件,反之亦然。 +因此,改變了一個形式參將數會跟著改變對應的 `arguments` 的屬性,反之亦然。 function foo(a, b, c) { arguments[0] = 2; diff --git a/doc/zhtw/function/scopes.md b/doc/zhtw/function/scopes.md index 3e151282..d443656f 100644 --- a/doc/zhtw/function/scopes.md +++ b/doc/zhtw/function/scopes.md @@ -160,7 +160,7 @@ JavaScript 中所有的作用區,包括 *全域作用域*,都有一個特殊 1. 當作用域內是否有 `var foo` 的定義。 2. 函式形式參數是否有使用 `foo` 名稱定義。 - 3. 函式自身是剖叫做 `foo`。 + 3. 函式自身是否叫做 `foo`。 4. 回溯到上一個層級然後再從第一個開始往下去查。 > **注意: ** 自定義 `arguments` 參數會阻止原生的 `arguments` 的物件創立 diff --git a/doc/zhtw/function/this.md b/doc/zhtw/function/this.md index 116a70df..361a06c4 100644 --- a/doc/zhtw/function/this.md +++ b/doc/zhtw/function/this.md @@ -1,6 +1,6 @@ ## `this` 的工作原理 -JavaScript 有移到完全部屬於其他語言處理 `this` 的處理機制。 +JavaScript 有一道完全不屬於其他語言處理 `this` 的處理機制。 在 **五** 種不同的情況下, `this` 指向的各不相同 ### 全域變數 @@ -42,8 +42,7 @@ JavaScript 有移到完全部屬於其他語言處理 `this` 的處理機制。 當使用 `function.prototype` 上的 `call` 或只 `apply` 方法時,函式內的 `this` 將會被 **顯示設置** 為函式調用的第一個參數。 -As a result, in the above example the *method case* does **not** apply, and `this` -inside of `foo` will be set to `bar`. +因此,在以上的例子中已不適用*函式調用*的原則,而且`this`會被設定指向`bar`。 > **Note:** `this` **cannot** be used to refer to the object inside of an `Object` > literal. So `var obj = {me: this}` will **not** result in `me` referring to @@ -51,56 +50,48 @@ inside of `foo` will be set to `bar`. ### 常見誤解 -While most of these cases make sense, the first can be considered another -mis-design of the language because it **never** has any practical use. +儘管大部分的例子都合理,但第一個例子(譯者注: 應該是指前面呼叫一個函式的那個例子)可以被視為一個語言的不良設計,因為它**從來**就沒有實際用途。 Foo.method = function() { function test() { - // this is set to the global object + // this 設定為全域 } test(); }; -A common misconception is that `this` inside of `test` refers to `Foo`; while in -fact, it **does not**. +一個常見的誤解是 `test` 中的 `this` 指向 `Foo` 物件,但實際上並**不是**。 -In order to gain access to `Foo` from within `test`, it is necessary to create a -local variable inside of `method` that refers to `Foo`. +為了在 `test` 中使用 `Foo` 物件,我們需要在 `method` 函式内部建立一個區域變數指向 `Foo`。 Foo.method = function() { var that = this; function test() { - // Use that instead of this here + // 這裡使用 that 而非 this } test(); }; -`that` is just a normal variable name, but it is commonly used for the reference to an -outer `this`. In combination with [closures](#function.closures), it can also -be used to pass `this` values around. +`that` 只是普通的名字,不過這個名字常被用用來指向外部的 `this`。 在 [閉包](#function.closures) 一節,可以看到它(`that`)可以取代 `this` 傳遞。 -As of ECMAScript 5 you can use the `bind` method combined with an anonymous function to achieve the same result. +在 ECMAScript 5 ,你可以使用 `bind` 結合匿名函式達到相同結果。 Foo.method = function() { var test = function() { - // this now refers to Foo + // this 指向 Foo }.bind(this); test(); }; -### Assigning Methods +### 函式表達式 -Another thing that does **not** work in JavaScript is function aliasing, which is -**assigning** a method to a variable. +另一個在 JavaScript 中**不會**運作的就是 function aliasing,也就是函式**賦值**給一個變數。 var test = someObject.methodTest; test(); -Due to the first case, `test` now acts like a plain function call; therefore, -`this` inside it will no longer refer to `someObject`. +上例中,`test` 就像一個普通的函式被调用;因此,函式内的 this 將不再指向 `someObject`。 -While the late binding of `this` might seem like a bad idea at first, in -fact, it is what makes [prototypal inheritance](#object.prototype) work. +雖然起初 `this` 的绑定特性似乎像是個壞主意,但事實上,它使得 [原型繼承](#object.prototype)得以運作。 function Foo() {} Foo.prototype.method = function() {}; @@ -110,7 +101,5 @@ fact, it is what makes [prototypal inheritance](#object.prototype) work. new Bar().method(); -When `method` gets called on an instance of `Bar`, `this` will now refer to that -very instance. - +當 `method` 被呼叫時,`this` 將會指向 `Bar` 的實體物件。 diff --git a/doc/zhtw/object/general.md b/doc/zhtw/object/general.md index aee1885c..6cd56600 100644 --- a/doc/zhtw/object/general.md +++ b/doc/zhtw/object/general.md @@ -69,7 +69,7 @@ JavaScript 的物件可以作為 [*Hashmaps*][1]使用,主要用來保存命 只有 `baz` 真正被刪除而已,所以從輸出結果中消失。 -### 屬姓名的語法 +### 屬性名的語法 var test = { 'case': 'I am a keyword, so I must be notated as a string', diff --git a/doc/zhtw/types/instanceof.md b/doc/zhtw/types/instanceof.md index 5bdb00d2..fa5e8c30 100644 --- a/doc/zhtw/types/instanceof.md +++ b/doc/zhtw/types/instanceof.md @@ -1,6 +1,6 @@ ## `instanceof` 操作符 -`instanceof` 操作符用來比較兩個建構函數的操作數。只有在比較字定義的物件時才有意義。這和 [typeof operator](#types.typeof)一樣用處不大。 +`instanceof` 操作符用來比較兩個建構函數的操作數。只有在比較自定義的物件時才有意義。這和 [typeof operator](#types.typeof)一樣用處不大。 ### 比較定意義物件 @@ -24,7 +24,7 @@ 'foo' instanceof String; // false 'foo' instanceof Object; // false -有一點需要注意的, `instanceof` 不能用來物件來自上下文不同的屬性(例如:瀏覽器中不同的文檔結構),因為它的建構函數不一樣。 +有一點需要注意的, `instanceof` 不會在來自不同的上下文的物件運作(例如:瀏覽器中不同的文檔結構),因為它的建構函數不一樣。 ### In Conclusion diff --git a/doc/zhtw/types/typeof.md b/doc/zhtw/types/typeof.md index 7058e55b..0a0908b0 100644 --- a/doc/zhtw/types/typeof.md +++ b/doc/zhtw/types/typeof.md @@ -3,7 +3,7 @@ `typeof` 操作符 (和 [`instanceof`](#types.instanceof)) 可能是最大的設計錯誤在 JavaScript,因為它幾乎不可能從它們那裡得到想要的結果。 -雖然 `instanceof` 還是有一些限制上的使用, `typeof` 只有一個實際上的運傭情形,但是 **不是** 用在檢查物件的類型。 +雖然 `instanceof` 還是有一些限制上的使用, `typeof` 只有一個實際上的運用情形,但是 **不是** 用在檢查物件的類型。 > **注意:** 由於 `typeof` 也可以像函式的語法被調用,例如 `typeof(obj)`,但這並是一個函數調用。 > 那兩個小括號只是用來計算一個表達式的值,這個返回值會作為 `typeof` 操作符的一個操作數。 @@ -67,8 +67,8 @@ JavaScript 標準文檔只給出了一種獲取 `[[Class]]` 值的方法,那 ### 結語 為了去檢查一個物件,強烈建議去使用 `Object.prototype.toString` 因為這是唯一可以依賴的方式。 -正如上面所看到的 `typeof` 的亦先返回值在標準文檔中未定義,因此不同的引擎可能不同。 +正如上面所看到的 `typeof` 的事先返回值在標準文檔中未定義,因此不同的引擎可能不同。 -除非為了檢測一個變數是否定義,我們應該避免是用 `typeof` 操作符。 +除非為了檢測一個變數是否定義,我們應該避免使用 `typeof` 操作符。 From 8f02c2f361c33164e2fe244f935a0c153de7c011 Mon Sep 17 00:00:00 2001 From: camilobernal Date: Fri, 15 May 2020 07:51:26 -0500 Subject: [PATCH 102/105] Fix word in functions-constructors (ES) --- doc/es/function/constructors.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/es/function/constructors.md b/doc/es/function/constructors.md index 0850cb4b..9c4e2946 100644 --- a/doc/es/function/constructors.md +++ b/doc/es/function/constructors.md @@ -48,7 +48,7 @@ Cuando una `nueva` keyword es omitidad, la función **no** devuelve un nuevo obj } Foo(); // undefined -Auqnue el ejemplo anterior puede parecer que trabaja en algunos casos, debido +Aunque el ejemplo anterior puede parecer que trabaja en algunos casos, debido a los trabajos de [`this`](#function.this) en JavaScript, que usará el *objeto global* como valor de `this`. From 3de9dc4d039ec5be4876f3e32896446219d55952 Mon Sep 17 00:00:00 2001 From: camilobernal Date: Fri, 15 May 2020 07:52:24 -0500 Subject: [PATCH 103/105] Fix word in functions-scopes (ES) --- doc/es/function/scopes.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/es/function/scopes.md b/doc/es/function/scopes.md index d641a939..c6bfb8e0 100644 --- a/doc/es/function/scopes.md +++ b/doc/es/function/scopes.md @@ -47,7 +47,7 @@ mayor implicación. test(); foo; // 21 -Dejando de lador la sentencia `var` dentro de la función `test` sobre escribiría el +Dejando de lado la sentencia `var` dentro de la función `test` sobre escribiría el valor de `foo`. Si bien al principio puede parecer un gran cambio, se tiene miles de líneas de código en JavaScript y no se usaría `var` introduciendose en un horrible y difícil detección de errores. From 78c0862ddae8e3b6b7f4b9a5b35f0fdfe5fdbd69 Mon Sep 17 00:00:00 2001 From: camilobernal Date: Fri, 15 May 2020 07:53:35 -0500 Subject: [PATCH 104/105] Fix word in functions-scopes (ES) --- doc/es/function/scopes.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/es/function/scopes.md b/doc/es/function/scopes.md index c6bfb8e0..00ed940c 100644 --- a/doc/es/function/scopes.md +++ b/doc/es/function/scopes.md @@ -68,7 +68,7 @@ horrible y difícil detección de errores. El bucle externo terminará después de la primera llamada a `subLoop`, desde `subLoop` sobreescribe el valor global de `i`. Usando `var` para el segundo bucle `for` se hace fácil evitar este error. La sentencia `var` no debe **nunca** dejarse a menos que -el *efecto deseado* es afectado por el ámbito exteriror. +el *efecto deseado* es afectado por el ámbito exterior. ### Variables locales From 06a3882008ef0704258f808d76bf2211c7db7e7a Mon Sep 17 00:00:00 2001 From: Tim Ruffles Date: Wed, 19 Jun 2024 16:11:30 +0100 Subject: [PATCH 105/105] Update README.md --- README.md | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index cb9cb3d4..be02cfd5 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,18 @@ JavaScript Garden ================= +2024 update: this project has not been actively maintained in years. The original author +[took the site down](https://github.com/BonsaiDen/JavaScript-Garden/commit/93278fbcafa569fd193f8784abc267e9db09c645) +in 2022 (no judgement - updating it would be a big project!). At that point it was already long out of date, e.g. missing +the new language features from ES6 onwards. + +Many excellent modern guides exist, e.g. [Eloquent Javascript](https://eloquentjavascript.net/), or +the [MDN guide](https://developer.mozilla.org/en-US/docs/Web/JavaScript). + +Thanks for all the maintainers and translators over the years! + +----- + **JavaScript Garden** is a growing collection of documentation about the most quirky parts of the JavaScript programming language. It gives advice to avoid common mistakes, subtle bugs, as well as performance issues and bad @@ -19,7 +31,7 @@ This guide is the work of two lovely Stack Overflow users, [Ivo Wetzel][6] [many others](https://github.com/BonsaiDen/JavaScript-Garden/graphs/contributors) who've worked hard to provide translations or fixes. -It's currently maintained by [Tim Ruffles](http://twitter.com/timruffles). +It was maintained by [Tim Ruffles](http://twitter.com/timruffles) from 2013-2020ish. ## Contributing