1
1

More than 1 year has passed since last update.

[Nodejs] thisが浮気者なのでbindで束縛する

Last updated at Posted at 2021-08-02

はじめに

めちゃ久しぶりに記事書きます。Pirikaraです。
最近ほぼJavascriptばっかり書いてますが、業務中に解決したやーつを共有したいと思います。

this

thisの挙動の違いについてはこちら

呼んだ所々で値が変わってしまうthis
今まで特に意識せずに使ってましたが、このthisの参照先が変わることで少々困ったことになりました。

Jestでthisを扱うコードをテストする時に詰んだ

こちらのmixinは、Vue.jsのコンポーネントにmethodsとして読み込まれる関数をまとめたものです。
バックエンド(Ruby on Rails)のコードは自動テストを走らせて品質を担保していますが、フロントのjsファイルに関してはE2Eテストを行なっていました。
E2Eだけでは見落としが発生してしまうので、フロント側にも段階的に自動テストを導入していくことになりました。

そこで、まずはコンポーネントのテストではなくJSファイルのテストを.....と思っていたのですが......

mixin.js

export function A(hoge) {
  return this.B(this.$store.hogehoge, hoge)
}

export function B(a, b) {
  return a*b
}
mixin.test.js

import * as mixin from 'path/to/mixin.js';
it('A関数に10を渡すと、50を返す', () => {
  expect(mixin.A(10)).toEqual(50);
})

A関数の中ではthisを取り扱っています。
mixinのコードはコンポーネント内のmethodsとして読み込まれるので、このthisはコンポーネント自身を指しています。
しかしながら、このテストを実行すると次のエラーが発生します。

TypeError:Cannot read property 'hogehoge' of undefined.

this.$storeでVuexのstoreを参照しようとしていますが、テスト環境で実行したこのthisはmixin自身を指しており、$storeという値はないためundefinedになります。
当然hogehogeという値も持っていないのでこのエラーになります。

このままではthisが影響してテストができません。

bindで束縛

Javascriptの関数オブジェクトには、bindという便利なメソッドがありました。
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Function/bind

このメソッドを使うと、関数内のthisを指定の値に固定した新しい関数を返します。
早速使ってみましょう。

mixin.test.js
import * as mixin from 'path/to/mixin.js';
it('A関数に10を渡すと、50を返す', () => {
  const mockTest = mixin.A.bind(5, 10) // 第一引数が関数内のthisの値になる
  expect(mockTest()).toEqual(50);
})

これでテストを正しく実行することができました。

ちなみに、下のように直接bindした関数をテストすると、
元の関数がそのまま(thisを固定できないまま)実行されてしまうので注意です。

mixin.test.js
import * as mixin from 'path/to/mixin.js';
it('A関数に10を渡すと、50を返す', () => {
  expect(mixin.A.bind(5, 10)).toEqual(50);
})

おわり

おわります。
またネタがあれば書きます。

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1