你了解vue3.0響應(yīng)式數(shù)據(jù)怎么實(shí)現(xiàn)嗎?

從 Proxy 說起

什么是Proxy

proxy翻譯過來的意思就是”代理“老虫,ES6對(duì)Proxy的定位就是target對(duì)象(原對(duì)象)的基礎(chǔ)上通過handler增加一層”攔截“祈匙,返回一個(gè)新的代理對(duì)象,之后所有在Proxy中被攔截的屬性,都可以定制化一些新的流程在上面洁闰,先看一個(gè)最簡(jiǎn)單的例子

const target = {}; // 要被代理的原對(duì)象
// 用于描述代理過程的handler
const handler = {
  get: function (target, key, receiver) {
    console.log(`getting ${key}!`);
    return Reflect.get(target, key, receiver);
  },
  set: function (target, key, value, receiver) {
    console.log(`setting ${key}!`);
    return Reflect.set(target, key, value, receiver);
  }}
// obj就是一個(gè)被新的代理對(duì)象
const obj = new Proxy(target, handler);
obj.a = 1 // setting a!
console.log(obj.a)// getting a!

上面的例子中我們?cè)趖arget對(duì)象上架設(shè)了一層handler扑眉,其中攔截了針對(duì)target的get和set腰素,然后我們就可以在get和set中間做一些額外的操作了

注意1:對(duì)Proxy對(duì)象的賦值操作也會(huì)影響到原對(duì)象target弓千,同時(shí)對(duì)target的操作也會(huì)影響Proxy献起,不過直接操作原對(duì)象的話不會(huì)觸發(fā)攔截的內(nèi)容~

obj.a = 1; // setting a!
console.log(target.a) // 1 不會(huì)打印 "getting a!"

注意2:如果handler中沒有任何攔截上的處理,那么對(duì)代理對(duì)象的操作會(huì)直接通向原對(duì)象

const target = {};
const handler = {};
const obj = new Proxy(target, handler);
obj.a = 1;
console.log(target.a) // 1

既然proxy也是一個(gè)對(duì)象呆抑,那么它就可以做為原型對(duì)象汁展,所以我們把obj的原型指向到proxy上后食绿,發(fā)現(xiàn)對(duì)obj的操作會(huì)找到原型上的代理對(duì)象炫欺,如果obj自己有a屬性,則不會(huì)觸發(fā)proxy上的get树姨,這個(gè)應(yīng)該很好理解

const target = {};
const obj = {};
const handler = {
    get: function(target, key){
            console.log(`get ${key} from ${JSON.stringify(target)}`);
            return Reflect.get(target, key);
    }}
const proxy = new Proxy(target, handler);
Object.setPrototypeOf(obj, proxy);
proxy.a = 1;
obj.b = 1
console.log(obj.a) // get a from {"a": 1}   1
console.log(obj.b) // 1

ES6的Proxy實(shí)現(xiàn)了對(duì)哪些屬性的攔截帽揪?

