2016-02-16 2 views
2

КодNode.js: Каков контекст оператора `this` при использовании в области модуля?

Я пишу следующий код и сохранить его как test.js:

var foo = 'I am local'; 
global.foo = 'I am global'; 

function print() { 
    console.log(this.foo); 
}; 

print(); 
console.log (this.foo); 

Я затем запустить его в терминале с помощью команды node test.js и возвращает:

I am global 
undefined 

Вопрос

Почему он не возвращается:

I am global 
I am global 

?

+0

Узел модулей не запускается в глобальном масштабе. – Bergi

+0

Спасибо @Bergi. Как бы вы это сформулировали тогда, когда console.log вызывается в файле вне любых функций, объектов и т. Д. Вы бы сказали, что он вызывается в «локальном контексте»? – rabbitco

+0

Он известен как «область модуля». – Bergi

ответ

3

Внутри модуля Node, this дизайн относится к exports объекта модуля:

console.log(this === exports); // true 

Создание console.log(this.foo) эквивалентно console.log(exports.foo).

Другими словами, ни один из this не относится к глобальному объекту, а локальные переменные магически становятся свойствами exports.

С exports.foo не существует, вы получаете undefined.

+0

Я думаю, что справедливо удивляться, почему этот оператор ссылается на объект экспорта. Это не может быть объяснено стандартным поведением оператора. Как представляется, это вызвано выбором разработчиками узла для установки значения для объекта экспорта. Хорошо знать. Локальные переменные не «волшебным образом появляются» на объекте экспорта, потому что они фактически являются частными переменными в функции, обертывающей модуль узла - также хорошо знать. Спасибо, что помогли мне поднять мои знания об Узле. – rabbitco

+0

Здесь нет аргументов. Значение 'this' зависит от того, как вызывается функция, поэтому вам нужно будет узнать, как обертка модуля вызывается, чтобы знать, что это означает. –

+0

Ну с добавленным замечанием - как я понимаю, - что в модульной области «этот» дизайн всегда относится к объекту 'export' ...? – rabbitco

1

Все файлы сценариев в Node.js выполняются в собственном контексте выполнения, в то время как браузеры выполняют все файлы сценариев в контексте глобального выполнения. При вызове функции без определенного контекста, обычно она будет установлена ​​по умолчанию для глобального object in Node.

print(); //global execution context -> 'I am global' 
console.log (this.foo); // no context -> undefined 
0

this свойство функции устанавливается, когда функция вызывается и точками по умолчанию для объекта вызывающей функции, если значение не задано с помощью таких методов, как bind, apply или call.

Стоит отметить, что модуль (эквивалент файла) в узле заворачивают в функции(), как это:

NativeModule.wrapper = [ 
    ‘(function (exports, require, module, __filename, __dirname) { ‘, 
    ‘\n});’ 
]; 

Это означает, что все фрагменты кода ниже, на самом деле выполняются внутри этого обертка. См. Where are vars stored in Nodejs для получения более подробной информации.

console.log (это) внутри функции

Следующий код:

var apple = ‘red’;   // private variable in the wrapper function 
global.apple = ‘yellow’; // property on the global object 

var foo = function() { 

    var apple = ‘green’; 
    console.log (this.apple); 
} 

foo(); 

возвращает yellow, поскольку внутренняя функция не может получить доступ к значению каких-либо внешних функций и в случае таких this Внутренние функции - это стандартное поведение this по умолчанию для глобального объекта (объект окна в браузерах).

console.log (это) внутри объекта

Следующий код:

var apple = ‘red’;   // private variable in the wrapper function 
global.apple = ‘yellow’; // property on the global object 

var myObject = { 

    orange: ‘orange’, 
    print: function() { 

    console.log (this.orange); 
    console.log (this.melon); 
}} 

myObject.print(); 

возвращает orange и undefined, потому что это myObject вызывающему print. Он возвращает undefined по отношению к this.melon, так как myObject не имеет собственности с названием melon.

Консоль.войти (это) в рамках модуля

Команда console.log это свойство на Node's глобального объекта со значением функции и, следовательно, можно было бы ожидать следующий код

global.apple = ‘yellow’; 
global.console.apple = 'yellow'; 

console.log(this.apple); 

для возврата yellow в console.log() это то же самое, что и global.console.log(). Это означает, что глобальный объект вызывается console.log(), поэтому вы ожидаете, что this укажет либо global.apple, либо global.console.apple. Однако некоторые функции глобального объекта фактически выполняются в области модуля (см. Global objects), и в этой области разработчики узла решили установить значение this объекту exports, который передается как параметр для обертывания функции модуль узла.

Приведенный выше код поэтому возвращает undefined, потому что exports не имеет собственности с именем apple.

+0

Ваш анализ странный. Значение 'this' * внутри *' console.log' (то есть, что связано с 'log') не имеет ничего общего с' this 'Вы ссылаетесь на' this.apple'. –

+0

@FelixKling: Не так странно, я думаю. См. отредактированный контент выше. Если вы установите global.foo = function() {console.log (this.apple) и глобальный .apple = 'green' и вызывать foo(), он вернет «зеленый». Поэтому почему бы не global.console.log (this.apple), а также вернуть «зеленый». Поскольку дизайнеры узла предпочитают пустить консоль .log запустить в области модуля и в этой области, чтобы установить значение этого объекта экспорта, переданного в функцию-обертку, в качестве параметра. Нелегко понять, знаете ли вы об этом. – rabbitco

+0

Ну, вы много фокусируетесь на 'console.log', но проблема не имеет к этому никакого отношения. Первые два примера просто демонстрируют, как «это» работает в двух конкретных ситуациях: обычный вызов функции (объект глобулы), метод объекта (объект). Это не относится ни к узлу, ни к 'console.log'. Последний пример особенно смущает и показывает, что вы еще не полностью поняли ситуацию (без обид) * «вы ожидаете, что следующий код [...] вернет« желтый ») * Я очень сомневаюсь в этом, что большинство разработчиков ожидал бы. Чтобы записать 'yellow',' this' нужно будет ссылаться на 'console' ... –

Смежные вопросы