2012-03-09 26 views
20

Cách được khuyến nghị để xử lý global object trong chế độ nghiêm ngặt ES5 trong môi trường máy chủ không xác định là gì?Nhận tham chiếu đến đối tượng toàn cục trong một môi trường không xác định ở chế độ nghiêm ngặt

ECMAScript không cung cấp cách tích hợp để tham chiếu đối tượng chung mà tôi biết. Nếu có, đây là câu trả lời tôi đang tìm kiếm.

Trong một môi trường đã biết được biết, đối tượng chung thường có thuộc tính tự tham chiếu. Kể từ khi đối tượng toàn cầu là VO cho phạm vi toàn cầu, tính chất của đối tượng toàn cầu là các biến toàn cầu, vì vậy chúng ta có thể sử dụng chúng có được một xử lý cho các đối tượng toàn cầu từ bất cứ đâu:

  • Trong một trình duyệt web, chúng ta có thể sử dụng window hoặc self.

  • Trong node.js, chúng tôi có thể sử dụng global.

Tuy nhiên, điều này không nhất thiết phải là trường hợp trong tất cả môi trường máy chủ. Theo như tôi biết, Windows Script Host không cung cấp bất kỳ cách nào để truy cập đối tượng toàn cầu. Cách được đề nghị để có được đối tượng toàn cầu trong WSH có vẻ là sử dụng từ khóa this trong một ngữ cảnh mà nó không giải quyết cho một đối tượng. Ví dụ:

var GLOBAL = (function(){return this}()); 

Kỹ thuật này sẽ làm việc cho bất kỳ môi trường máy chủ, nhưng không phải trong chế độ nghiêm ngặt, bởi vì một không xác định this không tham chiếu tới đối tượng toàn cầu trong strict mode:

Nếu đây được đánh giá trong vòng nghiêm ngặt mã chế độ, sau đó giá trị này không bị ép buộc đối tượng. Giá trị rỗng hoặc không xác định này không được chuyển đổi thành đối tượng chung và giá trị nguyên thủy không được chuyển đổi thành đối tượng bao bọc. Giá trị này được truyền qua một cuộc gọi hàm (bao gồm các cuộc gọi được thực hiện bằng Function.prototype.apply và Function.prototype.call) không ép buộc giá trị này truyền cho một đối tượng (10.4.3, 11.1.1, 15.3.4.3, 15.3. 4.4).

Đúng như dự đoán, kết quả mã sau vào undefined:

(function(){ 
    "use strict"; 
    var GLOBAL = (function(){return this}()); 
    console.log(GLOBAL); 
}()); 

Vì vậy, những gì là cách thích hợp để được một xử lý cho các đối tượng toàn cầu trong bất kỳ môi trường, không phân biệt chế độ nghiêm ngặt?

Bằng cách này, cách tiếp cận hiện tại của tôi là để sniff cho các biến toàn cầu tham khảo đối tượng toàn cầu như thế này:

var self, window, global = global || window || self; 

... và sau đó chỉ cần sử dụng global. Tôi nghĩ rằng đây là một giải pháp tồi vì một số lý do, hầu hết trong số đó là khá rõ ràng, và nó không giải quyết vấn đề WSH.

+1

bạn không thể 'sử dụng nghiêm ngặt'; (function (global) {}) (this) '? (Tôi không thử nghiệm điều này). – Marshall

+0

Điều đó hoạt động ở Node.js, ít nhất, @Marshall –

+0

@DavidEllis woops, đó là nền tảng lựa chọn của tôi O_o Tôi đoán tôi nên kiểm tra nó ở những người khác trước khi tôi nói bất cứ điều gì;) – Marshall

Trả lời

29

Trong ES5, bạn có thể nhận được một tham chiếu đến đối tượng toàn cầu từ bên trong chế độ nghiêm ngặt thông qua cuộc gọi eval gián tiếp:

"use strict"; 
var global = (1,eval)('this'); 

Hãy xem my article; đặc biệt tại số section on strict mode này.

+0

cảm ơn cho phản ứng, tôi đã đọc nhiều bài viết của bạn (mà là tuyệt vời bằng cách này) nhưng tôi phải đã bỏ lỡ này. Tôi đã nghĩ về việc sử dụng 'eval', nhưng không biết về mẹo lừa đảo này (chỉ sử dụng' eval' mà không đánh giá sự gián tiếp trong phạm vi chức năng, rõ ràng). –

+0

Cảm ơn các từ loại :) Nói về eval trick, tôi đã nghe một cái gì đó về Node.js không theo hành vi ES5 trong vấn đề đó và rằng có một số phép thuật khác đang diễn ra đằng sau hậu trường. Không bao giờ có cơ hội thử nghiệm nó, vì vậy bạn có thể muốn kiểm tra lại. Nó hoạt động trong tất cả các trình duyệt mà tôi từng thử, mặc dù, và nó _should_ làm việc về mặt lý thuyết, vì đó là cách nó được mô tả trong ES5. – kangax

+0

Tôi sẽ thử nghiệm nó trong nút ... nếu nó bị hỏng trong nút, tôi chỉ có thể kiểm tra một 'global' đã tồn tại để làm việc xung quanh (và đổi tên' global' trong ví dụ thành cái gì đó khác nó sẽ không đổ bóng 'global' nếu được gọi từ phạm vi hàm). Đây chính xác là những gì tôi đang tìm kiếm, cảm ơn bạn. –

1

Ở chế độ nghiêm ngặt, cách để tham chiếu đến đối tượng chung là gán một biến trong đối tượng chung tham chiếu chính nó.

Đó là this means the global object when in the global context, vì vậy giải pháp đơn giản là:

"use strict"; 
var global = global || this; 
(function() { global.hello = "world"; })(); 
console.log(hello); // Outputs 'world' as expected 

này có nghĩa là bạn phải làm ô nhiễm không gian tên toàn cầu với một tham chiếu đến chính nó, nhưng cũng giống như bạn nói, nó nên đã có được đó.

+0

Chờ, không phải tham chiếu đến 'global' thất bại trừ khi bạn sử dụng kiểm tra' typeof'? –

+2

@wilmoore: Không, bởi vì câu lệnh 'var' được hoisted. 'var global = global || điều này, 'được xử lý hiệu quả như' var global; global = global || điều này;Nếu 'global' đã tồn tại,' var global' là một no-op, nếu không nó sẽ được tạo với giá trị ban đầu là 'undefined', sau đó được ghi đè trong câu lệnh tiếp theo. –

+0

Vâng, khi tôi đăng lần đầu, tôi đã biết về 'var' hoisting, nhưng thành thật mà nói, tôi hoàn toàn không đặt nó lại với nhau trong bối cảnh cụ thể này. Cảm ơn cho người đứng đầu lên :) –

7

Trong global code, thisBinding được đặt thành đối tượng chung bất kể chế độ nghiêm ngặt. Điều đó có nghĩa là bạn có thể chuyển nó từ đó vào mô-đun của bạn IEFE:

// "use strict"; or not 
(function(global) { 
    "use strict"; 
    … 
    console.log(global); 
    … 
}(this)); 
+0

Thực ra nó giống với câu trả lời của @DavidEllis, nhưng không gây ô nhiễm phạm vi toàn cầu :-) – Bergi

Các vấn đề liên quan