メソッドを変数に代入・受け渡しすると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.write を logger.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パターンを実際に手で直すと、エラーメッセージのどこを読めばよいかが掴めます。