LoginSignup
2
1

More than 5 years have passed since last update.

JavaScriptのいけてない要素(ver 1.00)

Last updated at Posted at 2018-09-17

JavaScriptは猛省すべき

JavaScriptと関わって丸3年。
中級者になったくらいの気分。
うっかりはまった落とし穴を記す。
後続の人はよく避けられたい。


ES6は妥当

ReferenceError: * is not defined

  • コールバック関数中のthisで
    • 原因: コールバック関数が異なるスコープであり、thisが切り替わってしまうため
    • ES6で解決: アロー関数: ()=>{}
    • 反省点: bindしたりしなかったりの記述の不統一さや、よく使う式なのに記述タイプ量が多いこと

従来の書き方では、引数で渡すかbindしていた。あるいは冒頭にvar self = this; とか。

arr.forEach(function(){}, this)
arr.reduce(function(){}.bind(this), initialValue)

なお、引数リスト内で分割代入ができるらしいが、使えて便利な頻度はどれくらいか?

// 引数リスト内の分割代入もサポートしています
var f = ([a, b] = [1, 2], {x: c} = {x: a + b}) => a + b + c;
f(); // 6

  • 連想配列のループで
    • 原因: for-inループはenumerableなプロパティを拾うため
    • ES6で解決: for-of, Map
    • 反省点: 仕様の矛盾でしょう

従来の書き方では、意図通りに使うにはObject.keys()を使う必要があった。

Object.keys(hash).map(function(key){val = hash[key]; ...})

基底のObjectをそう簡単に拡張するなよ、と思う向きもあるかもわからんが、Objectの備える基礎メソッドが貧弱だから追加せざるをえないという。for...ofを見よ。

Object.keys(hash)ではなくhash.keys()にするには
Object.defineProperty(Object.prototype, 'keys', {
  enumerable: false,
  value: function() {
    return Object.keys(this);
  }
});

ただ、for-ofはargumentsやNodeListなどもループで回せるから改善されたように思えるが、文法要素を増やす対応が適切かは個人的には疑問。コンパイラの修正・検証・最適化に対する指示を考えると。


パッケージで解決

  • 文字列へのフォーマット関数sprintf()

prototypeに追加せざるを得ない

Array.prototype._push():Array

  • ループ中に除外する場合、記述が定型的に冗長になる
    • 原因: Array.prototype.push()の戻り値がlength
var result_caseofinloop = arr.reduce(function(acc, val){  
  if(cond)
    acc.push(f(val));
  return acc
}, [initialValue])

// そうではなく短く書きたいねん
var result_caseofinloop = arr.reduce((acc,val)=>{
 return cond ? acc._push(f(val)): acc
}, [initialValue])

// otherwise 除外してループというやり方もある。
// initialValueがなければいいけどな。unshiftも結果配列のlength返すという、、、もー。
var result_caseofbeforeloop = arr.filter(cond).map((val)=>{return f(val)}
result_caseofbeforeloop.unshift(initialValue);
// 性能的にどうなんやろ?
//

Object.prototype._assign(key, val): Object

  • ループ中の記述が定型的に冗長になる
    • 原因: 代入式の戻り値が右辺だから
// hashのキーでループ

var result_caseofinloop = Object.keys(hash).reduce(function(acc, key){
    acc[key] = f(hash[key])
  return acc
}, initialValue)

// 短く書きたいねん
var result_caseofinloop = hash.keys().reduce((acc, key)=>{
  return acc._assign(key, f(hash[key]))
}, initialValue)
// 除外条件付きなら、keys(cond)にするのも手やな。
var result_caseofinloop = hash.keys(cond).reduce((acc, key)=>{
  return acc._assign(key, f(hash[key]))
}, initialValue)
2
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
2
1