かもメモ

自分の落ちた落とし穴に何度も落ちる人のメモ帳

React JSX className に変数と固定値を混ぜて使いたい

ReactのJSXでクラス名を付ける時に変数と固定値な文字列を一緒に使いたいとき

コレはうまくいかない

  return (
    <button className="btn btn-${btnState}">BUTTON</button>
  );

文字列結合する

function Button() {
  const [btnState, setBtmState] = useState('primary');
  return (
    <button className={'btn btn-' + btnState}>BUTTON</button>
  );
}

テンプレート構文 (ES2015)を使う

function Button() {
  const [btnState, setBtmState] = useState('primary');
  return (
    <button className={`btn btn-${btnState}`}>BUTTON</button>
  );
}

変数で複数のクラスにするとき

.error とか変数があれば複数のクラス名になるような時、ただ結合しただけだと変数が空の時、HTMLのクラス属性の最後に空白ができて少し気持ち悪いです。
これを解決するには単純に trim() すればOKです。

テンプレート構文 (ES2015)を使う

function Button() {
  const [btnState, setBtmState] = useState('');
  return (
    <button className={`btn ${btnState}`.trim()}>BUTTON</button>
  );
}

配列結合 join()を使う

function Button() {
  const [btnState, setBtmState] = useState('');
  return (
    <button className={['btn', btnState].join(' ').trim()}>BUTTON</button>
  );
}

 
最後の空白が気持ち悪いかどうかは、まぁお気持ち的な要素が強いですが、いずれにせよ ``で囲うテンプレート構文を使うのが一番手っ取り早そうです。

trim()も標準になってるのでとても楽ですね。存在しないときはStringオブジェクトを拡張して独自実装してた時代が懐かしいです… 戻りたくはない


[参考]

WEB+DB PRESS Vol.110

WEB+DB PRESS Vol.110

JavaScript eval vs. new Function

文字列をそのままJavaScriptとして実行できる邪悪なパーツとされるevalnew Function のメモ。
node使ってモジュール入れてBabelしてwebpackする時代に使う事なんてなさそうだけど、、、

eval

グローバル・スコープ内にある変数にアクセスできる

let n = 3;
(function() {
  let a = 'foo';
  eval("console.log(a, n);"); // 'foo', 3
  // 変数の書き換え
  eval("a = 'bar'; n = 0;");
  console.log(a, n); // 'bar', 0
})();
console.log(typeof a, n); // undefined, 0

eval 内で作られる変数の扱いの違い

strict モードでない時、eval 内で作られた変数はスコープ内に作成される

eval("var a = 1");
console.log(a); // 1
console.log(window.a); // 1
(function() {
  eval("var b = 2");
  console.log(b); // 2
})();
console.log(window.b); // undefined
console.log(typeof b); // undefined

strict モードの時、eval 内で作られた変数は外に出ない

"use strict";
eval("var a = 1");
console.log(window.a); // undefined
console.log(typeof a); // undefined
(function() {
  eval("var b = 2");
  console.log(typeof b); // undefined
})();
console.log(window.b); // undefined
console.log(typeof b); // undefined

new Function

グローバルの変数にはアクセスできるが、スコープのローカル変数にはアクセスできない

let n = 3;
(function() {
  let a = 'foo';
  new Function("console.log(typeof a, n);")(); // undefined, 3
  // local 変数 a にアクセスできないので、グローバル変数を作成してしまう
  new Function("a = 'bar'; n = 0;")();
  console.log(a, n); // 'foo', 0
})();
console.log(a, n); // 'bar', 0

new Function 内で作られる変数の扱い

strictモードに関わらず、new Function 内で変数宣言して作成された変数は外部からアクセスできない。(new Function 内で実行されるスクリプトの local 変数)

new Function("var a = 1")();
console.log(typeof a); // undefined
(function() {
  new Function("var b = 2")();
  console.log(typeof b); // undefined
})();
console.log(typeof b); // undefined

 
今更感あふれる誰得な記事ができた。


[参考]

JavaScriptパターン ―優れたアプリケーションのための作法

JavaScriptパターン ―優れたアプリケーションのための作法

JavaScript (ES2015) super のメモ

ES2015 で使えるようになった class ですが、JavaScriptではあくまでクラスっぽいモノ(プロトタイプ・オブジェクト)として実装されているらしいので、継承元のプロパティやメソッドを使えるsuperがどうなってるのか気になったので調べてみたメモ。

super

const school = {
  school: 'スターライト学園',
};

const idol_type = {
  __proto__: school,
  type: 'cute',
};

const idol = {
  __proto__: idol_type,
  name: '星宮いちご',
  to_s() {
    return `${this.name} Type: ${super.type} 所属: ${super.school}`;
  }
};

idol.to_s();
// => 星宮いちご Type: cute 所属: スターライト学園
感想

superは該当する値やメソッドをprototypeチェーンを辿って探してくるキーワード。
ES2015から使えるようになったclassもあくまで昔やってたクラスっぽいオブジェクトの延長ナンダナって解って理解が進みました。
当時クラスっぽいものを作るのに使ってた newJavaScript: The Good Partsって本やブログで evil みたいな話みたことあるんだけどアレ class が出来たことによって許されたのかな??? チョット気になる。


[参考]

スーパーマリオ ウェットティッシュ ケース付 (80枚入)

スーパーマリオ ウェットティッシュ ケース付 (80枚入)

JavaScript: The Good Parts ―「良いパーツ」によるベストプラクティス

JavaScript: The Good Parts ―「良いパーツ」によるベストプラクティス