Code Fix

中級

メソッドを変数に代入・受け渡しするとthisが失われる

オブジェクトのメソッドを変数に代入したり、別の関数に渡して呼び出したりすると、呼び出し時にレシーバーの情報が失われ、thisがオブジェクトを指さなくなります。

なぜエラーが出ないのか

出力: undefined
(エラーなし)
JavaScriptは何も報告しません。文法として正しいためです
出力: undefined
実際の挙動 — 期待した結果と食い違っている箇所
見つけ方
エラーが出ないので、出力を目で確かめるか、コードを目で追うしかありません。この種の誤りが最も発見が遅れます

このエラーが出る典型パターン

パターン1

 1  const counter = { count: 5, getCount: function() { return this.count; } };
 2  const getCount = counter.getCount.bind(        );
                                               ^
 3  console.log(getCount());
出力: undefined期待: 5 (エラーにはなりません)

bind()に何も渡さないと、切り離されたgetCountを呼んでもthisはcounterを指しません。bind(counter)でthisを固定する必要があります。

直し方: (空)counter にします。

この問題を解いてみる →

広告
広告スロット(未設定)

パターン2

 1  const logger = { prefix: "[LOG]", write(msg) { return this.prefix + " " + msg; } };
 2  function run(fn) { return fn("hi"); }
 3  console.log(run(logger.write             ));
                                ^
出力: undefined hi期待: [LOG] hi (エラーにはなりません)

logger.writeを関数として渡すと、run内でfn("hi")と呼ばれた時点でレシーバーの情報が失われます。bindでthisをloggerに固定してから渡す必要があります。

直し方: logger.writelogger.write.bind(logger) にします。

この問題を解いてみる →

パターン3

 1  const logger = { prefix: "[LOG]", write(msg) { return this.prefix + " " + msg; } };
 2  const { write } = logger;
 3  console.log(write("hi")             );
                            ^
出力: undefined hi期待: [LOG] hi (エラーにはなりません)

分割代入で取り出したwriteはloggerとの結びつきを失っています。call(logger, ...)で明示的にthisを指定する必要があります。

直し方: write("hi")write.call(logger, "hi") にします。

この問題を解いてみる →

よくある誤解

「メソッドはどこから呼んでも同じオブジェクトに属する」という思い込みは誤りです。JavaScriptのthisは定義位置ではなく呼び出し方によって決まるため、切り離して渡した瞬間に本来のレシーバーとの結びつきは失われます。

まとめ

メソッドを変数に代入・受け渡しするとthisが失われるは中級でつまずきやすい項目です。上の3パターンを実際に手で直すと、エラーメッセージのどこを読めばよいかが掴めます。

演習をはじめる

関連するエラー

広告
広告スロット(未設定)