4

このコードについて:

var name = "Jaguar";
var car = {
  name:"Ferrari",
  getName:function(){
    return this.name;
  }
};

alert((car.getName = car.getName)());

出力は次のとおりJaguarです。

変数に含まれるオブジェクトではなく、オブジェクトがthis対応するのはなぜですか?Windowcar

thisオブジェクトの関数をそれ自体に再割り当てすると、関数が呼び出されたときにオブジェクトへの割り当てが失われるようです...

私は推測しようとしています:オブジェクトの関数の非再割り当てを監視する一種のメカニズム(変数またはその他を使用)が存在し、その状況が発生した場合、このメカニズムはthisキーワードの割り当てを防止します通常(オブジェクトと等しい)?

4

4 に答える 4

7

その理由はかなり微妙です。JavaScriptでは、関数がどのように呼び出されるかthisによって完全に決定されます。の呼び出し中にを設定するには、次のように、オブジェクトから取得した直後に呼び出す必要があります。thiscargetNamegetNamecar

car.getName() // or
car["getName"]()

Function#call(または、または を介し​​てFunction#apply、 の値をthis明示的に指定できます。)

あなたの例であなたがやっていることは、事実上これです:

// Set f to the result of the assignment expression,
// which is a reference to the getName function
var f = (car.getName = car.getName);

// Call it (separately)
f();

...違います。この方法で呼び出された関数はthis、グローバル オブジェクト (windowブラウザーでは ) に設定されます。(strict モードを除く; strict モードthisではundefined.)

詳細(私の貧血ブログから):

オブジェクトの関数が再割り当てされていないことを監視し、そのような状況が発生した場合、このメカニズムが通常どおり this キーワードの割り当てを防止する (変数またはその他を使用する) 一種のメカニズムが存在しますか?オブジェクト)?

その質問に従うかどうかは完全にはわかりませんが、常にプリセット値を持つ関数が必要な場合はthis、はい、それを行う方法がいくつかあります。

1 つは、新しい ES5 関数を使用することですbind

var name = "Jaguar";
var car = {
  name: "Ferrari"
};
car.getName = function(){
  return this.name;
}.bind(car);
alert((car.getName = car.getName)()); // "Ferrari"

bindthis指定した引数に常に設定されている関数を返します。

もう 1 つの方法は、クロージャーを使用することです。実際、bindES3 では のような関数を非常に簡単に作成できます。

function pseudoBind(func, thisArg) {
    return function() {
        return func.apply(thisArg, arguments);
    };
}

それはすべてを行うわけbindではありませんが、this一部を行います。次に、次のようになります。

var name = "Jaguar";
var car = {
  name: "Ferrari"
};
car.getName = pseudoBind(function(){
  return this.name;
}, car);
alert((car.getName = car.getName)()); // "Ferrari"

閉鎖の詳細 (ブログから):

将来の仕様では、事前設定された値を持つ関数を作成する宣言的な方法を取得する予定です (それらの構文にはキーワードではなく使用が含まれるため、thisいわゆる「アロー関数」)。=>function

于 2012-10-30T16:38:38.720 に答える
5

ああ、this解決...ちょっと見てみましょう。

var toy = {
    log : function () { console.log(this); }
};
toy.log() //logs the toy object

これまでのところ、解像度は静的であるように見えます。thisメソッドが定義された場所はどこでも、それがそのthis値です。

しかし!これを行うとどうなりますか:

var sneakyBastard = toy.log;
sneakyBastard(); //logs Window

this呼び出されたオブジェクトにバインドされます。の場合は、オブジェクトのコンテキストでtoy.log呼び出しました。ただし、にはコンテキストが設定されていないため、 を呼び出したかのようになります。logtoysneakyBastardwindow.sneakyBastard

では、あなたの表現でガチョウを見てみましょう (ガチョウ? ガンダー? いいえ...):

(car.getName = car.getName)()

...そして、割り当ては何を返しますか? 割り当てられた値、この場合は関数、car.getName. この表現を 2 つに分けることができます。

var returnedValue = (car.getName = car.getName);
returnedValue();

...そして、ここからそれは明らかです。

于 2012-10-30T16:43:41.267 に答える
2

getNameオブジェクトのコンテキストから呼び出す代わりに、グループ化演算子の戻り結果のコンテキストから呼び出しています(この場合、コンテキストはありません)

JavaScript では、明確なコンテキストが定義されていない場合、デフォルトが使用されます。デフォルトは...

  • 厳密モードの場合のグローバル オブジェクト

  • undefined厳格モードない場合

于 2012-10-30T16:37:35.743 に答える
1

関数呼び出し括弧 ( ()) を入れたので、式の結果 (car.getName = car.getName)( に割り当てられた値 (関数) ) がcar.getName呼び出されます。

于 2012-10-30T16:35:45.800 に答える