読者です 読者をやめる 読者になる 読者になる

少年易酔學難成

酒に交われば朱くなる

prototype.jsのせいでJSON.stringifyが使えない。

d.hatena.ne.jp
2016年も四半期が過ぎ去ろうとしているなか、今更この事象に遭遇した。

私が仕事で使っているframework様はprototype.js ver1.6.0.3をお使いになられていて、
prototype.jsをバージョンアップしてはならないとのお達しがあった。
加えて私はExcel方眼紙を駆使する毎日にも疲れており、たまにはコードを書きたい。

ということでObject#toJSONを使わないstringifyを書いた。

var stringify = function (target) {
    // replacerに対応するかしないか迷い中
    var type = typeof target;
    var cannotStringify = '';
    var isArray = Array.isArray;
    var stringifiedElems, keys;

    if (type === 'string') {
        return '"' + target + '"';
    } else if (type === 'number') {
        return '' + target;
    } else if (type === 'boolean') {
        return '' + target;
    } else if (target === null) {
        return '' + target;
    } else if (isArray(target)) {
        // prototype.jsのreduceはECMAのreduceとは互換性がないので
        // prototype.jsに汚染されていないreduceRightを使用する
        stringifiedElems = target.reduceRight(function (acc, e) {
            var stringifiedVal = stringify(e);
            if (stringifiedVal === cannotStringify) {
                return acc;
            } else {
                return [stringifiedVal].concat(acc);
            }
        }, []).join(',');
        return '[' + stringifiedElems + ']';
    } else if (type === 'object' && target !== null && !isArray(target)) {
        keys = Object.keys(target);
        // Object#toJSONなしで全てのオブジェクトに対応するのは難しいので
        // 基本的なオブジェクトのみ対応する。
        if (target instanceof String) {
            return stringify('' + target);
        } else if (target instanceof Number) {
            return stringify(+target);
        } else if (target instanceof Boolean) {
            return stringify(!!target);
        } else if (target instanceof Date) {
            return stringify(target.toISOString());
        } else {
            // prototype.jsのreduceはECMAのreduceとは互換性がないので
            // prototype.jsに汚染されていないreduceRightを使用する
            stringifiedElems = keys.reduceRight(function (acc, k) {
                var stringifiedVal = stringify(target[k]);
                if (stringifiedVal === cannotStringify || !target.hasOwnProperty(k)) {
                    return acc;
                } else {
                    return [stringify(k) + ':' + stringifiedVal].concat(acc);
                }
            }, []).join(',');
            return '{' + stringifiedElems + '}';
        }
    } else {
        return cannotStringify;
    }
};

ブログで書くほど大した処理ではないが、他に書くネタも無いし、指摘とか貰えると嬉しいので一応公開。

[追記]
完璧に対応するのは手間かかるので無理とはいえ、
最低でもStringオブジェクトなど基本的なオブジェクトは対応すべきでした。
replacerは後日対応するかもしれないし、しないかもしれない。
少なくとも仕事上は使われる気配はない。

会社の同期がSublimeTextに入信した。

同期はSublimeTextに入信したようだ。
私はEmacsを薦めたけど、「難しそう」という一言で一蹴された。

Emacs若輩者の私が語れることはあまりないが、Emacsの取っつきにくさはカルマであり、その先に幸福はあると思っている。

私は声を大にして言いたい。
SublimeTextのように執拗に課金を迫ってくる宗教で本当にいいの?

AutoHotKey事始

勤務先の個人用PCがシンクライアント+仮想デスクトップに移行するため、このままでは英字配列のHHKBが使えなくなってしまう。
対応策として、以下の二点を考え付いた。

  1. HHKBとシンクラの間で物理的にJP配列を英字配列に変換する
  2. 仮想デスクトップ上のアプリケーションの前で英字配列に変換する

前者は手軽に行うのは難しそうなので断念し、後者をAutoHotKeyで実現することにした。

パクった参考にしたサイトは以下の通り。
http://ahk.xrea.jp/index.html
http://qiita.com/844196/items/9fc1cd8470a9ad9c3a69

とりあえず、今の設定はこんな感じ。
一番右上のチルダのキーが効かないのが悩み。

*"::send, @
*&::send, {^}
*'::send, &
*(::send, *
*)::send, (
*+0::send, )
*=::send, _
*^::send, =
*~::send, {+}
*@::send, [
*`::send, {{}
[::send, ]
*+{::send, {}}
*]::send, \
*}::send, |
*+::send, :
+*::send, "
LWin::LAlt
LAlt::LWin
RWin::Send, {vkF3sc029}
*vkBA::send, '

JavaScriptで文字コード値⇔文字列変換

作成中のエラーメッセージが文字コード値で出力されたので、とりあえず何が起きてるか見るために文字列に変換する処理を書いてみた。

/**
 * 文字コード値→文字列
 */
function (cd) {
    var cdArr = cd.replace(/\\u([0-9a-fA-F]{1,4})/g, function () {
        return parseInt(arguments[1], 16) + ',';
    }).split(',');
    return String.fromCharCode.apply(String, cdArr);
}

ついでに逆の処理も書いた。

/**
 * 文字列→文字コード値
 */
function (str) {
    var i = str.length, temp = new Array(i);
    if (str === '') return '\\u0000';
    while (i--) {
        temp[i] = '\\u' + ('000' + str.charCodeAt(i).toString(16)).slice(-4);
    }
    return temp.join('');
}