Làm cách nào để kiểm tra xem tập lệnh có đang chạy trong Node.js không?


159

Tôi có một tập lệnh mà tôi đang yêu cầu từ tập lệnh Node.js, tôi muốn giữ cho công cụ JavaScript độc lập.

Ví dụ: tôi chỉ muốn làm exports.x = y;nếu nó chạy dưới Node.js. Làm thế nào tôi có thể thực hiện kiểm tra này?


Khi đăng câu hỏi này, tôi không biết tính năng mô-đun Node.js dựa trên CommonJS .

Đối với ví dụ cụ thể tôi đã đưa ra, một câu hỏi chính xác hơn sẽ là:

Làm thế nào một kịch bản có thể cho biết liệu nó đã được yêu cầu như là một mô-đun CommonJS?


3
Tôi không biết tại sao bạn lại cố gắng làm điều này, nhưng theo nguyên tắc thông thường, bạn nên sử dụng tính năng phát hiện thay vì phát hiện động cơ. quirksmode.org/js/support.html
Quentin

4
Đây thực sự là một yêu cầu về cách thực hiện phát hiện tính năng, nhưng câu hỏi mô tả kém về chính nó.
đơn sắc

đã xuất bản một thư viện để sử dụng cho riêng tôi, giúp việc này sẽ giúp npmjs.com/package/detect-is-node
abhirathore2006


Một vấn đề với câu hỏi và hầu hết các câu trả lời là giả định rằng chỉ có hai khả năng: Browser hoặc Node.js. Có khả năng đó không phải là trình duyệt cũng không phải Node.js, chẳng hạn như trường hợp với Oracle Java Nashorn. Nếu JDK được cài đặt, lệnh jjs cho phép bạn chạy các tập lệnh. Nhưng có nhiều khác biệt giữa Nashorn và Node.js nên bạn không thể đưa ra bất kỳ giả định nào. Và ai biết những lựa chọn nào trong tương lai có thể mang lại? Phát hiện tính năng là cần thiết.

Câu trả lời:


80

Bằng cách tìm kiếm hỗ trợ CommonJS , đây là cách thư viện Underscore.js thực hiện:

Chỉnh sửa: thành câu hỏi cập nhật của bạn:

(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._ = _;
    }
})();

Ví dụ ở đây giữ lại mô-đun Mô-đun.


45
Điều này phát hiện hỗ trợ CommonJS, trình duyệt có thể hỗ trợ.
mikemaccana

7
Có một vấn đề ở đây và thợ đóng đinh "đóng đinh". Tôi đang dùng thử CommonJS trong trình duyệt và trình tải mô-đun tôi đang sử dụng định nghĩa module.exports, vì vậy giải pháp này sẽ cho tôi biết chính xác tôi đang ở trong nút.
Đánh dấu Melville

1
@MarkMelville có thể tranh cãi, đây chính xác là những gì OP đang yêu cầu nên không phải là vấn đề .
Ross

13
Từ ngữ kém về phía tôi. Tôi có nghĩa là có một vấn đề với giải pháp này. OP có thể đã chấp nhận nó, nhưng tôi thì không.
Mark Melville

7
Đây chắc chắn KHÔNG phải là câu trả lời tốt nhất được đưa ra.
dùng3751385

107

Chà, không có cách nào đáng tin cậy để phát hiện chạy trong Node.js vì mọi trang web đều có thể dễ dàng khai báo các biến giống nhau, vì không có window mặc định đối tượng trong Node.js, bạn có thể đi theo cách khác và kiểm tra xem bạn có đang chạy bên trong không Trình duyệt.

Đây là những gì tôi sử dụng cho các lib nên hoạt động cả trong Trình duyệt và trong Node.js:

if (typeof window === 'undefined') {
    exports.foo = {};

} else {
    window.foo = {};
}

Nó vẫn có thể phát nổ trong trường hợp windowđược xác định trong Node.js nhưng không lý do chính đáng để ai đó làm điều này, vì bạn rõ ràng cần phải bỏ qua varhoặc đặt thuộc tính trên globalđối tượng.

BIÊN TẬP

