js對象的深入理解(四-----精華篇)

本篇將講解js對象的存取器,介紹兩個重要的對象方法

為什么vue不兼容IE8匈勋,因為IE8不兼容ESMAScript5包帚,Vue會將對象所有的屬性遍歷,使用Object.defineProperty把這些屬性全部轉(zhuǎn)為getter/setter.(存儲器)

在ES5中镊叁,對象的屬性值可以用一個或兩個方法代替,這兩個方法就是getter和setter走触,由getter和setter定義的屬性被稱為存取器屬性 晦譬,它不同于數(shù)據(jù)屬性,數(shù)據(jù)屬性只有一個簡單的值

當(dāng)我們查詢存取器屬性的值時互广,JavaScript調(diào)用getter方法(無參數(shù))敛腌。這個方法的返回值就是屬性存取表達(dá)式的值,將賦值表達(dá)式返回的值當(dāng)成參數(shù)傳入setter

我們之前提過對象的屬性特性惫皱,比如可寫可讀像樊,如果一個屬性同事時具有g(shù)etter|和setter方法,那么這個屬性就是一個讀/寫屬性旅敷,如果只有g(shù)etter 只有setter 就曉得了吧

getter和setter

我們簡單來看看如何使用

    var obj = {
    get p() {
        return 'getter';
    },
    set p(value) {
        console.log('setter: ' + value);
        return value
    }
    }
    console.log(obj.p) //getter
    console.log(obj.p=20) //setter:20

從這里我們能看出生棍,首先調(diào)用屬性會觸發(fā)對象的getter方法,設(shè)置屬性會觸發(fā)對象的setter方法媳谁,而且setter方法是可以全局操作的涂滴,我們看下面這個例子

    var b=10
    var that=this
    var obj = {
    get p() {
        return 'getter';
    },
    set p(value) {
        that.b=value
        return value
    }
    }
    obj.p=20
    console.log(b)//20

最簡單的運用

    var a={
        _age:18,//通過改變age判斷方法的觸發(fā)
        get age(){
            console.log('get')
            return this._age //getter方法沒有參數(shù)
        },
        set age(val){ //參數(shù)就是我們改變數(shù)據(jù)的操作
            console.log('set')
            return this._age=val
        }
    }
    console.log(a.age) //18 get
    a.age=21
    console.log(a.age) //21 set
我們再來聊聊對象的屬性特性,對象的四個特性晴音,可讀性(value)柔纵,可寫性(writable),可枚舉性(enumerable)锤躁,可配置性(configurable)搁料,這幾個單詞可以稍微加點印象,指不定哪天你在瀏覽文檔的時候就能翻到這幾個單詞系羞,比如undefined

我們之前就說過加缘,undefined是JavaScript的一個全局屬性
好,任何一個對象都有以上的屬性觉啊,Object也為我們提供了方法用來判斷

      var a={x:1}
      var b = Object.getOwnPropertyDescriptor(a,'x')
      console.log(b)  //{value: 1, writable: true, enumerable: true, configurable: true}

我們用存取器試試

    var a={
        _age:18,//通過改變age判斷方法的觸發(fā)
        get age(){
            console.log('get')
            return this._age //getter方法沒有參數(shù)
        },
        set age(val){ //參數(shù)就是我們改變數(shù)據(jù)的操作
            console.log('set')
            return this._age=val
        }
    }
    console.log(Object.getOwnPropertyDescriptor(a,'age')) //{set: undefined, enumerable: true, configurable: true, get: ?}

如果未設(shè)置getter setter方法對應(yīng)的就是undefined拣宏,相當(dāng)于get代替了value,set代替了writable杠人,繼承的屬性或者是不存在的屬性都將返回undefined勋乾,了解一下

接下來我們講一下對象兩個重要的方法,雖然說重要不過可能很多小伙伴沒見過

Object.defineProperties()和Object.defineProperty()

這兩個方法有點像哈嗡善,英語小王子一眼就能看出來單復(fù)數(shù)了哈

Object的defineProperty和defineProperties這兩個方法在js中的重要性十分重要辑莫,主要功能就是用來定義或修改這些內(nèi)部屬性,與之相對應(yīng)的getOwnPropertyDescriptor和getOwnPropertyDescriptors就是獲取這行內(nèi)部屬性的描述。后面兩個就不多做描述了

