Adi さん、この例で行ったことには 2 つの問題があります。最初の問題は、すぐに呼び出される関数内のthis === window
.
2 番目の問題は、これらがすべて関数式であることです。そのため、それらはすべてインラインで定義されています。
function makeIt () {
this.a = function () { this.b(); };
this.b = function () { console.log("B"); };
}
これは、late-static バインディングのために機能します。これが意味することは、 の内部では、関数が呼び出される瞬間までa
ブラウザは何を参照しているのかわからないということです。次に、その正確な瞬間を参照するthis
オブジェクトを見つけます。this
それ以外の場合は、変数を割り当てるのと同じです。
function makeIt () {
this.a = this.b;
this.b = "George";
}
そこでエラーになります。なんで?を割り当てている時点ではa
、b
まだ値がないためです。
function Foo () {
this.init = (function (context) { context.change(); }(this));
this.change = function () { doStuff(); };
}
では、この発言のどこが問題なのでしょうか? さて、すぐに呼び出す関数は、すぐに呼び出す関数です。つまり、問題を解決したとしても、 の値をパラメータとして内部スコープにthis
渡すことで...this
...まだ存在しないものを実行するように求めています。
function Foo () {
this.change = function () { doStuff(); };
this.init = (function (context) { context.change(); }(this));
}
それはうまくいくはずです。...でも...
……なんでわざわざそんなことするの?のように、自動的に構築したいのに、なぜpublic
init
プロパティ (これは)を与えるのでしょうか?undefined
なぜinit
undefined
ですか?何も返さないため-関数を実行して関数init
の戻り値に設定していますが、何も返していないため、に設定init
されundefined
ます。では、なぜinit
そこにあるのでしょうか。
2 つのソリューション:
function Foo () {
this.change = function () { doStuff(); };
var init = function () { this.change(); };
// other stuff......
init();
}
また:
function Foo () {
this.change = function () { doStuff(); };
// other stuff....
(function (context) {
context.change();
/* a bunch of other stuff that would be in init
if there was no other stuff, why not just call this.change()? */
}(this));
}
正直なところ、init
が非公開で自動的に実行される場合、create
本当に公開する必要があるのでしょうか? myObj.create();
すでに作成された後に呼び出すつもりですか?
次のようなことをしてみませんか:
function Foo () {
this.public1 = "Bob";
this.public2 = 32;
this.publicMethod = function () {};
var create = function () { /* initialize here */ };
create();
}
または繰り返しますが、それ以上のことをしている場合create
:
function Foo () {
this.public1 = "Bob";
this.public2 = 32;
this.arrayOfThings = [];
this.publicMethod = function () {};
var create = function () {},
overclock = function () {},
polish = function () {};
// Initialize Everything
(function (context) {
var thing;
for (/* ... */) {
thing = create();
polish(thing);
context.arrayOfThings.push(thing);
}
overclock(context.arrayOfThings);
}(this));
}
これで、すべての関数、プロパティ、および変数を 1 つのスコープで取得し、初期化を別のスコープで取得しました。すべてのセットアップ ロジックは、最終的なオブジェクトのロジックから分離されています... ...そして入力パラメーターに基づいてオブジェクトを分岐するようなことを行うことができます (同じインターフェイスを維持しながら、取得したものに基づいて提供されたものを変更するポリモーフィック コンストラクターや、すべての設計図が含まれている自己完結型のファクトリ パターンなど)。 100% プライベートで囲まれています)、実際の割り当てが if と for の混乱のように見えることはありません。
完成したオブジェクトの外でセットアップを呼び出す必要はありません (つまり、他の誰も完成したオブジェクトでセットアップを呼び出して再作成/リセットすることはできません) 。this.init
とにかく使用する匿名関数が 1 つだけだったのです。