3

次のコードを検討してください。

私が使用するhello機能ではthis.msg。これはうまくいきます。ただし、使用しないと、msg unfined エラーが発生しますthis。他の多くの OO 言語thisではコードを読者に明示するためだけに使用されているのに、なぜ JavaScript は混乱しているのでしょうか?

var smallMap = {
    msg: "Hellow ",
    hello: function(name) {
        console.log(this.msg + name);
    }
};
4

8 に答える 8

3

Javascript では特別なためthis、常に同じオブジェクトに適用されるとは限りません。たとえば、私はこれを行うことができます:

var smallMap = {
    msg: "Hellow ",
    hello: function(name) {
        console.log(this.msg + name);
    }
};

var smallMap2 = {
    msg: "Hellow2 ",
    hello: function(name) {
        console.log(this.msg + name);
    }
};
//here i set `this` to refer to `smallMap2` within smallMap
smallMap.hello.call( smallMap2, "the name" );
//will print "Hellow2 the name" instead of "Hellow the name"

this関数が呼び出されているオブジェクトを参照し、必ずしも関数がプロパティであるオブジェクトを参照しているわけではありません。詳細については、これを参照してください。

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this

これに関連する詳細については、callapply、およびbindも参照してください。

于 2013-07-06T02:49:43.033 に答える
3

「なぜ JavaScript は混乱するのか」

そうではありません。オブジェクト プロパティへのアクセス方法を管理する特定のルール セットがあります。これらのルールが他のすべての OO 言語と同じではないというだけです。

「他の多くの OO 言語thisでは、コードを読者に明示的にするためだけに使用されます」

Java などの一部の OO 言語でthisは、コードを読者に明示的にするためだけに使用されることがありますが、実際には完全にオプションというわけではなく、インスタンス変数 (メンバー) と同じ名前の他の変数を区別する必要があります (メソッド内のローカル変数など)。

JavaScript はオブジェクト指向ですが、Java などの他のオブジェクト指向言語のようなクラスやメンバー メソッドはありません。JavaScript では、関数はオブジェクトの一種であり、一般的には、任意の変数またはオブジェクト プロパティを任意の関数を参照するように設定できます。質問。例:

function test1() {
    alert('test1');
}
var obj1 = {
    prop1 : 'obj1',
    method1 : test1,
    method2 : function() {
       alert(this.prop1);
    }
}
var test2 = obj1.method2;

obj1.method1();                 // alerts 'test1'
test1();                        // alerts 'test1'
obj1.method2();                 // alerts 'obj1'
test2();                        // alerts undefined (probably; see note below)
test2.call({prop1 : 'test2'});  // alerts 'test2'
delete obj1.method2;            // remove the property
alert(obj1.method2);            // alerts undefined - property no longer exists
test2.call({prop1 : 'test2'});  // alerts 'test2' - the function still exists

obj1.method1リテラルの外で定義された関数、 で直接呼び出すことができる関数を参照していることに注意してくださいtest1()。同様にtest2、リテラルで定義されているが直接呼び出すことができる関数を参照するように設定されています。実際にmethod2プロパティを削除しても、test2()直接呼び出すことができます。

/を使用するようにmethod2/を定義しました。の値は、関数の呼び出し方法に応じて設定されます。「ドット」表記で呼び出すと、関数内ではドットの前のオブジェクトになります。関数を直接呼び出すと、非厳密モードでは になりますが、厳密モードでは未定義またはその他の値になる可能性があります-詳細についてはMDNを参照してください。または、上記の例のように、 orを指定して関数を呼び出し、明示的に他のオブジェクトに設定することもできます。test2this.prop1thisobj1.method2()thistest2()thiswindow.call().apply()this

于 2013-07-06T04:06:58.360 に答える
1

あなたが作成したのはオブジェクトです (または、少なくとも JS に関する限り)。オブジェクト自身のプロパティにアクセスしたい場合は、thisキーワードを使用する必要があります。

JS のオブジェクトは、変数と関数の単なるコレクションです。内部でオブジェクト独自の変数を使用する場合は、 を使用する必要がありますthis{}オブジェクトの定義で または 中括弧を使用して、このオブジェクトを作成しました。

オブジェクトの範囲外では、 を使用する必要があります<objectName>.var_or_func

于 2013-07-06T02:54:03.097 に答える
1

あなたがコーディングしたのはクラスではなく、オブジェクトです。

JavaScript の this という単語はスコープに関連しており、このコードの平和が含まれているオブジェクトには関連していません。

これを行うことで、あなたが望むようなものを得ることができます:

var smallMap = (function(){
    var msg = "Hellow ";

    return {
        hello : function(name) {
            console.log(msg + name);
        }
    }   

})();

つまり、this.msg も使用できません。試してみてください。

于 2013-07-06T02:55:10.300 に答える
1

Javascript は実際にはオブジェクト指向ではないため (オブジェクトが他のオブジェクトから直接継承できるということを意味する原型的なものです)、スコーピングの観点からは OO と同じように静かに動作しません。

あなたの例を取り上げて、それを使用して「hello」関数を別のオブジェクトに継承しましょう。

var new_obj;
new_obj.hello = smallMap.hello;

そこに、別のオブジェクトが同じ機能を持っています。残念ながら、この関数が on で呼び出されるnew_obj場合、たとえば:

new_obj.hello("test");

を定義new_obj.msgしない限り、 が得られますundefinedtest

ここで注意が必要です: 本当に欲しいものは何ですか? を使用するnew_obj.msgか、常に を使用しますsmallMap.msg。答えが後者の場合、関数内の hellosmallMap.msgの代わりに使用する必要があります。this.msgもちろんTMHO...

于 2013-07-06T03:24:54.590 に答える
0

Javascript では、プロパティが持つものを静的に決定することは不可能thisです。msgプロパティが削除されるか、メソッドhelloが新しいオブジェクトにアタッチされるか、通常の関数として呼び出される可能性があります。したがって、Javascript は、たとえオブジェクトがたまたま正しい名前のプロパティを持っていたとしても、修飾されていない識別子がオブジェクト プロパティではなく変数を参照していると想定する必要があります。ステートメントを使用して Javascript にオブジェクト プロパティを強制的に参照させるwithことは可能ですが、プロパティが何であるかがわからないため、これは一般的に恐ろしい考えと見なされます。

于 2013-07-06T02:51:59.723 に答える
0

オブジェクト リテラル ( { ... }) を使用することは、クラスを定義することと同じではありません。「hello」関数のスコープは、外部で定義した場合と同じです (例: smallMap.hello = function() { ... }.

于 2013-07-06T02:53:08.063 に答える
0

の理由は、 と書く代わりにの定義内でasと書いて参照thisできるようにするためです。静的に解決される他の変数とは異なり、動的に解決されます (これがなければアクセスできない理由です)。これは、「メソッド」を呼び出すためのドット表記を容易にするためにあり、Java 開発者にとって快適なブランケットとして存在します。(ただし、JavaScript には関数のオーバーロードがないため、 xf(y,z) は function の便利な名前空間を提供します。)arg1.func(arg2, arg3)arg1thisfuncfunc(arg1, arg2, arg3)thismsgf

于 2013-07-06T04:00:50.530 に答える