Để phát hiện xem tập lệnh của bạn có được yêu cầu như một mô-đun CommonJS hay không, điều đó một lần nữa không dễ dàng. Chỉ có điều chungJS chỉ định là A: Các mô-đun sẽ được đưa vào thông qua một lệnh gọi đến hàm requirevà B: Các mô-đun xuất mọi thứ thông qua các thuộc tính trên exportsđối tượng. Bây giờ làm thế nào được thực hiện được để lại cho hệ thống cơ bản. Node.js kết thúc nội dung của mô-đun trong một hàm ẩn danh:

function (exports, require, module, __filename, __dirname) { 

Xem: https://github.com/ry/node/blob/master/src/node.js#L325

Nhưng đừng cố phát hiện điều đó thông qua một số arguments.callee.toString()thứ điên rồ , thay vào đó chỉ sử dụng mã ví dụ của tôi ở trên để kiểm tra Trình duyệt. Node.js là một môi trường sạch hơn nên không chắc windowsẽ được khai báo ở đó.


2
Giới thiệu về "Node.js là một môi trường sạch hơn nên không chắc cửa sổ sẽ được khai báo ở đó.": Vâng, tôi vừa đến đây để tìm cách xem liệu tập lệnh của tôi có chạy trong trình duyệt được mô phỏng bởi node.js + JSDOM không hoặc trong một trình duyệt đơn giản ... Lý do là tôi có một vòng lặp vô hạn sử dụng setTimeout để kiểm tra vị trí URL, điều này rất tốt trong trình duyệt, nhưng giữ cho tập lệnh node.js chạy mãi mãi ... Vì vậy, có thể có một cửa sổ trong một tập lệnh node.js sau tất cả :)
Eric Bréchemier

1
@Eric Tôi rất nghi ngờ nó sẽ ở đó trong phạm vi toàn cầu, vì vậy trừ khi bạn nhập một cái gì đó như windowtrong dòng đầu tiên của mô-đun, bạn không nên có bất kỳ vấn đề nào. Bạn cũng có thể chạy một hàm vô danh và kiểm tra [[Class]]của thisbên trong nó (chỉ hoạt động trong chế độ không nghiêm ngặt) Xem "Class" dưới: bonsaiden.github.com/JavaScript-Garden/#typeof
Ivo Wetzel

1
Vấn đề của tôi khác một chút so với OP: Tôi không yêu cầu tập lệnh, nó được JSDOM tải với cửa sổ mô phỏng dưới dạng bối cảnh toàn cầu ... Nó vẫn được chạy bởi node.js + V8, chỉ trong một bối cảnh khác với các mô-đun thông thường.
Eric Bréchemier

1
Có lẽ ... tôi đã đi theo một hướng khác: 1) phát hiện hỗ trợ cho onhashchange ("onhashchange" trong cửa sổ) để tránh tạo vòng lặp vô hạn 2) mô phỏng hỗ trợ bằng cách đặt thuộc tính onhashchange trên cửa sổ mô phỏng trong tập lệnh node.js chính.
Eric Bréchemier

1
typeof self === 'object'có thể an toàn hơn vì typeof window === 'undefined'thất bại trong phạm vi nhân viên web.
Lewis

45

Hiện tại tôi đã vấp phải một phát hiện sai về Node mà không biết về môi trường Node trong Electron do phát hiện tính năng sai lệch. Các giải pháp sau đây xác định rõ ràng môi trường quá trình.


Chỉ xác định Node.js

(typeof process !== 'undefined') && (process.release.name === 'node')

Điều này sẽ khám phá nếu bạn đang chạy trong một quy trình Nút, vì process.release có chứa "siêu dữ liệu liên quan đến bản phát hành [Node-]" hiện tại.

Sau khi io.js sinh ra , giá trị của process.release.namecũng có thể trở thành io.js(xem tài liệu quy trình ). Để phát hiện đúng môi trường có sẵn Node, tôi đoán bạn nên kiểm tra như sau:

Xác định nút (> = 3.0.0) hoặc io.js

(typeof process !== 'undefined') &&
(process.release.name.search(/node|io.js/) !== -1)

Tuyên bố này đã được thử nghiệm với Node 5.5.0, Electron 0.36.9 (với Node 5.1.1) và Chrome 48.0.2564.116.