我們都知道vue雙向綁定原理就是Object.definePriperty()方法罩引,我們先看看Object.defineProperties()各吨,今天將以實現(xiàn)簡單的雙向綁定原理結(jié)束(還好今天UI小姐姐沒讓我改bug)

Object.definProperties()

功能:
方法直接在一個對象上定義一個或多個新的屬性或修改現(xiàn)有屬性,并返回該對象袁铐。
語法: Object.defineProperties(obj, props)

obj: 將要被添加屬性或修改屬性的對象
props: 該對象的一個或多個鍵值對定義了將要為對象添加或修改的屬性的具體配置(簡單來說就是映射表---看代碼就懂)

     var obj = new Object();
    Object.defineProperties(obj, {
        name: {
            value: '張三',
            configurable: false,
            writable: true,
            enumerable: true
        },
        age: {
            value: 18,
            configurable: true
        }
    })
    console.log(obj.name, obj.age) // 張三, 18

很容易理解哈揭蜒,然后我們看到我給age只設(shè)置了兩個屬性横浑,可讀可配置,我們來改一下看看行不行

     var obj = new Object();
    Object.defineProperties(obj, {
        name: {
            value: '張三',
            configurable: false,
            writable: true,
            enumerable: true
        },
        age: {
            value: 18,
            configurable: true
        }
    })
    obj.age=20
    console.log(obj.age) // 18  很明顯這是不可以滴

我們使用Object.getOwnPropertyDescriptor()方法看看屬性特性

     var obj = new Object();
    Object.defineProperties(obj, {
        name: {
            value: '張三',
            configurable: false,
            writable: true,
            enumerable: true
        },
        age: {
            value: 18,
            configurable: true
        }
    })
    var person = {
        name: '張三',
        age: 18
    }
    var desc = Object.getOwnPropertyDescriptor(obj, 'age'); 
    console.log(desc)   //obj.html:33 {value: 18, writable: false, enumerable: false, configurable: true}

沒配置的為false

    var person = {
        name: '張三',
        age: 18
    }
    var desc = Object.getOwnPropertyDescriptor(person, 'age'); 
    console.log(desc)  //{value: 18, writable: true, enumerable: true, configurable: true}

我們常用的對象操作屉更,默認(rèn)屬性都是true

之前介紹了delete 刪除對象屬性徙融,也就是configurable為ture是可以刪除的

    delete obj.age
    console.log(obj.age) //undefined   嚴(yán)格模式下出錯 非嚴(yán)格模式下可以運行

那么Object.defineProperties(obj, props)也是可以使用存取器了

     var obj = new Object();
    Object.defineProperties(obj, {
        name: {
            value: '張三',
            configurable: false,
            writable: true,
            enumerable: true
        },
        age: {
            value: 18,
            configurable: true
        },
        sex:{
            get(){
                return 'nan'
            }
        }
    })
    console.log(obj.sex) // nan

當(dāng)然也是可以配置屬性特性

        sex:{
            get(){
                return 'nan'
            },
            configurable: false,
            writable: true,
            enumerable: true
        }

這個方法還是很強(qiáng)大的,我們可以根據(jù)需要更改特性瑰谜,比如下方這個例子

    var obj={
        c:10
    }
    Object.defineProperties(obj, {
        name: {
            value: '張三',
            configurable: false,
            writable: true,
            enumerable: true
        },
        age: {
            value: 18,
            configurable: true
        },
        c:{          
            writable:false
        }

    })
    obj.c=20
    console.log(obj.c) // 10 設(shè)置成無法修改了

Object.defineProperty()

功能:
方法會直接在一個對象上定義一個新屬性欺冀,或者修改一個對象的現(xiàn)有屬性, 并返回這個對象萨脑。如果不指定configurable, writable, enumerable 隐轩,則這些屬性默認(rèn)值為false,如果不指定value, get, set渤早,則這些屬性默認(rèn)值為undefined

語法:Object.defineProperty(obj, prop, descriptor)
obj: 需要被操作的目標(biāo)對象
prop: 目標(biāo)對象需要定義或修改的屬性的名稱
descriptor: 將被定義或修改的屬性的描述符

    var obj={

        c:10
    }
    Object.defineProperties(obj, {
        name: {
            value: '張三',
            configurable: false,
            writable: true,
            enumerable: true
        },
        age: {
            value: 18,
            configurable: true
        },

        c:{
            writable:false
        }

    })
    Object.defineProperty(obj,'c',{value:20})
    console.log(obj.c) //20

