5

現在、グローバル Javascript ベースの API を実行する Web アプリケーションがあり、次のように初期化されています。

var Api = {
    someVar: "test",
    someFunction: function() {
        return "foo";
    }
}

この API は、Web アプリケーションに存在する多くの「ウィジェット」間で共有され、Api相互にデータを渡すことができるように、すべてこの単一のインスタンスから実行する必要があります。

AJAX は現在、たとえば widgets/mywidget.html でこれらのウィジェットをロードするために使用されており、たとえば次の場所に配置されています。<div id='widget_<random number>'>...</div>

コードの特定の他の部分は、 にさらに機能を追加することを選択する可能性がありApi、現在は次のように行われています。

Api.myExtension = {
    myNewFunction: function() {
        return "bar";
    }
}

ただし、この種の使用法では、次のような問題が発生します。

問題 1:Api = {} 1 つのウィジェット (これらはサードパーティによって提供される場合があります) が内部にコードを隠すことを決定し、すべてが存在するグローバルApivar を破壊し、アプリケーション全体を破壊するのと同様のことを行う場合はどうなりますか? Apiこの変数を外部から上書きされないように保護することはできますか? 「拡張」(新しいものの追加)のみが許可され、「削除/変更」は許可されません。すなわち:

Api.foo = { test: "bar" } // allowed
Api.someVar = "changing the existing someVar"; // not allowed

Apiたとえば、次のコードは「内部」にあります。

var Api = {
    Debug: {
        Messages = new Array,
        Write: function() {
            Api.Debug.Messages.push("test"); // allowed
        }
    }
}

Api.Debug.Messages.push("test 2"); // not allowed

私が考えた可能性のある解決策:

  1. この問題を解決するために単純にフレームを使用するとします。提供される は、Api互いに分離されました。Apiただし、多くの を実行している場合、何度もロードすると追加のオーバーヘッドが発生しWidget、ウィジェットの「ホスト」(フレームが存在するページ) と通信できなくなります。たとえば、ホストに伝えたい場合があります。通知を表示するには:Api.Notify.Show("Test")ですが、これApiは他のインスタンスから完全に独立しており、「ホスト」と通信できないため、そうすることができません

  2. Api の読み取りと書き込みに「ゲッター」および「セッター」関数のようなものを使用します。これを実装する方法がわからないので、これを実装する方法に関する指示についてのヘルプは大歓迎です!

  3. 1/2の混合?

4

4 に答える 4

2

を見てみましょう

Object.freeze

詳細はこちら

以下はMozillaのページのコード例です。

var obj = {
  prop: function (){},
  foo: "bar"
};

// New properties may be added, existing properties may be changed or removed
obj.foo = "baz";
obj.lumpy = "woof";
delete obj.prop;

var o = Object.freeze(obj);

assert(Object.isFrozen(obj) === true);

// Now any changes will fail
obj.foo = "quux"; // silently does nothing
obj.quaxxor = "the friendly duck"; // silently doesn't add the property

// ...and in strict mode such attempts will throw TypeErrors
function fail(){
  "use strict";
  obj.foo = "sparky"; // throws a TypeError
  delete obj.quaxxor; // throws a TypeError
  obj.sparky = "arf"; // throws a TypeError
}

fail();

// Attempted changes through Object.defineProperty will also throw
Object.defineProperty(obj, "ohai", { value: 17 }); // throws a TypeError
Object.defineProperty(obj, "foo", { value: "eit" }); // throws a TypeError

ただし、ブラウザのサポートはまだ部分的です

編集:カーネルジェームズの答えを参照してください、それはあなたの質問により関連性があります(フリーズはオブジェクトを保護しますが、オブジェクトの再割り当ては保護しません。ただし、constは保護します)ただし、ブラウザのサポートが制限されています。

于 2012-10-13T03:20:35.013 に答える
2

それを作るconstant

const Api = "hi";

Api = 0;

alert(Api); //"hi"
于 2012-10-13T04:02:22.987 に答える
2

「サードパーティ」のウィジェットがグローバル変数を上書きするのを防ぐ良い方法はありません。一般に、最終的なアプリケーションをまとめる担当者は、使用している JavaScript がグローバル名前空間を散らかしたり競合したりしないようにする責任があります。その方向でできる最善のことは、「Api」に素敵で一意の名前を付けることです。

私があなたを大いに助けることができると思うのは、あなたが言及した「ゲッターとセッター」を行う方法である「明らかにするパターン」のようなものです。

単純で役に立たない例は、次のようになります。

var Api = (function () {
    // private variable
    var myArray = [];

    return {
        addItem: function (newItem) {
            myArray.push(newItem);
        },
        printItems: function () {
            console.log("lots if items");
        }
    };
})();

Api.addItem("Hello, world");
Api.extensionValue = 5;

私の例の myArray のように、共有されるもの、つまり「シングルトン」データを明確に描写し、それらのアイテムを非公開にする必要があると思います。

于 2012-10-13T03:14:16.740 に答える
1

グローバル変数を保護する唯一の方法 (少なくとも私が考えることができる) は、ウィジェットが直接アクセスできないようにすることです。あなたが提案したように、これはフレーム関数を使用することで実現できます。ウィジェットが使用できるすべての機能を含むオブジェクトを作成し、それを各ウィジェットに渡す必要があります。例えば:

var Api = {
   widgetApi = {
      someFunction: function(){
          // ...
      }
   },
   addWidget:function(){
      var temp = this.widgetApi.constructor(); 

      for(var key in this.widgetApi)
         temp[key] = clone(this.widgetApi[key]);
      return temp;
   }
   // Include other variables that Widgets can't use
}

このようにして、ウィジェットは関数を実行し、ホストまたはグローバル変数と通信できますApi。変数を設定するには、ウィジェットはグローバル オブジェクトではなく、プライベート オブジェクトを編集します。フレーム (ウィジェットを表す) ごとに、オブジェクトのコピーを初期化または作成する必要があります。また、ウィジェットのインスタンスがメインオブジェクトに格納さwidgetApiれるように、おそらく配列内に格納する必要があります。Api

たとえば、与えられた<iframe id="widget"></iframe>

次のようにします。

var widget = document.getElementById("widget");
widget.contentWindow.Api = Api.addWidget();
widget.contentWindow.parent = null;
widget.contentWindow.top = null;

さらに、ウィジェットがメイン フレームのデータにアクセスできないように、すべてのフレームで変数parentと変数を nullに設定する必要があります。topこのメソッドをしばらくテストしていないので、これらの変数を null に設定することを回避する方法があるかもしれません。

于 2012-10-13T02:43:52.987 に答える