質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.04%

JavaScriptの小技募集

解決済

回答 6

投稿

  • 評価
  • クリップ 26
  • VIEW 4,306

score 734

JavaScriptは良くも悪くも記述の自由度が高い言語ですよね。
そんなJavaScriptには現場で使われるちょっとした小技や必須のテクニック、競技や問題向けの小技や荒技が存在する物と思います。
もしよければこんなのを現場では使ってる、コードゴルフでこれが有効ではないかというようなコードを共有しませんか?

必要なもので有名なのはprototypeやこれらですよね。
//即時関数
(function (){
  //
}());

//クロージャ
//……めちゃくちゃなコードですね
function a(_N){
  var n=_N;
  return {
    add :
      function (_n){
        return n+_n;
      }
  }
}
var NN=a(10);
NN.add(5);

競技や問題向けですと型変換は多用されますかね。
//暗黙の型変換 文字から数値
var s="100";
s-0;//number型

//暗黙の型変換 数値から文字
var n=250;
n+"";//string型
n+[];//string型

//暗黙の型変換 数字を使わず数値を作る
var v=+!v;//1
z|z;//0
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • 退会済みユーザー

    2016/04/10 17:36

    こちらの質問が他のユーザから「問題・課題が含まれていない質問」という指摘を受けました
    teratailでは、漠然とした興味から票を募るような質問や、意見の主張をすることを目的とした投稿は推奨していません。
    「編集」ボタンから編集を行い、質問の意図や解決したい課題を明確に記述していただくと回答が得られやすくなります。

回答 6

checkベストアンサー

+3

暗黙の型変換の1つに、+sというのがあって、これで数値にできます。あと、即時関数は、カッコを使わずに!function(){...}()とすれば1文字削れます。

XSSなどでたまに出現しますが、/foobar/.sourceとすることで、引用符なしで文字列を作れます。

いちばん強烈な技としては、[]['constructor']['constructor']('コード文字列')とすればFunctionコンストラクタを経由してコード実行ができるので、あとは文字列を記号にすることで任意のコードを記号だけで書き下せます

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2015/05/29 14:17

    !function(){...}()は戻り値がBooleanになり、反転する副作用がありますがローカル変数化するためだけに使っているならこっちのほうがよさそうですね
    二つ目は複数行の文字列を作る際に使ってる人がたまにいますよね
    一番下は初めて知りました……かなりトリッキーですね
    文字制限つきのコードゴルフで使えそうですね

    キャンセル

+1

これはよく使うので回答してみます。
条件分岐を&&||で書く。

//fが暗黙の型変換でtrueになるとき関数を実行
f && f();
//if(f) f();と同じ

//fが暗黙の型変換でfalseになるときどこかで定義してあるDEFAULT_FUNCTIONを代入
f || (f = DEFAULT_FUNCTION);
//if(!f) f = DEFAULT_FUNCTION;と同じ

//objがfalseのとき{}を代入
obj = obj || {};
//obj = obj ? obj : {}; と同じ
型変換でtrue,falseを短く書く

!0;//true;
!1;//false;

追記

オブジェクトの存在判定など。

//AudioContextの存在判定(なければfalseになり、あればそのオブジェクトが代入される)
window.AudioContext = window.AudioContext || window.webkitAudioContext || window.mozAudioContext;
//これとおなじ
if(window.AudioContext) window.AudioContext = window.AudioContext;
else if(window.webkitAudioContext)window.AudioContext = window.webkitAudioContext;
else if(window.mozAudioContext)window.AudioContext = window.mozAudioContext;
else window.AudioContext = false;

