ブログ

ServiceNow で Dot-Walking と Array.push() を使用して配列に値を追加する場合の注意点

ServiceNow開発部ブログ第11回目です。

Dot-Walking と Array.push() を使用して配列に値を追加していくと、最後にレコードに追加した値ですべての要素の値が上書きされてしまう場合があります。

その問題の事象と解決方法について記載しました。

事象

例えば、サービスポータルのページのうち、最近更新されていないページのタイトルを返すメソッド olderPages() を用意します。

var pages = olderPages("2020-01-01");
gs.info("\r\nページ一覧 : " + pages + " ");

function olderPages(date) {
  var recordList = [];
  var gr = new GlideRecord("sp_page");
  gr.addQuery("sys_updated_on", "<", date);
  gr.orderBy("title");
  gr.setLimit(5);//デモ用の上限
  gr.query();
  while (gr.next()) {
    gs.info("タイトル : " + gr.title + " \t 更新日時 : " + gr.sys_updated_on + " ");
    recordList.push(gr.title);
  }

  gs.info("\r\n返り値 : " + recordList + " ");
  return recordList;
}

上記のスクリプトを実行すると、olderPages() メソッドの while ループのデバッグでは5件とも gr.title の値が正しく表示されています。しかし、olderPages() メソッドの返り値では、5件目のレコードのタイトル Benchmarks Home が5回繰り返されてしまいます。return する直前に recordList の値を確認しても同様です。

*** Script: タイトル : Announcements 更新日時 : 2017-08-24 22:43:17
*** Script: タイトル : Approval Form 更新日時 : 2017-08-24 22:51:47
*** Script: タイトル : Approvals 更新日時 : 2017-08-24 22:51:47
*** Script: タイトル : Benchmarks 更新日時 : 2018-10-23 18:03:46
*** Script: タイトル : Benchmarks Home 更新日時 : 2017-06-30 01:13:10
*** Script:
返り値 : Benchmarks Home,Benchmarks Home,Benchmarks Home,Benchmarks Home,Benchmarks Home
*** Script:
ページ一覧 : Benchmarks Home,Benchmarks Home,Benchmarks Home,Benchmarks Home,Benchmarks Home

解決方法

Dot-Walking を使用した値を意図的にString化してから配列に追加すると解決できます。
例えば recordList.push(gr.title); の部分を以下のいずれかのように修正します。

  • recordList.push("" + gr.title);
  • recordList.push(gr.title.toString());

または、getValue() を使用して下記のように修正します。

  • recordList.push(gr.getValue("title"));

修正すると期待通りの結果が得られるようになります。

*** Script: タイトル : Announcements 更新日時 : 2017-08-24 22:43:17
*** Script: タイトル : Approval Form 更新日時 : 2017-08-24 22:51:47
*** Script: タイトル : Approvals 更新日時 : 2017-08-24 22:51:47
*** Script: タイトル : Benchmarks 更新日時 : 2018-10-23 18:03:46
*** Script: タイトル : Benchmarks Home 更新日時 : 2017-06-30 01:13:10
*** Script:
返り値 : Announcements,Approval Form,Approvals,Benchmarks,Benchmarks Home
*** Script:
ページ一覧 : Announcements,Approval Form,Approvals,Benchmarks,Benchmarks Home

関連するナレッジ : Adding new values to an array using Array.push() replaces all values in the array with the last value pushed

別解

最終的にカンマ区切りの文字列として使用することが明らかな場合、直接文字列を作成して返す、という別解もあります。String化を気にする必要がなくなります。

var pages = olderPages("2020-01-01");

/* 上記のスクリプトでは、pages を表示する際に、暗黙的に配列から文字列への変換(配列の join)が
行われていました。このスクリプトでは olderPages() の返り値がそのまま使用されています */
gs.info("\r\nページ一覧 : " + pages);

function olderPages(date) {
  var recordList = "";//上記のスクリプトとは違い、空の文字列です
  var gr = new GlideRecord("sp_page");
  gr.addQuery("sys_updated_on", "<", date);
  gr.orderBy("title");
  gr.setLimit(5);
  gr.query();
  while (gr.next()) {
    gs.info("タイトル : " + gr.title + " \t 更新日時 : " + gr.sys_updated_on + " ");
    recordList += gr.title + ",";//上記のスクリプトとは違い、文字列として追加しています
  }

  recordList.slice(0,-1);//最後のカンマを除去してから返します
  return recordList;
}

弊社公式Qiitaへも同様の記事を投稿しております。

pagetop