Sintaxe JavaScript - JavaScript syntax

A sintaxe do JavaScript é o conjunto de regras que definem um programa JavaScript estruturado corretamente.

Os exemplos abaixo usam a função de log do objeto de console presente na maioria dos navegadores para saída de texto padrão .

A biblioteca padrão JavaScript carece de uma função de saída de texto padrão oficial (com exceção de document.write). Dado que o JavaScript é usado principalmente para scripts do lado do cliente em navegadores da Web modernos e que quase todos os navegadores da Web fornecem a função de alerta , o alerta também pode ser usado, mas não é comumente usado.

Origens

Brendan Eich resumiu a ancestralidade da sintaxe no primeiro parágrafo da especificação do JavaScript 1.1 da seguinte maneira:

JavaScript pega emprestado a maior parte de sua sintaxe de Java , mas também herda de Awk e Perl , com alguma influência indireta de Self em seu sistema de protótipo de objeto.

Fundamentos

Sensibilidade a maiúsculas e minúsculas

JavaScript é sensível a maiúsculas e minúsculas . É comum iniciar o nome de um construtor com uma letra maiúscula e o nome de uma função ou variável com uma letra minúscula.

Exemplo:

var a=5;
console.log(a); // 5
console.log(A); // throws a ReferenceError: A is not defined

Espaço em branco e ponto e vírgula

Ao contrário do C , os espaços em branco na origem do JavaScript podem impactar diretamente a semântica . Os pontos-e-vírgulas encerram as declarações em JavaScript. Por causa da inserção automática de ponto-e-vírgula (ASI), algumas instruções bem formadas quando uma nova linha é analisada serão consideradas completas, como se um ponto-e-vírgula tivesse sido inserido antes da nova linha. Algumas autoridades aconselham o fornecimento de ponto-e-vírgula de terminação de instrução explicitamente, porque isso pode diminuir os efeitos indesejados da inserção automática de ponto-e-vírgula.

Existem dois problemas: cinco tokens podem iniciar uma instrução ou ser a extensão de uma instrução completa; e cinco produções restritas, em que as quebras de linha não são permitidas em certas posições, podendo gerar análise incorreta.

Os cinco tokens problemáticos são o parêntese de abertura " ( ", colchete de abertura " [ ", barra " / ", mais " + " e menos " - ". Destes, o parêntese de abertura é comum no padrão de expressão de função imediatamente invocado , e o colchete aberto ocorre às vezes, enquanto outros são bastante raros. O exemplo dado na especificação é:

a = b + c
(d + e).foo()

// Treated as:
//  a = b + c(d + e).foo();

com a sugestão de que a instrução anterior seja encerrada com um ponto e vírgula.

Alguns sugerem que, em vez do uso de líderes ponto e vírgula em linhas começando com ' ( ' ou ' [ ', de modo que a linha não é acidentalmente se juntou com a anterior. Isto é conhecido como um ponto e vírgula defensiva , e é especialmente recomendado, porque o código de outra forma, tornar-se ambíguo quando é reorganizado. Por exemplo:

a = b + c
;(d + e).foo()

// Treated as:
//  a = b + c;
//  (d + e).foo();

O ponto-e-vírgula inicial às vezes também é usado no início das bibliotecas JavaScript, no caso de serem anexados a outra biblioteca que omite um ponto-e-vírgula final, pois isso pode resultar em ambigüidade da instrução inicial.

As cinco produções restritas são retornar , lançar , interromper , continuar e pós-incremento / decremento. Em todos os casos, a inserção de ponto-e-vírgula não corrige o problema, mas torna a sintaxe analisada clara, tornando o erro mais fácil de detectar. return e throw recebem um valor opcional, enquanto break e continue recebem um rótulo opcional. Em todos os casos, o conselho é manter o valor ou rótulo na mesma linha da instrução. Isso geralmente aparece na instrução return, onde se pode retornar um grande literal de objeto, que pode ser colocado acidentalmente começando em uma nova linha. Para pós-incremento / decremento, há ambigüidade potencial com pré-incremento / decremento e, novamente, é recomendado simplesmente mantê-los na mesma linha.

return
a + b;

// Returns undefined. Treated as:
//   return;
//   a + b;
// Should be written as:
//   return a + b;

Comentários

A sintaxe do comentário é a mesma que em C ++ , Swift e muitas outras linguagens.

// a short, one-line comment

/* this is a long, multi-line comment
  about my script. May it one day
  be great. */

/* Comments /* may not be nested */ Syntax error */

Variáveis

Variáveis em JavaScript padrão não têm nenhum tipo anexado, então qualquer valor (cada valor tem um tipo) pode ser armazenado em qualquer variável. Começando com ES6 , a 6ª versão do idioma, as variáveis ​​podem ser declaradas com varpara variáveis ​​de escopo de função e / letou constque são para variáveis ​​de nível de bloco . Antes do ES6, as variáveis ​​só podiam ser declaradas com uma varinstrução. Os valores atribuídos às variáveis ​​declaradas com constnão podem ser alterados, mas suas propriedades podem. O identificador de uma variável deve começar com uma letra, sublinhado ( _ ) ou cifrão ( $ ), enquanto os caracteres subsequentes também podem ser dígitos ( 0-9 ). O JavaScript diferencia maiúsculas de minúsculas, portanto, os caracteres maiúsculos de "A" a "Z" são diferentes dos caracteres minúsculos de "a" a "z".

A partir do JavaScript 1.5, letras ISO 8859-1 ou Unicode (ou \ uXXXX sequências de escape Unicode) podem ser usadas em identificadores. Em certas implementações de JavaScript, o sinal de arroba (@) pode ser usado em um identificador, mas isso é contrário às especificações e não é suportado em implementações mais recentes.

Escopo e içamento

Variáveis ​​declaradas com vartêm escopo léxico em nível de função , enquanto aquelas com letou consttêm escopo em nível de bloco . As declarações são processadas antes que qualquer código seja executado. Isso é conhecido como içamento , e é equivalente a variáveis ​​sendodeclaradasparafrenteno topo da função ou bloco.

Com var, lete constdeclarações, somente a declaração é içada; atribuições não são içadas. Portanto, uma instrução no meio da função é equivalente a uma instrução de declaração no topo da função e uma instrução de atribuição naquele ponto no meio da função. Isso significa que os valores não podem ser acessados ​​antes de serem declarados; referência direta não é possível. Com o valor de uma variável é até que seja inicializado. As variáveis ​​declaradas com ou não podem ser acessadas até que sejam inicializadas, portanto, fazer referência à variável causará um erro. var x = 1var xx = 1varundefinedletconst

Declarações de funções, que declaram uma variável e atribuem uma função a ela, são semelhantes às declarações de variáveis, mas além de içar a declaração, também elevam a atribuição - como se a declaração inteira aparecesse no topo da função contida - e assim a referência direta também é possível: a localização de uma instrução de função dentro de uma função envolvente é irrelevante. Isto é diferente de uma expressão de função a ser atribuído a uma variável em um var, letou constdeclaração.

Então, por exemplo,

var func = function() { .. } // declaration is hoisted only
function func() { .. } // declaration and assignment are hoisted

O escopo do bloco pode ser produzido envolvendo todo o bloco em uma função e, em seguida, executando-o - isso é conhecido como o padrão de expressão de função imediatamente invocado - ou declarando a variável usando a letpalavra - chave.

Declaração e atribuição

Variáveis ​​declaradas fora de um escopo são globais . Se uma variável for declarada em um escopo superior, ela pode ser acessada por escopos filho.

Quando o JavaScript tenta resolver um identificador, ele procura no escopo local. Se esse identificador não for encontrado, ele procura no próximo escopo externo e assim por diante ao longo da cadeia de escopo até atingir o escopo global onde residem as variáveis ​​globais. Se ainda não for encontrado, o JavaScript gerará uma ReferenceErrorexceção.

Ao atribuir um identificador, o JavaScript passa exatamente pelo mesmo processo para recuperar esse identificador, exceto que se não for encontrado no escopo global , ele criará a "variável" no escopo onde foi criado. Como consequência, uma variável nunca declarada será global, se atribuída. Declarar uma variável (com a palavra-chave var) no escopo global (ou seja, fora de qualquer corpo de função (ou bloco no caso de let / const)), atribuir um identificador nunca declarado ou adicionar uma propriedade ao objeto global (geralmente janela ) também criar uma nova variável global.

Observe que o modo estrito do JavaScript proíbe a atribuição de uma variável não declarada, o que evita a poluição do namespace global.

Exemplos

Aqui estão alguns exemplos de declarações de variáveis ​​e escopo:

var x1 = 0; // A global variable, because it is not in any function
let x2 = 0; // Also global, this time because it is not in any block

