47
27

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

jsのbindは意味がわからない

Posted at

jsのbindは意味がわからない。

bind() メソッドは、呼び出された時に新しい関数を生成します。新しい関数が呼び出される時、this キーワードは与えられた値がセットされ、ます。2 個目以降の引数は、新しい関数より前に、ターゲット関数の引数として与えられます。
Function.prototype.bind() - JavaScript | MDN

「引数をbind(拘束)した新しい関数を作れる」という事はわかったけど、それ何が嬉しいの?と思っていた。
しかし先日、ある出来事をきっかけに理解することができたのでポエムを書いてみる。


この物語はフィクションです。登場する人物はすべて架空のもので(略


私はmodule(もしくはpackage)の開発者。githubを通じて便利な関数を公開している。

先日もredCharacterという超絶便利な関数を公開した所だ。

// java script
var redCharacter = function(val) {
  if (val >= 0) {
    return val;
  } else {
    return `<span style="color:red;">${val}</span>`;
  }
}
# coffee script
redCharacter = (val)->
  if val >= 0
    return val
  else
    return "<span style=\"color:red;\">#{val}</span>

見ての通り、引数の数字がマイナスなら赤字を返すという関数だ。
「赤字はdeficitだろ」というクレームはともかく、他にも要望が入った。

「文字色がredはドギツいので#CC0000くらいがいい」「いや#990000だ」「閾値はゼロ以外にも設定したい」などなど。
仕方がないので仕様を変えてみた。

// java script
redCharacter = function(val, color) {
  color = color || 'red';
  if (val >= 0) {
    return val;
  } else {
    return `<span style="color:${color};">${val}</span>`;
  }
}
# coffee script
redCharacter = (val, color)->
  color = color or 'red'
  if val >= 0
    return val
  else
    return "<span style=\"color:#{color};\">#{val}</span>

公開して数日、プルリクエストが来た。

はじめまして、こんにちは。
あなたの作ったredCharacterを使わせていただいています。とても便利です。
しかし私のプロジェクトでは赤字を#CC0000に統一しています。なのでredCharacter(-100, '#CC0000')といちいち色指定するのは不便です。
そこでbindできるように書き換えてみました。良ければPullお願いします。

ソースコードは以下のようになっている。

// javascript
redCharacter = function(val) {
  var color, threshold;
  color = (this != null ? this.color : void 0) != null ? this.color : 'red';
  threshold = (this != null ? this.threshold : void 0) ? this.threshold : 0;
  if (val >= threshold) {
    return val;
  } else {
    return `<span style="color:${color};">${val}</span>`;
  }
}
# coffee script
redCharacter = (val)->
  color = if @?.color? then @color else 'red'
  threshold = if @?.threshold then @threshold else 0
  if val >= threshold
    return val
  else
    return "<span style=\"color:#{color};\">#{val}</span>

使い方は以下。
文字色がredで良ければそのまま使える。

redCharacter(-100)
// '<span style="color:red;">-100</span>');

文字色を変えたければbindして新しい関数を作る。
新しい関数は文字色を#CC0000に拘束してあるので、引数を都度指定する必要が無い。

var newRedCharacter = redCharacter.bind({color: '#CC0000'})
newRedCharacter(-100)
// '<span style="color:#CC0000;">-100</span>'
newRedCharacter(100)
newRedCharacter(-20)
// 当然ながら何度でも使える

ちなみに、呼び出しが1回限りなら以下の方法でも良い。

redCharacter.call({color: 'pink'}, -100)
// '<span style="color:pink;">-100</span>'

そんなわけでbindとは「引数をbind(拘束)した新しい関数を作れる」関数である。
繰り返し使うカスタム関数を手軽に生成できるのが便利。

おまけ

qiitaのmarkdownって色記号をバッククオートで括るとサンプル色見られるんすね。
#ddd #123 #f90

47
27
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
47
27

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?