2013-05-29 56 views
6

我通常認爲全局範圍是一個始終可以從任何地方訪問的名稱空間。我想知道是否可以在的全球範圍內完全隱藏。例如,假設我們有一些代碼,我們想eval審視你們(在瀏覽器的控制檯):JavaScript - 如何從eval'd腳本中隱藏全局範圍

var code = 
    "console.log(this); " + // access the global object directly 
    "console.log(window); " + // access the global object as the window object 
    "newGlobalVar = 42; "; // implicitly create global object 
eval(code); 

通過包裝eval電話,thiswindow可以從code隱藏:

(function (window) { eval(code); }).call({}); 

但我無法停止code隱式創建全局變量。以某種方式可能嗎?我不想使用這些東西,我只是好奇。

+1

你想沙箱'eval''d /任意代碼?如果這是你的目標,有更好的方法。 –

+0

不,我只是想從用戶代碼屏蔽全局範圍。這使我想到了這個問題,這是關於理論的。 – kol

+1

然後,在現代瀏覽器中,理論上你可以[凍結](window)對象(https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze)。雖然我從來沒有嘗試過。 –

回答

7

如果你在相當現代瀏覽器中運行,則可以阻止大多通過使該陰影的windowself變量與參數的函數window訪問,並運行在嚴格模式的代碼。

var obj = {}; 

var func = new Function("self", "window", "'use strict';" + code); 

func.call(obj, obj, obj); 

console.log(obj); // see if there were any attempts to set global variables. 

任何試圖訪問windowself只會訪問我們的obj對象,並this值也將是我們obj

因爲我們處於嚴格模式,所以不允許使用隱式全局變量。另外,函數的默認值this將爲undefined,而不是window

我認爲有幾個黑客可能會解決這個問題,但這應該涵蓋大多數情況。

+1

看來你仍然可以訪問全局變量。 'code =「return location.href;」;','code =「return console;」;'和'code =「return top;」;'所有返回的結果。 – jongo45

+0

@ jongo45:是的,你可以訪問全局變量,因爲它們是全局變量。但是你不能對全球範圍進行任何操縱。我非常確定OP正試圖阻止新的全局變量的創建,而不是阻止所有變量的訪問。 – 2013-05-30 01:14:27

+0

@squint:不正確,top.myfunc =「123」;允許您在代碼運行後執行console.log(myfunc)。它應該在調用代碼之前迭代所有全局變量並使其成爲參數。 – Rahly

1

我接受@ squint的答案,因爲我認爲使用嚴格模式是解決方案。

但這個問題也可以在沒有嚴格模式的情況下解決。在這種情況下,一個可以緩存全局變量,eval代碼,右eval返回後,刪除不具有在高速緩存中的條目的全局變量(implcitly全局變量可以被刪除):

(function() { 
    var cache = []; 
    for (var prop in this) { 
    if (this.hasOwnProperty(prop)) { 
     cache.push(prop); 
    } 
    } 
    (function (window) { try { eval(code); } catch (e) { } }).call({}); 
    for (var prop in this) { 
    if (this.hasOwnProperty(prop) && cache[prop] === undefined) { 
     var success = delete this[prop]; 
    } 
    } 
})(); 

當eval'd代碼覆蓋以前創建的,隱含全局變量這不處理的情況下,但我不認爲這是不可能解決這個太:

(function() { 
    var cache = {}; 
    for (var prop in this) { 
    if (this.hasOwnProperty(prop)) { 
     cache[prop] = this[prop]; 
    } 
    } 
    (function (window) { try { eval(code); } catch (e) { } }).call({}); 
    for (var prop in this) { 
    if (this.hasOwnProperty(prop)) { 
     var success = delete this[prop]; 
     if (success && cache[prop] !== undefined) { 
     this[prop] = cache[prop]; 
     } 
    } 
    } 
})(); 
4

注:這是仍在工作進步,部分受到斜視代碼片段的啓發。

function quarantinedFunction(fnText){ 
    var exceptionKeys=[ 
     "eval","Object", //need exceptions for this else error. (ie, 'Exception: redefining eval is deprecated') 
     "Number","String","Boolean","RegExp","JSON","Date", 
    ]; 
    var forbiddenKeys=[ 
     "fn","fnText","forbiddenKeys","exceptionKeys","empty","oForbiddenKeys", 
    ]; 
    var oForbiddenKeys=Object.create(null); 
    var empty=Object.create(null); 
    Object.freeze(empty); 
    forbiddenKeys.forEach(function(key){ 
     oForbiddenKeys[key]=null; 
    }); 
    [this,self].forEach(function(obj){ 
     Object.getOwnPropertyNames(obj).forEach(function(key){ 
      if(!key.match(/^[\$\w]+$/))return; 
      oForbiddenKeys[key]=null; 
     }); 
    }); 
    exceptionKeys.forEach(function(key){ 
     delete oForbiddenKeys[key]; 
    }); 

    if(0){//debugging. 
     return function(){ 
      return Object.keys(oForbiddenKeys); 
      return Object.keys(empty); 
     }; 
    } 

    fnText=[ 
     '"use strict";', 
     "var "+Object.keys(oForbiddenKeys).join(", ")+";", 
     "{", 
     fnText, 
     "}" 
    ].join("\n"); 

    var fn= (function(){ 
     with(empty) 
     { 
      return new Function("self","window",fnText); 
     } 
    })(); 

    return function(){ 
     return fn.call(Object.create(null));  //self,window undefined 
     return fn.call(empty,empty,empty); //self,window are objects w/o properties 
    }; 
} 

輸出結果(從Firefox暫存器):

quarantinedFunction("return location.href;")(); 
/* 
Exception: location is undefined 
*/ 
quarantinedFunction("someGlobalVar=15;")(); 
/* 
Exception: assignment to undeclared variable someGlobalVar 
*/ 
quarantinedFunction("return 9*9;")(); 
/* 
81 
*/ 
quarantinedFunction("return console;")(); 
/* 
undefined 
*/ 

而且一些結果jsfiddle

注:一些意想不到的結果顯示在小提琴中,但沒有出現在其他工具中。在location變量返回時,小提琴是從Firefox極光瀏覽網頁的網址,但並非對鉻也沒有對暫存器devtool - Firefox的__noSuchMethod__或類似的「後期綁定」機制的可能是手工,導致性訪問,只有當被添加)。