SONICMOOV Googleページ

JavaScriptのObject.definePropertyを使ってみよう

JavaScriptのObject.definePropertyを使ってみよう

  • このエントリーをはてなブックマークに追加

フロントエンドエンジニアのQです。読者の皆様には全く興味がないであろう煩わしい前置きは抜きにして、早速JavaScriptのObject.definePropertyを使ってコードを改善する過程を紹介します。

サンプルとして以下の2次元ベクトルのオブジェクトのコードの一部を使います。とりあえずベクトルの長さを求めるメソッドが定義してあります。

 function Vector2D() { this.x = 0; this.y = 0; } Vector2D.prototype.getLength = function () { return Math.sqrt(this.x * this.x + this.y * this.y); }; 

ベクトルの長さはベクトルの成分が変化しない限りは同じ値になりますが、上のgetLength()では呼び出されるたびに計算し直しています。これをgetter/setterを使い、ベクトルの成分が変化した時のみベクトルの長さを再計算して、getLength()では計算済みの値を返すようにしてみます。 (今回は単純なプロパティへのアクセスをgetter/setter呼び出しにすることによるオーバーヘッド等は考えないことにします。そういうことにさせて下さい・・・!)

 function Vector2D() { this._x = 0; this._y = 0; this._length = 0; } Object.defineProperty(Vector2D.prototype, "x", { get: function () { return this._x; }, set: function (value) { this._x = value; this._length = Math.sqrt(this.x * this.x + this.y * this.y); } }); Object.defineProperty(Vector2D.prototype, "y", { get: function () { return this._y; }, set: function (value) { this._y = value; this._length = Math.sqrt(this.x * this.x + this.y * this.y); } }); Vector2D.prototype.getLength = function () { return this._length; }; 

getter/setterを使って、ベクトルの成分が変化した時のみベクトルの長さを再計算するようにできました。

以上!

・・・でもちょっと待ってください!この実装ではベクトルの成分が頻繁に変化する場合は、最初のコードよりも逆に計算が増えてしまいます。ベクトルの長さの再計算のタイミングを、ベクトルの成分が変化した時ではなく、ベクトルの成分が変化しベクトルの長さの値が必要になった時にしてみましょう。

 function Vector2D() { this._x = 0; this._y = 0; this._length = 0; this._changed = false; } Object.defineProperty(Vector2D.prototype, "x", { get: function () { return this._x; }, set: function (value) { this._x = value; this._changed = true; } }); Object.defineProperty(Vector2D.prototype, "y", { get: function () { return this._y; }, set: function (value) { this._y = value; this._changed = true; } }); Vector2D.prototype.getLength = function () { if (this._changed) { this._length = Math.sqrt(this.x * this.x + this.y * this.y); this._changed = false; } return this._length; }; 

今度こそgetter/setterを使って、インターフェースを変えずちょこっとパフォーマンスを向上させることができました。

以上!

ちなみに人によりますが、私は v.getLength() より v.length のようにアクセスしたがる派なので、以下の書き方が好みです。

 Object.defineProperty(Vector2D.prototype, "length", { get: function () { if (this._changed) { this._length = Math.sqrt(this.x * this.x + this.y * this.y); this._changed = false; } return this._length; } }); 

・・・

以上!

  • このエントリーをはてなブックマークに追加

記事作成者の紹介

Q(フロントエンドエンジニア)

フロントエンドでいろいろやっているQと申します。 ニックネームのQはエヴァQではない方のQです。

関連するSONICMOOVのサービス

フロントエンドエンジニア募集中!

×

SNSでも情報配信中!ぜひご登録ください。

×

SNSでも
情報配信中!
SONICMOOV Facebookページ SONICMOOV Twitter SONICMOOV Googleページ
フロントエンドエンジニア募集中!

新着の記事

mautic is open source marketing automation