2010-02-03 93 views
7

以下是我們想要壓縮的大型JS庫,YUI compressor如果發現「eval」語句沒有完全壓縮代碼,因爲擔心它會破壞別的東西。 這是偉大的,所有的,但我們確切地知道什麼是越來越eval'd,所以我們並不想讓它變得保守,因爲有在MooTools的JSON.decode的eval語句如何在不寫「eval」的情況下執行「eval」

所以基本上的問題是,有沒有替代(可能有創意)的方式來編寫一個表達式,返回eval函數? 我嘗試了幾個,但沒有骰子:

window['eval'](stuff); 
window['e'+'val'](stuff); 
// stuff runs in the global scope, we need local scope 

this['eval'](stuff); 
// this.eval is not a function 

(new Function("with(this) { return " + '(' + stuff + ')' + "}"))() 
// global scope again 

任何想法? THX

+0

因爲'eval'不被認爲是一種普通的功能,你可能會勝過YUI壓縮器,但是你會遇到瀏覽器,它們不會或很快不會讓你用任何其他名稱調用'eval'。 – 2010-02-03 23:29:35

回答

3

感謝所有的想法,我最終只是在構建腳本中做文本替換,輸出JS,基本上用eval代替$ EVAL $,所有東西都被壓縮後。我希望純粹的JS方式,但有這麼多不同的eval瀏覽器實現,它可能會更好地離開eval獨自

但基於Dimitar的答案和一些擺弄,這是我發現。 好像之所以這樣[「的eval」]沒有工作是因爲,它的發生,在MooTools的JSON.decode的地方,也是一個內部的哈希:

var JSON = new Hash({ 
// snip snip 
decode: function(string, secure){ 
    if ($type(string) != 'string' || !string.length) return null; 
    if (secure && !(/^[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]*$/).test(string.replace(/\\./g, '@').replace(/"[^"\\\n\r]*"/g, ''))) return null; 

    return this.eval('(' + string + ')'); // Firefox says: TypeError: this.eval is not a function 
} 

}); 

但是,如果我存儲「頂級」本地範圍(所有的代碼,包括mootools的,匿名函數中運行),那麼它的工作原理:

var TOP = this; 
var JSON = new Hash({ 
// snip snip 
decode: function(string, secure){ 
    if ($type(string) != 'string' || !string.length) return null; 
    if (secure && !(/^[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]*$/).test(string.replace(/\\./g, '@').replace(/"[^"\\\n\r]*"/g, ''))) return null; 

    return TOP.eval('(' + string + ')'); // All good, things run within the desired scope. 
} 

}); 

然而,這並不在Safari工作,所以底線是,我試圖做不能做到交叉兼容。 eval是一種特殊的敏感功能,每個瀏覽器都以不同的方式對待它。

0
var e = "e"; 
window[e+"val"](stuff); 
+0

這不起作用,事情在全球範圍內運行。也似乎不是可移植的,webkit問題'window [「e」+「val」](stuff)''' – adamJLev 2010-02-03 20:55:31

+0

'? – elcuco 2010-02-03 20:56:54

+0

'window.eval ===窗口['eval'] ===窗口['e'+'val']'所以沒有骰子..東西得到eval'd在窗口範圍這不是我們所需要的 – adamJLev 2010-02-03 21:01:56

0

如果可能的話,你可能會想嘗試其他的壓縮庫之一,因爲YUI是不是在鎮上唯一的遊戲了。

下面是關於其他可用壓縮工具的一些文章。

微軟和谷歌似乎也是閒着比YUI做得更好。

+0

謝謝爲建議。 我已經玩過Google Closure,但它對我們來說過於激進,重命名了太多東西並打破了代碼。需要一些時間來調整代碼才能運行,並且可能會引入新的錯誤。 這將是很好的檢查MS的東西,但我們是一個Java/OSX店 – adamJLev 2010-02-03 20:59:47

+0

谷歌關閉的竅門是隻使用簡單壓縮,如果失敗只是使用空白。這是一個安全的選擇,只是刪除所有的空白,這比沒有好。 – 2010-02-03 21:31:23

+0

這也適用於YUI,它縮小了所有這一切,但它並沒有用較短的變量替換長變量名稱,因爲這些變化 – adamJLev 2010-02-03 22:31:08

1

可以重構eval調用一些外部填充函數,它不是被壓縮文件的一部分嗎?

3

不知道如果我理解你,但你可以將一個函數到一個特定的地方(這)範圍:

var x = 5; 

var f = new Function('alert(this.x)'); 

function A(x){ 
    this.x = x; 
    f.apply(this,[]); 
} 

a = new A(10); 

這提醒10爲F施加A.this

1

是我遺漏了什麼?

var noteval = this.eval; // can be defined before the file is loaded 
noteval("alert('not eval. at all');"); 

(function() { 
    console.log(this); 
    noteval("alert('chavs!');"); 
}).bind(window)(); 

(function() { 
    console.log(this); 
    noteval("alert('crappy parents');"); 
}).bind(window.parent)(); 

檢查它http://www.jsfiddle.net/nGL79/與幀作爲不同的eval範圍。

而具體到MooTools的:

window["ev"+"al"].pass("alert('what');")(); 
this["ev"+"al"].pass("alert('no!');")(); // local scope too? 

var noteval = window["ev"+"al"].create({ 
    bind: this 
}); 

希望一些幫助......希望你不要函數eval必須直接調用,而不是由路另一個名字的功能雖然

+0

感謝這些想法,至少現在我明白爲什麼this.eval不起作用了。看看我自己的答案 – adamJLev 2010-02-04 00:00:16

0

這種方式需要jQuery。

function NotEval(code, callBack) { 
    $.ajax({ 
     url: 'data:application/javascript;charset=utf-8,' + encodeURIComponent(code), 
     cache:true, 
     success: function (r) { 
      if (typeof callBack === "function") { 
       callBack() 
      } 
     }, 
     error: function (r) { 
      console.log("Eval error"); 
      console.log(r) 
     } 
    }) 
} 
相關問題