MENU

お知らせ:2021/2/18 ツールサイト(affi-sapo-sv.com)から、開発ノートを独立させました。

 

JavaScriptゲッター・セッター

【JavaScript】 ゲッター/セッター関数を後から変更する方法

更新日:2021/02/01

 

使用する状況があまりなさそうだけれど、ゲッターとセッターの動作を別の関数に置き換える方法がないか考えてみました。

 

ゲッター/セッターに関する非推奨メソッド

 

JavaScriptがブラウザ上で動作する場合、標準オブジェクトに次のメソッドが追加されています。

 

__defineGetter__ : ゲッターを定義する
__defineSetter__ : セッターを定義する
__lookupGetter__: ゲッター関数を取得する
__lookupSetter__: セッター関数を取得する

 

 

使用例

 

  // セッターの追加
obj.prototype.__defineSetter__(
      "prop2",                      // プロパティ名
      function( v ){ this._v = v; } // 呼び出す関数
);
 
  // ゲッターの追加
obj.prototype.__defineGetter__(
      "prop2",                         // プロパティ名
      function(  ){ return  this._v; } // 呼び出す関数
);

 

しかし、これらのメソッドはレガシー機能として位置付けられ、非推奨となっています。

ゲッター/セッターの推奨定義方法

 

オブジェクトにゲッターとセッターを定義するとき、Object.definePropertyメソッドを使用することが推奨されています。

 


let value = 100;

Object.defineProperty(
         obj.prototype ,           // 追加先のオブジェクト
         "prop2" ,                  // プロパティ名
        {
           set : function( v ){ value = v; },
           get : function(  ){ return value; },
           configurable:true,
        }
)

 

このメソッドは、プロパティのconfigurable属性がfalseでなければ、再度呼び出すことで呼び出す関数を変更することができます。

 


Object.defineProperty(
         obj.prototype ,           // 追加先のオブジェクト
         "prop2" ,                  // プロパティ名
        {
           set : function( v ){ value = v * 100; },
           configurable:true,
        }
);

 

このとき、setまたはgetのみの指定も可能です。
指定されなかった方は、そのまま残ります。

ゲッター/セッター関数を取得して変更する

 

__lookupGetter__と__lookupSetter__が非推奨となりゲッターおよびセッター関数を取得するメソッドができなくなりました。

 

そこで他の方法で、取得してみます。

 

次のコードでプロパティの情報を取得します。

 


const ds = Object.getOwnPropertyDescriptor( オブジェクト, プロパティ名 );

 

取得した情報は、次のようなオブジェクトになっています。

 

{

get: 関数/undefined ,
set: 関数/undefined,
enumerable: true/false,
configurable: true/false
}

 

getとsetプロパティがundefinedでなければ、それが目的の関数となります。

 

プロパティがゲッター・セッターでない場合、オブジェクトにgetとsetがありません。
これらがあるかどうかをチェックすることで、プロパティが通常のものかどうかを確認することも可能です。

 

このオブジェクトは、そのままObject.definePropertyで使用できます。

 

getまたはsetプロパティに現在と異なる関数をセットすれば、ゲッター・セッターを変更できます。

 

変更例

 


function getObj(){
    let val=0;
    return {
        get val1(){
            return val;
        },
        set val1(v){
            val = v;
        },
    };
}
const obj = getObj();

const ds = Object.getOwnPropertyDescriptor(obj, "val1");

ds.get = ()=>300;
Object.defineProperty(obj, "val1", ds);

console.log( obj.val1 ); // 300

 

上の使用例を見てもらうと、変更後のゲッター関数は300を返しています。

 

ゲッター関数の変更理由として、戻り値の計算方法を変えたいということがあります。
そこで、val * 2 などを返したかったのですが、これは不可能でした。

 

理由については、次の記事を読んでみてください。
【JavaScript】 JSにおけるカプセル化手法

 

実際のところ、ゲッターとセッターを変更するとコードを追うことが非常に難しくなります。
そのため、取得値の変更等は関数内でフラグ等で管理すべきです。

 

また、ゲッターとセッターを変更するコードが第三者によって組み込まれる可能性があります。
重要なオブジェクトはObject.freeze()等で凍結することを検討したほうがいいですね。

記事の内容について

 

こんにちはけーちゃんです。
説明するのって難しいですね。


「なんか言ってることおかしくない?」
たぶん、こんなご意見あると思います。

裏付けを取りながら記事を作成していますが、僕の勘違いだったり、そもそも情報源の内容が間違えていたりで、正確でないことが多いと思います。

そんなときは、ご意見もらえたら嬉しいです。

ご意見はこちら。
https://note.affi-sapo-sv.com/info.php

【お願い】

お願い

■このページのURL


■このページのタイトル


■リンクタグ