function f() {
  var z = 'foxes', r = 'birds'; // 2 local variables
  m = 'fish'; // global, because it wasn't declared anywhere before

  function child() {
    var r = 'monkeys'; // This variable is local and does not affect the "birds" r of the parent function.
    z = 'penguins'; // Closure: Child function is able to access the variables of the parent function.
  }

  twenty = 20; // This variable is declared on the next line, but usable anywhere in the function, even before, as here
  var twenty;

  child();
  return x1 + x2; // We can use x1 and x2 here, because they are global
}

f();

console.log(z); // This line will raise a ReferenceError exception, because the value of z is no longer available
for (let i = 0; i < 10; i++) console.log(i);
console.log(i); // throws a ReferenceError: i is not defined
for (const i = 0; i < 10; i++) console.log(i); // throws a TypeError: Assignment to constant variable

const pi; // throws a SyntaxError: Missing initializer in const declaration

Tipos de dados primitivos

A linguagem JavaScript fornece seis tipos de dados primitivos :

  • Indefinido
  • Número
  • BigInt
  • Fragmento
  • boleano
  • Símbolo

Alguns dos tipos de dados primitivos também fornecem um conjunto de valores nomeados que representam as extensões dos limites do tipo. Esses valores nomeados são descritos nas seções apropriadas abaixo.

Indefinido

O valor de "undefined" é atribuído a todas as variáveis ​​não inicializadas e também é retornado ao verificar as propriedades do objeto que não existem. Em um contexto booleano, o valor indefinido é considerado um valor falso.

Nota: undefined é considerado um tipo primitivo genuíno. A menos que seja convertido explicitamente, o valor indefinido pode se comportar de maneira inesperada em comparação a outros tipos que são avaliados como falsos em um contexto lógico.

var test;                         // variable declared, but not defined, ...
                                  // ... set to value of undefined
var testObj = {};
console.log(test);                // test variable exists, but value not ...
                                  // ... defined, displays undefined
console.log(testObj.myProp);      // testObj exists, property does not, ...
                                  // ... displays undefined
console.log(undefined == null);   // unenforced type during check, displays true
console.log(undefined === null);  // enforce type during check, displays false

Nota: Não há literal de linguagem embutido para undefined. Portanto, não é uma maneira infalível de verificar se uma variável é indefinida, porque em versões anteriores ao ECMAScript 5, é legal para alguém escrever . Uma abordagem mais robusta é comparar usando . (x === undefined)var undefined = "I'm defined now";(typeof x === 'undefined')

Funções como esta não funcionarão conforme o esperado:

function isUndefined(x) { var u; return x === u; }             // like this...
function isUndefined(x) { return x === void 0; }               // ... or that second one
function isUndefined(x) { return (typeof x) === "undefined"; } // ... or that third one

Aqui, a chamada isUndefined(my_var)gera um ReferenceError se my_var for um identificador desconhecido, ao passo que não. typeof my_var === 'undefined'

Número

Os números são representados em binário como duplas de ponto flutuante IEEE-754 . Embora esse formato forneça uma precisão de quase 16 dígitos significativos , nem sempre pode representar exatamente números reais, incluindo frações.

Isso se torna um problema ao comparar ou formatar números. Por exemplo:

console.log(0.2 + 0.1 === 0.3); // displays false
console.log(0.94 - 0.01);       // displays 0.9299999999999999

Como resultado, uma rotina como o método toFixed () deve ser usada para arredondar os números sempre que eles forem formatados para saída .

Os números podem ser especificados em qualquer uma dessas notações:

345;    // an "integer", although there is only one numeric type in JavaScript
34.5;   // a floating-point number
3.45e2; // another floating-point, equivalent to 345
0b1011; // a binary integer equal to 11
0o377;   // an octal integer equal to 255
0xFF;   // a hexadecimal integer equal to 255, digits represented by the ...
        // ... letters A-F may be upper or lowercase

Há também um separador numérico, _ (o sublinhado), introduzido no ES2021:

// Note: Wikipedia syntax doesn't support numeric separators yet
1_000_000_000;    // Used with big numbers
1_000_000.5;      // Support with decimals
1_000e1_000;      // Support with exponents

// Support with binary, octals and hex
0b0000_0000_0101_1011;
0o0001_3520_0237_1327;
0xFFFF_FFFF_FFFF_FFFE;

// But you can't use them next to a non-digit number part, or at the start or end
_12; // Variable is not defined (the underscore makes it a variable identifier)
12_; // Syntax error (cannot be at the end of numbers)
12_.0; // Syntax error (doesn't make sense to put a separator next to the decimal point)
12._0; // Syntax error
12e_6; // Syntax error (next to "e", a non-digit. Doesn't make sense to put a separator at the start)
1000____0000; // Syntax error (next to "_", a non-digit. Only 1 separator at a time is allowed

As extensões + ∞ , −∞ e NaN (não é um número) do tipo de número podem ser obtidas por duas expressões de programa:

Infinity; // positive infinity (negative obtained with -Infinity for instance)
NaN;      // The Not-A-Number value, also returned as a failure in ...
          // ... string-to-number conversions

Infinity e NaN são números:

typeof Infinity;   // returns "number"
typeof NaN;        // returns "number"

Esses três valores especiais correspondem e se comportam como o IEEE-754 os descreve.

O construtor de número (usado como uma função), ou um + ou - unário, pode ser usado para realizar a conversão numérica explícita:

var myString = "123.456";
var myNumber1 = Number(myString);
var myNumber2 = +myString;

Quando usado como um construtor, um objeto de wrapper numérico é criado (embora seja de pouca utilidade):

myNumericWrapper = new Number(123.456);

No entanto, NaN não é igual a si mesmo:

const nan = NaN;
console.log(NaN == NaN);        // false
console.log(NaN === NaN);       // false
console.log(NaN !== NaN);       // true
console.log(nan !== nan);       // true

// You can use the isNaN methods to check for NaN
console.log(isNaN("converted to NaN"));     // true
console.log(isNaN(NaN));                    // true
console.log(Number.isNaN("not converted")); // false
console.log(Number.isNaN(NaN));             // true

BigInt

BigInts podem ser usados ​​para números inteiros arbitrariamente grandes . Especialmente números inteiros maiores que 2 53 - 1, que é o maior número que o JavaScript pode representar de forma confiável com a primitiva Number e representado pela constante Number.MAX_SAFE_INTEGER.

Ao dividir BigInts, os resultados são truncados .

Fragmento

