Vue2.X和MobX中的Object.defineProperty淳地,并與Proxy的對比

如題商模,Vue是一個js框架渠脉,MobX則是React進(jìn)行狀態(tài)管理的一個庫焚刚,兩者看起來并沒有什么關(guān)聯(lián)劝评,但是由于都使用了Object.defineProperty感局,使得兩者在數(shù)據(jù)綁定操作上不禁有些相似

由于Vue3.X已經(jīng)用Proxy重寫了他的數(shù)據(jù)綁定機(jī)制环疼,所以順帶了解一下Proxy

本文介紹了什么

  • Object.defineProperty與Proxy的使用
  • Object.defineProperty與Proxy的缺點(diǎn)
  • Object.defineProperty在Vue和MobX中造成的問題和解決辦法

Object.defineProperty與Proxy的使用

Object.defineProperty Object.defineProperty - MDN
/*
* obj : 要定義屬性的對象
* prop : 要定義或修改的屬性的名稱或 [`Symbol`]
* descriptor : 要定義或修改的屬性描述符
*    value: 該屬性對應(yīng)的值
*    writable
*    enumerable
*    configurable
*    get
*    set
*/
var o = {};
Object.defineProperty(o, "a", {
  value : 37,
  writable : true,
  enumerable : true,
  configurable : true,
  get: function () {},
  set: function () {}
});

在 descriptor 中不能 同時設(shè)置訪問器 (get 和 set) 和 wriable 或 value娩井,否則會錯设江,就是說想用(get 和 set)锦茁,就不能用(wriable 或 value中的任何一個)

Proxy Proxy - MDN

es6 Proxy - 阮一峰

const proxy = new Proxy({}, {
  get: function(target, key, receiver) {
    return receiver;
  }
});

const d = Object.create(proxy);
d.a === d // true
//d對象本身沒有a屬性,所以讀取d.a的時候叉存,會去d的原型proxy對象找码俩。
//這時,receiver就指向d歼捏,代表原始的讀操作所在的那個對象
});

get和set方法中的receiver參數(shù)參考Proxy get中的receiver問題

小結(jié)
  • Object.defineProperty是直接對原始對象進(jìn)行操作并返回稿存,Proxy是進(jìn)行一個類似多例的操作够傍,不會影響原始對象
  • Object.defineProperty的屬性較少,Proxy對數(shù)據(jù)劫持對handler方法較多挠铲,但兩者都有最基礎(chǔ)的get和set

Object.defineProperty與Proxy的缺點(diǎn)

Object.defineProperty的缺點(diǎn)

因?yàn)閐efineProperty的屬性限制冕屯,導(dǎo)致了三個問題
1、無法監(jiān)聽到數(shù)組的長度變化
2拂苹、由于只能劫持對象的屬性安聘,對于復(fù)雜對象需要對每個屬性進(jìn)行深度遍歷
3、由于只能劫持對象的屬性瓢棒,對象屬性有新增時浴韭,需要將對象的所有屬性都進(jìn)行遍歷進(jìn)行監(jiān)聽
為什么defineProperty不能檢測到數(shù)組長度的“變化”

數(shù)組的length屬性被初始化為如下
configurable為false也就是說length屬性不能修改,不能刪除脯宿,所以想我們想要通過get/set方法來監(jiān)聽length屬性是不可行的

{
  writable: true,
  enumerable: false,
  configurable: false,
}

驗(yàn)證對象新增的屬性在definproperty中能否被監(jiān)聽

let person = Object.defineProperty({age: 20}, 'name', {
    get: function() {
        console.log('get!!!');
        return name;
    },
    set: function(newName) {
        console.log('set!!!');
        name = newName;
    },
    enumerable: true,
    configurable: true
});
person.name; // 'get!!!'  'piers'
person.name = 'zhangpeng' // 'set!!!'  'zhangpeng'
person.age; //   'piers' 此時不會被get監(jiān)聽
person.age = '30'; // '30' 此時不會被set監(jiān)聽
Proxy的缺點(diǎn)
  • 由于是es6的特性念颈,所以存在瀏覽器兼容性問題
小結(jié)
  • Object.defineProperty有三個缺點(diǎn)
    1、無法監(jiān)聽到數(shù)組的長度變化
    2连霉、由于只能劫持對象的屬性榴芳,對于復(fù)雜對象需要對每個屬性進(jìn)行深度遍歷
    3、由于只能劫持對象的屬性跺撼,對象屬性有新增時窟感,需要將對象的所有屬性都進(jìn)行遍歷進(jìn)行監(jiān)聽
  • Proxy有一個缺點(diǎn)
    1、存在瀏覽器兼容性問題

Object.defineProperty在Vue和MobX中造成的問題

由于Object.defineProperty的三個缺點(diǎn)歉井,在Vue中有如下問題

// 在Vue中這種數(shù)組操作和對象操作柿祈,不會被Vue監(jiān)聽到
let vm1 = new Vue({
  data: {
     list: [1, 2, 3, 4]
  }
})
let vm2 = new Vue({
  data: {
    a: 1
  }
})
vm1.list[index] = newValue // 非響應(yīng)式的
vm1.list.length = newLength  // 非響應(yīng)式的
vm2.a = 2 // `vm.a` 是響應(yīng)式的
vm2.b = 2 // `vm.b` 是非響應(yīng)式的

對于Object.defineProperty的三個缺點(diǎn),我們一次來看Vue和MobX是如何進(jìn)行處理的

