Qual é o escopo das variáveis em JavaScript?
Qual é o âmbito das variáveis em javascript? Eles têm o mesmo escopo dentro e não fora de uma função? Ou isso importa? Além disso, onde estão armazenadas as variáveis se elas são definidas globalmente?
26 answers
-
Uma variável de âmbito global
// global scope var a = 1; function one() { alert(a); // alerts '1' }
-
Âmbito Local
// global scope var a = 1; function two(a) { // passing (a) makes it local scope alert(a); // alerts the given argument, not the global value of '1' } // local scope again function three() { var a = 3; alert(a); // alerts '3' }
-
Intermédio: nenhuma coisa como o scope de bloco em JavaScript (ES5; ES6 introduz
let
)A.
var a = 1; function four() { if (true) { var a = 4; } alert(a); // alerts '4', not the global value of '1' }
B.
var a = 1; function one() { if (true) { let a = 4; } alert(a); // alerts '1' because the 'let' keyword uses block scoping }
-
Intermédio: propriedades do objecto
var a = 1; function Five() { this.a = 5; } alert(new Five().a); // alerts '5'
-
Avançado: Encerramento
var a = 1; var six = (function() { var a = 6; return function() { // JavaScript "closure" means I have access to 'a' in here, // because it is defined in the function in which I was defined. alert(a); // alerts '6' }; })();
-
Avançado: resolução do âmbito baseada em protótipos
var a = 1; function seven() { this.a = 7; } // [object].prototype.property loses to // [object].property in the lookup chain. For example... // Won't get reached, because 'a' is set in the constructor above. seven.prototype.a = -1; // Will get reached, even though 'b' is NOT set in the constructor. seven.prototype.b = 8; alert(new seven().a); // alerts '7' alert(new seven().b); // alerts '8'
-
Global+Local: um caso extra complexo
var x = 5; (function () { console.log(x); var x = 10; console.log(x); })();
Isto irá imprimir
undefined
e10
em vez de5
e10
desde que o JavaScript move sempre as declarações variáveis (não inicializações) para o topo do escopo, tornando o código equivalente a:var x = 5; (function () { var x; console.log(x); x = 10; console.log(x); })();
-
Cláusula de captura-variável abrangida
Isto vai ser impresso.var e = 5; console.log(e); try { throw 6; } catch (e) { console.log(e); } console.log(e);
5
,6
,5
. Dentro da cláusula de capturae
esconde variáveis globais e locais. Mas este âmbito especial é apenas para a variável capturada. Se você escrevervar f;
dentro da cláusula de captura, então é exatamente o mesmo que se você tivesse definiu-o antes ou depois do bloco de ensaio.
Javascript usa cadeias de escopo para estabelecer o escopo para uma dada função. Existe tipicamente um escopo global, e cada função definida tem seu próprio escopo aninhado. Qualquer função definida dentro de outra função tem um escopo local que está ligado à função externa. É sempre a posição na fonte que define o escopo.
Um elemento na cadeia de escopo é basicamente um mapa com um ponteiro para o seu escopo pai.
Ao resolver uma variável, o javascript começa na mais profundo escopo e procura para fora.
As variáveis declaradas globalmente têm um âmbito global. Variáveis declaradas dentro de uma função são escopadas para essa função, e sombream variáveis globais do mesmo nome.
{[[2]} (tenho a certeza que existem muitas subtilezas que os programadores JavaScript reais serão capazes de apontar em outras respostas. Em particular, deparei-me com esta página sobre o que exatamentethis
significa a qualquer momento. Esperemos que este link mais introdutório seja suficiente para começar.)
- âmbito Global : as variáveis são conhecidas em toda a aplicação, desde o início da aplicação (*)
- âmbito funcional : as variáveis são conhecidas dentro a função são declarados em, desde o início da função (*)
JavaScript Moderno
A especificações de JavaScript mais recentes agora também permitir um terceiro escopo:
- âmbito do bloco : as variáveis são conhecidas dentro o bloco são declarados em, a partir do momento em que são declarados (**)
Como posso criar variáveis de tamanho de bloco? Tradicionalmente, você cria o seu variáveis como esta:
var myVariable = "Some text";
As variáveis de bloco são criadas assim:
let myVariable = "Some text";
Então, qual é a diferença entre o âmbito funcional e o escopo de bloco?
Para compreender a diferença entre o âmbito funcional e o âmbito do bloco, considere o seguinte código:
// i IS NOT known here
// j IS NOT known here
// k IS known here, but undefined
// l IS NOT known here
function loop(arr) {
// i IS known here, but undefined
// j IS NOT known here
// k IS known here, but has a value only the second time loop is called
// l IS NOT known here
for( var i = 0; i < arr.length; i++ ) {
// i IS known here, and has a value
// j IS NOT known here
// k IS known here, but has a value only the second time loop is called
// l IS NOT known here
};
// i IS known here, and has a value
// j IS NOT known here
// k IS known here, but has a value only the second time loop is called
// l IS NOT known here
for( let j = 0; j < arr.length; j++ ) {
// i IS known here, and has a value
// j IS known here, and has a value
// k IS known here, but has a value only the second time loop is called
// l IS NOT known here
};
// i IS known here, and has a value
// j IS NOT known here
// k IS known here, but has a value only the second time loop is called
// l IS NOT known here
}
loop([1,2,3,4]);
for( var k = 0; k < arr.length; k++ ) {
// i IS NOT known here
// j IS NOT known here
// k IS known here, and has a value
// l IS NOT known here
};
for( let l = 0; l < arr.length; l++ ) {
// i IS NOT known here
// j IS NOT known here
// k IS known here, and has a value
// l IS known here, and has a value
};
loop([1,2,3,4]);
// i IS NOT known here
// j IS NOT known here
// k IS known here, and has a value
// l IS NOT known here
Aqui, podemos ver que a nossa variável só é conhecida no primeiro para o laço, mas não antes e depois. No entanto, a nossa variável i
é conhecida em toda a função.
Também, considere que variáveis escopadas em bloco não são conhecidas antes de serem declaradas porque não são içadas. Você também não está autorizado a redeclarar o mesmo bloco scoped variável dentro do mesmo bloco. Isto faz com que variáveis com escopo em bloco sejam menos propensas a erros do que variáveis com escopo global ou funcional, que são içadas e que não produzem quaisquer erros em caso de múltiplas declarações.
É seguro usar hoje variáveis de tamanho de bloco?
Se é ou não seguro utilizar hoje, depende do seu ambiente:
Se estiver a gravar o código JavaScript do lado do servidor(nó.js), pode utilizar com segurança a declaração
let
.Se você está escrevendo código JavaScript do lado do cliente e usar um transpiler (como Traceur), você pode usar com segurança a declaração
let
, no entanto o seu código é provável que seja tudo menos ideal em relação ao desempenho.-
Se estás a escrever do lado do cliente Código JavaScript e não usar um transpiler, você precisa considerar o suporte do navegador.
Hoje, 23 de Fevereiro de 2016, estes são alguns navegadores que ou não suportam
let
ou têm apenas suporte parcial:- Internet explorer 10 e abaixo (sem suporte)
- Firefox 43 e abaixo (sem suporte)
- Safari 9 e abaixo (sem suporte)
- Opera Mini 8 e abaixo (sem suporte)
- Android browser 4 e abaixo (sem suporte)
- Opera 36 e abaixo (suporte parcial)
- Chome 51 e abaixo (suporte parcial)
Como controlar o suporte do navegador
Para uma visão actualizada dos navegadores que suportam a declaração let
no momento da sua leitura desta resposta, Veja em esta página.
(*) âmbito global e funcional as variáveis podem ser inicializadas e usadas antes de serem declaradas porque as variáveis de JavaScript são içado.Isto significa que as declarações são sempre muito importantes.
(**) variáveis com escopo em bloco não são listadas
<script>
var globalVariable = 7; //==window.globalVariable
function aGlobal( param ) { //==window.aGlobal();
//param is only accessible in this function
var scopedToFunction = {
//can't be accessed outside of this function
nested : 3 //accessible by: scopedToFunction.nested
};
anotherGlobal = {
//global because there's no `var`
};
}
</script>
Vai querer investigar os encerramentos e como usá-los para fazer membros privados.
A chave, pelo que eu entendo, é que Javascript tem nível de função scoping vs o mais comum scoping bloco C.
Em "Javascript 1.7" (extensão do Mozilla para Javascript) pode-se também declarar variáveis de block-scope com let
declaração:
var a = 4;
let (a = 3) {
alert(a); // 3
}
alert(a); // 4
A ideia de sondar em JavaScript quando foi originalmente desenhada por Brendan Eich veio da HyperCard Linguagem de programação Hipertalk.
Nesta linguagem, os ecrãs foram feitos de forma semelhante a uma pilha de cartões de índice. Havia um cartão mestre referido como o fundo. Era transparente e pode ser visto como a carta de baixo. Qualquer conteúdo desta carta base foi compartilhado com cartas colocadas em cima dela. Cada cartão colocado em cima tinha o seu próprio conteúdo que levou precedência sobre a carta anterior, mas ainda tinha acesso às cartas anteriores, se desejado.
É exactamente assim que o sistema de scoping JavaScript é concebido. Só tem nomes diferentes. As cartas em JavaScript são conhecidas como contextos de execução ECMA. Cada um destes contextos contém três partes principais. Um ambiente variável, um ambiente lexical e uma ligação deste tipo. Voltando à referência de cartões, o ambiente lexical contém todo o conteúdo de cartas anteriores mais baixas na pilha. O contexto atual está no topo da pilha e qualquer conteúdo declarado lá será armazenado no ambiente variável. O ambiente variável terá precedência no caso de colisões de nome.
Esta ligação irá apontar para o objecto que o contém. Às vezes, os âmbitos ou contextos de execução mudam sem que o objeto contendo mude, como em uma função declarada onde o objeto contendo pode ser window
ou um construtor funcao.
Estes contextos de execução são criados quando o controlo é transferido. O controle é transferido quando o código começa a ser executado, e isso é feito principalmente a partir da execução da função.
Então essa é a explicação técnica. Na prática, é importante lembrar que em JavaScript- os âmbitos são tecnicamente "contextos de execução"
- os contextos formam uma pilha de ambientes onde as variáveis são armazenadas
- o topo da pilha tem precedência (sendo o fundo o contexto global)
- cada função cria um contexto de execução (mas nem sempre uma nova ligação)
Aplicar isto a um dos exemplos anteriores (5. "Fechamento") nesta página, é possível seguir a pilha de contextos de execução. Neste exemplo, há três contextos na pilha. Eles são definidos pelo contexto exterior, o contexto na função imediatamente invocada chamada por var seis, e o contexto na função retornada dentro do var a função imediatamente invocada do six.
O contexto exterior. Ele tem uma variável de ambiente de um = 1
ii) O IIFE contexto, tem um léxico, de um ambiente = 1, mas uma variável de ambiente de a = 6, que tem precedência na pilha
iii) A função retornada contexto, tem um léxico, de um ambiente = 6 e que é o valor referenciado no alerta quando chamado.
2) os âmbitos são aninhados por funções até ao âmbito global.
3) as propriedades são resolvidas através da cadeia de protótipos. A declaração com traz nomes de propriedade de objeto para o escopo lexical definido pelo bloco com.
Editar: ECMAAScript 6 (Harmony) é especulado para suportar let, e eu sei que o chrome permite uma bandeira de "harmonia", então talvez ele a apoie..
Seria um suporte para o scoping de nível de bloco, mas você tem que usar a palavra-chave para fazer isso acontecer.
{[[2]}EDIT: baseado na indicação de Benjamin para fora das declarações com e captura nos comentários, eu editei o post,e adicionei mais. Tanto as declarações com como as declarações de capturas introduzem variáveis nos respectivos blocos, e que é um âmbito de bloco. As variáveis são aliadas às propriedades dos objetos que passam para eles. //chrome (v8)
var a = { 'test1':'test1val' }
test1 // error not defined
with (a) { var test1 = 'replaced' }
test1 // undefined
a // a.test1 = 'replaced'
Editar: clarificando exemplo:
O Test1 é escopado para o bloco com, mas é alias a um.test1. "Var test1" cria uma nova variável test1 no contexto léxico superior (função, ou global), a menos que seja uma propriedade de um -- que é.
Caramba! Tenha cuidado ao usar' com ' -- assim como var é um noop se a variável já está definida na função, também é um noop com relação aos nomes importado do objecto! Um pequeno Aviso sobre o nome que já está a ser definido tornaria isto muito mais seguro. Eu, pessoalmente, nunca usarei isto por causa disto.Descobri que muitas pessoas novas no JavaScript têm dificuldade em compreender que a herança está disponível por padrão na linguagem e que o escopo da função é o único escopo, até agora. Dei uma extensão a uma linda que escrevi no final do ano passado chamada JSPretty. O escopo da função de cores do recurso no código e sempre associa uma cor a todas as variáveis declaradas nesse escopo. O fecho é mostrado visualmente quando uma variável com uma cor de um escopo é usada em um diferente ambito.
Tenta a funcionalidade em:
Ver uma demonstração em:
Ver o código em:
- http://prettydiff.com/lib/jspretty.js
- https://github.com/austincheney/Pretty-Diff/blob/master/lib/jspretty.js
Actualmente o recurso oferece suporte para uma profundidade de 16 funções aninhadas, mas atualmente não colorem variáveis globais.
JavaScript tem apenas dois tipos de escopo:
- âmbito Global : Global não é nada mais que um âmbito de nível de janela.Aqui, variável presente em toda a aplicação.
-
âmbito funcional : variável declarada dentro de uma função com
var
A Palavra-chave tem âmbito funcional.
Sempre que uma função é chamada, um objeto de escopo variável é criado (e incluído na cadeia de escopo) que é seguido por variáveis em Forum.
a = "global";
function outer(){
b = "local";
console.log(a+b); //"globallocal"
}
outer();
Cadeia de âmbito -- >
- a função Window level -
a
eouter
está ao nível superior na cadeia de âmbito. - Quando a função externa chama uma nova
variable scope object
(e está incluída na cadeia de âmbito) adicionada com a variávelb
dentro dela.
Agora, quando uma variável a
necessita, procura primeiro o escopo variável mais próximo e, se a variável não estiver lá, passa para o próximo objecto da cadeia de escopo variável.o que é neste caso o nível da janela.
Apenas para adicionar às outras respostas, O scope é uma lista de pesquisa de todos os identificadores declarados (variáveis), e impõe um conjunto rigoroso de regras sobre como estes são acessíveis ao código de execução atual. Esta consulta pode ser para fins de atribuição à variável, que é uma referência LHS (lado esquerdo), ou pode ser para fins de recuperação de seu valor, que é uma referência RHS (lado direito). Estas pesquisas são o que o motor JavaScript está fazendo internamente quando é compilando e executando o código.
Por isso, nesta perspectiva, acho que uma imagem ajudaria o que encontrei nos âmbitos e nos Encerramentos por Kyle Simpson.Citando o seu ebook:
O edifício representa o conjunto de regras aninhadas do nosso programa. O primeiro piso do edifício representa o seu âmbito de execução actual, onde quer que estejas. O nível superior do edifício é o âmbito global. Você resolve as referências LHS e RHS por olhando para o seu andar actual, e se não o encontrares, apanhas o elevador para o andar seguinte., olhando para ali, depois para a próxima, e assim por diante. Assim que chegares ao último andar (o escopo global), ou você encontra o que está procurando, ou você mas tens de parar de qualquer maneira.Uma coisa que vale a pena mencionar, "Scope look-up stops uma vez que encontre o primeiro jogo". [[1] esta ideia de "níveis de escopo" explica porque "isto" pode ser alterado com um recém-criado escopo, se estiver a ser observado numa função aninhada. Aqui está um link que vai para todos esses detalhes, Tudo o que você queria saber sobre o scope javascript
Execute o código. espero que isto dê uma ideia sobre a localização.
Name = 'global data';
document.Name = 'current document data';
(function(window,document){
var Name = 'local data';
var myObj = {
Name: 'object data',
f: function(){
alert(this.Name);
}
};
myObj.newFun = function(){
alert(this.Name);
}
function testFun(){
alert("Window Scope : " + window.Name +
"\nLocal Scope : " + Name +
"\nObject Scope : " + this.Name +
"\nCurrent document Scope : " + document.Name
);
}
testFun.call(myObj);
})(window,document);
Âmbito Global:
As variáveis globais são exactamente como as estrelas globais (Jackie Chan, Nelson Mandela). Você pode acessá-los (obter ou definir o valor), a partir de qualquer parte de sua aplicação. As funções globais são como eventos globais (Ano Novo, Natal). Você pode executá-los (chamar) a partir de qualquer parte de sua aplicação.//global variable
var a = 2;
//global function
function b(){
console.log(a); //access global variable
}
Âmbito Local:
Se você está nos EUA, você pode conhecer Kim Kardashian, celebridade infame (ela de alguma forma consegue fazer os tablóides). Mas as pessoas lá fora dos EUA não a reconhecerão. Ela é uma estrela local, ligada ao seu território.As variáveis locais são como as estrelas locais. Você só pode acessá-los (obter ou definir o valor) dentro do escopo. Uma função local é como eventos Locais - você pode executar apenas (celebrar) dentro desse escopo. Se você quiser acessá-los de fora do escopo, você terá um erro de referência
function b(){
var d = 21; //local variable
console.log(d);
function dog(){ console.log(a); }
dog(); //execute local function
}
console.log(d); //ReferenceError: dddddd is not defined
Verificar este artigo para uma compreensão aprofundada do âmbito de Aplicação
- o âmbito de cada declaração var está associado à função mais imediatamente envolvente
- se não existe uma função envolvente para uma declaração var, é âmbito global
Assim, quaisquer blocos que não sejam funções não criam um novo escopo. Isso explica porque OS for-loops sobrepõem variáveis com escopo exterior:
var i = 10, v = 10;
for (var i = 0; i < 5; i++) { var v = 5; }
console.log(i, v);
// output 5 5
Usando funções em vez disso:
var i = 10, v = 10;
$.each([0, 1, 2, 3, 4], function(i) { var v = 5; });
console.log(i,v);
// output 10 10
No primeiro exemplo, houve sem escopo de bloco, então as variáveis inicialmente declaradas foram substituídas. No segundo exemplo, havia um novo escopo devido à função, de modo que as variáveis inicialmente declaradas foram sombreadas, e não sobrescritas.
É quase tudo o que precisas de saber em termos de scoping JavaScript, excepto:
- tentar / apanhar introduzir um novo âmbito apenas para a própria variável de excepção, outras variáveis não têm novo âmbito
- aparentemente, a cláusula com-cláusula é outra excepção, mas usando-a com-cláusula muito desencorajado ( https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/with)
Então você pode ver JavaScript scoping é na verdade extremamente simples, embora nem sempre intuitivo. Algumas coisas a ter em conta:
- as declarações var são colocadas no topo do âmbito de aplicação. Isto significa que não importa onde a declaração var acontece, para o compilador é como se o próprio var acontece no topo
- declarações var múltiplas no mesmo espaço âmbito de Aplicação combinado
Este código:
var i = 1;
function abc() {
i = 2;
var i = 3;
}
console.log(i); // outputs 1
É equivalente a:
var i = 1;
function abc() {
var i; // var declaration moved to the top of the scope
i = 2;
i = 3; // the assignment stays where it is
}
console.log(i);
Isto pode parecer contra intuitivo, mas faz sentido na perspectiva de um criador de linguagem imperativo.
Modern Js, ES6+, 'const
' and 'let
'
Você deve estar usando escopo de bloco para cada variável que você cria, assim como a maioria das outras línguas principais. var
é obsoleto. Isso torna o seu código mais seguro e mais sustentável.
const
95% dos casos . Faz com que a variável referência não possa mudar. Array, object, and DOM node properties can change and should likely be const
.
let
deve ser utilizado para qualquer variável à espera de ser transferida. Isto inclui dentro de um laço for. Se alguma vez alterar o valor para além da inicialização, use let
.
O âmbito do bloco significa que a variável só estará disponível dentro dos parêntesis em que é declarada. Isto se estende a âmbitos internos, incluindo funções anônimas criadas dentro do seu escopo.
Só existem âmbitos funcionais em JS. Não para tapar os buracos! Você pode ver o que está içando também.
var global_variable = "global_variable";
var hoisting_variable = "global_hoist";
// Global variables printed
console.log("global_scope: - global_variable: " + global_variable);
console.log("global_scope: - hoisting_variable: " + hoisting_variable);
if (true) {
// The variable block will be global, on true condition.
var block = "block";
}
console.log("global_scope: - block: " + block);
function local_function() {
var local_variable = "local_variable";
console.log("local_scope: - local_variable: " + local_variable);
console.log("local_scope: - global_variable: " + global_variable);
console.log("local_scope: - block: " + block);
// The hoisting_variable is undefined at the moment.
console.log("local_scope: - hoisting_variable: " + hoisting_variable);
var hoisting_variable = "local_hoist";
// The hoisting_variable is now set as a local one.
console.log("local_scope: - hoisting_variable: " + hoisting_variable);
}
local_function();
// No variable in a separate function is visible into the global scope.
console.log("global_scope: - local_variable: " + local_variable);
Cada pedaço de código JavaScript (código global ou funções) tem uma cadeia de escopo associada a ele. Este âmbito de Aplicação
cadeia é uma lista ou cadeia de objetos que define as variáveis que estão "em escopo" para que
codigo. Quando o JavaScript precisa de procurar o valor de uma variável x
(um processo chamado
resolução variável , começa por olhar para o primeiro objecto da cadeia. Se esse objecto
uma propriedade chamada {[[0]} , o valor dessa propriedade é usado. Se o primeiro objecto não ter
uma propriedade chamada {[[0]}, JavaScript continua a pesquisa com o próximo objecto da cadeia.
Se o segundo objecto não tiver uma propriedade chamada x
, a pesquisa passa para o seguinte
protesto, e assim por diante. Se x
não é propriedade de nenhum dos objectos da cadeia de escopo, então
x
não está em escopo para esse código, e ocorre um ReferenceError.
Em código JavaScript de nível superior (ou seja, Código Não contido em qualquer definição de função),
a cadeia de escopo consiste de um único objeto, o global objecto. Numa função não aninhada,
a cadeia de escopo consiste de dois objetos. O primeiro é o objeto que define a função
parâmetros e variáveis locais, e o segundo é o objeto global. Numa função aninhada,
a cadeia de escopo tem três ou mais objetos. É importante entender como esta cadeia
of objects is created. Quando uma função é definida , ela armazena a cadeia de escopo então em efeito.
Quando essa função é invocada , cria um novo objecto para armazenar o seu local variáveis, e
adiciona esse novo objeto à cadeia de escopo armazenada para criar uma nova cadeia, mais longa, que
representa o escopo para essa invocação de função. Isto torna-se mais interessante para
funções aninhadas porque cada vez que a função externa é chamada, a função interna é
definido de novo. Uma vez que a cadeia de escopo difere em cada invocação da função externa,
a função interna será sutilmente diferente cada vez que for definida-o código de o interior
a função será idêntica em cada invocação da função exterior, mas da cadeia de escopo
associado a esse código será diferente.
Esta noção de cadeia de âmbito é crucial para a compreensão dos encerramentos .
var a = new Date();
function f1(b)
{
b.setDate(b.getDate()+1);
alert(b.getDate());
}
f1(a);
alert(a.getDate());
O meu entendimento é que existem 3 âmbitos: global scope, disponível globalmente; local scope, disponível para uma função inteira, independentemente dos blocos; e block scope, disponível apenas para o bloco, declaração ou expressão em que foi usado. O escopo Global e local é indicado com a palavra-chave "var", dentro ou fora de uma função, e o escopo de bloco é indicado com a palavra-chave "let".
Para aqueles que acreditam que existe apenas âmbito global e local, por favor explique por que Mozilla teria uma página inteira descrevendo as nuances do scope de bloco em JS.Https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/let
Em JavaScript existem dois tipos de escopo:
- âmbito de Aplicação Local
- âmbito Global
A função abaixo tem uma variável de âmbito local carName
. E esta variável não é acessível de fora da função.
function myFunction() {
var carName = "Volvo";
alert(carName);
// code here can use carName
}
A classe abaixo tem uma variável de âmbito Global carName
. E esta variável é acessível de todos os lugares da classe.
class {
var carName = " Volvo";
// code here can use carName
function myFunction() {
alert(carName);
// code here can use carName
}
}
Em EcmaScript5, existem essencialmente dois âmbitos, âmbito local e escopo global, mas no EcmaScript6 temos basicamente três âmbitos, de âmbito local, alcance global e um novo escopo chamado escopo de bloco.
O exemplo do campo de aplicação é: -
for ( let i = 0; i < 10; i++)
{
statement1...
statement2...// inside this scope we can access the value of i, if we want to access the value of i outside for loop it will give undefined.
}
O ECMAScript 6 introduziu as palavras-chave let e const. Estas palavras-chave podem ser usadas no lugar da palavra-chave var. Ao contrário da palavra-chave var, as palavras-chave let e const suportam a declaração de âmbito local dentro de declarações de bloco.
var x = 10
let y = 10
const z = 10
{
x = 20
let y = 20
const z = 20
{
x = 30
// x is in the global scope because of the 'var' keyword
let y = 30
// y is in the local scope because of the 'let' keyword
const z = 30
// z is in the local scope because of the 'const' keyword
console.log(x) // 30
console.log(y) // 30
console.log(z) // 30
}
console.log(x) // 30
console.log(y) // 20
console.log(z) // 20
}
console.log(x) // 30
console.log(y) // 10
console.log(z) // 10
ES5
e mais velhos:
As variáveis de Javascript eram inicialmente (pre ES6
) função lexicalmente escopada. O termo escopo Lexico significa que você pode ver o escopo das variáveis "olhando" para o código.
Todas as variáveis declaradas com a palavra-chave var
são escopadas para a função. No entanto, se outras funções são declaradas dentro dessa função essas funções terão acesso às variáveis das funções externas. Isto é chamado de cadeia de escopo . Funciona. da seguinte forma:
- Quando uma função procura resolver um valor variável, primeiro olha para o seu próprio âmbito. Este é o corpo da função, ou seja, tudo entre parêntesis encaracolados {} (excepto para as variáveis dentro outras funções que estão neste âmbito).
- Se não conseguir encontrar a variável dentro do corpo da função, subirá até à cadeia {[32] } e olhará para o âmbito da variável na função onde a função foi definida. Isto é o que se entende com escopo léxico, podemos ver no código onde esta função foi definida e, portanto, pode determinar a cadeia de escopo apenas olhando para o código.
Exemplo:
// global scope
var foo = 'global';
var bar = 'global';
var foobar = 'global';
function outerFunc () {
// outerFunc scope
var foo = 'outerFunc';
var foobar = 'outerFunc';
innerFunc();
function innerFunc(){
// innerFunc scope
var foo = 'innerFunc';
console.log(foo);
console.log(bar);
console.log(foobar);
}
}
outerFunc();
foo
, bar
, e foobar
para a consola é o seguinte:
- tentamos logar foo para o console, o foo pode ser encontrado dentro da função {[[8]} em si. Por conseguinte, o valor of foo is resolved to the string
innerFunc
. - tentamos logar a barra para a consola, a barra não pode ser encontrada dentro da função {[[8]} em si. Portanto, precisamos escalar a cadeia de escopo. Primeiro olhamos para a função externa na qual a função
innerFunc
foi definida. Esta é a funçãoouterFunc
. No escopo deouterFunc
podemos encontrar a barra variável, que contém a string 'outerFunc'. - o foobar não pode ser encontrado no innerFunc. . Portanto, temos de subir o escopo. cadeia {[32] } para o âmbito innerFunc. Também não pode ser encontrado aqui, subimos outro nível para o âmbito global ([31]} (ou seja, o âmbito mais externo). Encontramos aqui a barra de rodapé variável que contém a cadeia 'global'. Se não tivesse encontrado a variável depois de escalar a cadeia de escopo, o motor JS lançaria um referenceError.
ES6
(ES 2015) e mais velhos:
Os mesmos conceitos de âmbito Lexico e de âmbito escópico ainda se aplicam em ES6
. No entanto, uma nova forma de foram introduzidas variáveis declarativas. Existem os seguintes:
-
let
: cria uma variável com escopo em bloco -
const
: cria uma variável com escopo em bloco que tem de ser inicializada e não pode ser reatribuída
A maior diferença entre var
e let
/const
is that var
is function scoped whereas let
/const
estão a ser vigiados. Aqui está um exemplo para ilustrar isto:
let letVar = 'global';
var varVar = 'global';
function foo () {
if (true) {
// this variable declared with let is scoped to the if block, block scoped
let letVar = 5;
// this variable declared with let is scoped to the function block, function scoped
var varVar = 10;
}
console.log(letVar);
console.log(varVar);
}
foo();
No acima exemplo letVar registra o valor global porque as variáveis declaradas com let
são escopadas em bloco. Eles deixam de existir fora de seu respectivo bloco, então a variável não pode ser acessada fora do bloco if.
-
Global scope : a variável que é anunciada no global scope pode ser usada em qualquer lugar do programa muito suavemente. Por exemplo:
var carName = " BMW"; // code here can use carName function myFunction() { // code here can use carName }
-
Âmbito funcional ou âmbito Local: a variável declarada neste âmbito só pode ser utilizada na sua própria função. Por exemplo:
// code here can not use carName function myFunction() { var carName = "BMW"; // code here can use carName }
Global: variável declarada fora de uma função
Local: variável declarada dentro de uma função, e só pode ser chamada nesse âmbito