2012-10-30 42 views
5

Tôi nhận thấy rằng một số tập lệnh cũ mà tôi đang làm việc cho một dự án không hoạt động nữa sau khi nhóm của tôi nâng cấp lên Dojo 1.8. Cụ thể, biến toàn cầu mà chúng tạo ra không còn được tạo nữa.Dojo 1.8 - tạo biến toàn cục theo yêu cầu

Tôi đào xung quanh và phát hiện ra rằng nhóm Dojo 1.8 phản đối rất nhiều với các biến toàn cầu. Vì vậy, phản đối, trên thực tế, rằng họ làm cho nó thể chất không thể cho người sử dụng để tạo ra một biến toàn cầu trong một kịch bản yêu cầu sử dụng đoạn mã sau vào cuối của họ đòi hỏi:

req.eval = 
     function(text, hint){ 
      return eval_(text + "\r\n////@ sourceURL=" + hint); 
     }; 
var eval_ = new Function('return eval(arguments[0]);'); 

Đó là tuyệt vời và tất cả, nhưng cái cũ mã tôi đang làm việc với không thể thay đổi, vì vậy tôi đã cố gắng tìm ra cách để có được xung quanh điều này và thực hiện eval trong bối cảnh cục bộ để thay thế.

May mắn thay, dojo.eval vẫn còn ở đó từ các phiên bản cũ hơn của Dojo và điều đó thực hiện những gì tôi muốn. Vì vậy, tôi chỉ cần truy cập vào req.eval và thay đổi chức năng để thực hiện return dojo.eval(...) hoặc thậm chí chỉ eval(...) trong một số trường hợp nhất định.

Vấn đề là, tôi chưa thể tìm ra cách truy cập vào req. Đây là những gì sẽ xảy ra:

Tôi bao gồm dojo.js trong thẻ tập lệnh ở đầu tệp HTML của tôi. Nó tải trong tập tin kịch bản riêng của nó.

dojo.require có thể truy cập từ các tệp của riêng tôi. Nó được xác định với define trong tệp tập lệnh:

'dojo/_base/loader':function(){ 
define(["./kernel", "../has", "require", "module", "./json", "./lang", "./array"], function(dojo, has, require, thisModule, json, lang, array) { 

Tôi không chắc liệu điều đó có quan trọng hay không. Dù sao, trong phạm vi dojo.require, tôi có thể thấy một cái gì đó gọi là injectModule, trong khi trong tập tin của riêng tôi, tôi không thể. injectModule là một biến địa phương để bạn không thể nhìn thấy nó với this. Nó được định nghĩa trong một chức năng ẩn danh khi bắt đầu của tập tin, ví dụ:

(function(){ ... injectModule = function(){} ... })(); 

Bên trong injectModule chức năng, có dòng sau:

req.getText(url, legacyMode!=sync, xhrCallback);

đó đi vào req.eval. Vì vậy, injectModule có thể xem req.

Tôi không biết phải làm gì. Không có thủ thuật JavaScript bất chính nào của tôi đã giúp tôi thậm chí bắt đầu điều hướng khung lưới này. Một khởi đầu tốt sẽ là tìm cách xem injectModule từ tập tin kịch bản bên ngoài của tôi gọi số dojo.require. Mặc dù vậy, tôi đã không thể làm điều đó với 'bind', bởi vì nó là một biến cục bộ được định nghĩa trong một hàm ẩn danh. Điều này thậm chí sẽ có thể?

Để làm cho mọi việc dễ dàng hơn một chút, đây là một bản tóm tắt:

Tập 1:

<script src="dojo.js"></script> 
dojo.require(File 3); 
console.log(globalVar); 

Tập 2:

(function(){req.eval = unhelpful function})(); 
define(["require"], function(module){ 
    dojo.require = function(x){req.eval(x)} 
}); 

Tập 3:

globalVar = ...; 

tôi có thể sửa đổi tập tin 1 và 3, nhưng tập tin 3 wi sẽ luôn luôn cần một biến toàn cầu. Tôi không thể sửa đổi tập tin 2. Mục tiêu là thay đổi req.eval trong tệp 2 thành một chức năng tốt hơn.

Khai báo biến toàn cầu trước đó không hoạt động do thay đổi phạm vi có nghĩa là tệp 3 vẫn không thể xem được.

Phản ánh và thay thế chuỗi không hoạt động vì phạm vi sai và JS được rút gọn ở phía máy chủ.

Ghi đè các phương thức từ tệp 1 không hoạt động vì tôi không thể nhìn thấy thông qua phạm vi.

Sử dụng chức năng JavaScript bind cũng không có hiệu quả.

+0

Các bạn đã thử 'window.globalVar = 42' trong tập tin 3? – James

+0

Tôi đã không làm việc đó, cảm ơn bạn. Tôi không thực sự hiểu làm thế nào 'n = 5' và' window.n = 5' kết thúc là khác nhau. –

Trả lời

2

Phạm vi toàn cầu có thể được truy cập thông qua đối tượng window toàn cầu, vì vậy window.foo = 'bar' cũng giống như tạo biến toàn cầu foo. Thông tin chi tiết về điều này tại đây: https://stackoverflow.com/a/4862268/168382

+1

Điều này làm việc, mặc dù tôi vẫn không chắc chắn tại sao. Tôi đã nghĩ rằng 'n = 5' và' window.n = 5' cũng giống như vậy, nhưng tôi đoán cách Dojo làm nó làm cho chúng làm những việc khác nhau, nơi thứ hai vẫn hoạt động. –

+0

Câu trả lời khác về bí danh 'global' của Dojo có vẻ chính xác hơn vì nó sẽ hoạt động trong các ngữ cảnh như Node.js; tài liệu ở đây: http://dojotoolkit.org/reference-guide/1.8/dojo/_base/kernel.html#dojo-base-kernel-global – slikts

3

Vì điều này, dojo đã tạo dojo.global. Nó sẽ trỏ đến window trong đó dojo đã được tải (tốt cho bố trí khung).

Vì vậy, khai báo các biến toàn cầu của bạn như sau:

require([ "dojo/_base/kernel", ... ] , function(kernel) { 
    kernel.global.globalVariable = 1; 
    console.log('set') 
}) 

dojo.addOnLoad(function() {console.log('get', globalVariable);}); 
+2

Trong Dojo 1.8 'global' hiện nằm trong' dojo/_base/kernel', do đó, nó là 'kernel.global' thay vì' dojo.global' – slikts

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