Google Apps Scriptでオブジェクトに直接追加しているプロパティだけループする方法


みなさん、こんにちは!
タカハシ(@ntakahashi0505)です。

「初心者でもわかるGoogle Apps Scriptのクラス」をテーマにシリーズ連載をお送りしております。

前回の記事はこちら。

Google Apps Scriptで自作オブジェクトについてプロパティを追加・削除するメソッドの作り方
「初心者でもわかるGoogle Apps Scriptのクラス:をテーマにお送りしております。今回は、GASで自作のオブジェクトについてプロパティを追加するメソッドと削除するメソッドの作り方です。

自作オブジェクトについてプロパティを追加したり削除したりするメソッドの作り方をお伝えしました。

さて、その前回の記事でメソッドを作ったわけですが、そのおかげでfor~in文のループ対象にメソッドも入っちゃうという困ったことが起きちゃいます。

今回は、それをObject.keysメソッドを使って回避する方法をお伝えしていきます。

ということで、Google Apps Scriptでオブジェクトに直接追加しているプロパティのみをループする方法です。

では、行ってみましょう!

スポンサーリンク

前回のおさらい

まず、対象としているスプレッドシートは以下のようなものです。

スプレッドシートのテーブル

まず、この一行ずつのデータを表すクラスを作りましたが、それが以下のコードです。

(function(global){

  var Person = function(record){
    var _id = record[0];
    this.name = record[1];
    this.gender = record[2];
    this.birthday = record[3];
    
    Object.defineProperties(this, {
      id: {
        get: function(){
          return _id;
        }
      }
    });
  };
  
  Person.prototype.greet = function(){
    Browser.msgBox(this.name + "です、こんにちは!");
  };
  
  Person.prototype.log = function(){
    Logger.log('%s|%s|%s|%s|', this.id, this.name, this.gender, this.birthday);
  };

  global.Person = Person;

})(this);

各フィールドを格納するプロパティと、いくつかの単純なメソッドで構成されています。

そして、スプレッドシートにはそのデータが複数行ありますので、それをオブジェクトを使った集合として取り扱うべく、もう一つクラスを作りました。

(function(global){

  var Persons = function() {

    var values = SpreadsheetApp.getActiveSheet().getDataRange().getValues();
    values.shift();
    
    for(var i = 0; i < values.length; i++){
      var p = new Person(values[i]);
      this[p.id] = p;
    }      
  };
  
  Persons.prototype.add = function(record){
    var p = new Person(record);
    this[p.id] = p;
    return this[p.id];
  };
  
  Persons.prototype.remove = function(id){
    delete this[id];
  };
  
  global.Persons = Persons;

})(this);

このクラスPersonsについて、要素を追加するaddメソッドと、要素を削除するdeleteメソッドを追加したのが前回でした。

メソッドもプロパティであることから起こる問題

さて、このクラスPersonsですが、生成したインスタンスにはidをプロパティに、Personオブジェクトを値に、データを集合として扱うオブジェクトのもとになります。

ですが、上記2つのメソッドを追加したことで、ちょっと困ったことが既に起こっています。

以下のようなスクリプトを実行すると、どのような困ったことが起きているかがわかります。

function myFunction() {  
  
  var persons = new Persons();  
  for(var id in persons){
    persons[id].log();
  }      
    
}

スプレッドシートからデータを取得し、Personsクラスのインスタンスを作ります。

そして、その内容をfor~in文を使ってログ出力しようとするものです。

ただ、実行すると…

オブジェクトのループではメソッドも対象になってエラーになる

このように、「TypeError: オブジェクト function (record) {...} で関数 log が見つかりません。」というエラーが出てしまうのです。

原因はわかりますか?

for~in文のループはメソッドも対象になる

for~in文は、オブジェクト内のすべてのプロパティを取り出してループをするステートメントです。

今回の例でいうと、以下の3つがPersonsオブジェクトのメンバーとして期待しちゃいますよね。

  1. プロパティa01: BobのPersonオブジェクト
  2. プロパティa02: TomのPersonオブジェクト
  3. プロパティa03: IvyのPersonオブジェクト

ただ、思い出してください。

プロパティに関数を格納したものが、メソッドでしたよね。

てことは、以下の2つのメソッドもfor~in文のループの対象となります。

  1. プロパティadd: add関数の処理
  2. プロパティremove: remove関数の処理

これらの値は、Personオブジェクトではありませんから、logメソッドを実行できない…したがってエラーが出るというわけです。

オブジェクトに直接追加したプロパティのみをループする

それで、どうするか…ということなのですが、addメソッドもremoveメソッドも、オブジェクトに直接追加しているメソッドではなく、コンストラクタのprototypeプロパティに追加しているという点に注目します。

オブジェクトに直接追加しているプロパティだけ取り出す便利なメソッドがありまして、それがObject.keysメソッドです。

以下のように記述することで、指定したオブジェクトの直接追加しているプロパティのみを配列で取得します。

Object.keys(オブジェクト)

ちなみに、以下の記事で以前お伝えしたdefinePropertiesメソッドによるプロパティは除外されます。

GASでdefinePropertiesメソッドを使ってクラスにプロパティを定義する方法
「初心者でもわかるGoogle Apps Scriptでクラスを作ろう!」をテーマとしたシリーズをお送りしています。今回はGASでdefinePropertiesメソッドを使ってプロパティを定義する方法です。

純粋に直接追加されたプロパティだけを抽出してくれるんですね。

Object.keysメソッドを使ったループ

では、早速使用してみましょう。

Object.keysメソッドは配列を返しますので、forEachメソッドでループできますね。

関数myFunctionを以下のように変更しました。

function myFunction() {  
  
  var persons = new Persons();

  Object.keys(persons).forEach(
    function(id) {
      persons[id].log();
    }
  );  
    
}

実行すると、エラーも発生せず、以下のように正しいログ出力を得ることができました。

Object.keysで取得した配列にループした結果

まとめ

以上、Google Apps Scriptでオブジェクトに直接追加しているプロパティのみをループする方法をお伝えしました。

オブジェクトのループは、for~in文だけというわけにはいかないんですね。

勉強になります。

では、次回はループしてログ出力する処理をメソッド化していきます。

GASでselfを使って関数の中からインスタンスを表すthisを使えるようにする方法
「初心者でもわかるGoogle Apps Scriptのクラス」をテーマにお送りしています。今回は、GASでselfを使って関数の中からインスタンスを表すthisを使えるようにする方法です。

どうぞお楽しみに!

連載目次:初心者向けGoogle Apps Scriptでクラスを作ろう

使いどころやそのメリットが分かりづらいGASの「クラス」。本シリーズでは、初心者でもわかるように「これでもか!」とじっくり着実にクラスとそのメリットについて解説をしていきます。
  1. 【初心者向け】Google Apps Scriptでクラスを理解するためのオブジェクトの基礎知識
  2. 初心者でもできるGoogle Apps Scriptで最も簡単なクラスを作る方法
  3. Google Apps Scriptでクラスに最も簡単なプロパティを追加する方法
  4. Google Apps Scriptでクラスに最も簡単なメソッドを追加する方法
  5. Google Apps Scriptでスプレッドシートのデータの1行分を表すクラスを作る方法
  6. GASでゲッターを使って簡単なプロパティを作成する方法
  7. GASでセッターを使ってプロパティの入力に制限をかける

タイトルとURLをコピーしました