Significado de “isto” em módulos e funções de node.js

Eu tenho um arquivo JavaScript que é carregado por require .

 // loaded by require() var a = this; // "this" is an empty object this.anObject = {name:"An object"}; var aFunction = function() { var innerThis = this; // "this" is node global object }; aFunction(); (function(anyParameter){ console.log(anyParameter.anObject); })( this // "this" is same having anObject. Not "global" ); 

Minha pergunta é: this em var a = this; é um object vazio, enquanto que this declarações em funções são sombras do object global node.js. Eu sei que this palavra-chave é diferente em funções, mas eu não conseguia entender porque primeiro this não é igual a global e this em funções é igual a global.

Como o node.js injetar global para this em escopos de function e por que não injetá-lo para o escopo do módulo?

Aqui estão alguns fatos fundamentais que você deve entender para esclarecer a situação:

  • No código de nível superior em um módulo Node, this é equivalente a module.exports . Esse é o object vazio que você vê.

  • Quando você usa this dentro de uma function, o valor this é determinado novamente antes de cada execução da function, e seu valor é determinado pelo modo como a function é executada . Isso significa que duas invocações do mesmo object de function poderiam ter valores diferentes se os mecanismos de invocação forem diferentes (por exemplo, aFunction() vs. aFunction.call(newThis) vs. emitter.addEventListener("someEvent", aFunction); etc .) No seu caso, aFunction() no modo não-estrito executa a function com this conjunto para o object global.

  • Quando os arquivos JavaScript são require d como módulos Node, o mecanismo Node executa o código do módulo dentro de uma function wrapper. Essa function de quebra de módulo é invocada com um conjunto para module.exports . (Lembre-se, acima, uma function pode ser executada com um valor abitrary.)

Assim, você obtém valores diferentes porque cada this deles reside dentro de uma function diferente: o primeiro está dentro da function wrapper do módulo criada pelo Nó e o segundo está dentro de uma aFunction .

Para entender isso, você precisa entender que o Node.js na verdade envolve o código do seu módulo em uma function, como esta

 (function (exports, require, module, __filename, __dirname) { var test = function(){ console.log('From test: ' + this); }; console.log(this); test(); }); 

Explicação detalhada pode ser encontrada nesta resposta .


Agora, essa function empacotada é invocada como esta

 var args = [self.exports, require, self, filename, dirname]; return compiledWrapper.apply(self.exports, args); 

Portanto, this , no nível do módulo, é realmente o object de exports .

Você pode confirmar que assim

 console.log(this, this === module.exports); // {} true 

É porque o object global padrão em um módulo Node.js é o object exports , e você está chamando test() que não especifica this . No JS tradicional, this aponta para o object global, com use strict , this será nulo.

this pode apontar para qualquer coisa, só depende de como você a chama.

  • test() : Usa o object global ( exports ) como this , a menos que esteja no modo estrito, onde this será nulo;
  • test.call({}) ou test.apply({}) : você está especificando o que usar como this (o primeiro parâmetro)
  • var obj = {testRef: test}; obj.testRef() var obj = {testRef: test}; obj.testRef() : this está definido à esquerda do . isto é, obj

Contando a resposta do quatro olho

É verdade que this no nível superior do módulo é exports , mas isso não significa necessariamente que this test() interno test() também aponte para a mesma coisa de onde foi chamado.


Tentando provar que this e o object global apontam para exports

  myGLobal = 5; this.myGlobal; // 5