8

契約はここにあります。圧縮したい大きな JS ライブラリがありますが、YUI コンプレッサーは、「eval」ステートメントが見つかった場合、他の何かを壊す恐れがあるため、コードを完全には圧縮しません。それは素晴らしいことですが、私たちは何が評価されているかを正確に知っているので、MooTools の JSON.decode に 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

何か案は?どうも

4

7 に答える 7

4

すべてのアイデアのおかげで、すべてが圧縮された後、基本的に $EVAL$ を eval に置き換えて、JS を出力するビルド スクリプトでテキスト置換を行うことになりました。私は純粋に JS の方法を望んでいましたが、非常に多くの異なる eval ブラウザー実装があるため、おそらく eval をそのままにしておく方がよいでしょう。

しかし、ディミターの答えといくつかのいじりに基づいて、ここに私が見つけたものがあります. this['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 は特殊な扱いやすい関数であり、ブラウザーごとに扱いが異なります。

于 2010-02-03T23:57:08.057 に答える
3

理解できたかどうかわかりませんが、特定のローカル (this) スコープに関数を適用できます。

var x = 5;

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

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

a = new A(10);

f が A.this で適用されると、これは 10 をアラートします。

于 2010-02-03T22:59:52.963 に答える
1

圧縮されているファイルの一部ではない外部シム関数への eval 呼び出しをリファクタリングできますか?

于 2010-02-03T22:45:09.123 に答える
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/を確認してください。

そして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が取得されないことを願っていますが、別の名前の関数を介してではなく、直接呼び出す必要があります

于 2010-02-03T23:14:16.257 に答える
0
var e = "e";
window[e+"val"](stuff);
于 2010-02-03T20:52:41.807 に答える
0

可能であれば、他の圧縮ライブラリの 1 つを試してみることをお勧めします。これは、YUI が唯一のゲームではなくなったためです。

利用可能な他の圧縮ツールに関するいくつかの記事を次に示します。

いずれにせよ、Microsoft と Google は YUI よりも優れた仕事をしているようです。

于 2010-02-03T20:53:12.167 に答える