さらに別の環境検出:  
(意味:ここでの答えのほとんどは問題ありません。)
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 ?..
}
少し偏執的ですね?より多くのグローバルをチェックすることで、これをより詳細にすることができます。
しかし、しないでください。
上記のこれらすべてはとにかく偽造/シミュレーションすることができます。
たとえば、globalオブジェクトを偽造するには:
global = {
    toString: function () {
        return '[object global]';
    },
    GLOBAL: global,
    setImmediate: function (a, b, c, d) {}
 };
 setImmediate = function (a, b, c, d) {};
 ...
これはノードの元のグローバルオブジェクトにアタッチされませんがwindow、ブラウザでオブジェクトにアタッチされます。したがって、ブラウザ内のノード環境にいることを意味します。
人生は短いです!
私たちの環境が偽物であるかどうかを気にしますか?愚かな開発者globalがグローバルスコープで呼び出されるグローバル変数を宣言すると発生します。または、悪意のある開発者がなんとかして環境にコードを挿入します。
これをキャッチするとコードが実行されない場合がありますが、アプリの他の多くの依存関係がこれに巻き込まれる可能性があります。したがって、最終的にはコードが壊れます。コードが十分であれば、他の人が行った可能性のあるすべての愚かな間違いを気にしないでください。
だから何?
2つの環境をターゲットにする場合:ブラウザーとノード。
"use strict"; windowまたは単にを確認するかglobal、そして、あなたのコードがこれらの環境のみをサポートすることをドキュメントで明確に示してください。それでおしまい!
var isBrowser = typeof window !== 'undefined'
    && ({}).toString.call(window) === '[object Window]';
var isNode = typeof global !== "undefined" 
    && ({}).toString.call(global) === '[object global]';
あなたのユースケースで可能であれば; 環境検出の代わりに; try / catchブロック内で同期機能検出を行います。(これらの実行には数ミリ秒かかります)。
例えば
function isPromiseSupported() {
    var supported = false;
    try {
        var p = new Promise(function (res, rej) {});
        supported = true;
    } catch (e) {}
    return supported;
}