質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

Q&A

2回答

1103閲覧

JavaScriptにおける関数内のthisの渡され方、ルールについて

退会済みユーザー

退会済みユーザー

総合スコア0

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

0グッド

3クリップ

投稿2018/10/11 13:29

以下のコードにおいてthisがどうやって働いているのかがいまいち分かっていません。自分の認識があっているか、またほかに注意点があるかなど教えていただきたいです。
環境はchromeブラウザです、一応。

JavaScript

1// 全ての関数が使用できるdelayメソッドを追加 2// メソッド内ではその関数を this() で呼び出し 3Function.prototype.delay = function d() { 4 alert('with delay'); 5 this() 6}; 7function f() { 8 alert('do the f!!') 9}; 10 11f.delay() 12// with delay 13// do the f!!

自分の認識
1.まず関数定義の時点では、delay, fそれぞれに実行コードが格納されるのみでスコープは作られていない。
2.f.delay()が実行された瞬間に

  • 関数fのレキシカルスコープが作成される(自信がありません)
  • f のスコープ内で'delay'メソッドを探す
  • 見つからないため f の__proto__であるFunction.prototypeに探しに行く
  • 定義されたdelayが実行される。この時点でdelayのレキシカルスコープが作成される(これは自信があります)

3.delay()の内部が実行される

  • alert('with delay')が実行される
  • this()が実行される(結果は // do the f!! つまりf自身が呼び出されている。)

thisは常に obj.func() の.の前を指す?
なんか違うような気もしますがこれであっているのでしょうか。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

f のスコープ内で'delay'メソッドを探す

レキシカルスコープは、関数内のコードで使われる変数に関する話で、f.delayの探索とは関係しません。メソッドなどプロパティの探索は、オブジェクト自身→プロトタイプ→プロトタイプのプロトタイプ…と、プロトタイプチェーンを進んでいきます。

thisは常に obj.func() の.の前を指す?

thisが指すものは、何通りも考えられます。

  • ただfunc()のように呼んだ場合…thisはグローバルオブジェクト(非strict)またはundefined(strict)
  • new Constructor()のようにnewありで呼んだ場合…thisは新規作成されるオブジェクト
  • obj.foo()のように呼んだ場合…thisobj
  • Function.prototype.callFunction.prototype.applyで呼ぶ場合…1つ目の引数がthisとして渡される

Function.prototype.bindを使うと、どんな呼び方をしてもthisが固定された関数を作ることもできます。

投稿2018/10/11 14:10

maisumakun

総合スコア145184

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2018/10/11 14:33

スコープ(enviroment?)とプロパティの探索の区別がついていなかったようです。質問とはずれますがすっきりしました。ありがとうございます。 call/apply/bindやnew演算子は、特殊な場合というかその関数や演算子自身の効果として理解できるのですが、obj.func() のように素で呼ばれた場合は objを指すという認識で大丈夫でしょうか。 であればグローバルスコープ内でfunc()を実行する際、thisがwindowを指したり、strict下でundefinedになるのは一貫性があるなという気もします。 let f = obj.func() などした際に this が浮いてしまうのは上の規則によるものですか。それともあえてそういう仕様にしているのでしょうか。 this の探索にスコープは関係しますか? 質問ばかりですみません。まだ少し混乱している感じです。
退会済みユーザー

退会済みユーザー

2018/10/11 14:42

すみません let f = obj.func ですね。これも代入の際には実行されずコードだけが写されて、 f() とした際に初めてコードが読まれると考えればグローバルスコープ内での実行になるので this = undefined になるのも一貫性がありますね。 今自分の中で一貫した認識ができた気がするのですが、これであっていますでしょうか。 ふわふわとした質問ばかりですみません。
maisumakun

2018/10/12 02:10

> obj.func() のように素で呼ばれた場合は objを指すという認識で大丈夫でしょうか。 bindしていなければobjになります。
think49

2018/10/12 03:34

obj.func がアロー関数の場合に異なります。
退会済みユーザー

退会済みユーザー

2018/10/12 12:37

お二人ともありがとうございます。 自分の中で理解は進んだ気がするのですが混乱が増した気もします。個別の状況だったりでは理由もつけて挙動を予測できるのですが、全体として一貫した説明ができない感じです。 ちょっと整理してから自己解決の形でまとめてみたいと思います。それまでは未解決状態で放置します。すみません。
guest

0

こんにちは。
maisumakunさんのご回答を手がかりとして、ご自身の理解を整理されるのがよろしいかと思います。
その一助となればと考え、定評ある書籍からthisについての説明やサンプルコードを、以下引用しました。

「JavaScript Ninjaの極意」

jQueryの開発者 ジョン・レシグ さんは、以下のように this呼び出しコンテクスト と呼ぶことを推奨しています。

this パラメータが指し示すものは、実際には(Javaのように)その関数が宣言された方法によって定義されるのではなく、その関数が呼び出された方法によって定義される。だから thisは **呼び出しコンテクスト(invocation context)**と呼ぶのが正しい。※

[訳注] 事実、David Flanagan の「JavaScript 第6版」(村上列訳、オライリー・ジャパン、2012年)では、原著の英文も訳文も、このように書かれている(同著の第8章の冒頭部分を参照)。本書でも、「関数コンテクスト」(function context)という呼び方を排して、「呼び出しコンテクスト」という訳語で統一した。

「開眼! JavaScript」 第6章 this サンプルコード

もう一冊、 this の理解のための良書を挙げておきます。

この本では第6章全体を割いて、thisについて説明しています。章の内容は以下です。

6章 this 6.1 thisとは何か、およびthisは何を参照するか 6.2 thisの値はどのように決められるのか? 6.3 入れ子関数内では、thisはグローバルオブジェクトを参照する 6.4 入れ子関数内でthisを見失う問題をスコープチェーンを使って回避する 6.5 call()やapply()を使ってthisの値をコントロールする 6.6 thisキーワードをユーザ定義のコンストラクタ関数で使う 6.7 プロトタイプメソッド内のthisは生成されるインスタンスを参照する

また、サンプルコードが jsFiddle で提供されており、以下の記事

は、(手前味噌で恐縮ですが)この第6章のサンプルコード一覧です。

以上、参考になれば幸いです。

投稿2018/10/13 23:10

編集2018/10/14 06:41
jun68ykt

総合スコア9058

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問