如何使用getter與setter方法添加JS對(duì)象-創(chuàng)新互聯(lián)

這篇文章將為大家詳細(xì)講解有關(guān)如何使用getter與setter方法添加JS對(duì)象,文章內(nèi)容質(zhì)量較高,因此小編分享給大家做個(gè)參考,希望大家閱讀完這篇文章后對(duì)相關(guān)知識(shí)有一定的了解。

10年積累的成都網(wǎng)站建設(shè)、成都網(wǎng)站設(shè)計(jì)經(jīng)驗(yàn),可以快速應(yīng)對(duì)客戶對(duì)網(wǎng)站的新想法和需求。提供各種問(wèn)題對(duì)應(yīng)的解決方案。讓選擇我們的客戶得到更好、更有力的網(wǎng)絡(luò)服務(wù)。我雖然不認(rèn)識(shí)你,你也不認(rèn)識(shí)我。但先建設(shè)網(wǎng)站后付款的網(wǎng)站建設(shè)流程,更有周村免費(fèi)網(wǎng)站建設(shè)讓你可以放心的選擇與我們合作。

定義 getter 與 setter

1.通過(guò)對(duì)象初始化器在創(chuàng)建對(duì)象的時(shí)候指明(也可以稱為通過(guò)字面值創(chuàng)建對(duì)象時(shí)聲明)

(function () {
  var o = {
    a : 7,
    get b(){return this.a +1;},//通過(guò) get,set的 b,c方法間接性修改 a 屬性
    set c(x){this.a = x/2}
  };
  console.log(o.a);
  console.log(o.b);
  o.c = 50;
  console.log(o.a);
})();

在 chrome 中調(diào)試視圖如下:

如何使用getter與setter方法添加JS對(duì)象

可以看到對(duì)象下多了 get 屬性以及 set 屬性
輸出結(jié)果如下:

如何使用getter與setter方法添加JS對(duì)象

當(dāng)然 get 語(yǔ)句與 set 語(yǔ)句可以聲明多次用來(lái)對(duì)應(yīng)多個(gè) gettersetter
使用這種方法的好處是可以在聲明屬性的時(shí)候同時(shí)聲明對(duì)應(yīng)的 gettersetter
這里就有人問(wèn)了,能不能將o 對(duì)象的 get 及 set 方法的方法名都改成 “a”,這樣就可以直接通過(guò)“.”來(lái)訪問(wèn)方法直接操作

(function () {
  var o = {
    a : 7,
    get a(){return this.a +1;},//死循環(huán)
    set a(x){this.a = x/2}
  };
  console.log(o.a);
  console.log(o.b);
  o.c = 50;
  console.log(o.a);
})();

打開(kāi) chrome 查看創(chuàng)建后的視圖如下:

如何使用getter與setter方法添加JS對(duì)象

可以看到這個(gè)時(shí)候的 get 與 set 方法已經(jīng)和上面不同,但是是否真的能起作用呢,答案是否定的,當(dāng)我們通過(guò) o.a 調(diào)用的是 get語(yǔ)句 聲明的 a方法,進(jìn)入到該方法后遇到 this.a 方法繼續(xù)調(diào)用該方法形成死循環(huán)最終導(dǎo)致死循環(huán)報(bào)內(nèi)存溢出錯(cuò)誤。

新語(yǔ)法(ES6):暫時(shí)只有 firefox 支持,其他瀏覽器會(huì)報(bào)錯(cuò)

(function () {
  var b = "bb";
  var c = "cc";
  var o = {
    a : 7,
    get [b](){return this.a +1;},
    set [c](x){this.a = x/2},
  };
  console.log(o.a);
  console.log(o[b]);
  o["cc"] = 50;
  console.log(o.a);
})();

打開(kāi) firefox 查看調(diào)試:

如何使用getter與setter方法添加JS對(duì)象

輸出結(jié)果如下:

如何使用getter與setter方法添加JS對(duì)象

2.使用 Object.create 方法

引用 MDN:

概述
Object.create() 方法創(chuàng)建一個(gè)擁有指定原型和若干個(gè)指定屬性的對(duì)象。

