phi

I'm a Game Programmer and Frontend Engineer passionate about programming education. Math / C / C++ / C# / JavaScript / HTML5 / CSS3 / Python

phiaryjust a creator

JavaScript 黒魔術 - 文字列をキーとしてネストしたプロパティにアクセスする

9 years ago

はじめに

JavaScript の 黒魔術です.

オブジェクトの中にオブジェクトがあってさらにその中にオブジェクトがある. んでその末端のオブジェクトが持つプロパティにサクッとアクセス(get/set)できたら素敵やん!

ってことで, 今回はそれを実現する方法について紹介します.

JavaScript の柔軟性を活かせばこんなこともやれちゃいますよ っていう tips です. 速度的な観点から見ると実用性は微妙なので使用する際にはくれぐれもご注意下さい.

Runstant Demo

とりあえずデモです. 左下のコンソールに実行結果が表示されています.

Object.prototype.$get()

getter です.

define

実装です.

reduce 使って再帰的にオブジェクトを取得して,
最後の値を返しています.

Object.defineProperty(Object.prototype, '$get', {  
  value: function(key) {
    return key.split('.').reduce(function(t, v) {
      return t && t[v];
    }, this);
  },
});

usage

使い方です. こんな感じで使えます.

var obj = {  
  a: {
    b: {
      c: '1234',
    },
  },
};

console.log(obj.$get('a.b.c')); // 1234  
console.log(obj.$get('c.b.a')); // undefined  

Object.prototype.$set()

setter です.

define

定義です.

$get 同様, 最後の要素になるまで再帰的に オブジェクトを参照しています.

存在しなければオブジェクトを作成します.

Object.defineProperty(Object.prototype, '$set', {  
  value: function(key, value) {
    key.split('.').reduce(function(t, v, i, arr) {
      if (i === (arr.length-1)) {
        t[v] = value;
      }
      else {
        if (!t[v]) t[v] = {};
        return t[v];
      }
    }, this);
  },
});

usage

使い方です. こんな感じで使えます.

var obj = {  
  a: {
    b: {
      c: '1234',
    },
  },
};

obj.$set('a.b.c', '4321');  
console.log(obj.$get('a.b.c')); // 4321  
obj.$set('c.b.a', 'hoge');  
console.log(obj.$get('c.b.a')); // hoge  

おわりに

当然, 直接アクセスするのに比べて高負荷ですが, これを使うことでコードがスッキリする場面もあるかと思います.

もしよければ導入してみてください.

ちなみに今回紹介したメソッドは phina.js の実装から抜粋した機能だったりします.
よかったら phina.js も触ってみてください♪

phina.js にはこういった tips が山程あるので, ちょこちょこ紹介していきたいと思います.