通過上面的例子了解了Proxy的原理后转晰,我們來看下ES6目前實(shí)現(xiàn)了哪些屬性的攔截查邢,以及他們分別可以做什么扰藕? 下面是 Proxy 支持的攔截操作一覽芳撒,一共 13 種

  • get(target, propKey, receiver):攔截對(duì)象屬性的讀取笔刹,比如proxy.foo和proxy['foo'];
  • set(target, propKey, value, receiver):攔截對(duì)象屬性的設(shè)置舌菜,比如proxy.foo = v或proxy['foo'] = v,返回一個(gè)布爾值;
  • has(target, propKey):攔截propKey in proxy的操作染乌,返回一個(gè)布爾值懂讯。
  • deleteProperty(target, propKey):攔截delete proxy[propKey]的操作褐望,返回一個(gè)布爾值;
  • ownKeys(target):攔截Object.getOwnPropertyNames(proxy)、
    Object.getOwnPropertySymbols(proxy)实蔽、Object.keys(proxy)局装、for…in循環(huán)铐尚,返回一個(gè)數(shù)組宣增。該方法返回目標(biāo)對(duì)象所有自身的屬性的屬性名矛缨,而Object.keys()的返回結(jié)果僅包括目標(biāo)對(duì)象自身的可遍歷屬性;
  • getOwnPropertyDescriptor(target, propKey):攔截Object.getOwnPropertyDescriptor(proxy, propKey)箕昭,返回屬性的描述對(duì)象;
  • defineProperty(target, propKey, propDesc):攔截Object.defineProperty(proxy, propKey, propDesc)落竹、Object.defineProperties(proxy, propDescs),返回一個(gè)布爾值;
  • preventExtensions(target):攔截Object.preventExtensions(proxy),返回一個(gè)布爾值;
  • getPrototypeOf(target):攔截Object.getPrototypeOf(proxy)桨武,返回一個(gè)對(duì)象;
  • isExtensible(target):攔截Object.isExtensible(proxy)呀酸,返回一個(gè)布爾值;
  • setPrototypeOf(target, proto):攔截Object.setPrototypeOf(proxy, proto)琼梆,返回一個(gè)布爾值。如果目標(biāo)對(duì)象是函數(shù)错览,那么還有兩種額外操作可以攔截;
  • apply(target, object, args):攔截 Proxy 實(shí)例作為函數(shù)調(diào)用的操作倾哺,比如proxy(…args)、proxy.call(object, …args)忌愚、proxy.apply(…);
  • construct(target, args):攔截 Proxy 實(shí)例作為構(gòu)造函數(shù)調(diào)用的操作硕糊,比如new proxy(…args);

以上是目前es6支持的proxy简十,具體的用法不做贅述勺远,有興趣的可以到阮一峰老師的es6入門去研究每種的具體用法时鸵,其實(shí)思想都是一樣的饰潜,只是每種對(duì)應(yīng)了一些不同的功能~

實(shí)際場(chǎng)景中 Proxy 可以做什么彭雾?

實(shí)現(xiàn)私有變量

js的語法中沒有private這個(gè)關(guān)鍵字來修飾私有變量,所以基本上所有的class的屬性都是可以被訪問的半沽,但是在有些場(chǎng)景下我們需要使用到私有變量者填,現(xiàn)在業(yè)界的一些做法都是使用”_變量名“來”約定“這是一個(gè)私有變量占哟,但是如果哪天被別人從外部改掉的話榨乎,我們還是沒有辦法阻止的,然而铐姚,當(dāng)Proxy出現(xiàn)后谦屑,我們可以用代理來處理這種場(chǎng)景氢橙,看代碼:

const obj = {
    _name: 'nanjin',
    age: 19,
    getName: () => {
        return this._name;
    },
    setName: (newName) => {
        this._name = newName;
    }}
const proxyObj = obj => new Proxy(obj, {
    get: (target, key) => {
        if(key.startsWith('_')){
            throw new Error(`${key} is private key, please use get${key}`)
        }
        return Reflect.get(target, key);
    },
    set: (target, key, newVal) => {
        if(key.startsWith('_')){
            throw new Error(`${key} is private key, please use set${key}`)
        }
        return Reflect.set(target, key, newVal);
    }})
const newObj = proxyObj(obj);
console.log(newObj._name) // Uncaught Error: _name is private key, please use get_name
newObj._name = 'newname'; // Uncaught Error: _name is private key, please use set_name
console.log(newObj.age) // 19
console.log(newObj.getName()) // nanjin

可見悍手,通過proxyObj方法坦康,我們可以實(shí)現(xiàn)把任何一個(gè)對(duì)象都過濾一次诡延,然后返回新的代理對(duì)象肆良,被處理的對(duì)象會(huì)把所有_開頭的變量給攔截掉,更進(jìn)一步夭谤,如果有用過mobx的同學(xué)會(huì)發(fā)現(xiàn)mobx里面的store中的對(duì)象都是類似于這樣的

有handler 和 target朗儒,說明mobx本身也是用了代理模式醉锄,同時(shí)加上Decorator函數(shù)恳不,在這里就相當(dāng)于把proxyObj使用裝飾器的方式來實(shí)現(xiàn),Proxy + Decorator 就是mobx的核心原理啦~

vue響應(yīng)式數(shù)據(jù)實(shí)現(xiàn)

