JavaScriptの純粋関数とは何か?[30seconds of interviews]

純粋関数とは何か?

純粋関数(pure function)とは、これら2つの条件を満たす関数を指す。

  • 同じ入力が与えられると、その関数は同じ出力を返す。
  • 関数は、その関数のスコープにおいて副作用を起こさない。

純粋関数は、上記の2つの条件を満たす限り、関数内のローカルデータを変更することができる。

Pure

const a = (x, y) => x + y
const b = (arr, value) => arr.concat(value)
const c = arr => [...arr].sort((a, b) => a - b)

Impure

const a = (x, y) => x + y + Math.random()
const b = (arr, value) => (arr.push(value), arr)
  • tips
    • 純粋関数は、その信頼性のため推測が用意にできる。
    • 全ての関数は、明示的に副作用を起こさない限り純粋関数であるべきである。
    • もし関数が値を返さないのであれば、すなわち副作用が起こることを示している。

30secondsofinterviews.org

JavaScriptでパイプ関数を作成する [30seconds of interviews]

以下の挙動をする pipe関数を作成する

const square = v => v * v
const double = v => v * 2
const addOne = v => v + 1
const res = pipe(square, double, addOne)
res(3) // 19; addOne(double(square(3)))
  • 与えられた全ての関数をスプレッド演算子...を使って収集する。
  • pipe処理の初期値としてxを受け取るようにする。
  • Array.prototype.reduce()を使って一連の関数を実行する。そのとき、reduceで逐次得た結果を次の関数の引数として渡すようにする。
const pipe = (...fns) => x => fns.reduce((v, fn) => fn(v), x)

上記をわかりやすく冗長に書くと以下のようになる。

const pipe = (...fns) => {
  return (x) => {
    return fns.reduce((v, fn) => fn(v), x)
  }
}

30secondsofinterviews.org

Javascriptオブジェクトをクローンする [30seconds of interviews]

How do you clone an object in JavaScript?

スプレッド構文...を使うと、オブジェクト自身の列挙可能なプロパティを新しいオブジェクトにコピーできる。オブジェクトの浅いクローン(shallow clone)が作成される。

const obj = { a: 1, b: 2 }
const shallowClone = { ...obj }

上記のテクニックでは、prototypeは無視される。さらにネストされたオブジェクトはクローンされずそれらの参照がコピーされるので、ネストされたオブジェクトは依然としてオリジナルと同じオブジェクトを参照する。ディープクローンする場合は、オブジェクト内にネストされる可能性のある任意のタイプのオブジェクト(Date, RegExp, Function, Setなど)を効果的にクローンするために上記の方法よりはるかに複雑になる。

色々なコピー方法:

30secondsofinterviews.org

CSS BEMとは何か? [30seconds of interviews]

What is CSS BEM?

BEMとは、スコープ問題を解決するために名前空間を定義することでよりCSSをメンテナンスしやすくするCSSクラスの命名規則

BEMはblock, element, modifier の略。blockはプロジェクトを通して再利用可能なスタンドアロンコンポーネントであり、サブコンポーネント(elements)の名前空間として機能する。modifiersは blockまたはelementが特定の状態にあるとき、または異なる構造やスタイルのときにフラグとして利用される。

/* block component */
.block {
}

/* element */
.block__element {
}

/* modifier */
.block__element--modifier {
}

マークアップの例

<nav class="navbar">
  <a href="/" class="navbar__link navbar__link--active"></a>
  <a href="/" class="navbar__link"></a>
  <a href="/" class="navbar__link"></a>
</nav>

上のケースの場合、navbar はblock, navbar__linkはelement(navberコンポーネントの外では意味をなさない)、navbar__link--activeはmodifier(navbar__link 要尾とは異なる状態を示す)。

modifiersは冗長なので、多くの場合、modifierとしてis- *フラグを使用される。

<a href="/" class="navbar__link is-active"></a>

これらは、必ずelementに連鎖し、決して単独で使用しない。

.navbar__link.is-active {
}

30secondsofinterviews.org

HTML5 Web Storage(ローカルストレージ/セッションストレージ)とは何か [30seconds of interviews]

HTML5 Web Storageとは何か

HTML5では、ウェブサイトはブラウザのローカルにデータを保存できる。データはname-valueペアで格納され、ウェブページは自身で格納したデータにのみアクセスができる。

localStorageとsessionStorage

ライフタイムの違い

  • localStorageに格納されたデータは永続的。ウェブアプリケーションが削除する、またはユーザが自らブラウザのデータを削除するまでは、データは永続する。
  • sessionStorageはウィンドウまたはデータを格納したブラウザタブと同じライフタイムを持つ。タブが完全に閉じられると、sessionStorageに格納されたデータは削除される。

スコープの違い

どちらのstorageも、オリジンが異なると格納されたオブジェクトは共有されないため、スコープはオリジン単位となる。

  • sessionStorageは、同じオリジンの2つのブラウザのタブに、別々のsessionStorageデータを持つ。
  • sessionStorageは、localStorageとは異なり同じオリジンの同じスクリプトでも、タブが異なる場合お互いのsessionStorageにアクセスできない。
tips
  • 以前はクッキーでストレージが行われていた。
  • この保存サイズの制限は、クッキーより遥かに大きく(少なくとも5MB)、高速である。
  • データは決してサーバーに転送されず、クライアントが要求した場合のみ使用される。

30secondsofinterviews.org

scriptタグのdefer/async属性の違い [30seconds of interviews]

30secondsofinterviews.org

30 seconds of interviewsを一通り読んで面白かったので紹介していきたい

What are defer and async attributes on a <script> tag?

<script src="myscript.js"></script>
<script src="myscript.js" defer></script>
<script src="myscript.js" async></script>
  • いずれの属性も指定しない場合、スクリプトは同期的にダウンロード・実行され、ドキュメントのパースはスクリプトの実行が終了するまで中断される。スクリプトは順番に実行される

  • defer属性はドキュメントのパース中にスクリプトをダウンロードする。DOMContentLoadedイベントリスナ内のスクリプト実行と同様に、ドキュメントのパース完了後に実行される。deferスクリプトは順番に実行される。

  • async属性はドキュメントのパース中にスクリプトをダウンロードする。パースが完全に終了する前に、スクリプトを実行する。asyncスクリプトは必ずしも順番に実行されない。

  • tips

    • スクリプトが互いに依存している場合は、deferを使用する。
    • スクリプトが独立している場合は、asyncを使用する。
    • DOMが必ず準備されていなければならない、かつ実行するスクリプトがDOMContentLoaded内に置かれていない場合、deferを使用する。

Vue.js 基底inputコンポーネントを作る

inputの基底コンポーネントを作る。

v-modelは使わずに、@inputでそのまま親に変更されたvalueをemitする。

# input基底コンポーネント
Vue.component('baseInput', {
  props: ['initValue'],
  template: `
    <input
      type="text"
      :value="initValue"
      @input="$emit('inputText', $event.target.value)"
    />
  `
})

example

See the Pen vue.js base-input component by tic40 (@ccpzjoh) on CodePen.