Xác định nút (> = 0.10.0) hoặc io.js

(typeof process !== 'undefined') &&
(typeof process.versions.node !== 'undefined')

Nhận xét của @ daluege đã truyền cảm hứng cho tôi nghĩ về một bằng chứng tổng quát hơn. Điều này sẽ hoạt động từ Node.js> = 0.10 . Tôi đã không tìm thấy một định danh duy nhất cho các phiên bản trước.


Ps: Tôi đang đăng câu trả lời đó ở đây vì câu hỏi dẫn tôi đến đây, mặc dù OP đang tìm kiếm câu trả lời cho một câu hỏi khác.


2
Đây dường như là cách tiếp cận đáng tin cậy nhất, cảm ơn bạn. Mặc dù chỉ hoạt động cho phiên bản> = 3.0.0.
filip

@daluege - cảm ơn vì cảm hứng. Tôi không may không tìm thấy bằng chứng thấp hơn 0,10.
Florian Breisch

3
Tôi đã tìm thấy bằng cách sử dụng webpack phản ứng processprocess.versiontồn tại trong gói, vì vậy tôi đã thêm một kiểm tra bổ sung cho process.versionvị trí process.release.nodekhông xác định ở phía máy khách nhưng có phiên bản nút làm giá trị ở phía máy chủ
Aaron

@Aaron: cảm ơn vì gợi ý đó. Tôi không thể tìm thấy bất kỳ định nghĩa nào về process.versionbiến số (trong phản ứng, webpack hoặc Reac-webpack). Tôi sẽ đánh giá cao bất kỳ gợi ý nào trong đó biến phiên bản được xác định để thêm nó vào câu trả lời. Tùy thuộc vào phát hành.node ràng buộc cho nút> = 3.xx
Florian Breisch

2
Một lớp lót và an toàn hơn:function isNodejs() { return typeof "process" !== "undefined" && process && process.versions && process.versions.node; }
sáng chói

25

Vấn đề với việc cố gắng tìm ra môi trường mà mã của bạn đang chạy là bất kỳ đối tượng nào cũng có thể được sửa đổi và tuyên bố khiến nó gần như không thể tìm ra đối tượng nào có nguồn gốc từ môi trường và đã được chương trình sửa đổi.

Tuy nhiên, có một vài thủ thuật chúng ta có thể sử dụng để tìm ra chắc chắn bạn đang ở trong môi trường nào.

Hãy bắt đầu với giải pháp được chấp nhận chung được sử dụng trong thư viện gạch dưới:

typeof module !== 'undefined' && module.exports

Kỹ thuật này thực sự hoàn toàn tốt cho phía máy chủ, vì khi requirehàm được gọi, nó đặt lại thisđối tượng thành một đối tượng trống và xác định lại modulecho bạn một lần nữa, nghĩa là bạn không phải lo lắng về bất kỳ sự giả mạo nào bên ngoài. Miễn là mã của bạn được tải vào require, bạn an toàn.

Tuy nhiên, điều này sụp đổ trên trình duyệt, vì bất kỳ ai cũng có thể dễ dàng xác định moduleđể làm cho nó có vẻ như đó là đối tượng bạn đang tìm kiếm. Một mặt đây có thể là hành vi bạn muốn, nhưng nó cũng chỉ ra những biến mà người dùng thư viện có thể sử dụng trong phạm vi toàn cầu. Có lẽ ai đó muốn sử dụng một biến với tên moduleexportsbên trong của nó để sử dụng khác. Không thể, nhưng chúng ta là ai để đánh giá biến người khác có thể sử dụng, chỉ vì môi trường khác sử dụng tên biến đó?

Tuy nhiên, mẹo nhỏ là nếu chúng tôi giả định rằng tập lệnh của bạn đang được tải trong phạm vi toàn cầu (sẽ là nếu nó được tải thông qua thẻ tập lệnh) thì một biến không thể được bảo lưu trong bao đóng bên ngoài, vì trình duyệt không cho phép điều đó . Bây giờ hãy nhớ trong nút, thisđối tượng là một đối tượng trống, tuy nhiên, modulebiến vẫn có sẵn. Đó là bởi vì nó được tuyên bố trong một đóng cửa bên ngoài. Vì vậy, sau đó chúng tôi có thể sửa lỗi kiểm tra gạch dưới bằng cách thêm một kiểm tra bổ sung:

this.module !== module

Với điều này, nếu ai đó tuyên bố moduletrong phạm vi toàn cầu trong trình duyệt, nó sẽ được đặt trong thisđối tượng, điều này sẽ khiến thử nghiệm thất bại, bởi vì this.module, sẽ là cùng một đối tượng như mô-đun. Trên nút, this.modulekhông tồn tại và moduletồn tại trong một bao đóng bên ngoài, do đó thử nghiệm sẽ thành công, vì chúng không tương đương.

Do đó, bài kiểm tra cuối cùng là:

typeof module !== 'undefined' && this.module !== module

Lưu ý: Mặc dù điều này hiện cho phép modulebiến được sử dụng tự do trong phạm vi toàn cầu, nhưng vẫn có thể bỏ qua điều này trên trình duyệt bằng cách tạo một bao đóng mới và khai báo moduletrong đó, sau đó tải tập lệnh trong bao đóng đó. Tại thời điểm đó, người dùng đang sao chép hoàn toàn môi trường nút và hy vọng biết họ đang làm gì và đang cố gắng thực hiện một kiểu nút yêu cầu. Nếu mã được gọi trong thẻ script, nó sẽ vẫn an toàn trước mọi đóng cửa bên ngoài mới.


2
Wow, cảm ơn vì đã giải thích rõ ràng lý do đằng sau mỗi phần của một lớp lót của bạn.
Jon Coombs

có được Cannot read property 'module' of undefinedvì điều này không được xác định trong các thử nghiệm mocha chẳng hạn
srghma

20

Các hoạt động sau đây trong trình duyệt trừ khi cố ý, phá hoại rõ ràng:

if(typeof process === 'object' && process + '' === '[object process]'){
    // is node
}
else{
    // not node
}

B Bam.


4
var process = {toString: function () {return '[process process]'; }};
Nick Desaulniers

1
Có một số lý do tại sao bạn sử dụng process+''thay vì process.toString()?
hại

3
Hầu hết. Sử dụng cái này thay thế:Object.prototype.toString.call(process)
sospedra

2
Đây là câu trả lời tốt nhất cho câu hỏi này.
loretoparisi

3
@harmic: var process = null;sẽ khiến trường hợp thứ hai thất bại. Trong cả Javascript và Java, biểu thức '' + xtạo ra giống như x.toString()ngoại trừ khi xkhó chịu, cái trước tạo ra "null"hoặc "undefined"cái sau sẽ gây ra lỗi.
joeytwiddle

17

Đây là một cách khá hay để làm điều đó:

const isBrowser = this.window === this;

Điều này hoạt động vì trong các trình duyệt, biến 'toàn cầu' này có tham chiếu tự gọi là 'cửa sổ'. Tài liệu tham khảo tự này không tồn tại trong Node.

  • Trong trình duyệt, 'đây' là một tham chiếu đến đối tượng toàn cầu, được gọi là 'cửa sổ'.
  • Trong Nút 'này' là một tham chiếu đến đối tượng module.exports.
    • 'Đây' không phải là một tham chiếu đến đối tượng toàn cầu Node, được gọi là 'toàn cầu'.
    • 'Đây' không phải là tham chiếu đến không gian khai báo biến mô-đun.

Để phá vỡ trình duyệt được đề xuất ở trên, bạn sẽ phải làm một cái gì đó như sau

this.window = this;

trước khi thực hiện kiểm tra.


Tại sao không đơn giản const isBrowser = this.window !== undefined? Và trong lý thuyết trong nút tôi có thể làm this.window = thisđể đánh lừa giải pháp.
Tyler Long

11

Một phát hiện môi trường khác :

(Ý nghĩa: hầu hết các câu trả lời ở đây đều ổn.)

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 ?..
}

Một chút hoang tưởng phải không? Bạn có thể làm này tiết hơn bằng cách kiểm tra để biết thêm globals .

Nhưng ĐỪNG!.

Tất cả những điều trên có thể được làm giả / mô phỏng bằng mọi cách.