1哩至、無法監(jiān)聽數(shù)組長度屬性變化的問題
  • Vue重寫了push躏嚎、pop、shift菩貌、unshift卢佣、splice、sort菜谣、reverse這七個數(shù)組方法珠漂,是的這些方法可以響應(yīng)式晚缩,參考Vue文檔說明
  • MobX則是會在定義的時候尾膊,默認(rèn)把類數(shù)組長度預(yù)留999個單位
    這樣其實(shí)不會對性能有損耗,因?yàn)閖s中對數(shù)據(jù)的遍歷除了for循環(huán)還有forEach荞彼、map冈敛、filter、some等鸣皂,除了for循環(huán)外(for,for...of)抓谴,其他的遍歷都是對鍵值的遍歷
let arr = [1];
arr[1000] = 1;
function a () {
  console.time();
  for(let i = 0; i < arr.length; i++) {
    console.log(arr[i]);
  }
}
function b () {
  console.time();
  arr.forEach((item) => {
    console.log(item);
  })
}
a(); //default: 567.1669921875ms
b(); //default: 0.81982421875ms
2暮蹂、需要對對象的深層屬性或者新增屬性進(jìn)行遍歷,達(dá)到監(jiān)聽的目的

總結(jié)

  • Object.defineProperty與Proxy的使用上的區(qū)別
    1集侯、Object.defineProperty是直接對原始對象進(jìn)行操作并返回,Proxy是進(jìn)行一個類似多例的操作帜消,不會影響原始對象
    2棠枉、Object.defineProperty的屬性較少,Proxy對數(shù)據(jù)劫持對handler方法較多泡挺,但兩者都有最基礎(chǔ)的get和set辈讶,可以將Proxy看成是Object.defineProperty的加強(qiáng)版
  • Object.defineProperty與Proxy的缺點(diǎn)
    1、Object.defineProperty無法監(jiān)聽到數(shù)組的長度變化
    2娄猫、Object.defineProperty由于只能劫持對象的屬性贱除,對于復(fù)雜對象需要對每個屬性進(jìn)行深度遍歷
    3、Object.defineProperty由于只能劫持對象的屬性媳溺,對象屬性有新增時勘伺,需要將對象的所有屬性都進(jìn)行遍歷進(jìn)行監(jiān)聽
    4、Proxy存在瀏覽器兼容性問題
  • Object.defineProperty在Vue和MobX中造成的問題和解決辦法
    1褂删、Vue通過重寫數(shù)據(jù)的七個方法飞醉,MobX通過提前將類數(shù)組聲明為長度999,避免無法監(jiān)聽數(shù)組長度的問題
    2屯阀、Vue和MobX都是用遍歷的方式來監(jiān)聽深層對象屬性和新增的屬性
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末缅帘,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子难衰,更是在濱河造成了極大的恐慌钦无,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,602評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件盖袭,死亡現(xiàn)場離奇詭異失暂,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)鳄虱,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,442評論 2 382
  • 文/潘曉璐 我一進(jìn)店門弟塞,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人拙已,你說我怎么就攤上這事决记。” “怎么了倍踪?”我有些...
    開封第一講書人閱讀 152,878評論 0 344
  • 文/不壞的土叔 我叫張陵系宫,是天一觀的道長索昂。 經(jīng)常有香客問我,道長扩借,這世上最難降的妖魔是什么椒惨? 我笑而不...
    開封第一講書人閱讀 55,306評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮潮罪,結(jié)果婚禮上框产,老公的妹妹穿的比我還像新娘。我一直安慰自己错洁,他們只是感情好秉宿,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,330評論 5 373
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著屯碴,像睡著了一般描睦。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上导而,一...
    開封第一講書人閱讀 49,071評論 1 285
  • 那天忱叭,我揣著相機(jī)與錄音,去河邊找鬼今艺。 笑死韵丑,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的虚缎。 我是一名探鬼主播撵彻,決...
    沈念sama閱讀 38,382評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼实牡!你這毒婦竟也來了陌僵?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,006評論 0 259
  • 序言:老撾萬榮一對情侶失蹤创坞,失蹤者是張志新(化名)和其女友劉穎碗短,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體题涨,經(jīng)...
    沈念sama閱讀 43,512評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡偎谁,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,965評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了纲堵。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片巡雨。...
    茶點(diǎn)故事閱讀 38,094評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖婉支,靈堂內(nèi)的尸體忽然破棺而出鸯隅,到底是詐尸還是另有隱情,我是刑警寧澤向挖,帶...
    沈念sama閱讀 33,732評論 4 323
  • 正文 年R本政府宣布蝌以,位于F島的核電站,受9級特大地震影響何之,放射性物質(zhì)發(fā)生泄漏跟畅。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,283評論 3 307
  • 文/蒙蒙 一溶推、第九天 我趴在偏房一處隱蔽的房頂上張望徊件。 院中可真熱鬧,春花似錦蒜危、人聲如沸虱痕。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,286評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽部翘。三九已至,卻和暖如春响委,著一層夾襖步出監(jiān)牢的瞬間新思,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,512評論 1 262
  • 我被黑心中介騙來泰國打工赘风, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留夹囚,地道東北人。 一個月前我還...
    沈念sama閱讀 45,536評論 2 354
  • 正文 我出身青樓邀窃,卻偏偏與公主長得像荸哟,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子瞬捕,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,828評論 2 345

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