Значение "this" в node.js модулях и функциях
У меня есть файл JavaScript, который загружается 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"
);
Мой вопрос: this
в var a = this;
- пустой объект, тогда как операторы this
в функциях являются тенями глобального объекта node.js. Я знаю, что ключевое слово this
отличается от функций, но я не мог понять, почему первая this
не равна глобальным, а this
в функциях равна глобальным.
Как node.js вводят global
в this
в области видимости функций и почему он не вводит его в область видимости модуля?
Ответы
Ответ 1
Вот несколько фундаментальных фактов, которые вы должны понять, чтобы прояснить ситуацию:
-
В коде верхнего уровня в модуле Node this
эквивалентен module.exports
. Это пустой объект, который вы видите.
-
Когда вы используете this
внутри функции, значение this
определяется заново перед каждым исполнением функции, а ее значение определено как выполняется функция. Это означает, что две вызовы одного и того же функционального объекта могут иметь разные значения this
, если механизмы вызова различны (например, aFunction()
vs. aFunction.call(newThis)
vs. emitter.addEventListener("someEvent", aFunction);
и т.д.). В вашем случае aFunction()
в нестрогом режиме запускается функция с this
, установленным для глобального объекта.
-
Когда файлы JavaScript являются require
d как модули Node, механизм Node запускает код модуля внутри функции-обертки. Эта функция обматывания модулей вызывается с помощью this
, установленного на module.exports
. (Вспомните, что выше, функция может быть запущена со значением this
)
Таким образом, вы получаете разные значения this
, потому что каждый this
находится внутри другой функции: первая находится внутри функции Node -created module-wrapper, а вторая находится внутри aFunction
.
Ответ 2
Чтобы понять это, вам нужно понять, что Node.js фактически переносит ваш код модуля в функцию, например,
(function (exports, require, module, __filename, __dirname) {
var test = function(){
console.log('From test: ' + this);
};
console.log(this);
test();
});
Подробное объяснение можно найти в этом ответе.
Теперь эта завернутая функция фактически вызывается как это
var args = [self.exports, require, self, filename, dirname];
return compiledWrapper.apply(self.exports, args);
Итак, this
, на уровне модуля, на самом деле является объектом exports
.
Вы можете подтвердить, что вот так
console.log(this, this === module.exports);
// {} true
Ответ 3
Это потому, что глобальный объект по умолчанию в модуле Node.js является объектом exports
, и вы вызываете test()
, который не указывает this
. В традиционном JS this
указывает на глобальный объект, при use strict
, this
будет null.
this
может указывать на что угодно, это зависит только от того, как вы его называете.
-
test()
: использует глобальный объект (exports
) как this
, если только в строгом режиме, где this
будет null;
-
test.call({})
или test.apply({})
: Вы указываете, что использовать как this
(первый параметр)
-
var obj = {testRef: test}; obj.testRef()
: this
устанавливается слева от .
, то есть obj
Противодействие ответ на этот вопрос
Верно, что this
на верхнем уровне модуля exports
, но это не обязательно означает, что this
внутри test()
также укажет на то же, что и там, откуда он был вызван.
Попытка доказать, что this
и глобальный объект указывают на exports
myGLobal = 5;
this.myGlobal; // 5