語(yǔ)法
Object.create(proto, [ propertiesObject ])

我們都知道使用 Object.create 方法傳遞一個(gè)參數(shù)的時(shí)候可以創(chuàng)建一個(gè)以該參數(shù)為原型的對(duì)象 淺談 JS 創(chuàng)建對(duì)象的 8 種模式
第二個(gè)參數(shù)是可選項(xiàng),是一個(gè)匿名的參數(shù)對(duì)象,該參數(shù)對(duì)象是一組屬性與值,該對(duì)象的屬性名稱將是新創(chuàng)建的對(duì)象的屬性名稱,值是屬性描述符(包擴(kuò)數(shù)據(jù)描述符或存取描述符,具體解釋看后面的內(nèi)容 什么是屬性描述符)。
通過(guò)屬性描述符我們可以實(shí)現(xiàn)為新創(chuàng)建的對(duì)象添加 get 方法以及 set 方法

(function () {
  var o = null;
  o = Object.create(Object.prototype,//指定原型為 Object.prototype
      {
        bar:{
          get :function(){
            return 10;
          },
          set : function (val) {
            console.log("Setting `o.bar` to ",val);
          }
        }
      }//第二個(gè)參數(shù)
    );
  console.log(o.bar);
  o.bar = 12;
})();

在 chrome 中調(diào)試試圖如下:

如何使用getter與setter方法添加JS對(duì)象

可以看到新創(chuàng)建對(duì)象通用多了 get 以及 set 屬性
輸出結(jié)果如下:

如何使用getter與setter方法添加JS對(duì)象

上面這個(gè)例子并沒(méi)有用來(lái)針對(duì)的 get 方法以及 set 方法使用的屬性

(function () {
  var o = null;
  o = Object.create(Object.prototype,//指定原型為 Object.prototype
      {
        bar:{
          get :function(){
            return this.a;
          },
          set : function (val) {
            console.log("Setting `o.bar` to ",val);
            this.a = val;
          },
          configurable :true
        }
      }//第二個(gè)參數(shù)
    );
  o.a = 10;
  console.log(o.bar);
  o.bar = 12;
  console.log(o.bar);
})();

亦或:

(function () {
  var o = {a:10};
  o = Object.create(o,//指定原型為 o 這里實(shí)際可以理解為繼承
      {
        bar:{
          get :function(){
            return this.a;
          },
          set : function (val) {
            console.log("Setting `o.bar` to ",val);
            this.a = val;
          },
          configurable :true
        }
      }//第二個(gè)參數(shù)
    );
  console.log(o.bar);
  o.bar = 12;
  console.log(o.bar);
})();

輸出結(jié)果如下:

如何使用getter與setter方法添加JS對(duì)象

使用這種方式的好處是可配置性高,但初學(xué)者容易迷糊。

3.使用 Object.defineProperty 方法

引用 MDN:

概要
Object.defineProperty() 方法直接在一個(gè)對(duì)象上定義一個(gè)新屬性,或者修改一個(gè)已經(jīng)存在的屬性, 并返回這個(gè)對(duì)象。
語(yǔ)法
Object.defineProperty(obj, prop, descriptor)
參數(shù)
obj
需要定義屬性的對(duì)象。
prop
需被定義或修改的屬性名。
descriptor
需被定義或修改的屬性的描述符。

(function () {
  var o = { a : 1}//聲明一個(gè)對(duì)象,包含一個(gè) a 屬性,值為1
  Object.defineProperty(o,"b",{
    get: function () {
      return this.a;
    },
    set : function (val) {
      this.a = val;
    },
    configurable : true
  });

  console.log(o.b);
  o.b = 2;
  console.log(o.b);
})();

這個(gè)方法與前面兩種的區(qū)別是:使用前面兩種只能在聲明定義的時(shí)候指定 getter 與 setter,使用該方法可以隨時(shí)的添加或修改。

如果說(shuō)需要一次性批量添加 getter 與 setter 也是沒(méi)問(wèn)題的,使用如下方法:

4.使用 Object.defineProperties方法

MDN:

概述
Object.defineProperties() 方法在一個(gè)對(duì)象上添加或修改一個(gè)或者多個(gè)自有屬性,并返回該對(duì)象。
語(yǔ)法
Object.defineProperties(obj, props)
參數(shù)
obj
將要被添加屬性或修改屬性的對(duì)象
props
該對(duì)象的一個(gè)或多個(gè)鍵值對(duì)定義了將要為對(duì)象添加或修改的屬性的具體配置

不難看出用法與 Object.defineProperty 方法類似

(function () {
  var obj = {a:1,b:"string"};
  Object.defineProperties(obj,{
    "A":{
      get:function(){return this.a+1;},
      set:function(val){this.a = val;}
    },
    "B":{
      get:function(){return this.b+2;},
      set:function(val){this.b = val}
    }
  });

  console.log(obj.A);
  console.log(obj.B);
  obj.A = 3;
  obj.B = "hello";
  console.log(obj.A);
  console.log(obj.B);
})();

輸出結(jié)果如下:

如何使用getter與setter方法添加JS對(duì)象

5.使用 Object.prototype.__defineGetter__ 以及 Object.prototype.__defineSetter__ 方法

(function () {
  var o = {a:1};
  o.__defineGetter__("giveMeA", function () {
    return this.a;
  });
  o.__defineSetter__("setMeNew", function (val) {
    this.a = val;
  })
  console.log(o.giveMeA);
  o.setMeNew = 2;
  console.log(o.giveMeA);
})();

輸出結(jié)果為1和2
查看 MDN 有如下說(shuō)明:

如何使用getter與setter方法添加JS對(duì)象

什么是屬性描述符

MDN:

對(duì)象里目前存在的屬性描述符有兩種主要形式:數(shù)據(jù)描述符和存取描述符。

  1. 數(shù)據(jù)描述符是一個(gè)擁有可寫(xiě)或不可寫(xiě)值的屬性。

  2. 存取描述符是由一對(duì) getter-setter 函數(shù)功能來(lái)描述的屬性。

  3. 描述符必須是兩種形式之一;不能同時(shí)是兩者。

數(shù)據(jù)描述符和存取描述符均具有以下可選鍵值:

configurable
當(dāng)且僅當(dāng)這個(gè)屬性描述符值為 true 時(shí),該屬性可能會(huì)改變,也可能會(huì)被從相應(yīng)的對(duì)象刪除。默認(rèn)為 false。
enumerable
true 當(dāng)且僅當(dāng)該屬性出現(xiàn)在相應(yīng)的對(duì)象枚舉屬性中。默認(rèn)為 false。

數(shù)據(jù)描述符同時(shí)具有以下可選鍵值:

value
與屬性相關(guān)的值。可以是任何有效的 JavaScript 值(數(shù)值,對(duì)象,函數(shù)等)。默認(rèn)為 undefined。
writable
true 當(dāng)且僅當(dāng)可能用 賦值運(yùn)算符 改變與屬性相關(guān)的值。默認(rèn)為 false。

存取描述符同時(shí)具有以下可選鍵值:

get
一個(gè)給屬性提供 getter 的方法,如果沒(méi)有 getter 則為 undefined。方法將返回用作屬性的值。默認(rèn)為 undefined。
set
一個(gè)給屬性提供 setter 的方法,如果沒(méi)有 setter 則為 undefined。該方法將收到作為唯一參數(shù)的新值分配給屬性。默認(rèn)為 undefined。

以上是摘自MDN的解釋,看起來(lái)是很晦澀的,具體什么意思呢:
首先我們從以上解釋知道該匿名參數(shù)對(duì)象有個(gè)很好聽(tīng)的名字叫屬性描述符,屬性描述符又分成兩大塊:數(shù)據(jù)描述符以及存取描述符(其實(shí)只是一個(gè)外號(hào),給指定的屬性集合起個(gè)外號(hào))。

數(shù)據(jù)描述符包括兩個(gè)屬性 : value 屬性以及 writable 屬性,第一個(gè)屬性用來(lái)聲明當(dāng)前欲修飾的屬性的值,第二個(gè)屬性用來(lái)聲明當(dāng)前對(duì)象是否可寫(xiě)即是否可以修改