這樣就可以更改值了职车,哪怕你是不可寫的,當(dāng)然這是在可配置的情況下

     c:{
            writable:false,
            configurable: false
        }

如果是不可配置的蛛芥,就會報錯注意一下
Object.defineProperty配置的對象是不可枚舉的

    var obj={ 
    }
    Object.defineProperty(obj,'c',{value:20})
    for(var index in obj){
       console.log(index)  // kong
    }
   console.log(obj.c)// 20

但是可以取到這個屬性哦

    var obj={
        c:10
    }
    Object.defineProperty(obj,'c',{writable:false})
    obj.c=20
    console.log(obj.c)// 10

很多方法在嚴(yán)格模式下是會報錯的提鸟,如果我們已經(jīng)設(shè)置了不可寫做出修改操作,在嚴(yán)格模式下會報錯仅淑,這三個參數(shù)都是必填称勋,第三個參數(shù)寫個{}也行,不能不寫

兩種方法還是很類似的涯竟,當(dāng)然啦 也有這兩種方法沒辦法為所欲為的時候赡鲜,簡單介紹一下對象的屬性

原型屬性

這個我們快速過,之前我們講的Object.create()就是很好的代表

類屬性

對象的類屬性是個字符串庐船,用來表示對象的類型信息银酬,然而ES3與ES5都未設(shè)置這個屬性的方法,有一種間接的方法可以查詢到它

   function classof(obj){
    
    if(obj==null){
        return 'Null'
    }
    if(obj==undefined){
        return "Undefined"
    }
    return Object.prototype.toString.call(obj).slice(8,-1) //字符串過濾
   }
   console.log(classof(null)) //Null
   console.log(classof(1)) //Number
   console.log(classof("")) //String
   console.log(classof(false)) //Boolean
   console.log(classof(/./))  //RegExp

toString() 是 Object 的原型方法筐钟,調(diào)用該方法揩瞪,默認(rèn)返回當(dāng)前對象的 [[Class]] 。這是一個內(nèi)部屬性篓冲,其格式為 [object Xxx] 李破,其中 Xxx 就是對象的類型。我把前面的內(nèi)容去了更明了

可擴(kuò)展性

對象的可擴(kuò)展性用以表示是否可以給對象添加新屬性壹将,非常強(qiáng)悍嗤攻,之前提到的兩個方法在這里只有瑟瑟發(fā)抖的份

        var a={
            b:10
        }
        console.log(Object.isExtensible(a)) //true

如果為true表明是可擴(kuò)展的
我們強(qiáng)力改變讓它不可擴(kuò)展

        var a={
            b:10
        }
        Object.preventExtensions(a) 
        console.log(Object.isExtensible(a)) //false

擴(kuò)展性用以表示是否可以給對象添加新屬性

        var a={
            b:10
        }
        a.c=20
        console.log(a.c) //20
        Object.preventExtensions(a)
        a.d=30
        console.log(a.d) //undefined

我們使用defineProperty嘗試一下

        var a={
            b:10
        }
        a.c=20
        console.log(a.c) //20
        Object.preventExtensions(a)
        a.d=30
        Object.defineProperty(a,'e',{value:40})
        console.log(a.d) //undefined
        console.log(a.e) //報錯 對象不可擴(kuò)展 

可擴(kuò)展性屬性的目的是將對象鎖定,防止外界的干擾诽俯,不過如果是繼承的屬性就沒法拒絕妇菱,爸爸給的東西不管好的壞的都得乖乖受著

簡單介紹一下可擴(kuò)展性,有興趣的可以去了解一下Object.seal()封閉,Object.freeze()凍結(jié)闯团,更兇殘

序列化對象

簡單提一下辛臊,序列化對象是指將對象的狀態(tài)轉(zhuǎn)成字符串,也可將字符串還原為對象偷俭。
就是我們常用的JSON.strstringify()和JSON.parse()轉(zhuǎn)字符串和轉(zhuǎn)對象
JSON的全稱就是 “JavaScript Object Notation”---------JavaScript對象表示法