//addEventListener なければattachEventを[on]で使えるようにする
var on = ['addEventListener ', 'attachEvent'];
var i = -1;
window[on[++i]] || window[on[++i];
on = on[i];

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2015/06/03 23:49

    回答ありがとうございます。
    条件分岐の記述を&&はコードゴルフで用いることがありますね。
    orは他の方も回答しているようにクロスブラウザ対応やデフォルト値を使用するかの判別に便利ですよね。

    if(!window.addEventListener){//定義されてなければtrueに
    //イベントメソッドの互換性を持たせる処理
    }
    のような処理も見ますよね

    キャンセル

0

有名なのだとビット演算で小数の整数化とかですかね?
var f = 12.34;
var i = f | 0; // ==> 12

あまり推奨されないかもしれませんが、たまにビルドインオブジェクトのprototype拡張をすることがあります。
!!String.prototype.hoge
|| Object.defineProperty(String.prototype, "hoge", {
    value: function(){
        return this;
    }
});

後はメソッドの統一とかですか。
Element.prototype.matches = Element.prototype.matches ||
    Element.prototype.matchesSelector ||
    Element.prototype.webkitMatchesSelector ||
    Element.prototype.mozMatchesSelector ||
    Element.prototype.msMatchesSelector ||
    Element.prototype.oMatchesSelector;

小技というと違うような気もしますが…。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2015/05/29 14:11

    確かに使いますね、小数の切捨。
    下二つはクロスブラウザのときとか必要なことがありますよね

    キャンセル

0

あまり規模が小さくないがasync/awaitをgenerator/yield再現するのためのco

function co(gfn) {
  return function () {
    var gen = gfn.apply(this, arguments)
    return new Promise(function (res, rej) {
      function resume(v) {
        var r = gen.next(v)
        Promise.resolve(r.value).then(r.done ? res : resume).catch(rej)
      }
      resume()
    })
  }
}

//例

function wait(ms) {
  return new Promise(function (res) {
    setTimeout(res, ms)
  })
}

var test = co(function* () {
  console.log('T')
  yield wait(1000)
  console.log('E')
  yield wait(1000)
  console.log('S')
  yield wait(1000)
  console.log('T')
})


console.log('--start--')
test().then(function () {
  console.log('--done--')
})

またHTMLも含むのであれば任意の文字列をテキストファイルとしてダウンロードするためのこれ
var blob = new Blob(['テキスト'])
var link = document.createElement('a')
link.href = URL.createObjectURL(blob)
link.download = 'ファイルネーム.txt' 
link.click()

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2015/05/29 19:01

    なるほど。非同期ですか
    DLもいいですね。自分が知っているのはイベントオブジェクトを作成してクリックを発火させるものでしたがこの場合はclick()がそれに相当するのでしょうか?

    キャンセル

  • 2015/05/31 04:52

    全てのHTMLElementにはclickメソッドがあるのでイベントのディスパッチは必要ないですね。
    https://html.spec.whatwg.org/multipage/interaction.html#dom-click

    キャンセル

  • 2015/05/31 15:41

    HTMLElement.click()はclickイベントの発火ではないのですか?
    説明を読んだ感じだとそういったものかと思ったのですが実装が違ったりするのですかね?

    キャンセル

  • 2015/05/31 19:04

    clickイベントも発火しますし、実際にその要素をクリックしたのと同じような効果がもたらされます。

    キャンセル

0

みなさん使ってるとは思いますが・・・・。
jQueryで、アニメーションか、CSSのチェンジだけかを判定させる時、
当てるCSSを一度オブジェクトに格納して当てたりしてます。
var addCSS = {width: int, height: int, top: float, left: float};
var animationFlg = true;

if (animationFlg) {
 tagetDOM.animate(addCSS, time, ease, callBack);
} else {
 tagetDOM.css(addCSS);
}

また、メソッドもテキストで格納したりとか

var runMethod;
var addPosition = 'bottom';

if (addPosition = 'bottom') {
 runMethod = 'append';
} else {
 runMethod = 'prepend';
}

tagetDOM[runMethod](addDOM);

小技というより、条件分岐でなるたけ一元管理できるように、ですね。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2015/06/04 14:52

    二つ目のaddPosition="bottom"は===ではないでしょうか
    標準のJSでも使われることがありますね

    キャンセル

0

class を定義したり、それを extend するというときは、
coffeescript で書いて、 coffee -p -b  で javacript に変換してしまうことがあります。

# See http://leko.jp/archives/407
class Parent
  constructor: (@name) ->

  move: (meters) ->
    console.log @name + " moved #{meters}m."

class Child extends Parent
  move: ->
    console.log "slithering..."
    super 5

child = new Child("kato")
child.move()
$ coffee 1.coffee slithering... kato moved 5m.

$ coffee -p -b 1.coffee > 2.js
$ node 2.js
slithering...

$ cat 2.js
var Child, Parent, child,
  extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
  hasProp = {}.hasOwnProperty;

Parent = (function() {
  function Parent(name) {
    this.name = name;
  }

  Parent.prototype.move = function(meters) {
    return console.log(this.name + (" moved " + meters + "m."));
  };

  return Parent;

})();

Child = (function(superClass) {
  extend(Child, superClass);

  function Child() {
    return Child.__super__.constructor.apply(this, arguments);
  }

  Child.prototype.move = function() {
    console.log("slithering...");
    return Child.__super__.move.call(this, 5);
  };

  return Child;

})(Parent);

child = new Child("kato");

child.move();

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2015/06/08 03:06

    coffeescriptは可読性などの点で優れていると聞いたことがありますね
    設計する際もコードの流れが読みやすい利点がありそうですね

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.04%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る