ある日にthisを使用したVue.jsのコードを作成して、起動しました。
その際、起動は正常終了するのですがブラウザを開いた際に
・Uncaught (in promise) TypeError: Cannot read properties of undefined (reading ‘name’)
が発生しましました。
本記事では、このエラーついての対象方法を記載します。
- MacBook Air (macOS Ventura 13.4.1)
- Visual Studio Code 1.81.1
- Vue CLI 5.0.8
- Vue3.2.13
- ブラウザ Google Chrome
今回、エラーとなったコードになります。
後述しますが、原因はアロー関数部分になります。
また、コードの動作としては、入力テキストに文字を入力するとブラウザのコンソールに入力した文字が出力されます。
<template>
<div id="app">
<input type="text" v-model="name"/>
</div>
</template>
<script>
export default {
data: () => {
return {
name: "",
}
},
updated: () => {
console.log(this.name)
}
}
</script>
以下ブラウザ上で、入力テキストに文字を入力するとエラーが表示されます。
エラー内容は、「Uncaught (in promise) TypeError: Cannot read properties of undefined (reading ‘name’)」となっています。
原因を調査しましたところ、Vue 2.xの「Vue インスタンス」ガイドの注意事項として、以下の記述があります。
インスタンスプロパティまたはコールバックでアロー関数 を使用しないでください。 例えば、 created: () => console.log(this.a) や vm.$watch('a', newValue => this.myMethod()) です。 アロー関数は this をもたないため、this は他の変数と同様に見つかるまで親スコープをレキシカルに探索され、そしてしばしば、Uncaught TypeError: Cannot read property of undefined または Uncaught TypeError: this.myMethod is not a function のようなエラーが発生します。
要するに「this」をアロー関数内で使用するとエラーが出るぞ!ということです。
今回のVue.jsの実行環境は、Vue 3ですが同様の内容だと考えました。
もう少し詳しく調べてみると通常関数とアロー関数で「this」の指す意味合いが変わってくるそうです。
アロー関数の「this」はレキシカルスコープ(静的スコープ)で、関数を定義した時点でスコープが決まるようです。
対処方法は簡単で、アロー関数を通常関数に置き換えると解決します。
// アロー関数 // 通常関数
updated: () => { updated: function() {
console.log(this.name) → console.log(this.name)
} }
対処方法がわかったのでエラーコードのアロー関数を通常関数に置き換えて再度実行してみます。
※dataについては、今回の事例のエラーには関係ありませんが合わせて置き換えています。
<template>
<div id="app">
<input type="text" v-model="name"/>
</div>
</template>
<script>
export default {
data: function() {
return {
name: "",
}
},
updated: function() {
console.log(this.name)
}
}
</script>
エラー時と同様にブラウザ上で、入力テキストに文字を入力して確認します。
コンソールを見るとエラーが発生せずに、処理が正常終了したことを確認できました。
最近、JavaScriptのコードは基本アロー関数で書くようになってきていると思います。
そのせいもあって、原因を突き止めるために時間がかかってしまいました。(アロー関数は関係ないだろうと思っていました)
そのため、Vue.jsでは通常関数(function)を使用して記述を統一する方が良いと感じました。
あと、「this」もなんとなく使っていたのですがある程度は理解することが大切ですね。
今回は、this.nameという形でエラーの対応を記載しましたが、this.$refs.〜やthis.$watch()などで「Uncaught TypeError: Cannot read properties of undefined (reading ‘〜’)」が出た際もアロー関数を使用していないかを一度確認してみてください。
同様の内容だった場合、通常関数に置き換えるだけで解決できます。