存取描述符就包括 get 與 set 屬性用來(lái)聲明欲修飾的象屬性的 getter 及 setter

屬性描述符內(nèi)部,數(shù)據(jù)描述符與存取描述符只能存在其中之一,但是不論使用哪個(gè)描述符都可以同時(shí)設(shè)置 configurable 屬性以及enumerable 屬性。
configurable屬性用來(lái)聲明欲修飾的屬性是否能夠配置,僅有當(dāng)其值為 true 時(shí),被修飾的屬性才有可能能夠被刪除,或者重新配置。
enumerable 屬性用來(lái)聲明欲修飾屬性是否可以被枚舉。

知道了什么是屬性描述符,我們就可以開(kāi)始著手創(chuàng)建一些對(duì)象并開(kāi)始配置其屬性

創(chuàng)建屬性不可配置不可枚舉的對(duì)象

//使用默認(rèn)值配置
(function () {
  var obj = {};//聲明一個(gè)空對(duì)象
  Object.defineProperty(obj,"key",{
    value:"static"
            //沒(méi)有設(shè)置 enumerable 使用默認(rèn)值 false
            //沒(méi)有 configurable 使用默認(rèn)值 false
            //沒(méi)有 writable 使用默認(rèn)值 false
  });

  console.log(obj.key);      //輸出 “static”
  obj.key = "new"         //嘗試修改其值,修改將失敗,因?yàn)?nbsp;writable 為 false
  console.log(obj.key);      //輸出 “static”
  obj.a = 1;//動(dòng)態(tài)添加一個(gè)屬性
  for(var item in obj){ //遍歷所有 obj 的可枚舉屬性
     console.log(item);
  }//只輸出一個(gè) “a” 因?yàn)?nbsp;“key”的 enumerable為 false
})();
//顯示配置 等價(jià)于上面
(function () {
  var obj = {};
  Object.defineProperty(obj,"key",{
    enumerable : false,
    configurable : false,
    writable : false,
    value : "static"
  })
})();
//等價(jià)配置
(function () {
  var o = {};
  o.a = 1;
  //等價(jià)于
  Object.defineProperty(o,"a",{value : 1,
                writable : true,
                configurable : true,
                enumerable : true});
  
  Object.defineProperty(o,"a",{value :1});
  //等價(jià)于
  Object.defineProperty(o,"a",{value : 1,
                writable : false,
                configurable : false,
                enumerable : false});
})();

Enumerable 特性
屬性特性 enumerable 決定屬性是否能被 for...in 循環(huán)或 Object.keys 方法遍歷得到

(function () {
  var o = {};
  Object.defineProperty(o,"a",{value :1,enumerable :true});
  Object.defineProperty(o,"b",{value :2,enumerable :false});
  Object.defineProperty(o,"c",{value :2});//enumerable default to false
  o.d = 4;//如果直接賦值的方式創(chuàng)建對(duì)象的屬性,則這個(gè)屬性的 enumerable 為 true

  for(var item in o){ //遍歷所有可枚舉屬性包括繼承的屬性
    console.log(item);
  }

  console.log(Object.keys(o));//獲取 o 對(duì)象的所有可遍歷屬性不包括繼承的屬性

  console.log(o.propertyIsEnumerable('a'));//true
  console.log(o.propertyIsEnumerable('b'));//false
  console.log(o.propertyIsEnumerable('c'));//false
})();

輸出結(jié)果如下:

如何使用getter與setter方法添加JS對(duì)象

Configurable 特性