VUE的雙向綁定涉及到模板編譯,響應(yīng)式數(shù)據(jù)神妹,訂閱者模式等等鸵荠,有興趣的可以看這里蛹找,因?yàn)檫@篇文章的主題是proxy哨坪,因此我們著重介紹一下數(shù)據(jù)響應(yīng)式的過程当编。

2.x版本

在當(dāng)前的vue2.x的版本中,在data中聲名一個(gè)obj后金顿,vue會(huì)利用Object.defineProperty來遞歸的給data中的數(shù)據(jù)加上get和set揍拆,然后每次set的時(shí)候嫂拴,加入額外的邏輯慧妄。來觸發(fā)對(duì)應(yīng)模板視圖的更新塞淹,看下偽代碼:

const defineReactiveData = data => {
    Object.keys(data).forEach(key => {
        let value = data[key];
        Object.defineProperty(data, key, {
         get : function(){
            console.log(`getting ${key}`)
            return value;
         },
         set : function(newValue){
            console.log(`setting ${key}`)
            notify() // 通知相關(guān)的模板進(jìn)行編譯
            value = newValue;
         },
         enumerable : true,
         configurable : true
        })
    })}

這個(gè)方法可以給data上面的所有屬性都加上get和set饱普,當(dāng)然這只是偽代碼套耕,實(shí)際場(chǎng)景下我們還需要考慮如果某個(gè)屬性還是對(duì)象我們應(yīng)該遞歸下去,來試試:

const data = {
    name: 'nanjing',
    age: 19
}
defineReactiveData(data)
data.name // getting name  'nanjing'
data.name = 'beijing';  // setting name

可以看到當(dāng)我們get和set觸發(fā)的時(shí)候匈挖,已經(jīng)能夠同時(shí)觸發(fā)我們想要調(diào)用的函數(shù)拉,Vue雙向綁定過程中舶吗,當(dāng)改變this上的data的時(shí)候去更新模板的核心原理就是這個(gè)方法誓琼,通過它我們就能在data的某個(gè)屬性被set的時(shí)候腹侣,去觸發(fā)對(duì)應(yīng)模板的更新齿穗。

現(xiàn)在我們?cè)趤碓囋囅旅娴拇a:

const data = {
    userIds: ['01','02','03','04','05']
}
defineReactiveData(data);
data.userIds // getting userIds ["01", "02", "03", "04", "05"]
// get 過程是沒有問題的缤灵,現(xiàn)在我們嘗試給數(shù)組中push一個(gè)數(shù)據(jù)
data.userIds.push('06') // getting userIds 

what ? setting沒有被觸發(fā)腮出,反而因?yàn)槿×艘淮蝩serIds所以觸發(fā)了一次getting~,
不僅如此作儿,很多數(shù)組的方法都不會(huì)觸發(fā)setting攻锰,比如:push,pop,shift,unshift,splice,sort,reverse這些方法都會(huì)改變數(shù)組娶吞,但是不會(huì)觸發(fā)set械姻,所以Vue為了解決這個(gè)問題楷拳,重新包裝了這些函數(shù),同時(shí)當(dāng)這些方法被調(diào)用的時(shí)候陶耍,手動(dòng)去觸發(fā)notify()烈钞;看下源碼:

// 獲得數(shù)組原型const arrayProto = Array.prototype
export const arrayMethods = Object.create(arrayProto)
// 重寫以下函數(shù)const methodsToPatch = [
  'push',
  'pop',
  'shift',
  'unshift',
  'splice',
  'sort',
  'reverse'
]
methodsToPatch.forEach(function(method) {
  // 緩存原生函數(shù)
  const original = arrayProto[method]
  // 重寫函數(shù)
  def(arrayMethods, method, function mutator(...args) {
    // 先調(diào)用原生函數(shù)獲得結(jié)果
    const result = original.apply(this, args)
    const ob = this.__ob__
    let inserted
    // 調(diào)用以下幾個(gè)函數(shù)時(shí),監(jiān)聽新數(shù)據(jù)
    switch (method) {
      case 'push':
      case 'unshift':
        inserted = args
        break
      case 'splice':
        inserted = args.slice(2)
        break
    }
    if (inserted) ob.observeArray(inserted)
    // 手動(dòng)派發(fā)更新
    ob.dep.notify()
    return result
  })
})

