Как проверить, работает ли скрипт под node.Яш?
У меня есть скрипт, который мне нужен от узла.сценарий js, который я хочу сохранить независимым от движка javascript.
Так, например, я хочу сделать:
exports.x = y;
только если он работает в узле.js. как я могу выполнить этот тест?
Edit: при публикации этого вопроса я не знал узел.функция модулей js основана на на CommonJS.
для конкретного примера я дал бы более точный вопрос бывало:
как скрипт может определить, требуется ли он в качестве модуля commonjs?
17 ответов
Это как подчеркивания.js библиотека делает это (ища поддержку CommonJS):
Edit: к вашему обновленному вопросу:
(function () {
// Establish the root object, `window` in the browser, or `global` on the server.
var root = this;
// Create a reference to this
var _ = new Object();
var isNode = false;
// Export the Underscore object for **CommonJS**, with backwards-compatibility
// for the old `require()` API. If we're not in CommonJS, add `_` to the
// global object.
if (typeof module !== 'undefined' && module.exports) {
module.exports = _;
root._ = _;
isNode = true;
} else {
root._ = _;
}
})();
пример здесь сохраняет шаблон модуля.
Ну, нет надежного способа обнаружить запуск в узле.js, так как каждый веб-сайт может легко объявить те же переменные, но, поскольку нет window
объект в узле.js по умолчанию вы можете пойти другим путем и проверить, работаете ли вы внутри браузера.
это то, что я использую для библиотек, которые должны работать как в браузере, так и под узлом.js:
if (typeof window === 'undefined') {
exports.foo = {};
} else {
window.foo = {};
}
он все еще может взорваться, если это window
определяется в узле.js, но нет хороший причина для кого-то сделать это, так как вам явно нужно уходить из var
или установите свойство на
проблема с попыткой выяснить, в какой среде работает ваш код, заключается в том, что любой объект может быть изменен и объявлен, что делает почти невозможным выяснить, какие объекты являются родными для среды, и которые были изменены программой.
тем не менее, есть несколько трюков, которые мы можем использовать, чтобы выяснить, в какой среде вы находитесь.
давайте начнем с общепринятого решения, которое используется в подчеркивании библиотека:
typeof module !== 'undefined' && module.exports
этот метод на самом деле отлично подходит для серверной стороны, как когда require
вызывается функция, она сбрасывает this
объект для пустого объекта и переопределяет module
для вас снова, то есть вам не нужно беспокоиться о каких-либо внешних вмешательствах. Пока ваш код загружен с помощью require
, вы в безопасности.
однако, это разваливается на части в браузере, как любой может легко определить module
чтобы казалось, что это объект, который вы ищете. С одной стороны, это может быть поведение, которое вы хотите, но оно также диктует, какие переменные пользователь библиотеки может использовать в глобальной области. Может кто-то хочет использовать переменную с именем module
и exports
внутри него для другого использования. Маловероятно, но кто мы такие, чтобы судить, какие переменные может использовать кто-то другой, только потому, что другая среда использует это имя переменной?
фишка в том, что если мы предполагаем, что ваш скрипт загруженная в глобальную область (которая будет, если она загружена через тег скрипта) переменная не может быть зарезервирована во внешнем закрытии, потому что браузер этого не позволяет. Теперь помните в узле, то
в настоящее время я наткнулся на неправильное обнаружение узла, который не известно о среде узла в Электрон из-за вводящей в заблуждение функции обнаружения. Следующие решения явно идентифицируют процесс-среду.
Идентифицировать Узел.Яш только
(typeof process !== 'undefined') && (process.release.name === 'node')
это обнаружит, работаете ли вы в узле-процессе, так как process.release
содержит "метаданные, связанные с текущей [Node-]release".
после отродьем io.js значение process.release.name
может стать io.js
(см. процесс-doc). Чтобы правильно определить среду, готовую к узлу, я думаю, вы должны проверить следующее:
определить узел (>= 3.0.0) или io.js
(typeof process !== 'undefined') &&
(process.release.name.search(/node|io.js/) !== -1)
этот оператор был протестирован с узлом 5.5.0, Electron 0.36.9 (с узлом 5.1.1) и Chrome 48.0.2564.116.
идентифицировать узел (>= 0.10.0) или Ио.js
(typeof process !== 'undefined') &&
(typeof process.versions.node !== 'undefined')
комментарий@daluege вдохновил меня подумать о более общем доказательстве. Это должно работать от узла.js>= 0.10. Я не нашел уникального идентификатора для предыдущих версий.
P. s.: Я размещаю этот ответ здесь, так как вопрос привел меня сюда, хотя OP искал ответ на другой вопрос.
в браузере работает следующее, если только намеренно, явно не саботируется:
if(typeof process === 'object' && process + '' === '[object process]'){
// is node
}
else{
// not node
}
БАМ.
большинство предлагаемых решений на самом деле могут быть подделаны. Надежный способ-проверить внутренний Class
свойство глобального объекта с помощью Object.prototype.toString
. Внутренний класс не может быть подделан в JavaScript:
var isNode =
typeof global !== "undefined" &&
{}.toString.call(global) == '[object global]';
вот довольно классный способ сделать это:
const isBrowser = this.window === this;
это работает, потому что в браузерах глобальная переменная "this" имеет самостоятельную ссылку под названием "window". Эта ссылка на себя не существует в Node.
- в браузере " это "- это ссылка на глобальный объект, называемый окно''.
- в узле 'this' есть ссылка на модуль.поставляемый
объект.
- " это " - это не ссылка на глобальный объект узла, называемый "глобальный".
- " это " - это не ссылка на пространство объявления переменной модуля.
чтобы сломать предложенную выше проверку браузера, вам нужно будет сделать что-то вроде следующего
this.window = this;
перед выполнением проверки.
еще один обнаружение окружающей среды:
(значение: Большинство ответов здесь в порядке.)
function isNode() {
return typeof global === 'object'
&& String(global) === '[object global]'
&& typeof process === 'object'
&& String(process) === '[object process]'
&& global === global.GLOBAL // circular ref
// process.release.name cannot be altered, unlike process.title
&& /node|io\.js/.test(process.release.name)
&& typeof setImmediate === 'function'
&& setImmediate.length === 4
&& typeof __dirname === 'string'
&& Should I go on ?..
}
немного параноик, да? Вы можете сделать это более подробным, проверив больше глобальные.
но не надо!.
все это можно подделать в любом случае имитация.
например, чтобы подделать
Как насчет использования объекта процесса и проверки execPath на node
?
как скрипт может определить, требуется ли он в качестве модуля commonjs?
связанный: чтобы проверить, требуется ли это как модуль против запуска непосредственно в узле, вы можете проверить require.main !== module
.
http://nodejs.org/docs/latest/api/modules.html#accessing_the_main_module
вот мой вариант того, что выше:
(function(publish) {
"use strict";
function House(no) {
this.no = no;
};
House.prototype.toString = function() {
return "House #"+this.no;
};
publish(House);
})((typeof module == 'undefined' || (typeof window != 'undefined' && this == window))
? function(a) {this["House"] = a;}
: function(a) {module.exports = a;});
чтобы использовать его, вы изменяете " дом " на второй последней строке, чтобы быть тем, что вы хотите, чтобы имя модуля было в браузере, и публикуете то, что вы хотите, чтобы значение модуля было (обычно конструктор или литерал объекта).
в браузерах глобальный объект является окном, и он имеет ссылку на себя (есть окно.окно, которое = = window). Мне кажется, что это вряд ли произойдет, если вы находитесь в браузере или в среде, которая хочет, чтобы вы верили, что вы в браузере. Во всех остальных случаях, если объявлена глобальная переменная "module", она использует то, что в противном случае она использует глобальный объект.
Я использую process
для проверки узла.Яш вот так
if (typeof(process) !== 'undefined' && process.version === 'v0.9.9') {
console.log('You are running Node.js');
} else {
// check for browser
}
или
if (typeof(process) !== 'undefined' && process.title === 'node') {
console.log('You are running Node.js');
} else {
// check for browser
}
документирована здесь
узел.js имеет process
объект, пока у вас нет другого скрипта, который создает process
вы можете использовать его, чтобы определить, работает ли код на узле.
var isOnNodeJs = false;
if(typeof process != "undefined") {
isOnNodeJs = true;
}
if(isOnNodeJs){
console.log("you are running under node.js");
}
else {
console.log("you are NOT running under node.js");
}
Это довольно безопасный и прямой способ обеспечения совместимости между javascript на стороне сервера и на стороне клиента, который также будет работать с browserify, RequireJS или CommonJS на стороне клиента:
(function(){
// `this` now refers to `global` if we're in NodeJS
// or `window` if we're in the browser.
}).call(function(){
return (typeof module !== "undefined" &&
module.exports &&
typeof window === 'undefined') ?
global : window;
}())
редактировать: относительно вашего обновленного вопроса: " как скрипт может сказать, требуется ли он в качестве модуля commonjs?" я не думаю, что это может. Вы можете проверить, является ли exports
объект (if (typeof exports === "object")
), поскольку спец требует, чтобы он был предоставлен модулям, но все, что говорит вам об этом ... exports
- это объект. :-)
оригинальный ответ:
Я уверен, что есть определенный символ NodeJS ( нет, вы должны использовать EventEmitter
, возможноrequire
чтобы получить модуль Events, см. ниже), которые вы могли бы проверить, но, как сказал Дэвид, в идеале вам лучше обнаружить функцию (а не среду), если это имеет смысл.
обновление: возможно, что-то вроде:
if (typeof require === "function"
&& typeof Buffer === "function"
&& typeof Buffer.byteLength === "function"
&& typeof Buffer.prototype !== "undefined"
&& typeof Buffer.prototype.write === "function") {
но это просто говорит вам, что вы находитесь в среде с require
и что-то очень, очень похожее на NodeJS Buffer
. :-)
возьмите источник узла.js и измените его, чтобы определить переменную, такую как runningOnNodeJS
. Проверьте эту переменную в коде.
Если у вас нет собственной частной версии node.js, откройте запрос функции в проекте. Попросите, чтобы они определили переменную, которая дает вам версию node.js, что вы бежите. Затем проверьте эту переменную.
очень старый пост, но я просто решил его, обернув операторы require в try - catch
try {
var fs = require('fs')
} catch(e) {
alert('you are not in node !!!')
}