(function () {
  var o = {};
  Object.defineProperty(o,"a",{get: function () {return 1;},
                configurable : false} );
                //enumerable 默認(rèn)為 false,
                //value 默認(rèn)為 undefined,
                //writable 默認(rèn)為 false,
                //set 默認(rèn)為 undefined
                 
  //拋出異常,因?yàn)樽铋_(kāi)始定義了 configurable 為 false,故后期無(wú)法對(duì)其進(jìn)行再配置
  Object.defineProperty(o,"a",{configurable : true} );
  //拋出異常,因?yàn)樽铋_(kāi)始定義了 configurable 為 false,故后期無(wú)法對(duì)其進(jìn)行再配置,enumerable 的原值為 false
  Object.defineProperty(o,"a",{enumerable : true} );
  //拋出異常,因?yàn)樽铋_(kāi)始定義了 configurable 為 false,set的原值為 undefined
  Object.defineProperty(o,"a",{set : function(val){}} );
  //拋出異常,因?yàn)樽铋_(kāi)始定義了 configurable 為 false,故無(wú)法進(jìn)行覆蓋,盡管想用一樣的來(lái)覆蓋
  Object.defineProperty(o,"a",{get : function(){return 1}});
  //拋出異常,因?yàn)樽铋_(kāi)始定義了 configurable 為 false,故無(wú)法將其進(jìn)行重新配置把屬性描述符從存取描述符改為數(shù)據(jù)描述符
  Object.defineProperty(o,"a",{value : 12});

  console.log(o.a);//輸出1
  delete o.a;   //想要?jiǎng)h除屬性,將失敗
  console.log(o.a);//輸出1
  
})();

提高及擴(kuò)展
1.屬性描述符中容易被誤導(dǎo)的地方之 writable 與 configurable

(function () {
  var o = {};
  Object.defineProperties(o,{
    "a": {
      value:1,
      writable:true,//可寫(xiě)
      configurable:false//不可配置
      //enumerable 默認(rèn)為 false 不可枚舉
    },
    "b":{
      get :function(){
        return this.a;
      },
      configurable:false
    }
  });
  console.log(o.a);  //1
  o.a = 2;      //修改值成功,writable 為 true
  console.log(o.a);  //2
  Object.defineProperty(o,"a",{value:3});//同樣為修改值成功
  console.log(o.a);  //3

  //將其屬性 b 的屬性描述符從存取描述符重新配置為數(shù)據(jù)描述符
  Object.defineProperty(o,"b",{value:3});//拋出異常,因?yàn)?nbsp;configurable 為 false
})();

2.通過(guò)上面的學(xué)習(xí),我們都知道傳遞屬性描述符參數(shù)時(shí),是定義一個(gè)匿名的對(duì)象,里面包含屬性描述符內(nèi)容,若每定義一次便要?jiǎng)?chuàng)建一個(gè)匿名對(duì)象傳入,將會(huì)造成內(nèi)存浪費(fèi)。故優(yōu)化如下:

(function () {
  var obj = {};

  //回收同一對(duì)象,即減少內(nèi)存浪費(fèi)
  function withValue(value){
    var d = withValue.d ||(
      withValue.d = {
        enumerable : false,
        configurable : false,
        writable : false,
        value :null
      }
      );
    d.value = value;
    return d;
  }
  Object.defineProperty(obj,"key",withValue("static"))
})();

關(guān)于如何使用getter與setter方法添加JS對(duì)象就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,可以學(xué)到更多知識(shí)。如果覺(jué)得文章不錯(cuò),可以把它分享出去讓更多的人看到。

另外有需要云服務(wù)器可以了解下創(chuàng)新互聯(lián)scvps.cn,海內(nèi)外云服務(wù)器15元起步,三天無(wú)理由+7*72小時(shí)售后在線,公司持有idc許可證,提供“云服務(wù)器、裸金屬服務(wù)器、高防服務(wù)器、香港服務(wù)器、美國(guó)服務(wù)器、虛擬主機(jī)、免備案服務(wù)器”等云主機(jī)租用服務(wù)以及企業(yè)上云的綜合解決方案,具有“安全穩(wěn)定、簡(jiǎn)單易用、服務(wù)可用性高、性價(jià)比高”等特點(diǎn)與優(yōu)勢(shì),專為企業(yè)上云打造定制,能夠滿足用戶豐富、多元化的應(yīng)用場(chǎng)景需求。

本文名稱:如何使用getter與setter方法添加JS對(duì)象-創(chuàng)新互聯(lián)
本文URL:http://www.bm7419.com/article20/dgcgco.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供面包屑導(dǎo)航、域名注冊(cè)、商城網(wǎng)站品牌網(wǎng)站設(shè)計(jì)、自適應(yīng)網(wǎng)站、電子商務(wù)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

網(wǎng)站優(yōu)化排名