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?

Author: John Slegers, 2009-02-01

26 answers

Acho que o melhor que posso fazer é dar-te alguns exemplos para estudares. Programadores Javascript são praticamente classificados por quão bem eles entendem o escopo. Pode, por vezes, ser bastante contra-intuitivo.
  1. Uma variável de âmbito global

    // global scope
    var a = 1;
    
    function one() {
      alert(a); // alerts '1'
    }
    
  2. Â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'
    }
    
  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
    }
    
  4. Intermédio: propriedades do objecto

    var a = 1;
    
    function Five() {
      this.a = 5;
    }
    
    alert(new Five().a); // alerts '5'
    
  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'
      };
    })();
    
  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'
    

  7. Global+Local: um caso extra complexo

    var x = 5;
    
    (function () {
        console.log(x);
        var x = 10;
        console.log(x); 
    })();
    

    Isto irá imprimir undefined e 10 em vez de 5 e 10 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); 
    })();
    
  8. Cláusula de captura-variável abrangida

    var e = 5;
    console.log(e);
    try {
        throw 6;
    } catch (e) {
        console.log(e);
    }
    console.log(e);
    
    Isto vai ser impresso.5, 6, 5. Dentro da cláusula de captura e esconde variáveis globais e locais. Mas este âmbito especial é apenas para a variável capturada. Se você escrever var 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.
 2305
Author: Triptych, 2018-08-20 10:07:51

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.

 222
Author: krosenvold, 2012-08-14 07:54:06

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 exatamente this significa a qualquer momento. Esperemos que este link mais introdutório seja suficiente para começar.)
 96
Author: Jon Skeet, 2014-02-25 18:12:12
JavaScript da velha escola Tradicionalmente, o JavaScript só tem dois tipos de escopo:
  1. âmbito Global : as variáveis são conhecidas em toda a aplicação, desde o início da aplicação (*)
  2. âmbito funcional : as variáveis são conhecidas dentro a função são declarados em, desde o início da função (*)
Não vou falar sobre isso, já que ... já são muitas outras respostas que explicam a diferença.
JavaScript Moderno

A especificações de JavaScript mais recentes agora também permitir um terceiro escopo:

  1. â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)

enter image description here


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

 57
Author: John Slegers, 2018-03-06 22:25:33
Aqui está um exemplo:
<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.
 35
Author: geowa4, 2009-02-01 08:48:09

A chave, pelo que eu entendo, é que Javascript tem nível de função scoping vs o mais comum scoping bloco C.

Aqui está um bom artigo sobre o assunto.

 28
Author: James McMahon, 2012-05-15 17:38:30

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
 23
Author: kennytm, 2010-04-06 11:19:39

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.

enter image description here

 18
Author: Travis J, 2015-09-14 20:29:53
Há um escopo global, um escopo de função, e o com e captura. Não há escopo de nível 'block' em geral para variáveis -- as declarações com e as declarações de capturas adicionam nomes aos seus blocos.

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.
 16
Author: Gerard ONeill, 2014-06-06 17:13:06

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:

Actualmente o recurso oferece suporte para uma profundidade de 16 funções aninhadas, mas atualmente não colorem variáveis globais.

 9
Author: austincheney, 2013-03-21 17:31:11

JavaScript tem apenas dois tipos de escopo:

  1. âmbito Global : Global não é nada mais que um âmbito de nível de janela.Aqui, variável presente em toda a aplicação.
  2. â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 -- >

  1. a função Window level - a e outer está ao nível superior na cadeia de âmbito.
  2. Quando a função externa chama uma nova variable scope object (e está incluída na cadeia de âmbito) adicionada com a variável b 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.

 8
Author: Anshul, 2014-09-21 20:49:17

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.

image

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
 8
Author: James Drinkard, 2016-03-30 13:33:04

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);
 7
Author: Yeasin Abedin Siam, 2014-10-18 09:54:56

Â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

 7
Author: KhanSharp, 2016-02-23 18:56:04
Existem quase dois tipos de scopes JavaScript:
  • 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:

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.
 5
Author: jackbean818, 2015-10-29 16:12:19

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.

 5
Author: Gibolt, 2017-12-08 19:03:40

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);
 4
Author: koredalin, 2015-07-11 18:13:01

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 .

 4
Author: Fanyo SILIADIN, 2017-01-28 11:16:18
Tenta este curioso exemplo. No exemplo abaixo se a fosse um numérico inicializado em 0, você veria 0 e então 1. Exceto a é um objeto e javascript vai passar f1 um ponteiro de um ao invés de uma cópia dele. O resultado é que você recebe o mesmo alerta em ambas as vezes.
var a = new Date();
function f1(b)
{
    b.setDate(b.getDate()+1);
    alert(b.getDate());
}
f1(a);
alert(a.getDate());
 3
Author: Mig82, 2013-08-10 17:37:14

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

 3
Author: mrmaclean89, 2017-09-16 22:35:07

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 
    }
}
 2
Author: Abdur Rahman, 2017-11-01 09:16:18

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.
}
 1
Author: Vivek Mehta, 2017-12-15 07:49:36

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
 1
Author: Dava E., 2018-02-09 15:37:12

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:

  1. 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).
  2. 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();
O que acontece quando tentamos registar as variáveis foo, bar, e foobar para a consola é o seguinte:
  1. 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.
  2. 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ção outerFunc. No escopo de outerFunc podemos encontrar a barra variável, que contém a string 'outerFunc'.
  3. 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.

 0
Author: Willem van der Veen, 2018-09-30 09:23:31
Há dois tipos de âmbitos em JavaScript.
  1. 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 
    }
    
  2. Â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
    }
    
 -2
Author: A. Randhawa, 2016-01-11 05:32:02

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

 -3
Author: poisonlocc, 2015-01-03 19:35:52