上面是官方的源碼蛾狗,我們可以實(shí)現(xiàn)一下push的偽代碼,為了省事算吩,直接在prototype上下手了~

const push = Array.prototype.push;
Array.prototype.push = function(...args){
    console.log('push is happenning');
    return push.apply(this, args);
}
data.userIds.push('123') // push is happenning

通過這種方式偎巢,我們可以監(jiān)聽到這些的變化兼耀,但是vue官方文檔中有這么一個(gè)注意事項(xiàng)

由于 JavaScript 的限制瘤运,Vue 不能檢測(cè)以下變動(dòng)的數(shù)組:

  • 當(dāng)你利用索引直接設(shè)置一個(gè)項(xiàng)時(shí),例如:vm.items[indexOfItem] = newValue
  • 當(dāng)你修改數(shù)組的長(zhǎng)度時(shí)但金,例如:vm.items.length = newLength
    這個(gè)最根本的原因是因?yàn)檫@2種情況下冷溃,受制于js本身無法實(shí)現(xiàn)監(jiān)聽似枕,所以官方建議用他們自己提供的內(nèi)置api來實(shí)現(xiàn)年柠,我們也可以理解到這里既不是defineProperty可以處理的彪杉,也不是包一層函數(shù)就能解決的,這就是2.x版本現(xiàn)在的一個(gè)問攀唯。

回到這篇文章的主題侯嘀,vue官方會(huì)在3.x的版本中使用proxy來代替defineProperty處理響應(yīng)式數(shù)據(jù)的過程,我們先來模擬一下實(shí)現(xiàn)吠谢,看看能否解決當(dāng)前遇到的這些問題工坊;

3.x版本

我們先來通過proxy實(shí)現(xiàn)對(duì)data對(duì)象的get和set的劫持敢订,并返回一個(gè)代理的對(duì)象,注意昭齐,我們只關(guān)注proxy本身矾柜,所有的實(shí)現(xiàn)都是偽代碼怪蔑,有興趣的同學(xué)可以自行完善

const defineReactiveProxyData = data => new Proxy(data,{
        get: function(data, key){
            console.log(`getting ${key}`)
            return Reflect.get(data, key);
        },
        set: function(data, key, newVal){
            console.log(`setting ${key}`);
            if(typeof newVal === 'object'){ // 如果是object缆瓣,遞歸設(shè)置代理
                return Reflect.set(data, key, defineReactiveProxyData(newVal));
            }
            return Reflect.set(data, key, newVal);
        }
    })
const data = {
    name: 'nanjing',
    age: 19
};
const vm = defineReactiveProxyData(data);
vm.name // getting name  nanjing
vm.age = 20; // setting age  20

看起來我們的代理已經(jīng)起作用啦捆愁,之后只要在setting的時(shí)候加上notify()去通知模板進(jìn)行編譯就可以了,然后我們來嘗試設(shè)置一個(gè)數(shù)組看看呻逆;

vm.userIds = [1,2,3] //  setting userIds
vm.userIds.push(1);
// getting userIds 因?yàn)槲覀儠?huì)先訪問一次userids
// getting push 調(diào)用了push方法咖城,所以會(huì)訪問一次push屬性
// getting length 數(shù)組push的時(shí)候 length會(huì)變宜雀,所以需要先訪問原來的length
// setting 3 通過下標(biāo)設(shè)置的握础,所以set當(dāng)前的index是3
// setting length 改變了數(shù)組的長(zhǎng)度禀综,所以會(huì)set length
// 4 返回新的數(shù)組的長(zhǎng)度

回顧2.x遇到的第一個(gè)問題苔严,需要重新包裝Array.prototype上的一些方法届氢,使用了proxy后不需要了退子,解決了~絮供,繼續(xù)看下一個(gè)問題

vm.userIds.length = 2
// getting userIds 先訪問
// setting length 在設(shè)置
vm.userIds[1] = '123'
// getting userIds 先訪問
// setting 1 設(shè)置index=1的item
// "123"