Uma string em JavaScript é uma sequência de caracteres. Em JavaScript, as strings podem ser criadas diretamente (como literais) colocando a série de caracteres entre aspas duplas (") ou simples ('). Essas strings devem ser escritas em uma única linha, mas podem incluir caracteres de nova linha de escape (como \ n). O padrão JavaScript permite que o caractere de crase (`, também conhecido como acento grave ou crase ) cite strings literais de várias linhas, mas isso é compatível apenas com alguns navegadores a partir de 2016: Firefox e Chrome, mas não o Internet Explorer 11.

var greeting = "Hello, World!";
var anotherGreeting = 'Greetings, people of Earth.';

Caracteres individuais dentro de uma cadeia de caracteres pode ser acedido usando o charAt método (fornecida por String.prototype ). Esta é a forma preferida ao acessar caracteres individuais em uma string, porque também funciona em navegadores não modernos:

var h = greeting.charAt(0);

Em navegadores modernos, caracteres individuais dentro de uma string podem ser acessados ​​(como strings com apenas um único caractere) por meio da mesma notação das matrizes:

var h = greeting[0];

No entanto, as strings de JavaScript são imutáveis :

greeting[0] = "H"; // Fails.

Aplicar o operador de igualdade ("==") a duas strings retorna verdadeiro, se as strings tiverem o mesmo conteúdo, o que significa: do mesmo comprimento e contendo a mesma sequência de caracteres (maiúsculas e minúsculas são significativas para alfabetos). Assim:

var x = "World";
var compare1 = ("Hello, " +x == "Hello, World"); // Here compare1 contains true.
var compare2 = ("Hello, " +x == "hello, World"); // Here compare2 contains  ...
                                                 // ... false since the ...
                                                 // ... first characters ...
                                                 // ... of both operands ...
                                                 // ... are not of the same case.

As cotações do mesmo tipo não podem ser aninhadas, a menos que tenham escape .

var x = '"Hello, World!" he said.'; // Just fine.
var x = ""Hello, World!" he said."; //  Not good.
var x = "\"Hello, World!\" he said."; // Works by escaping " with \"

O construtor String cria um objeto string (um objeto envolvendo uma string):

var greeting = new String("Hello, World!");

Esses objetos têm um método valueOf que retorna a string primitiva envolvida neles:

var s = new String("Hello !");
typeof s; // Is 'object'.
typeof s.valueOf(); // Is 'string'.

A igualdade entre dois objetos String não se comporta como com primitivos de string:

var s1 = new String("Hello !");
var s2 = new String("Hello !");
s1 == s2; // Is false, because they are two distinct objects.
s1.valueOf() == s2.valueOf(); // Is true.

boleano

JavaScript fornece um tipo de dados booleano com literais verdadeiros e falsos . O operador typeof retorna a string "boolean" para esses tipos primitivos . Quando usado em um contexto lógico, 0 , -0 , nulo , NaN , indefinido e a string vazia ( "" ) são avaliados como falsos devido à coerção automática de tipo . Todos os outros valores (o complemento da lista anterior) são avaliados como verdadeiros , incluindo as strings "0" , "falso" e qualquer objeto.

Conversão de tipo

A coerção automática de tipo pelos operadores de comparação de igualdade ( ==e !=) pode ser evitada usando os operadores de comparação de verificação de tipo ( ===e !==).

Quando a conversão de tipo é necessária, o JavaScript converte operandos Boolean , Number , String ou Object da seguinte maneira:

Número e String
A string é convertida em um valor numérico. JavaScript tenta converter o literal numérico da string em um valor do tipo Número. Primeiro, um valor matemático é derivado do literal numérico da string. Em seguida, esse valor é arredondado para o valor do tipo Número mais próximo.
boleano
Se um dos operandos for um booleano, o operando booleano será convertido em 1 se for verdadeiro ou em 0 se for falso .
Objeto
Se um objeto é comparado com um número ou string, o JavaScript tenta retornar o valor padrão para o objeto. Um objeto é convertido em um valor String ou Numérico primitivo, usando os métodos .valueOf () ou .toString () do objeto. Se isso falhar, um erro de tempo de execução será gerado.

Douglas Crockford defende os termos " verdadeiro " e " falso " para descrever como os valores de vários tipos se comportam quando avaliados em um contexto lógico, especialmente em relação a casos extremos . Os operadores lógicos binários retornavam um valor booleano nas versões anteriores do JavaScript, mas agora eles retornam um dos operandos. O operando esquerdo é retornado, se puder ser avaliado como: falso , no caso de conjunção : ( a && b), ou verdadeiro , no caso de disjunção : ( a || b); caso contrário, o operando direito é retornado. A coerção automática de tipo pelos operadores de comparação pode ser diferente para casos de operandos booleanos mistos e compatíveis com números (incluindo strings que podem ser avaliadas como um número, ou objetos que podem ser avaliados como tal string), porque o operando booleano será comparado como um valor numérico. Isso pode ser inesperado. Uma expressão pode ser convertida explicitamente em uma primitiva Booleana dobrando o operador lógico de negação : ( !! ), usando a função Boolean () ou usando o operador condicional : ( c ? t : f).

// Automatic type coercion
console.log(true  ==   2 ); // false... true  → 1 !== 2 ←  2
console.log(false ==   2 ); // false... false → 0 !== 2 ←  2
console.log(true  ==   1 ); // true.... true  → 1 === 1 ←  1
console.log(false ==   0 ); // true.... false → 0 === 0 ←  0
console.log(true  ==  "2"); // false... true  → 1 !== 2 ← "2"
console.log(false ==  "2"); // false... false → 0 !== 2 ← "2"
console.log(true  ==  "1"); // true.... true  → 1 === 1 ← "1"
console.log(false ==  "0"); // true.... false → 0 === 0 ← "0"
console.log(false ==  "" ); // true.... false → 0 === 0 ← ""
console.log(false ==  NaN); // false... false → 0 !== NaN

console.log(NaN == NaN); // false...... NaN is not equivalent to anything, including NaN.

// Type checked comparison (no conversion of types and values)
console.log(true === 1); // false...... data types do not match

// Explicit type coercion
console.log(true === !!2);   // true.... data types and values match
console.log(true === !!0);   // false... data types match, but values differ
console.log( 1  ? true : false); // true.... only ±0 and NaN are "falsy" numbers
console.log("0" ? true : false); // true.... only the empty string is "falsy"
console.log(Boolean({}));    // true.... all objects are "truthy"

O novo operador pode ser usado para criar um wrapper de objeto para uma primitiva booleana. No entanto, o operador typeof não retorna booleano para o invólucro do objeto, ele retorna o objeto . Como todos os objetos são avaliados como verdadeiros , um método como .valueOf () ou .toString () deve ser usado para recuperar o valor agrupado . Para coerção explícita ao tipo booleano, a Mozilla recomenda que a função Boolean () (sem novo ) seja usada em preferência ao objeto booleano.

var b = new Boolean(false);   // Object  false {}
var t = Boolean(b);           // Boolean true
var f = Boolean(b.valueOf()); // Boolean false
var n = new Boolean(b);       // Not recommended
n = new Boolean(b.valueOf()); // Preferred

if (0 || -0 || "" || null || undefined || b.valueOf() || !new Boolean() || !t) {
  console.log("Never this");
} else if ([] && {} && b && typeof b === "object" && b.toString() === "false") {
  console.log("Always this");
}

Símbolo

Novo no ECMAScript6. Um símbolo é um identificador único e imutável.

Exemplo:

var x = Symbol(1);
var y = Symbol(1);
x === y; // => false

var symbolObject = {};
var normalObject = {};

// since x and y are unique,
// they can be used as unique keys in an object
symbolObject[x] = 1;
symbolObject[y] = 2;

symbolObject[x]; // => 1
symbolObject[y]; // => 2

// as compared to normal numeric keys
normalObject[1] = 1;
normalObject[1] = 2; // overrides the value of 1

normalObject[1]; // => 2

// changing the value of x does not change the key stored in the object
x = Symbol(3);
symbolObject[x]; // => undefined

// changing x back just creates another unique Symbol
x = Symbol(1);
symbolObject[x]; // => undefined

Existem também símbolos bem conhecidos .

Um dos quais é Symbol.iterator; se algo implementado Symbol.iterator, é iterável:

let x = [1, 2, 3, 4]; // x is an Array
x[Symbol.iterator] === Array.prototype[Symbol.iterator]; // and Arrays are iterable

const xIterator = x[Symbol.iterator](); // The [Symbol.iterator] function should provide an iterator for x
xIterator.next(); // { value: 1, done: false }
xIterator.next(); // { value: 2, done: false }
xIterator.next(); // { value: 3, done: false }
xIterator.next(); // { value: 4, done: false }
xIterator.next(); // { value: undefined, done: true }
xIterator.next(); // { value: undefined, done: true }

// for..of loops automatically iterate values
for (const value of x) {
   console.log(value); // 1 2 3 4
}

// Sets are also iterable:
[Symbol.iterator] in Set.prototype; // true

for (const value of new Set(['apple', 'orange'])) {
   console.log(value); // "apple" "orange"
}

Objetos nativos

A linguagem JavaScript fornece um punhado de objetos nativos . Os objetos nativos do JavaScript são considerados parte da especificação do JavaScript. Apesar do ambiente JavaScript, esse conjunto de objetos deve estar sempre disponível.

Variedade

Um Array é um objeto JavaScript prototipado do construtor Array projetado especificamente para armazenar valores de dados indexados por chaves inteiras. Arrays, ao contrário do tipo de objeto básico, são prototipados com métodos e propriedades para ajudar o programador em tarefas de rotina (por exemplo, join , slice e push ).

Como na família C , os arrays usam um esquema de indexação baseado em zero: um valor inserido em um array vazio por meio do método push ocupa o 0º índice do array.

var myArray = [];            // Point the variable myArray to a newly ...
                             // ... created, empty Array
myArray.push("hello World"); // Fill the next empty index, in this case 0
console.log(myArray[0]);           // Equivalent to console.log("hello World");

Os arrays têm uma propriedade de comprimento que é garantida sempre maior do que o maior índice inteiro usado no array. Ele é atualizado automaticamente, se for criada uma propriedade com um índice ainda maior. Escrever um número menor na propriedade length removerá índices maiores.

Elementos de Array s podem ser acessados ​​usando a notação normal de acesso de propriedade de objeto:

myArray[1];  // the 2nd item in myArray
myArray["1"];

Os dois acima são equivalentes. Não é possível usar a anotação "ponto" ou strings com representações alternativas do número:

myArray.1;     // syntax error
myArray["01"]; // not the same as myArray[1]

A declaração de uma matriz pode usar um literal de Array ou o construtor de Array :

let myArray;

// Array literals
myArray = [1, 2]; // length of 2
myArray = [1, 2,]; // same array - You can also have an extra comma at the end

// It's also possible to not fill in parts of the array
myArray = [0, 1, /* hole */, /* hole */, 4, 5]; // length of 6
myArray = [0, 1, /* hole */, /* hole */, 4, 5,]; // same array
myArray = [0, 1, /* hole */, /* hole */, 4, 5, /* hole */,]; // length of 7

// With the constructor
myArray = new Array(0, 1, 2, 3, 4, 5); // length of 6
myArray = new Array(365);              // an empty array with length 365

Os arrays são implementados de forma que apenas os elementos definidos usem memória; eles são " matrizes esparsas ". Definir e só usa espaço para esses dois elementos, assim como qualquer outro objeto. O comprimento da matriz ainda será relatado como 58. O comprimento máximo de uma matriz é 4.294.967.295 que corresponde ao número binário de 32 bits (11111111111111111111111111111111111111) 2 . myArray[10] = 'someThing'myArray[57] = 'somethingOther'

Pode-se usar o literal de declaração de objeto para criar objetos que se comportam de maneira muito semelhante a matrizes associativas em outras linguagens:

dog = {color: "brown", size: "large"};
dog["color"]; // results in "brown"
dog.color;    // also results in "brown"

Pode-se usar os literais de declaração de objeto e array para criar rapidamente arrays que são associativos, multidimensionais ou ambos. (Tecnicamente, o JavaScript não oferece suporte a matrizes multidimensionais, mas pode-se imitá-los com matrizes de matrizes.)

cats = [{color: "brown", size: "large"},
    {color: "black", size: "small"}];
cats[0]["size"];      // results in "large"

dogs = {rover: {color: "brown", size: "large"},
    spot: {color: "black", size: "small"}};
dogs["spot"]["size"]; // results in "small"
dogs.rover.color;     // results in "brown"

Encontro

Um objeto Date armazena uma contagem de milissegundos assinada com zero representando 01/01/1970 00:00:00 UT e um intervalo de ± 108 dias. Existem várias maneiras de fornecer argumentos para o construtor Date . Observe que os meses são baseados em zero.

new Date();                       // create a new Date instance representing the current time/date.
new Date(2010, 2, 1);             // create a new Date instance representing 2010-Mar-01 00:00:00
new Date(2010, 2, 1, 14, 25, 30); // create a new Date instance representing 2010-Mar-01 14:25:30
new Date("2010-3-1 14:25:30");    // create a new Date instance from a String.

Métodos para extrair campos são fornecidos, bem como um toString útil :

var d = new Date(2010, 2, 1, 14, 25, 30); // 2010-Mar-01 14:25:30;

// Displays '2010-3-1 14:25:30':
console.log(d.getFullYear() + '-' + (d.getMonth() + 1) + '-' + d.getDate() + ' '
    + d.getHours() + ':' + d.getMinutes() + ':' + d.getSeconds());

// Built-in toString returns something like 'Mon Mar 01 2010 14:25:30 GMT-0500 (EST)':
console.log(d);

Erro

Mensagens de erro personalizadas podem ser criadas usando a classe Error :

throw new Error("Something went wrong.");

Eles podem ser detectados pelos blocos try ... catch ... finally, conforme descrito na seção sobre tratamento de exceções .

Matemática

O objeto Math contém várias constantes relacionadas à matemática (por exemplo, π ) e funções (por exemplo, cosseno). (Observe que o objeto Math não tem construtor, ao contrário de Array ou Date . Todos os seus métodos são "estáticos", ou seja, métodos de "classe".) Todas as funções trigonométricas usam ângulos expressos em radianos , não graus ou grados .

Algumas das constantes contidas no objeto Math
Propriedade Valor retornado
arredondado para 5 dígitos
Descrição
Math.E 2.7183 e : Logaritmo natural de base
Math.LN2 0,69315 Logaritmo natural de 2
Math.LN10 2,3026 Logaritmo natural de 10
Math.LOG2E 1,4427 Logaritmo para a base 2 de e
Math.LOG10E 0,43429 Logaritmo para a base 10 de e
Math.PI 3,14159 π : circunferência / diâmetro de um círculo
Math.SQRT1_2 0,70711 Raiz quadrada de ½
Math.SQRT2 1,4142 Raiz quadrada de 2
Métodos do objeto Math
Exemplo Valor retornado
arredondado para 5 dígitos
Descrição
Math.abs (-2,3) 2,3 Valor absoluto
Math.acos (Math.SQRT1_2) 0,78540 rad. = 45 ° Arccosine
Math.asin (Math.SQRT1_2) 0,78540 rad. = 45 ° Arcsine
Math.atan (1) 0,78540 rad. = 45 ° Arco de meio círculo tangente (- π / 2 a + π / 2)
Math.atan2 (-3,7, -3,7) -2,3562 rad. = -135 ° Arco de círculo inteiro tangente (- π a + π )
Math.ceil (1.1) 2 Teto: arredondar para cima para o menor inteiro ≥ argumento
Math.cos (Math.PI / 4) 0,70711 Cosine
Math.exp (1) 2.7183 Função exponencial : e elevado a esta potência
Math.floor (1.9) 1 Piso: arredondar para baixo para o maior inteiro ≤ argumento
Math.log (Math.E) 1 Logaritmo natural, base e
Math.max (1, -2) 1 Máximo: (x> y)? x: y
Math.min (1, -2) -2 Mínimo: (x <y)? x: y
Math.pow (-3, 2) 9 Exponenciação (elevada à potência de): Math.pow (x, y) dá x y
Math.random () por exemplo, 0,17068 Número pseudoaleatório entre 0 (inclusivo) e 1 (exclusivo)
Math.round (1,5) 2 Arredonde para o número inteiro mais próximo; metades das frações são arredondadas para cima (por exemplo, 1,5 rodadas para 2)
Math.sin (Math.PI / 4) 0,70711 Seno
Math.sqrt (49) 7 Raiz quadrada
Math.tan (Math.PI / 4) 1 Tangente

Expressão regular

/expression/.test(string);     // returns Boolean
"string".search(/expression/); // returns position Number
"string".replace(/expression/, replacement);

// Here are some examples
if (/Tom/.test("My name is Tom")) console.log("Hello Tom!");
console.log("My name is Tom".search(/Tom/));          // == 11 (letters before Tom)
console.log("My name is Tom".replace(/Tom/, "John")); // == "My name is John"

Classes de personagens

// \d  - digit
// \D  - non digit
// \s  - space
// \S  - non space
// \w  - word char
// \W  - non word
// [ ] - one of
// [^] - one not of
//  -  - range

if (/\d/.test('0'))                   console.log('Digit');
if (/[0-9]/.test('6'))                console.log('Digit');
if (/[13579]/.test('1'))              console.log('Odd number');
if (/\S\S\s\S\S\S\S/.test('My name')) console.log('Format OK');
if (/\w\w\w/.test('Tom'))             console.log('Hello Tom');
if (/[a-zA-Z]/.test('B'))             console.log('Letter');

Correspondência de caracteres

// A...Z a...z 0...9  - alphanumeric
// \u0000...\uFFFF    - Unicode hexadecimal
// \x00...\xFF        - ASCII hexadecimal
// \t                 - tab
// \n                 - new line
// \r                 - CR
// .                  - any character
// |                  - OR

if (/T.m/.test('Tom')) console.log ('Hi Tom, Tam or Tim');
if (/A|B/.test("A"))  console.log ('A or B');

Repetidores

// ?   - 0 or 1 match
// *   - 0 or more
// +   - 1 or more
// {n}   - exactly n
// {n,}  - n or more
// {0,n} - n or less
// {n,m} - range n to m

if (/ab?c/.test("ac"))       console.log("OK"); // match: "ac", "abc"
if (/ab*c/.test("ac"))       console.log("OK"); // match: "ac", "abc", "abbc", "abbbc" etc.
if (/ab+c/.test("abc"))      console.log("OK"); // match: "abc", "abbc", "abbbc" etc.
if (/ab{3}c/.test("abbbc"))  console.log("OK"); // match: "abbbc"
if (/ab{3,}c/.test("abbbc")) console.log("OK"); // match: "abbbc", "abbbbc", "abbbbbc" etc.
if (/ab{1,3}c/.test("abc"))  console.log("OK"); // match: "abc", "abbc", "abbbc"

Âncoras

// ^  - string starts with
// $  - string ends with

if (/^My/.test("My name is Tom"))   console.log ("Hi!");
if (/Tom$/.test("My name is Tom"))  console.log ("Hi Tom!");

Subexpressão

// ( )  - groups characters

if (/water(mark)?/.test("watermark")) console.log("Here is water!"); // match: "water", "watermark",
if (/(Tom)|(John)/.test("John"))      console.log("Hi Tom or John!");

Bandeiras

// /g  - global
// /i  - ignore upper/lower case
// /m  - allow matches to span multiple lines

console.log("hi tom!".replace(/Tom/i, "John"));  // == "hi John!"
console.log("ratatam".replace(/ta/, "tu"));      // == "ratutam"
console.log("ratatam".replace(/ta/g, "tu"));     // == "ratutum"

Métodos avançados

my_array = my_string.split(my_delimiter);
// example
my_array = "dog,cat,cow".split(",");      // my_array==["dog","cat","cow"];

my_array = my_string.match(my_expression);
// example
my_array = "We start at 11:30, 12:15 and 16:45".match(/\d\d:\d\d/g); // my_array==["11:30","12:15","16:45"];

Capturando grupos

var myRe = /(\d{4}-\d{2}-\d{2}) (\d{2}:\d{2}:\d{2})/;
var results = myRe.exec("The date and time are 2009-09-08 09:37:08.");
if (results) {
  console.log("Matched: " + results[0]); // Entire match
  var my_date = results[1]; // First group == "2009-09-08"
  var my_time = results[2]; // Second group == "09:37:08"
  console.log("It is " + my_time + " on " + my_date);
} else console.log("Did not find a valid date!");

Função

Cada função em JavaScript é uma instância do construtor Function :

// x, y is the argument. 'return x + y' is the function body, which is the last in the argument list.
var add = new Function('x', 'y', 'return x + y');
add(1, 2); // => 3

A função add acima também pode ser definida usando uma expressão de função:

var add = function(x, y) {
  return x + y;
};
add(1, 2); // => 3

No ES6, a sintaxe da função de seta foi adicionada, permitindo que as funções que retornam um valor sejam mais concisas. Eles também retêm o this do objeto global em vez de herdá-lo de onde foi chamado / sobre o que foi chamado, ao contrário da expressão function () {} .

var add = (x, y) => {return x + y;};
// values can also be implicitly returned (i.e. no return statement is needed)
var addImplicit = (x, y) => x + y;

add(1, 2); // => 3
addImplicit(1, 2) // => 3

Para funções que precisam ser içadas, há uma expressão separada:

function add(x, y) {
  return x + y;
}
add(1, 2); // => 3

O içamento permite que você use a função antes de ser "declarada":

add(1, 2); // => 3, not a ReferenceError
function add(x, y) {
  return x + y;
}

Uma instância de função possui propriedades e métodos.

function subtract(x, y) {
  return x - y;
}

console.log(subtract.length); // => 2, arity of the function (number of arguments)
console.log(subtract.toString());

/*
"function subtract(x, y) {
  return x - y;
}"
*/

Operadores

O operador '+' está sobrecarregado : ele é usado para concatenação de strings e adição aritmética. Isso pode causar problemas ao misturar cordas e números inadvertidamente. Como um operador unário, ele pode converter uma string numérica em um número.

// Concatenate 2 strings
console.log('He' + 'llo'); // displays Hello

// Add two numbers
console.log(2 + 6);  // displays 8

// Adding a number and a string results in concatenation (from left to right)
console.log(2 + '2');    // displays 22
console.log('$' + 3 + 4);  // displays $34, but $7 may have been expected
console.log('$' + (3 + 4)); // displays $7
console.log(3 + 4 + '7'); // displays 77, numbers stay numbers until a string is added

// Convert a string to a number using the unary plus
console.log(+'2' === 2); // displays true
console.log(+'Hello'); // displays NaN

Da mesma forma, o operador '*' está sobrecarregado: ele pode converter uma string em um número.

console.log(2 + '6'*1);  // displays 8
console.log(3*'7'); // 21
console.log('3'*'7'); // 21
console.log('hello'*'world'); // displays NaN

Aritmética

JavaScript suporta os seguintes operadores aritméticos binários :

+ Adição
- subtração
* multiplicação
/ divisão (retorna um valor de ponto flutuante)
% módulo (retorna o resto)
** exponenciação

JavaScript suporta os seguintes operadores aritméticos unários :

+ conversão unária de string em número
- negação unária (inverte o sinal)
++ incremento (pode ser prefixo ou postfix)
- decremento (pode ser prefixo ou posfixo)
var x = 1;
console.log(++x); // x becomes 2; displays 2
console.log(x++); // displays 2; x becomes 3
console.log(x);  // x is 3; displays 3
console.log(x--); //  displays 3; x becomes 2
console.log(x);  //  displays 2; x is 2
console.log(--x); //  x becomes 1; displays 1

O operador de módulo exibe o restante após a divisão pelo módulo. Se números negativos estiverem envolvidos, o valor retornado depende do operando.

var x = 17;
console.log(x%5); // displays 2
console.log(x%6); // displays 5
console.log(-x%5); // displays -2
console.log(-x%-5); // displays -2
console.log(x%-5); // displays 2

Para sempre retornar um número não negativo, adicione novamente o módulo e aplique o operador de módulo novamente:

var x = 17;
console.log((-x%5+5)%5); // displays 3

Atribuição

= atribuir
+ = adicionar e atribuir
- = subtrair e atribuir
* = multiplique e atribua
/ = dividir e atribuir
% = módulo e atribuir
** = exponenciação e atribuição

Atribuição de tipos primitivos

var x = 9;
x += 1; 
console.log(x); // displays: 10
x *= 30;
console.log(x); // displays: 300
x /= 6;
console.log(x); // displays: 50
x -= 3;
console.log(x); // displays: 47
x %= 7;
console.log(x); // displays: 5

Atribuição de tipos de objeto

/**
 * To learn JavaScript objects...
 */
var object_1 = {a: 1};		// assign reference of newly created object to object_1
var object_2 = {a: 0};
var object_3 = object_2;	// object_3 references the same object as object_2 does
	 
object_3.a = 2;
message();	        	// displays 1 2 2
	 
object_2 = object_1;		// object_2 now references the same object as object_1
	        	        // object_3 still references what object_2 referenced before
message();		        // displays 1 1 2
	 
object_2.a = 7;  	        // modifies object_1
message();		        // displays 7 7 2

object_3.a = 5;                 // object_3 doesn't change object_2
message();	                // displays 7 7 5

object_3 = object_2;	
object_3.a=4;                  // object_3 changes object_1 and object_2
message();                     // displays 4 4 4

/**
 * Prints the console.log message
 */
function message() {
	console.log(object_1.a + " " + object_2.a + " " + object_3.a);
}

Atribuição de reestruturação

No JavaScript da Mozilla, desde a versão 1.7, a atribuição de desestruturação permite a atribuição de partes de estruturas de dados a várias variáveis ​​ao mesmo tempo. O lado esquerdo de uma atribuição é um padrão que se assemelha a um objeto / array literal aninhado arbitrariamente contendo valores-l em suas folhas que devem receber as subestruturas do valor atribuído.

var a, b, c, d, e;
[a, b, c] = [3, 4, 5];
console.log(a + ',' + b + ',' + c); // displays: 3,4,5
e = {foo: 5, bar: 6, baz: ['Baz', 'Content']};
var arr = [];
({baz: [arr[0], arr[3]], foo: a, bar: b}) = e;
console.log(a + ',' + b + ',' + arr);	// displays: 5,6,Baz,,,Content
[a, b] = [b, a];		// swap contents of a and b
console.log(a + ',' + b);		// displays: 6,5

[a, b, c] = [3, 4, 5]; // permutations
[a, b, c] = [b, c, a];
console.log(a + ',' + b + ',' + c); // displays: 4,5,3

Operador de espalhamento / repouso

O padrão ECMAScript 2015 introduz o operador " ... ", para os conceitos relacionados de "sintaxe de propagação" e "parâmetros restantes"

A sintaxe de propagação fornece outra maneira de desestruturar matrizes. Indica que os elementos em um array especificado devem ser usados ​​como parâmetros em uma chamada de função ou os itens em um literal de array.

Em outras palavras, " ... " transforma " [... foo] " em " [foo [0], foo [1], foo [2]] " e " this.bar (... foo); "em" this.bar (foo [0], foo [1], foo [2]); ".

var a = [1, 2, 3, 4];

// It can be used multiple times in the same expression
var b = [...a, ...a]; // b = [1, 2, 3, 4, 1, 2, 3, 4];

// It can be combined with non-spread items.
var c = [5, 6, ...a, 7, 9]; // c = [5, 6, 1, 2, 3, 4, 7, 9];

// For comparison, doing this without the spread operator 
// creates a nested array.
var d = [a, a]; // d = [[1, 2, 3, 4], [1, 2, 3, 4]]

// It works the same with function calls
function foo(arg1, arg2, arg3) {
    console.log(arg1 + ':' + arg2 + ':' + arg3);
}

// You can use it even if it passes more parameters than the function will use
foo(...a); // "1:2:3" → foo(a[0], a[1], a[2], a[3]);

// You can mix it with non-spread parameters
foo(5, ...a, 6); // "5:1:2" → foo(5, a[0], a[1], a[2], a[3], 6);

// For comparison, doing this without the spread operator
// assigns the array to arg1, and nothing to the other parameters.
foo(a); // "1,2,3,4:undefined:undefined"

Quando ... é usado em uma declaração de função , indica um parâmetro rest . O parâmetro rest deve ser o parâmetro nomeado final na lista de parâmetros da função. Ele será atribuído a um Array contendo quaisquer argumentos passados ​​para a função além dos outros parâmetros nomeados. Em outras palavras, ele obtém "o resto" dos argumentos passados ​​para a função (daí o nome).

function foo(a, b, ...c) {
    console.log(c.length);
}

foo(1, 2, 3, 4, 5); // "3" → c = [3, 4, 5]
foo('a', 'b'); // "0" → c = []

Os parâmetros de descanso são semelhantes ao objeto de argumentos de Javascript , que é um objeto semelhante a um array que contém todos os parâmetros (nomeados e não nomeados) na chamada de função atual. Ao contrário dos argumentos , no entanto, os parâmetros rest são verdadeiros objetos Array , portanto, métodos como .slice () e .sort () podem ser usados ​​diretamente neles.

O operador ... só pode ser usado com objetos Array . (No entanto, há uma proposta para estendê-lo aos Objetos em um futuro padrão ECMAScript.)

Comparação

== igual
! = não igual
> Maior que
> = Melhor que ou igual a
< Menor que
<= menos que ou igual a
=== idênticos (iguais e do mesmo tipo)
! == não idênticos

Variáveis ​​que fazem referência a objetos são iguais ou idênticas apenas se fizerem referência ao mesmo objeto:

var obj1 = {a: 1};
var obj2 = {a: 1};
var obj3 = obj1;
console.log(obj1 == obj2);  //false
console.log(obj3 == obj1);  //true
console.log(obj3 === obj1); //true

Veja também String .

Lógico

JavaScript fornece quatro operadores lógicos:

No contexto de uma operação lógica, qualquer expressão é avaliada como verdadeira, exceto o seguinte :

  • Strings: "" , '' ,
  • Números: 0 , -0 , NaN ,
  • Especial: nulo , indefinido ,
  • Booleano: falso .

A função Booleana pode ser usada para converter explicitamente em uma primitiva do tipo Boolean :

// Only empty strings return false
console.log(Boolean("")      === false);
console.log(Boolean("false") === true);
console.log(Boolean("0")     === true);

// Only zero and NaN return false
console.log(Boolean(NaN) === false);
console.log(Boolean(0)   === false);
console.log(Boolean(-0)  === false); // equivalent to -1*0
console.log(Boolean(-2)  === true);

// All objects return true
console.log(Boolean(this) === true);
console.log(Boolean({})   === true);
console.log(Boolean([])   === true);

// These types return false
console.log(Boolean(null)      === false);
console.log(Boolean(undefined) === false); // equivalent to Boolean()

O operador NOT avalia seu operando como um booleano e retorna a negação. Usar o operador duas vezes consecutivas, como uma negativa dupla , converte explicitamente uma expressão em uma primitiva do tipo Boolean:

console.log( !0 === Boolean(!0));
console.log(Boolean(!0) === !!1);
console.log(!!1 === Boolean(1));
console.log(!!0 === Boolean(0));
console.log(Boolean(0) === !1);
console.log(!1 === Boolean(!1));
console.log(!"" === Boolean(!""));
console.log(Boolean(!"") === !!"s");
console.log(!!"s" === Boolean("s"));
console.log(!!"" === Boolean(""));
console.log(Boolean("") === !"s");	
console.log(!"s" === Boolean(!"s"));

O operador ternário também pode ser usado para conversão explícita:

console.log([] == false); console.log([] ? true : false); // “truthy”, but the comparison uses [].toString()
console.log([0] == false); console.log([0]? true : false); // [0].toString() == "0"
console.log("0" == false); console.log("0"? true : false); // "0" → 0 ... (0 == 0) ... 0 ← false
console.log([1] == true); console.log([1]? true : false); // [1].toString() == "1"
console.log("1" == true); console.log("1"? true : false); // "1" → 1 ... (1 == 1) ... 1 ← true
console.log([2] != true); console.log([2]? true : false); // [2].toString() == "2"
console.log("2" != true); console.log("2"? true : false); // "2" → 2 ... (2 != 1) ... 1 ← true

Expressões que usam recursos como pós-incremento ( i ++ ) têm um efeito colateral antecipado . JavaScript fornece avaliação de curto-circuito de expressões; o operando direito só é executado se o operando esquerdo não for suficiente para determinar o valor da expressão.

console.log(a || b);  // When a is true, there is no reason to evaluate b.
console.log(a && b);  // When a is false, there is no reason to evaluate b.
console.log(c ? t : f); // When c is true, there is no reason to evaluate f.

Nas primeiras versões de JavaScript e JScript , os operadores lógicos binários retornavam um valor booleano (como a maioria das linguagens de programação derivadas de C). No entanto, todas as implementações contemporâneas retornam um de seus operandos em vez disso:

console.log(a || b); // if a is true, return a, otherwise return b
console.log(a && b); // if a is false, return a, otherwise return b

Os programadores que estão mais familiarizados com o comportamento em C podem achar esse recurso surpreendente, mas ele permite uma expressão mais concisa de padrões, como coalescência nula :

var s = t || "(default)"; // assigns t, or the default value, if t is null, empty, etc.

Atribuição lógica

?? = Tarefa nula
|| = Lógico ou atribuição
&& = Lógica e atribuição

Bit a bit

JavaScript suporta os seguintes operadores binários bit a bit :

E E
| OU
^ XOR
! NÃO
<< deslocar para a esquerda (preenchimento zero à direita)
>> deslocar para a direita (propagação de sinal); cópias do
bit mais à esquerda (bit de sinal) são deslocadas da esquerda
>>> deslocar para a direita (preenchimento zero à esquerda). Para números positivos,
>> e >>> produzem o mesmo resultado.

Exemplos:

x=11 & 6;
console.log(x); // 2

JavaScript suporta o seguinte operador unário bit a bit :

~ NÃO (inverte os bits)

Atribuição bit a bit

JavaScript oferece suporte aos seguintes operadores de atribuição binária:

& = e
| = ou
^ = xor
<< = deslocar para a esquerda (preenchimento zero à direita)
>> = deslocar para a direita (propagação de sinal); cópias do
bit mais à esquerda (bit de sinal) são deslocadas da esquerda
>>> = deslocar para a direita (preenchimento zero à esquerda). Para números positivos,
>> = e >>> = produzem o mesmo resultado.

Exemplos:

x=7;
console.log(x); // 7
x<<=3;
console.log(x); // 7->14->28->56

Fragmento

= atribuição
+ concatenação
+ = concatenar e atribuir

Exemplos:

str = "ab" + "cd";  // "abcd"
str += "e";      // "abcde"

str2 = "2" + 2;     // "22", not "4" or 4.

??

O operador mais próximo do JavaScript é ??, o "operador de coalescência nula", que foi adicionado ao padrão na 11ª edição do ECMAScript . Em versões anteriores, ele poderia ser usado por meio de um plug-in Babel e no TypeScript . Ele avalia seu operando à esquerda e, se o valor do resultado não for "nulo" ( nullou undefined), assume esse valor como seu resultado; caso contrário, avalia o operando à direita e assume o valor resultante como seu resultado.

No exemplo a seguir, aserá atribuído o valor de bse o valor de bnão for nullou undefined, caso contrário, será atribuído 3.

const a = b ?? 3;

Antes do operador de coalescência nula, os programadores usariam o operador lógico OR ( ||). Mas onde ??procura especificamente nullou undefined, os ||olhares de operador para qualquer Falsas valor: null, undefined, "", 0, NaN, e, claro, false.

No exemplo a seguir, aserá atribuído o valor de bse o valor de bfor verdadeiro , caso contrário, será atribuído 3.

const a = b || 3;

Estruturas de controle

Declarações compostas

Um par de chaves {} e uma sequência fechada de instruções constituem uma instrução composta, que pode ser usada sempre que uma instrução pode ser usada.

Se ... mais

if (expr) {
  //statements;
} else if (expr2) {
  //statements;
} else {
  //statements;
}

Operador condicional (ternário)

O operador condicional cria uma expressão que é avaliada como uma de duas expressões, dependendo de uma condição. Isso é semelhante à instrução if que seleciona uma das duas instruções para executar dependendo de uma condição. Ou seja, o operador condicional é para expressões e se é para declarações.

 result = condition ? expression : alternative;

é o mesmo que:

 if (condition) {
  result = expression;
 } else {
  result = alternative;
 }

Ao contrário da instrução if , o operador condicional não pode omitir seu "outro ramo".

Declaração de mudança

A sintaxe da instrução switch JavaScript é a seguinte:

 switch (expr) {
  case SOMEVALUE:
   // statements;
   break;
  case ANOTHERVALUE:
   // statements;
   break;
  default:
   // statements;
   break;
 }
  • pausa; é opcional; no entanto, geralmente é necessário, pois, de outra forma, a execução do código continuará no corpo do próximo bloco de caso.
  • Adicione uma instrução break ao final do último caso como uma medida de precaução, no caso de casos adicionais serem adicionados posteriormente.
  • Os valores literais de string também podem ser usados ​​para os valores de caso.
  • Expressões podem ser usadas em vez de valores.
  • O caso padrão (opcional) é executado quando a expressão não corresponde a nenhum outro caso especificado.
  • Chaves são obrigatórias.

For loop

A sintaxe do loop for JavaScript é a seguinte:

 for (initial; condition; loop statement) {
  /*
   statements will be executed every time
   the for{} loop cycles, while the
   condition is satisfied
  */
 }

ou

 for (initial; condition; loop statement(iteration)) // one statement

For ... in loop

A sintaxe do JavaScript for ... in loopé a seguinte:

for (var property_name in some_object) {
  // statements using some_object[property_name];
}
  • Itera por meio de todas as propriedades enumeráveis ​​de um objeto.
  • Itera por meio de todos os índices usados ​​da matriz, incluindo todas as propriedades definidas pelo usuário do objeto da matriz, se houver. Portanto, pode ser melhor usar um loop for tradicional com um índice numérico ao iterar em matrizes.
  • Existem diferenças entre os vários navegadores da Web com relação a quais propriedades serão refletidas com a instrução for ... in loop. Em teoria, isso é controlado por uma propriedade de estado interna definida pelo padrão ECMAscript chamada "DontEnum", mas na prática, cada navegador retorna um conjunto ligeiramente diferente de propriedades durante a introspecção. É útil testar uma determinada propriedade usando }. Portanto, adicionar um método ao protótipo de array com } pode fazer com que loops percorram o nome do método.if (some_object.hasOwnProperty(property_name)) { ...Array.prototype.newMethod = function() {...for ... in

Loop while

A sintaxe do loop while JavaScript é a seguinte:

while (condition) {
  statement1;
  statement2;
  statement3;
  ...
}

Faça ... loop while

A sintaxe do JavaScript do ... while loopé a seguinte:

do {
  statement1;
  statement2;
  statement3;
  ...
} while (condition);

Com

A instrução with adiciona todas as propriedades e métodos do objeto fornecido ao escopo do bloco a seguir, permitindo que sejam referenciados como se fossem variáveis ​​locais.

with (document) {
  var a = getElementById('a');
  var b = getElementById('b');
  var c = getElementById('c');
};
  • Observe a ausência de documento. antes de cada chamada getElementById () .

A semântica é semelhante à instrução with de Pascal .

Como a disponibilidade de instruções with prejudica o desempenho do programa e acredita-se que reduza a clareza do código (uma vez que qualquer variável pode realmente ser uma propriedade de um delimitador com ), essa instrução não é permitida no modo estrito .

Etiquetas

JavaScript oferece suporte a rótulos aninhados na maioria das implementações. Os loops ou blocos podem ser rotulados para a instrução break e os loops para continuar . Embora goto seja uma palavra reservada, goto não é implementado em JavaScript.

loop1: for (var a = 0; a < 10; a++) {
  if (a == 4) {
    break loop1; // Stops after the 4th attempt
  }
  console.log('a = ' + a);
  loop2: for (var b = 0; b < 10; ++b) {
    if (b == 3) {
     continue loop2; // Number 3 is skipped
    }
    if (b == 6) {
     continue loop1; // Continues the first loop, 'finished' is not shown
    }
    console.log('b = ' + b);
  }
  console.log('finished');
}
block1: {
  console.log('Hello'); // Displays 'Hello'
  break block1;
  console.log('World'); // Will never get here
}
goto block1; // Parse error.

Funções

Uma função é um bloco com uma lista de parâmetros (possivelmente vazia) que normalmente recebe um nome. Uma função pode usar variáveis ​​locais. Se você sair da função sem uma instrução de retorno, o valor undefined será retornado.

function gcd(segmentA, segmentB) {
  var diff = segmentA - segmentB;
  if (diff == 0) 
    return segmentA;
  return diff > 0 ? gcd(segmentB, diff) : gcd(segmentA, -diff);
}
console.log(gcd(60, 40)); // 20

var mygcd = gcd; // mygcd is a reference to the same function as gcd. Note no argument ()s.
console.log(mygcd(60, 40)); // 20

Funções são objetos de primeira classe e podem ser atribuídas a outras variáveis.

O número de argumentos fornecidos ao chamar uma função pode não corresponder necessariamente ao número de argumentos na definição da função; um argumento nomeado na definição que não possui um argumento correspondente na chamada terá o valor undefined (que pode ser convertido implicitamente em false). Dentro da função, os argumentos também podem ser acessados ​​por meio do objeto argumentos ; isso fornece acesso a todos os argumentos usando índices (por exemplo ), incluindo aqueles além do número de argumentos nomeados. (Com a lista de argumentos tem um .length propriedade, que é não um exemplo de matriz , que não tem métodos tais como .slice () , .Sort () , etc.) arguments[0], arguments[1], ... arguments[n]

function add7(x, y) {
  if (!y) {
    y = 7;
  }
  console.log(x + y + arguments.length);
};
add7(3); // 11
add7(3, 4); // 9

Valores primitivos (número, booleano, string) são passados ​​por valor. Para objetos, é a referência ao objeto que é passado.

var obj1 = {a : 1};
var obj2 = {b : 2};
function foo(p) {
  p = obj2; // Ignores actual parameter
  p.b = arguments[1];
}
foo(obj1, 3); // Does not affect obj1 at all. 3 is additional parameter
console.log(obj1.a + " " + obj2.b); // writes 1 3

As funções podem ser declaradas dentro de outras funções e acessar as variáveis ​​locais da função externa. Além disso, eles implementam fechamentos completos lembrando-se das variáveis ​​locais da função externa, mesmo após a saída da função externa.

var v = "Top";
var bar, baz;
function foo() {
  var v = "fud";
  bar = function() { console.log(v) };
  baz = function(x) { v = x; };
}
foo();
baz("Fugly");
bar(); // Fugly (not fud) even though foo() has exited.
console.log(v); // Top

Assíncrono / aguardar

O operador await em JavaScript só pode ser usado de dentro de uma função assíncrona. Se o parâmetro for uma promessa , a execução da função assíncrona será retomada quando a promessa for resolvida (a menos que a promessa seja rejeitada, caso em que será gerado um erro que pode ser tratado com o tratamento de exceção normal do JavaScript ). Se o parâmetro não for uma promessa, o próprio parâmetro será retornado imediatamente.

Muitas bibliotecas fornecem objetos de promessa que também podem ser usados ​​com await, desde que correspondam à especificação para promessas de JavaScript nativas. No entanto, as promessas da biblioteca jQuery não eram compatíveis com Promises / A + até o jQuery 3.0.

Aqui está um exemplo (modificado a partir deste artigo):

async function createNewDoc() {
  let response = await db.post({}); // post a new doc
  return await db.get(response.id); // find by id
}

async function main() {
  try {
    let doc = await createNewDoc();
    console.log(doc);
  } catch (err) {
    console.log(err);
  }
}
main();
O Node.js versão 8 inclui um utilitário que permite usar os métodos baseados em callback da biblioteca padrão como promessas.

Objetos

Por conveniência, os tipos são normalmente subdivididos em primitivos e objetos . Objetos são entidades que têm uma identidade (são iguais a si mesmas) e que mapeiam nomes de propriedades para valores ("slots" na terminologia de programação baseada em protótipo ). Os objetos podem ser considerados como matrizes associativas ou hashes e são frequentemente implementados usando essas estruturas de dados. No entanto, os objetos têm recursos adicionais, como uma cadeia de protótipo, que as matrizes associativas comuns não têm.

JavaScript possui vários tipos de objetos embutidos, nomeadamente Array , Boolean , Date , Function , Math , Number , Object , RegExp e String . Outros objetos são "objetos de host", definidos não pela linguagem, mas pelo ambiente de execução. Por exemplo, em um navegador, objetos de host típicos pertencem ao DOM (janela, formulário, links, etc.).

Criação de objetos

Os objetos podem ser criados usando um construtor ou um literal de objeto. O construtor pode usar uma função de objeto interna ou uma função personalizada. É uma convenção que funções de construtor recebem um nome que começa com uma letra maiúscula:

// Constructor
var anObject = new Object();

// Object literal
var objectA = {};
var objectA2 = {};  // A != A2, {}s create new objects as copies.
var objectB = {index1: 'value 1', index2: 'value 2'};

// Custom constructor (see below)

Literais de objeto e literais de matriz permitem criar facilmente estruturas de dados flexíveis:

var myStructure = {
  name: {
    first: "Mel",
    last: "Smith"
  },
  age: 33,
  hobbies: ["chess", "jogging"]
};

Esta é a base para JSON , que é uma notação simples que usa sintaxe semelhante a JavaScript para troca de dados.

Métodos

Um método é simplesmente uma função atribuída a um nome de propriedade de um objeto. Ao contrário de muitas linguagens orientadas a objetos, não há distinção entre uma definição de função e uma definição de método em JavaScript relacionado a objetos. Em vez disso, a distinção ocorre durante a chamada de função; uma função pode ser chamada como um método.

Quando chamado como um método, a variável local padrão esta é apenas definir automaticamente para a instância do objeto à esquerda do " ". (Existem também métodos de chamada e aplicação que podem definir isso explicitamente - alguns pacotes, como o jQuery, fazem coisas incomuns com isso .)

No exemplo abaixo, Foo está sendo usado como construtor. Não há nada de especial sobre um construtor - é apenas uma função simples que inicializa um objeto. Quando usado com a nova palavra-chave, como é a norma, esta é definida como um objeto em branco recém-criado.

Observe que no exemplo abaixo, Foo está simplesmente atribuindo valores aos slots, alguns dos quais são funções. Assim, ele pode atribuir funções diferentes a instâncias diferentes. Não há prototipagem neste exemplo.

function px() { return this.prefix + "X"; }

function Foo(yz) {
  this.prefix = "a-";
  if (yz > 0) {
    this.pyz = function() { return this.prefix + "Y"; };
  } else {
    this.pyz = function() { return this.prefix + "Z"; };
  }
  this.m1 = px;
  return this;
}

var foo1 = new Foo(1);
var foo2 = new Foo(0);
foo2.prefix = "b-";

console.log("foo1/2 " + foo1.pyz() + foo2.pyz());
// foo1/2 a-Y b-Z

foo1.m3 = px; // Assigns the function itself, not its evaluated result, i.e. not px()
var baz = {"prefix": "c-"};
baz.m4 = px; // No need for a constructor to make an object.

console.log("m1/m3/m4 " + foo1.m1() + foo1.m3() + baz.m4());
// m1/m3/m4 a-X a-X c-X

foo1.m2(); // Throws an exception, because foo1.m2 doesn't exist.

Construtores

As funções do construtor simplesmente atribuem valores aos slots de um objeto recém-criado. Os valores podem ser dados ou outras funções.

Exemplo: Manipulando um objeto:

function MyObject(attributeA, attributeB) {
  this.attributeA = attributeA;
  this.attributeB = attributeB;
}

MyObject.staticC = "blue"; // On MyObject Function, not object
console.log(MyObject.staticC); // blue

object = new MyObject('red', 1000);

console.log(object.attributeA); // red
console.log(object["attributeB"]); // 1000

console.log(object.staticC); // undefined
object.attributeC = new Date(); // add a new property

delete object.attributeB; // remove a property of object
console.log(object.attributeB); // undefined

delete object; // remove the whole Object (rarely used)
console.log(object.attributeA); // throws an exception

O próprio construtor é referenciado no slot do construtor do protótipo do objeto . Então,

function Foo() {}
// Use of 'new' sets prototype slots (for example, 
// x = new Foo() would set x's prototype to Foo.prototype,
// and Foo.prototype has a constructor slot pointing back to Foo).
x = new Foo();
// The above is almost equivalent to
y = {};
y.constructor = Foo;
y.constructor();
// Except
x.constructor == y.constructor // true
x instanceof Foo // true
y instanceof Foo // false
// y's prototype is Object.prototype, not
// Foo.prototype, since it was initialised with
// {} instead of new Foo.
// Even though Foo is set to y's constructor slot,
// this is ignored by instanceof - only y's prototype's
// constructor slot is considered.

As funções são os próprios objetos, que podem ser usados ​​para produzir um efeito semelhante às "propriedades estáticas" (usando a terminologia C ++ / Java), conforme mostrado abaixo. (O objeto de função também tem uma propriedade de protótipo especial , conforme discutido na seção "Herança" abaixo.)

A exclusão de objetos raramente é usada, pois o mecanismo de script fará a coleta de lixo de objetos que não estão mais sendo referenciados.

Herança

JavaScript oferece suporte a hierarquias de herança por meio de prototipagem na forma de Self .

No exemplo a seguir, a classe Derived herda da classe Base . Quando d é criado como Derivado , a referência à instância base de Base é copiada para d.base .

Derive não contém um valor para aBaseFunction , portanto, é recuperado de aBaseFunction quando aBaseFunction é acessada . Isso fica claro ao alterar o valor de base.aBaseFunction , que é refletido no valor de d.aBaseFunction .

Algumas implementações permitem que o protótipo seja acessado ou definido explicitamente usando o slot __proto__ conforme mostrado abaixo.

function Base() {
  this.anOverride = function() { console.log("Base::anOverride()"); };

  this.aBaseFunction = function() { console.log("Base::aBaseFunction()"); };
}

function Derived() {
  this.anOverride = function() { console.log("Derived::anOverride()"); };
}

base = new Base();
Derived.prototype = base; // Must be before new Derived()
Derived.prototype.constructor = Derived; // Required to make `instanceof` work

d = new Derived();    // Copies Derived.prototype to d instance's hidden prototype slot.
d instanceof Derived; // true
d instanceof Base;    // true

base.aBaseFunction = function() { console.log("Base::aNEWBaseFunction()"); }

d.anOverride();    // Derived::anOverride()
d.aBaseFunction(); // Base::aNEWBaseFunction()
console.log(d.aBaseFunction == Derived.prototype.aBaseFunction); // true

console.log(d.__proto__ == base); // true in Mozilla-based implementations and false in many others.

O seguinte mostra claramente como as referências aos protótipos são copiadas na criação da instância, mas as alterações em um protótipo podem afetar todas as instâncias que se referem a ele.

function m1() { return "One"; }
function m2() { return "Two"; }
function m3() { return "Three"; }

function Base() {}

Base.prototype.m = m2;
bar = new Base();
console.log("bar.m " + bar.m()); // bar.m Two

function Top() { this.m = m3; }
t = new Top();

foo = new Base();
Base.prototype = t;
// No effect on foo, the *reference* to t is copied.
console.log("foo.m " + foo.m()); // foo.m Two

baz = new Base();
console.log("baz.m " + baz.m()); // baz.m Three

t.m = m1; // Does affect baz, and any other derived classes.
console.log("baz.m1 " + baz.m()); // baz.m1 One

Na prática, muitas variações desses temas são usadas e podem ser poderosos e confusos.

Manipulação de exceção

JavaScript inclui uma instrução de try ... catch ... finally tratamento de exceção para lidar com erros de tempo de execução.

A try ... catch ... finallyinstrução captura exceções resultantes de um erro ou uma instrução de lançamento. Sua sintaxe é a seguinte:

try {
  // Statements in which exceptions might be thrown
} catch(errorValue) {
  // Statements that execute in the event of an exception
} finally {
  // Statements that execute afterward either way
}

Inicialmente, as instruções dentro do bloco try são executadas. Se uma exceção for lançada, o fluxo de controle do script será imediatamente transferido para as instruções no bloco catch, com a exceção disponível como o argumento de erro. Caso contrário, o bloco catch é ignorado. O bloco catch pode lançar (errorValue) , se não quiser tratar um erro específico.

Em qualquer caso, as instruções no bloco finally são sempre executadas. Isso pode ser usado para liberar recursos, embora a memória seja automaticamente coletada como lixo.

Tanto a cláusula catch quanto a finally podem ser omitidas. O argumento catch é obrigatório.

A implementação do Mozilla permite várias instruções catch, como uma extensão do padrão ECMAScript. Eles seguem uma sintaxe semelhante à usada em Java :

try { statement; }
catch (e if e == "InvalidNameException")  { statement; }
catch (e if e == "InvalidIdException")    { statement; }
catch (e if e == "InvalidEmailException") { statement; }
catch (e)                                 { statement; }

Em um navegador, o evento onerror é mais comumente usado para interceptar exceções.

onerror = function (errorValue, url, lineNr) {...; return true;};

Funções e métodos nativos

(Não relacionado a navegadores da Web.)

eval (expressão)

Avalia o primeiro parâmetro como uma expressão, que pode incluir instruções de atribuição. Variáveis ​​locais para funções podem ser referenciadas pela expressão. No entanto, evalrepresenta um grande risco de segurança, pois permite que um malfeitor execute código arbitrário, portanto, seu uso é desencorajado.

(function foo() {
  var x = 7;
  console.log("val " + eval("x + 2"));
})(); // shows val 9.

Veja também

Referências

Leitura adicional

  • Danny Goodman: JavaScript Bible , Wiley, John & Sons, ISBN  0-7645-3342-8 .
  • David Flanagan, Paula Ferguson: JavaScript: The Definitive Guide , O'Reilly & Associates, ISBN  0-596-10199-6 .
  • Thomas A. Powell, Fritz Schneider: JavaScript: The Complete Reference , McGraw-Hill Companies, ISBN  0-07-219127-9 .
  • Axel Rauschmayer: Speaking JavaScript: An In-Depth Guide for Programmers , 460 páginas, O'Reilly Media, 25 de fevereiro de 2014, ISBN  978-1449365035 . ( edição online gratuita )
  • Emily Vander Veer: JavaScript For Dummies, 4ª Edição , Wiley, ISBN  0-7645-7659-3 .

links externos