Ví dụ để giả mạo globalđối tượng:

global = {
    toString: function () {
        return '[object global]';
    },
    GLOBAL: global,
    setImmediate: function (a, b, c, d) {}
 };
 setImmediate = function (a, b, c, d) {};
 ...

Điều này sẽ không được gắn vào đối tượng toàn cầu ban đầu của Node nhưng nó sẽ được gắn vào windowđối tượng trong trình duyệt. Vì vậy, nó sẽ ám chỉ rằng bạn đang ở trong Node env bên trong trình duyệt.

Cuộc đời thật ngắn ngủi!

Chúng ta có quan tâm nếu môi trường của chúng ta bị làm giả? Nó sẽ xảy ra khi một số nhà phát triển ngu ngốc tuyên bố một biến toàn cầu được gọi làglobal trong phạm vi toàn cầu. Hoặc một số dev ác tiêm mã trong env của chúng tôi bằng cách nào đó.

Chúng tôi có thể ngăn mã của chúng tôi thực thi khi chúng tôi bắt được điều này nhưng rất nhiều phụ thuộc khác của ứng dụng của chúng tôi có thể bị vướng vào điều này. Vì vậy, cuối cùng mã sẽ phá vỡ. Nếu mã của bạn đủ tốt, bạn không nên quan tâm đến từng lỗi lầm ngớ ngẩn có thể xảy ra với người khác.

Vậy thì sao?

Nếu nhắm mục tiêu 2 môi trường: Trình duyệt và Nút;
"use strict"; và chỉ đơn giản là kiểm tra windowhoặc global; và chỉ rõ rằng trong các tài liệu mà mã của bạn chỉ hỗ trợ các môi trường này. Đó là nó!

var isBrowser = typeof window !== 'undefined'
    && ({}).toString.call(window) === '[object Window]';

var isNode = typeof global !== "undefined" 
    && ({}).toString.call(global) === '[object global]';

Nếu có thể cho trường hợp sử dụng của bạn; thay vì phát hiện môi trường; thực hiện phát hiện tính năng đồng bộ trong một khối thử / bắt. (những thứ này sẽ mất vài mili giây để thực thi).

ví dụ

function isPromiseSupported() {
    var supported = false;
    try {
        var p = new Promise(function (res, rej) {});
        supported = true;
    } catch (e) {}
    return supported;
}

9

Hầu hết các giải pháp đề xuất thực sự có thể được làm giả. Một cách mạnh mẽ là kiểm tra Classtài sản nội bộ của đối tượng toàn cầu bằng cách sử dụng Object.prototype.toString. Lớp bên trong không thể được làm giả bằng JavaScript:

var isNode = 
    typeof global !== "undefined" && 
    {}.toString.call(global) == '[object global]';

2
Điều này sẽ trở lại đúng theo trình duyệt.
alt

1
Bạn đã kiểm tra điều đó? Tôi không thể thấy trình duyệt có thể thay đổi lớp bên trong của một đối tượng. Điều này sẽ yêu cầu thay đổi mã trong JavaScript VM hoặc ghi đè Object.prototype.toStringthực sự xấu.
Fabian Jakobs

Tôi đã thử nó. Đây là những gì browserify làm: var global=typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {};
Vanuan

Bạn thấy, trong Chrome, ({}.toString.call(window))là bằng nhau "[object global]".
Vanuan

2
Thật lạ, vì window.toString()sản xuất"[object Window]"
Vanuan

5

Gì về việc sử dụng các đối tượng xử lý và kiểm tra execPath cho node?

process.execPath

Đây là tên đường dẫn tuyệt đối của tệp thực thi đã bắt đầu quá trình.

Thí dụ:

/ usr / local / bin / nút


2
Thế còn window.process = {execPath: "/usr/local/bin/node"};?
Toàn cảnh


4

Đây là biến thể của tôi về những gì ở trên:

(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;});

Để sử dụng nó, bạn sửa đổi "Nhà" trên dòng cuối cùng thứ hai thành bất cứ thứ gì bạn muốn tên của mô-đun nằm trong trình duyệt và xuất bản bất cứ thứ gì bạn muốn giá trị của mô-đun (thường là hàm tạo hoặc đối tượng theo nghĩa đen ).