從上面的例子中我們可以看到茶敏,不管是直接改變數(shù)組的length還是通過某一個(gè)下標(biāo)改變數(shù)組的內(nèi)容惊搏,proxy都能攔截到這次變化恬惯,這比defineProperty方便太多了酪耳,2.x版本中的第二個(gè)問題刹缝,在proxy中根本不會(huì)出現(xiàn)了梢夯。

總結(jié)1

通過上面的例子和代碼,我們看到Vue的響應(yīng)模式如果使用proxy會(huì)比現(xiàn)在的實(shí)現(xiàn)方式要簡(jiǎn)化和優(yōu)化很多噪奄,很快在即將來臨的3.0版本中勤篮,大家就可以體驗(yàn)到了色罚。不過因?yàn)閜roxy本身是有兼容性的戳护,比如ie瀏覽器涤垫,所以在低版本的場(chǎng)景下蝠猬,vue會(huì)回退到現(xiàn)在的實(shí)現(xiàn)方式榆芦。

總結(jié)2

回歸到proxy本身喘鸟,設(shè)計(jì)模式中有一種典型的代理模式,proxy就是js的一種實(shí)現(xiàn)崎淳,它的好處在于拣凹,我可以在不污染本身對(duì)象的條件下恨豁,生成一個(gè)新的代理對(duì)象,所有的一些針對(duì)性邏輯放到代理對(duì)象上去實(shí)現(xiàn)菊匿,這樣我可以由A對(duì)象计福,衍生出B,C,D…每個(gè)的處理過程都不一樣象颖,從而簡(jiǎn)化代碼的復(fù)雜性,提升一定的可讀性可款,比如用proxy實(shí)現(xiàn)數(shù)據(jù)庫(kù)的ORM就是一種很好的應(yīng)用闺鲸,其實(shí)代碼很簡(jiǎn)單埃叭,關(guān)鍵是要理解背后的思想,同時(shí)能夠舉一反三~

擴(kuò)展:

1.Proxy.revocable()

這個(gè)方法可以返回一個(gè)可取消的代理對(duì)象

const obj = {};
const handler = {};
const {proxy, revoke} = Proxy.revocable(obj, handler);
proxy.a = 1
proxy.a // 1
revoke();
proxy.a // Uncaught TypeError: Cannot perform 'get' on a proxy that has been revoked

一旦代理被取消了壁袄,就不能再?gòu)拇韺?duì)象訪問了

打印proxy 可以看到IsRevoked變?yōu)閠rue了

2.代理對(duì)象的this問題

因?yàn)閚ew Proxy出來的是一個(gè)新的對(duì)象嗜逻,所以在如果你在target中有使用this缭召,被代理后的this將指向新的代理對(duì)象嵌巷,而不是原來的對(duì)象搪哪,這個(gè)時(shí)候,如果有些函數(shù)是原對(duì)象獨(dú)有的惑朦,就會(huì)出現(xiàn)this指向?qū)е碌膯栴}已维,這種場(chǎng)景下垛耳,建議使用bind來強(qiáng)制綁定this

看代碼:

const target = new Date();
const handler = {};
const proxy = new Proxy(target, handler);
proxy.getDate(); // Uncaught TypeError: this is not a Date object.

因?yàn)榇砗蟮膶?duì)象并不是一個(gè)Date類型的堂鲜,不具有g(shù)etDate方法的护奈,所以我們需要在get的時(shí)候霉旗,綁定一下this的指向

const target = new Date();
const handler = {
    get: function(target, key){
        if(typeof target[key] === 'function'){
            return target[key].bind(target) // 強(qiáng)制綁定
            this到原對(duì)象
        }
        return Reflect.get(target, key)
    }
};
const proxy = new Proxy(target, handler);
proxy.getDate(); // 6

這樣就可以正常使用this啦厌秒,當(dāng)然具體的使用還要看具體的場(chǎng)景,靈活運(yùn)用吧檐晕!

作者:Guokai
鏈接:https://juejin.im/post/5cf8b51ae51d45590a445b0d

求點(diǎn)贊辟灰,求關(guān)注~


