ServiceNowのScript Include（スクリプトインクルード）の色々な記述方法を調べた

# はじめに
ServiceNowで個別機能開発などのカスタマイズを行う際にライブラリ的な使い方ができる機能としてScript Includeがあり、公開情報（Docs）に以下が記載されている通り独自のクラスや関数を定義して再利用を可能にします。

>Script Includeは、サーバー上で実行されるJavaScriptを保存するために使用されます。サーバースクリプトで使用するJavaScript関数とクラスを保存するためのScript Includeを作成します。各Script Includeは、オブジェクトクラスまたは関数のいずれかを定義します。

具体的な使用方法はDocsの同ページに記載があり、Script Includeを新規作成する際に、名前を指定するとスクリプトフィールド上にテンプレートが自動入力されるのでプロトタイプに関数などの処理を記述しますが、それ以外にどの様な記述であれば動作するのかが気になり調べてみました。
※ServiceNowでコードを書くことはありますがJavaScript自体は素人ですのでツッコミどころは多数あるかと思いますがご容赦ください。


# ベーシックな記述方法
まず一番ベーシックな記述方法です。
既にまえがきで記載したとおりですが、名前を指定するとテンプレートが自動入力されるのであとはスクリプトフィールドで処理を追記していくだけです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3748053/3d8f9fa6-5e53-4d98-5830-ce9eed5f709e.png)

特徴としてはScript Includeのレコードにつけた名前と同じ変数名で宣言する関数オブジェクトが1つだけ存在しているという点です。

[実行結果]
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3748053/f336beea-a50f-9460-6adb-b28e1bf095d6.png)


## テンプレートで行われていること
余談ですがテンプレート 1行目の「Class.create()」が、どの様な処理を行っているのか確認したところScript IncludeのPrototypeServerを呼び出しおり、以下に置き換えることもできます。

```javascript:Class.create() 置き換え
var BasicSI = function() {
    if (this.initialize)
        this.initialize.apply(this, arguments);
    };
```


# プロトタイプを使用しない場合
プロトタイプを使用しない場合ですが、ベーシックな記述方法と同様にレコードの名前とスクリプトの変数名が一致するようにします。
また、以下の例ではテンプレートからの変更箇所を減らすためにClass.create()を使用していますが、通常のオブジェクトとして宣言しても問題ありません。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3748053/c3d15678-861f-c6b3-a755-ad39b9b13183.png)

[実行結果]
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3748053/7f085a34-93ed-e3f4-9cde-90ea7528b3d4.png)


# 通常のクラスを使用する場合
JavaScriptの通常のクラスとして宣言した場合や無名クラスとして変数に代入した場合ですが結論から言うと動作しません。というより構文エラーとなり保存することができません。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3748053/fea8c1e9-019b-e19f-c17f-1f30a38ea8b0.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3748053/c7e801c3-c9bd-042a-b572-9a6e48441b60.png)


# 定数として使用する場合
定数（的）として使用する場合ですが、これまでと同様にレコードの名前とスクリプトの変数名が一致するようにします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3748053/9eb29c27-313b-8a17-8fde-d63e164f6651.png)

[実行結果]
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3748053/fc4c6d24-5de4-b22e-9792-c5d9c1934663.png)


しかし、実際に使用するケースでは関連する複数の定数を宣言できなければ不便だと思います。オブジェクトのプロパティとして記述することでも対応できますが、その場合は定数として呼び出す際に「オブジェクト名.プロパティ名」となり、毎回オブジェクト名を記述するのが手間になってきます。これを回避するために変数名で2つ以上を記述をしてみますが、その場合は以下の通り名前と異なる変数を呼び出すことはできません。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3748053/1005727b-f404-ceff-0a1f-66aa9aab5377.png)

[実行結果（失敗）]
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3748053/e3939ff7-a6cb-ad14-1e35-8bbae97190a6.png)

通常Script Includeは名前を記述すればそのまま呼び出すことが可能ですが、この様な場合は呼び出す側でgs.include(”Script Include名”)を使用することで対処します。

[実行結果（成功）]
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3748053/aa9236dd-4c9c-9436-f69b-2053c63d971e.png)

# 関数を宣言する場合
関数を宣言する場合は定数として使用する場合と同様です。
関数1つだけであれば名前と関数名が一致するようにします。2つ以上、かつ名前と関数名が異なる場合は呼び出す側でgs.includeを使用します。

## 関数が1つのみ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3748053/c962ba0d-e44b-48c1-84d1-0d89740c9538.png)

[実行結果]
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3748053/5346bb0f-8a81-0d86-09ff-4937588e1316.png)

## 関数が2つ以上、かつ名前と関数名が異なる

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3748053/abb9e19b-3a37-eac0-5982-a45c7aeb9440.png)

[実行結果]
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3748053/fd0848ec-b585-8191-6b67-95eacffd8052.png)


# まとめ
色々なパターンを試しましたが、名前を一致させるか呼び出す側でgs.includeを使用すればServiceNow上で実行できるコードはScript Includeでもだいたい動かせる（テンプレートから外れた記述ができる）という結果になりました。