4

JavaScriptで完全に自動化された単体テストを作成しようとしていますが、さまざまなJS関数でいくつかのプライベート変数を読み取る方法を探しています。特権メンバーを関数/オブジェクトに注入する方法を思い出した(そして「JSにはプライベートのようなものはない」という圧倒的な発生を見つけた)が、その方法を示すリソースが見つからない。

私はのプロパティを読み通そうとしていますが.prototype、方法があれば、ここにいる誰かが、私が自分で見つけるよりも速く私をどこに向けるべきかを知っているでしょう。

ありがとう

アップデート

  1. 特権とは、オブジェクトの外部から使用可能であり、「プライベート」変数(外部から読み取ることができない変数)を読み取るためのアクセス権を持つ関数を意味します。Crockfordの説明については、http://javascript.crockford.com/private.htmlを参照してください。

  2. 注入しようとしている関数のサンプルはですo2。ここで、の値を検証する必要がありますx(これは単純化された例であり、実際のコードはいくつかの変換を行い、個別にテストする予定の他の関数に送信します)。

    var o2 = function() {
        var x = 'me';
    };
    

更新2:応答に時間を割いてくれたすべての人に感謝します。他のSAの質問で「JSにはプライベートはない」と言われているのに、ここでの圧倒的な反応は「プライベートはプライベート」であることがわかります。それは、私がまだ知らなかった潜在的な抜け穴へのある種の洞察であると私が望んでいたというよりも、修辞的な解説のようなものだと思います。

4

4 に答える 4

3

あなたの質問に対する正しい答え

私たちはできる限りあなたを助けようとしますが、あなたの質問に対する正しい答えは簡単です:

...できません

クロージャーの外部から直接アクセスできるとしたら、クロージャー変数は何の役に立つでしょうか?

プライベート変数を持つオブジェクトがある場合、それらはコンストラクター関数である関数クロージャーの外ではアクセスできません。

var c = function() {
    var priv = "private";
    this.get = function() {
        return priv;
    };
}

var o = new c();
o.injected = function() {
    return priv; // ERROR!!!!!! priv doesn't exist in function scope
};

もちろん、すべてを関数クロージャー内に囲む場合は別の問題ですが、オブジェクトのプライベートはなく、このクロージャー内のすべてのプロトタイプ間で共有される関数クロージャーの内部になります。

(function(){

    var intrn = "internal";

    // omit "var" to make it global
    c = function() {
        this.get = function() {
            return intrn;
        };
    };

    // omit "var" to make it global
    o = new c();
    o.injected = function() {
        return intrn; // WORKS
    };
})();

o.injected();

しかし、これはオブジェクトプライベートとは異なります...

于 2012-04-05T14:10:05.990 に答える
1

私はパーティーにかなり遅れていることを知っていますが、可能です. AFAIKですがeval()、ヘルパーメソッドの使用が必要です:

function foo(){
    var a = 'a';
    this.addMethod = function(prop, val){
        this[prop] = eval('(' + val.toString() + ')');
    }
}
var bar = new foo();
bar.b = 'b';
var Fn = function(){return a + this.b}
bar.addMethod('getValue', Fn);
bar.getValue(); //yields 'ab'

eval()この場合、クロージャーのコンテキスト内で関数を再定義するために使用できます。ただし、使用は危険です。特にユーザー入力eval()は絶対に行わないでください。eval()ただし、テスト スイート/スクリプトで使用する場合は問題ありません。

于 2014-06-19T15:56:48.343 に答える
0

JavaScriptオブジェクトで特権とプライベートを実現する方法についてのCrockfordの論文を読むことをお勧めします。

特権とは、オブジェクトの外部ではアクセスできないが、他のメソッドによって呼び出し可能であり、実際にはオブジェクトのメソッドであるメソッドを意味する場合、オブジェクトにメソッドを配置するため、実際にはそれを行う方法はありません。 javascript 誰でも呼びましょう。

メソッドによってのみ呼び出すことができる関数を追加したいだけの場合は、オブジェクトであるプライベート メンバー変数 (Crockford がそれを実装する方法を参照) を持つことでそれを行うことができ、そのオブジェクトにメソッドを配置できます。その後、すべての既存のメソッド (Crockford がコンストラクターでプライベート メンバー データへのアクセスを提案する方法で実装) は、それらのメソッドを呼び出すことができます。それらは技術的には別のオブジェクトのメンバーになりますが、必要に応じてオブジェクトのインスタンス データへのプライベート アクセスを与えることができます。

それはすべてかなり複雑なので、実際に解決しようとしている問題を説明すれば、おそらくより良い答えが得られるでしょう.

于 2012-04-04T23:23:21.320 に答える
0

私はあなたがそれを行うことができるとは思わない. 次のコードを検討してください。

function foo() {
    var privateVar = 10;            
    this.privilegedMethod = function() {
         return privateVar;   
    }
}
var obj = new foo();

ここでは、メソッドが定義されたときに作成されたクロージャの一部であるため、privilegedMethodにアクセスできます。privateVarもちろん、インスタンス化後にいつでも新しいメソッドをオブジェクトにアタッチできます。

obj.newMethod = function() { return "hello" };
alert(obj.newMethod()); // alerts "hello"

しかし、この新しいメソッドは にアクセスできませんprivateVar

于 2012-04-04T23:23:41.647 に答える