?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末芥喇,一起剝皮案震驚了整個(gè)濱河市乃坤,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌湿诊,老刑警劉巖厅须,帶你破解...
    沈念sama閱讀 218,941評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異错沽,居然都是意外死亡千埃,警方通過查閱死者的電腦和手機(jī)放可,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,397評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門耀里,熙熙樓的掌柜王于貴愁眉苦臉地迎上來冯挎,“玉大人咙鞍,你說我怎么就攤上這事∫籽簦” “怎么了潦俺?”我有些...
    開封第一講書人閱讀 165,345評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵事示,是天一觀的道長(zhǎng)肖爵。 經(jīng)常有香客問我劝堪,道長(zhǎng)秒啦,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,851評(píng)論 1 295
  • 正文 為了忘掉前任驻呐,我火速辦了婚禮含末,結(jié)果婚禮上佣盒,老公的妹妹穿的比我還像新娘顽聂。我一直安慰自己,他們只是感情好务豺,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,868評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著蚪燕,像睡著了一般馆纳。 火紅的嫁衣襯著肌膚如雪鲁驶。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,688評(píng)論 1 305
  • 那天督禽,我揣著相機(jī)與錄音狈惫,去河邊找鬼胧谈。 笑死荸频,一個(gè)胖子當(dāng)著我的面吹牛试溯,可吹牛的內(nèi)容都是我干的遇绞。 我是一名探鬼主播,決...
    沈念sama閱讀 40,414評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼付鹿!你這毒婦竟也來了舵匾?” 一聲冷哼從身側(cè)響起俊抵,我...
    開封第一講書人閱讀 39,319評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎坐梯,沒想到半個(gè)月后徽诲,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,775評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡吵血,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,945評(píng)論 3 336
  • 正文 我和宋清朗相戀三年盐肃,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了语卤。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,096評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖瘪菌,靈堂內(nèi)的尸體忽然破棺而出弛秋,到底是詐尸還是另有隱情军俊,我是刑警寧澤爸邢,帶...
    沈念sama閱讀 35,789評(píng)論 5 346
  • 正文 年R本政府宣布浇辜,位于F島的核電站柳洋,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏测蹲。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,437評(píng)論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望示辈。 院中可真熱鬧,春花似錦膝迎、人聲如沸限次。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,993評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽勾笆。三九已至,卻和暖如春蒲每,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背淮阐。 一陣腳步聲響...
    開封第一講書人閱讀 33,107評(píng)論 1 271
  • 我被黑心中介騙來泰國(guó)打工挑随, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人柒桑。 一個(gè)月前我還...
    沈念sama閱讀 48,308評(píng)論 3 372
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像昆稿,于是被迫代替她去往敵國(guó)和親少欺。 傳聞我的和親對(duì)象是個(gè)殘疾皇子夫椭,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,037評(píng)論 2 355

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

  • 國(guó)家電網(wǎng)公司企業(yè)標(biāo)準(zhǔn)(Q/GDW)- 面向?qū)ο蟮挠秒娦畔?shù)據(jù)交換協(xié)議 - 報(bào)批稿:20170802 前言: 排版 ...
    庭說閱讀 10,986評(píng)論 6 13
  • Proxy 概述 Proxy 用于修改某些操作的默認(rèn)行為洞豁,等同于在語言層面做出修改,所以屬于一種“元編程”(met...
    pauljun閱讀 3,251評(píng)論 0 1
  • 來自深入理解ES6第十二章挑辆,由于最近業(yè)務(wù)中經(jīng)常用到洒嗤,記錄一下 這里內(nèi)容都太學(xué)術(shù)了吉挣,有一篇簡(jiǎn)單介紹Proxy作用的文...
    NowhereToRun閱讀 1,011評(píng)論 0 1
  • defineProperty() 學(xué)習(xí)書籍《ECMAScript 6 入門 》 Proxy Proxy 用于修改某...
    Bui_vlee閱讀 654評(píng)論 0 1
  • 今天际跪,上午的時(shí)候上課的狀態(tài)不夠好肠虽。因?yàn)轭檻]著幼兒園的事闲延,一直想著想?yún)⒓赢厴I(yè)晚會(huì)可幼兒園又要加班找颓。我的天使也...
    請(qǐng)叫我小嘟嘟閱讀 290評(píng)論 0 0