Как обнаруживать, если мой код работает в Node.js но не в браузере, не используя new Function ()?

Этот ответ (на английском) объясняет, как знать, работает ли твой язык сценариев JavaScript в Node.js или в браузере, но зависит от использования new Function(), что не функционирует в браузере, если ты используешь CSP без unsafe-eval (и это важно в моем проекте).

Я знаю, что есть несколько чувствительных, но ошибочных форм также, как он может состоять в том, чтобы видеть если window или process.versions.node они определены, но легко определять эти переменные, чтобы обманывать в программу.

Есть какая-то другая форма, которая была бы непогрешимой, обнаруживания, если я нахожусь в браузере или в Node.js, не используя new Function()?

Я предполагаю, что, по крайней мере, я могу пробовать это в одном try {} и, если я нахожусь в Node.js, я могу быть с достоверностью, и если я не могу использовать менее непогрешимую форму.

11
задан 23.05.2017, 15:39
3 ответа

Есть решение основываясь в localStorage (что преобразовывает целые числа, хранившиеся в "strings"). Я не нашел способ дурачить обнаружение с node, потому что не возможно ловить добавку ключа, которая не знает, который будет.

Функция isDOM возврати true в браузере (который он выносил бы localStorage или же все современные) и возврати false в node.js

function isDOM(){
    try{
        var key;
        while(localStorage[key='detect-dom-'+Math.random()]) ;
        localStorage[key]=1;
        return localStorage[key]!==1;
    }catch(err){
        return false;
    }
}

console.log('isDOM', isDOM());

if(!isDOM()){
    global.localStorage=[];
    Object.observe(global.localStorage, function(changes){
        changes.forEach(function(change){
            if(typeof change.object[change.name] != "string" && change.name=='add' || change.name=='update'){
                change.object[change.name] = ""+change.object[change.name];
            }
            console.log(change, JSON.stringify(change.object[change.name]));
        });
    });
}

console.log('cheat isDOM', isDOM());

Попытка ловчить - с Object.observe но в асинхронное существо оно не функционирует. Может быть, было возможно ловчить в будущем с Proxy (в Mozilla), но в node 4 не идет


мой предыдущий ответ основываясь на примечательной идее:

Есть версия, которая делает то же самое. Но она не является совершенной (он лучше, что функция с new Function что также не является совершенной, потому что он не обнаруживает global.window = global выполненный в node).

Давайте анализировать твою необходимость.

Все зависит от, каковой была твоя гипотеза конфликта.

Если то, что ищется, состоит в том, чтобы обнаруживать кто-то в node, что хочет заставить думать, что ты находишься в DOM, чтобы подделывать обнаружение, я по крайней мере не нашел решение.

Если то, что ищется, он состоит в том, чтобы обнаруживать как можно лучше, если это DOM или Node, например смотря если windows === this но боятся, что кто-то несущественно написал в каком-то модуле global.window = global для какой-то редкой вещи, возможно пробовать удалять global.window. Идут мои доказательства:

function isDOM(){
    try{
      if(typeof window !== "undefined" && this === window){
        if(window.window === window){
          try{
            window.temporarySaveWindow = window.window;
            delete window.window;
            if(window.window){
              delete window.temporarySaveWindow;
              return true;
            }
            global.window = window.temporarySaveWindow;
            delete window.temporarySaveWindow;
            return false;
          }catch(err){
            delete window.temporarySaveWindow;
            return false;
          }
        }
      }else{
        return false;
      }
    }catch(err){
      return false;
    }
}

var isDOM2=new Function("try {return this===window;}catch(e){ return false;}");

console.log('isDOM', isDOM());

if(!isDOM()){
    global.window = global;
    Object.defineProperty(global, 'window', {configurable: false});
}

console.log('cheat isDOM', isDOM());
3
ответ дан 01.12.2019, 08:12

Ты мог бы обнаруживать, если он признан объектом module и window будьте неопределенным, благодаря тому, что если tipeas в консоли node:

> typeof module
'object'
> module
Module {
  id: '<repl>',
  exports: {},
  parent: undefined,
  filename: null,
  loaded: false,
  children: [],
  paths: [ ... ]
}
> window
ReferenceError: window is not defined

Сказанный это, уже состойте в том, чтобы ты принял решение создать функцию, которую он возвращал бы true или false, ты считал бы логику следующей:

/**
 * Valida que module y window existan para determinar true | false
 * @return Boolean
 */
function isNode () {
    return (
        typeof module !== 'undefined'
        && typeof window === 'undefined'
        && module.exports
    ) ? true : false;
}

В конце концов в твоем коде ты мог бы иметь называть это так:

if (isNode()) {
    // Código si sí
} else {
    // Código si no
}
0
ответ дан 01.12.2019, 08:12

Если мы осваиваемся в случае browserify, чего querГ©s один cГіdigo отлично в node и в браузере, что может делаться определяя стоимость "browser" в package.json В ·

Идея тогда состоит в том, что, вместо того, чтобы один пишет cГіdigo условно, он это перемещает, если я нахожусь в браузере и другой вещи в node используя один cГіdigo как:

function presentar_datos () {
  if (is_node()) {
    // magia en node
  } else {
    // magia del navegador
  }
}

Идея что escribГ-s эта funciГіn два раза, в двух отличных файлах и ты используешь require, и browserify он посылает тебе отличный файл в browser.

# presentar_datos.js
module.exports = function () {
  // magia en node
}

И ты делаешь одну versiГіn специально для browser:

# presentar_datos_browser.js
module.exports = function () {
  // magia en node
}

DespuГ©s в package.json escribГ-s:

{
  ...
  "browser": {
    "presentar_datos.js": "presentar_datos_browser.js"
  }
}
0
ответ дан 01.12.2019, 08:12

Теги

Похожие вопросы