Trong các trình duyệt, đối tượng toàn cầu là cửa sổ và nó có một tham chiếu đến chính nó (có window.window là == window). Dường như với tôi rằng điều này khó có thể xảy ra trừ khi bạn ở trong trình duyệt hoặc trong môi trường muốn bạn tin rằng bạn đang ở trong trình duyệt. Trong tất cả các trường hợp khác, nếu có một biến 'mô-đun' toàn cầu được khai báo, thì nó sử dụng nếu không nó sử dụng đối tượng toàn cục.


4

Tôi đang sử dụng processđể kiểm tra node.js như vậy

if (typeof(process) !== 'undefined' && process.version === 'v0.9.9') {
  console.log('You are running Node.js');
} else {
  // check for browser
}

hoặc là

if (typeof(process) !== 'undefined' && process.title === 'node') {
  console.log('You are running Node.js');
} else {
  // check for browser
}

Tài liệu ở đây


2
process.titlecó thể thay đổi
Ben Barkay

Sau đó kiểm tra tiêu đề bạn đã thay đổi thành. Hoặc sử dụng process.version
Chris

Nếu bạn đang viết cho một thư viện (như bạn nên làm), bạn sẽ không thể mong đợi tiêu đề nên là gì
Ben Barkay

3

Khi viết bài này, câu trả lời này là một tùy chọn "sắp ra mắt", vì nó tận dụng các tính năng rất mới của JavaScript.

const runtime = globalThis.process?.release?.name || 'not node'
console.log(runtime)

Các runtimegiá trị sẽ là một trong hai nodehoặcnot node .

Như đã đề cập, điều này phụ thuộc vào một vài tính năng JavaScript mới. globalThislà một tính năng hoàn thiện trong thông số ECMAScript 2020. Tùy chọn kết nối / nullish kết hợp ( ?một phần củaglobalThis.process?.release?.name ) được hỗ trợ trong công cụ V8, đi kèm với Chrome 80. Kể từ ngày 4/8/2020, mã này sẽ hoạt động trong trình duyệt nhưng sẽ không hoạt động trong Node 13 do nhánh Node 13 sử dụng V8 7.9.xxx. Tôi tin rằng Node 14 (do phát hành vào ngày 21/4/2020) được cho là sử dụng V8 8.x +.

Cách tiếp cận này đi kèm với một liều lượng hạn chế hiện tại. Tuy nhiên; tốc độ mà các trình duyệt / Node được phát hành, cuối cùng nó sẽ là một lớp lót đáng tin cậy.


1
Đây phải là câu trả lời được chấp nhận! và mọi người nên sử dụng nút 14 btw
Sceat

2

Node.js có processđối tượng, miễn là bạn không có bất kỳ tập lệnh nào khác tạo processBạn có thể sử dụng nó để xác định xem mã có chạy trên Node không.

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");
}

2

Đây là một cách khá an toàn và đơn giản để đảm bảo khả năng tương thích giữa javascript phía máy chủ và phía máy khách, cũng sẽ hoạt động với browserify, RequireJS hoặc CommonJS bao gồm phía máy khách:

(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;
}())

1

Chỉnh sửa : Liên quan đến câu hỏi cập nhật của bạn: "Làm thế nào một tập lệnh có thể cho biết liệu nó có được yêu cầu như một mô-đun commonjs không?" Tôi không nghĩ rằng nó có thể. Bạn có thể kiểm tra xem có phải exportslà một đối tượng ( if (typeof exports === "object")) không, vì thông số kỹ thuật yêu cầu nó được cung cấp cho các mô-đun, nhưng tất cả những gì cho bạn biết rằng ... exportslà một đối tượng. :-)


Câu trả lời gốc:

Tôi chắc chắn có một số biểu tượng dành riêng cho NodeJS ( EventEmittercó lẽ không, bạn phải sử dụng requiređể có được mô-đun sự kiện; xem bên dưới ) mà bạn có thể kiểm tra, nhưng như David nói, lý tưởng hơn là bạn nên phát hiện ra tính năng này (đúng hơn là hơn môi trường) nếu nó có ý nghĩa để làm như vậy.

Cập nhật : Có lẽ một cái gì đó như:

if (typeof require === "function"
    && typeof Buffer === "function"
    && typeof Buffer.byteLength === "function"
    && typeof Buffer.prototype !== "undefined"
    && typeof Buffer.prototype.write === "function") {

Nhưng điều đó chỉ cho bạn biết rằng bạn đang ở trong một môi trường requirevà một cái gì đó rất, rất giống như của NodeJS Buffer. :-)


Tôi vẫn có thể phá vỡ điều đó bằng cách thiết lập tất cả nội dung trong Trang web ... điều đó quá mức cần thiết;) Kiểm tra để vào Trình duyệt dễ dàng hơn vì môi trường Node sạch hơn.
Ivo Wetzel

1
@Ivo: Vâng, xem câu cuối cùng của tôi. Tôi có thể dễ dàng phá vỡ kiểm tra của bạn bằng cách xác định một windowbiến trong ứng dụng NodeJS. :-)
TJ Crowder

1
@ Ivo: Tôi sẽ không có mặt tại tất cả ngạc nhiên nếu ai đó định nghĩa windowtrong một module NodeJS, vì vậy họ có thể bao gồm mã mà dựa vào windowlà đối tượng toàn cầu và không muốn thay đổi mã. Tôi sẽ không làm điều đó, bạn sẽ không, nhưng tôi cá là ai đó có. :-) Hoặc họ đã từng sử dụng windowý nghĩa hoàn toàn khác.
TJ Crowder

1
@Ivo : yuiblog.com/blog/2010/04/09/ ' là một lý do tại sao đối tượng cửa sổ có thể được xác định trong node.js
slebetman

1
@TJCrowdertypeof process !== "undefined" && process.title === "node"
Raynos

0
const isNode =
  typeof process !== 'undefined' &&
  process.versions != null &&
  process.versions.node != null;


-1

Lấy nguồn của node.js và thay đổi nó để xác định một biến như runningOnNodeJS. Kiểm tra biến đó trong mã của bạn.

Nếu bạn không thể có phiên bản riêng của node.js, hãy mở một yêu cầu tính năng trong dự án. Yêu cầu họ xác định một biến cung cấp cho bạn phiên bản của node.js mà bạn đang chạy. Sau đó kiểm tra biến đó.


1
Điều đó một lần nữa không giải quyết được vấn đề (về cơ bản không thể giải quyết được) của anh ấy, tôi lại có thể tạo một biến như vậy trong Trình duyệt. Cách tốt hơn là ngăn các tập lệnh tạo windowtoàn cục, đoán tôi sẽ gửi yêu cầu tính năng trên tập lệnh đó.
Ivo Wetzel

@Ivo: Đó là một ý tưởng tồi sẽ phá vỡ mã sử dụng jsdom ( github.com/tmpvar/jsdom ) để thực hiện thao tác dom phía máy chủ bằng các thư viện quen thuộc như YUI và jQuery. Và có mã hiện đang được sản xuất.
slebetman

@slebetman Không, nó sẽ không phá vỡ jsdom. Tôi đang nói về toàn cầu , giống như không có câu lệnh var toàn cầu , mã ví dụ ở đó sử dụng varcâu lệnh, những người vừa rò rỉ nó vào không gian tên toàn cầu, vậy thì họ không có khái niệm về các mô-đun độc lập sau đó
Ivo Wetzel

@Ivo đó là loại bạo lực, nó giống như nói rằng chúng ta nên có khả năng ăn bánh ngọt vì mọi người ăn quá nhiều chất béo. Bạn phải làm lộn xộn không gian tên toàn cầu để đạt được một thư viện sẽ hoạt động liên mô-đun. Hoặc bạn có thể gói tất cả trong một mô-đun duy nhất, nhưng sau đó thì sao?
Ben Barkay

-1

Bài viết rất cũ, nhưng tôi chỉ giải quyết nó bằng cách gói các câu lệnh yêu cầu trong một lần thử - bắt

try {
     var fs = require('fs')
} catch(e) {
     alert('you are not in node !!!')
}

2
Điều đó không đúng, bạn có thể sử dụng browserify để sử dụng các cuộc gọi yêu cầu "nodeish"
fat
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.