7

データベースからその場でロードしたいオブジェクトの「ライブラリ」があります。各オブジェクトには、オブジェクトのタイプに応じて特定の時間に呼び出される独自の特殊関数が付属しています。これが機能しないことが指摘されていますが、理想的にはこれを実行できるようにしたいと思います。

library = {
  "myObj" : {"name" : "myObj", "type" : "myType", "function" : function () { } } //, etc
}

文字列"myObj"はプログラムにかなり渡されますが、一度にアクセスする必要があるのはオブジェクトの特定の値だけであり、状況によっては、実行する必要のある特定の関数があります。問題は、さまざまな機能で存在する可能性のある数百、最終的には数千の潜在的なオブジェクトを見ていることです。

このように呼び出される関数を格納する「正しい」方法は何ですか。evalを呼び出すことは、実行中に非常に危険であり、xss攻撃などを有効にする可能性があることを私は知っています。大規模なswitchステートメントや追加機能の肥大化したロードを本当に避けたいです。また、解決策はできるだけ簡潔にしたいと思います。

これが出てきたのはこれが初めてではありません。; /

ご協力いただきありがとうございます。

4

7 に答える 7

10

文字列としてロードした後、evalを使用して関数を再作成するだけです。したがって、myObjJSONからオブジェクトを逆シリアル化し、プロパティがある場合:

myObj = {
    ....
    function: "function() { ... }"
}

あなたはそれを実際の関数に非常に簡単に変えることができます:

eval("myObj.func = " + myObj.func);

http://jsfiddle.net/kceTr/

ああ-それが編集だったのか、それとも以前に見逃したのかはわかりません-しかし、re:eval。

Evalはツールです。関数をデータベースに保存したい。コードに変換するために「評価」する必要がある場合、またはそれを行うための他の魔法の方法があった場合、実際には大きな違いはありません。誰かがDB内のデータを変更できる場合、その人は関数を変更できます。

関数を保存する必要がある場合は、evalがツールです。それは本質的に「悪い」ものではなく、誤用しやすいので悪いものです。うまく使うかどうかはあなた次第です。

クライアントで実行されているものはすべて、クライアントで実行されているだけであることを忘れないでください。悪意のある人がevalでできることは何もありません。それは、Chromeデバッガーでもっと簡単にできることではありません。誰でもクライアント上でいつでも好きなコードを実行できます。受信したものを処理する方法を決定するのはサーバー次第です。そもそもクライアントにとって安全なものは何もありません...

于 2012-07-28T03:16:34.167 に答える
2

オブジェクトのプロトタイプを変更することは、私が持っている半分の考えです。

あなたは次のようなあなたの図書館を持っています

library = {
  "myObj" : {"name" : "myObj", "type" : "myType", "function" : function () { } } //, etc
}

あなたはあなたが知っているオブジェクト(それを呼びましょうtheObj)を持っていますmyObj(おそらく文字列のために?プロパティ?)

theObj.__proto__ = library["myObj"];

そうすれば実行できます

theObj.function(...);

jsfiddleの例(大まかな!)。また、 protoには注意してください。非推奨です(1)(2

関数のシリアル化に関して、dbから関数を丸呑みしてjsを返すサーバーサイドを指すスクリプトタグを使用して関数を取得できますか?(スクリプトブロックで)ページをレンダリングするときに、それらをインラインで含めるだけですか?または、他のすべてが失敗した場合、データベースに格納されている関数がクリーンで安全であることがわかっている限り、evalは機能するはずです。

于 2012-07-28T04:15:36.920 に答える
0

より良いアプローチは、オブジェクトを「スリープ」するときにオブジェクトのプロパティをシリアル化し、適切なメソッドを定義してオブジェクトの新しいインスタンスにプロパティを再アタッチすることでオブジェクトを「ウェイクアップ」することです。

于 2012-07-28T02:58:14.397 に答える
0

あなたがそれで何をしているのかは問題ありません。ただし、私があなたである場合は、読みやすさと整頓のために、関数を外部で作成し、オブジェクトキーに割り当てるだけにします。

ここでは評価は必要ありません。代わりに、ストアド関数にアクセスしたいときはいつでもこの方法で実行してください-

library.myObj.function()

于 2012-07-28T06:10:53.423 に答える
0
  • 関数のパラメーター化に最善を尽くし、最終的にタイポロジーをできるだけ少なくします。
  • それらをサーバー上の個々のJSファイルに保存してから、必要なファイルを名前で動的にロードします。
  • JSONには、必要な関数を含むファイルの名前のみを保存します。そしてもちろん、サーバー上で簡単に使用できるように、すでにロードされているファイルをキャッシュします。

ちょうど私の2セント。

于 2016-12-31T22:44:48.847 に答える
0

require実際にシリアル化できるのは、呼び出しを含むファイル全体だけです。これを行うと、モジュールを作成し、エクスポートおよびmodule.exportsを実行し、ファイルを囲む関数を使用してファイルを評価し、module.exportsをそのファイルから取得できます。

完全に安全というわけではありませんが、そのためには、VM2value-censorship(私が取り組んできたもの)のようなものを使用して、eval()を呼び出してマシンまたはネットワーク全体を所有しないようにする必要があります。

于 2019-01-31T19:36:35.243 に答える
0

一般的には良い考えではないため、これを行う正しい方法はありません。

ただし、とにかくそれを実行したい場合は、.toJSONメソッドを使用してFunctionのプロトタイプを拡張するだけです。

Function.prototype.toJSON = function(){ return this.toString(); }

次に、JSON.stringifyを使用するだけで、関数が文字列としてシリアル化されます。

ほとんどの場合、それは一般的に良い考えではありません。これを実行したい状況はほとんどありませんが、それでも、おそらくより良い方法があります。

于 2019-08-11T12:42:29.747 に答える