我們寫個簡易的雙向綁定結(jié)束這篇js對象

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <meta http-equiv="Cache-Control" content="max-age=31536000">
        <meta http-equiv="X-UA-Compatible" content="ie=edge">
        <title>Document</title>
    </head>
    <body>
                <p>
                   <input type="text" id="input1">
                </p>
                <p>
                    <input type="text" id="input2">
                </p>

    </body>
    <script>
     
    var oIn1 = document.getElementById('input1');
    var oIn2 = document.getElementById('input2');
    var obj = {};
    Object.defineProperties(obj, { //我這邊用的是defineProperties 因為網(wǎng)上大多都是defineProperty 希望小伙伴有個區(qū)別
        val1: {
            configurable: true,
            get: function() {
                oIn1.value = '';  //初始定義 為空
                oIn2.value = '';
                return ''
            },
            set: function(newValue) { // val1 改變的時候 給oIn2賦值
                oIn2.value = newValue;
            }
        },
        val2: {
            configurable: true,
            get: function() {
                oIn1.value = '';
                oIn2.value = '';
                return ''
            },
            set: function(newValue) {
                oIn1.value = newValue;
            }
        }
    })
    oIn1.value = obj.val1;  //調(diào)用getter 初始為''
    oIn1.oninput=function(){ //input事件不懂的可以百度一下
        obj.val1 = oIn1.value; //觸發(fā)set給in2賦值  
    }
    oIn2.oninput=function(){
     obj.val2 = oIn2.value;
    }
     </script>
    </html>

希望你可以理解浪讳,不懂歡迎留言

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末缰盏,一起剝皮案震驚了整個濱河市涌萤,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌口猜,老刑警劉巖负溪,帶你破解...
    沈念sama閱讀 217,826評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異济炎,居然都是意外死亡川抡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,968評論 3 395
  • 文/潘曉璐 我一進(jìn)店門须尚,熙熙樓的掌柜王于貴愁眉苦臉地迎上來崖堤,“玉大人,你說我怎么就攤上這事耐床∶茚#” “怎么了?”我有些...
    開封第一講書人閱讀 164,234評論 0 354
  • 文/不壞的土叔 我叫張陵撩轰,是天一觀的道長胯甩。 經(jīng)常有香客問我,道長堪嫂,這世上最難降的妖魔是什么偎箫? 我笑而不...
    開封第一講書人閱讀 58,562評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮皆串,結(jié)果婚禮上淹办,老公的妹妹穿的比我還像新娘。我一直安慰自己恶复,他們只是感情好怜森,可當(dāng)我...
    茶點故事閱讀 67,611評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著寂玲,像睡著了一般塔插。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上拓哟,一...
    開封第一講書人閱讀 51,482評論 1 302
  • 那天想许,我揣著相機(jī)與錄音,去河邊找鬼。 笑死流纹,一個胖子當(dāng)著我的面吹牛糜烹,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播漱凝,決...
    沈念sama閱讀 40,271評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼疮蹦,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了茸炒?” 一聲冷哼從身側(cè)響起愕乎,我...
    開封第一講書人閱讀 39,166評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎壁公,沒想到半個月后感论,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,608評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡紊册,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,814評論 3 336
  • 正文 我和宋清朗相戀三年比肄,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片囊陡。...
    茶點故事閱讀 39,926評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡芳绩,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出撞反,到底是詐尸還是另有隱情妥色,我是刑警寧澤,帶...
    沈念sama閱讀 35,644評論 5 346
  • 正文 年R本政府宣布痢畜,位于F島的核電站垛膝,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏丁稀。R本人自食惡果不足惜吼拥,卻給世界環(huán)境...
    茶點故事閱讀 41,249評論 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望线衫。 院中可真熱鬧凿可,春花似錦、人聲如沸授账。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,866評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽白热。三九已至敛助,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間屋确,已是汗流浹背纳击。 一陣腳步聲響...
    開封第一講書人閱讀 32,991評論 1 269
  • 我被黑心中介騙來泰國打工续扔, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人焕数。 一個月前我還...
    沈念sama閱讀 48,063評論 3 370
  • 正文 我出身青樓纱昧,卻偏偏與公主長得像,于是被迫代替她去往敵國和親堡赔。 傳聞我的和親對象是個殘疾皇子识脆,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,871評論 2 354

推薦閱讀更多精彩內(nèi)容