成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

BiuJS[v1.0]說(shuō)明文檔(2):數(shù)據(jù)劫持

Terry_Tai / 2228人閱讀

摘要:是一個(gè)輕巧的框架它實(shí)現(xiàn)了數(shù)據(jù)的雙向綁定并提供一些基本的指令幫助你提升效率,比如,,,,是的,如你所見(jiàn),以開(kāi)頭的指令是它的獨(dú)特標(biāo)識(shí)行左右的代碼量,讓應(yīng)用的開(kāi)發(fā)和加載的一瞬完成倉(cāng)庫(kù)訂閱清單前文說(shuō)到提供了一個(gè)強(qiáng)大的接口我們就用它來(lái)劫持?jǐn)?shù)據(jù)不過(guò)在此

BiuJS
BiuJS是一個(gè)輕巧的mvvm框架
它實(shí)現(xiàn)了數(shù)據(jù)的雙向綁定
并提供一些基本的指令幫助你提升效率,比如$for$model,$if,$click,$style
是的,如你所見(jiàn),以$開(kāi)頭的指令是它的獨(dú)特標(biāo)識(shí)
1000行左右的代碼量,讓應(yīng)用的開(kāi)發(fā)和加載biu的一瞬完成
BiuJS倉(cāng)庫(kù): https://github.com/veedrin/biu
訂閱清單

前文說(shuō)到JavaScript提供了一個(gè)強(qiáng)大的接口Object.defineProperty

我們就用它來(lái)劫持?jǐn)?shù)據(jù)

不過(guò)在此之前,我們還有一點(diǎn)準(zhǔn)備工作要做

還記得前文提過(guò)的數(shù)組(訂閱清單)嗎?我們要造一個(gè)數(shù)組來(lái)裝東西

其實(shí)很簡(jiǎn)單

function Dep() {
    this.subs = [];
}

Dep.prototype.addSub = function(sub) {
    this.subs.push(sub);
};

Dep.prototype.notify = function(newValue) {
    for (let i = 0; i < this.subs.length; i++) {
        this.subs[i].update(newValue);
    }
};

真的就是造個(gè)數(shù)組這么簡(jiǎn)單

再來(lái)一個(gè)添加數(shù)組成員的方法,一個(gè)遍歷數(shù)組的方法

因?yàn)?b>Dep.prototype.notify觸發(fā)的開(kāi)關(guān)在setter那里,也就是說(shuō)前者依賴后者。Dep取其依賴之意

為了方便,我們還有一個(gè)取巧的地方,把訂閱者掛到Dep名下,作為Dep的靜態(tài)屬性緩存起來(lái)

function Dep() {
    this.subs = [];
}

Dep.target = null;

Dep.prototype.addSub = function(sub) {
    this.subs.push(sub);
};

Dep.prototype.notify = function(newValue) {
    for (let i = 0; i < this.subs.length; i++) {
        this.subs[i].update(newValue);
    }
};
劫持對(duì)象屬性

然后再回過(guò)頭來(lái)說(shuō)劫持的事

BiuJS主方法傳進(jìn)來(lái)的data是一個(gè)對(duì)象,我們把它轉(zhuǎn)成數(shù)組再遍歷

Object.keys(data).forEach((key) => {
    let value = data[key];
    let dep = new Dep;

    Object.defineProperty(data, key, {
        enumerable: true,
        configurable: true,
        get: function() {
            Dep.target && dep.addSub(Dep.target);
            return value;
        },
        set: function(newValue) {
            if (value === newValue) {
                return;
            }
            value = newValue;
            dep.notify(newValue);
        }
    });
});

每個(gè)屬性都會(huì)得到一個(gè)訂閱清單的實(shí)例,用來(lái)放它的訂閱者

getter負(fù)責(zé)把訂閱者添加進(jìn)來(lái),setter負(fù)責(zé)通知訂閱者更新

訂閱者是什么時(shí)候掛到Dep.target上的?這個(gè)我們暫且不表

有一個(gè)問(wèn)題,data可能是嵌套的對(duì)象,而且可能嵌套的很深,所以我們要用遞歸深度劫持

Observer.prototype.observe = function(data) {
    if (!data || typeof data !== "object") {
        return;
    }
    let self = this;

    Object.keys(data).forEach((key) => {
        let value = data[key];
        // do something
        self.observe(value);
    });
};

遞歸停止的條件就是(嵌套)data為空,或者(嵌套)data不是對(duì)象

劫持?jǐn)?shù)組方法

問(wèn)題又來(lái)了,假如(嵌套)data的值是數(shù)組呢?

我們來(lái)看一個(gè)例子

let data = {
    key: [1, 2]
};

let value = data.key;

Object.defineProperty(data, "key", {
    enumerable: true,
    configurable: true,
    get: function() {
        return value;
    },
    set: function(newValue) {
        value = newValue;
        console.log("captured");
    }
});

data.key = [1, 2, 3]; // 控制臺(tái)打印"captured"
data.key.push(3); // 控制臺(tái)沒(méi)有打印

數(shù)組本身變化是可以被捕捉到的,用方法操作數(shù)組,setter也很絕望啊

不要悲傷,不要絕望,數(shù)組開(kāi)外掛,我們就查外掛

Object.defineProperty是對(duì)象的方法呀,難道要讓數(shù)組變性嗎?

是的

let arrayObject = Object.create(Array.prototype);

console.log(arrayObject); // Array{}

有了它,我們就可以查外掛了

let arrayProto = Array.prototype;
let arrayObject = Object.create(arrayProto);
let methods = ["push", "pop", "unshift", "shift", "slice", "splice", "concat"];

methods.forEach((method) => {
    let origin = arrayProto[method];

    Object.defineProperty(arrayObject, method, {
        enumerable: true,
        writable: true,
        configurable: true,
        value: function() {
            let args = Array.from(arguments);
            let result = origin.apply(this, args);
            dep.notify(Array.from(this));
            return result;
        }
    });
});

上面的意思就是來(lái)一個(gè)偷天換日,把數(shù)組的方法名的value換成我們自己定義的函數(shù)

因?yàn)槭菙?shù)組的方法,這里的this指向的就是被操作的數(shù)組本身

在內(nèi)部還是用apply調(diào)用原方法,獲得返回值返回給我們自己定義的函數(shù)

在外面看起來(lái)是一樣的,只不過(guò)加了一條:悄悄的通知訂閱者更新

這回我們不需要?jiǎng)跓?b>setter了,數(shù)組的方法不是繞過(guò)了setter么,我們只要拿到操作完后的新數(shù)組,遞給訂閱者就好了

簡(jiǎn)直就是碟中諜有沒(méi)有!

當(dāng)然,要達(dá)到效果,還需要最后一招:移花接木

methods.forEach((method) => {
    let origin = arrayProto[method];

    Object.defineProperty(arrayObject, method, {
        // do something
    });
});

arr.__proto__ = arrayObject;

把我們自己定義的方法嫁接到被監(jiān)測(cè)數(shù)組的原型上

一招偷天換日,一招碟中諜,一招移花接木

殊不知,我們已經(jīng)在數(shù)組的方法身上植入了芯片,外掛game over

最后,遞歸的時(shí)候,我們要判斷一下,對(duì)象和數(shù)組走的是不同的路

if (!Array.isArray(value)) {
    this.observe(value);
} else {
    this.observeArray(value, dep);
}
寫在后面

以上就是BiuJS劫持?jǐn)?shù)據(jù)以及添加到訂閱清單里的過(guò)程

歡迎到BiuJS倉(cāng)庫(kù): https://github.com/veedrin/biu了解詳情

更歡迎StarFork

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/92278.html

相關(guān)文章

  • BiuJS[v1.0]說(shuō)明文檔(1):總體結(jié)構(gòu)

    摘要:是一個(gè)輕巧的框架它實(shí)現(xiàn)了數(shù)據(jù)的雙向綁定并提供一些基本的指令幫助你提升效率,比如,,,,是的,如你所見(jiàn),以開(kāi)頭的指令是它的獨(dú)特標(biāo)識(shí)行左右的代碼量,讓應(yīng)用的開(kāi)發(fā)和加載的一瞬完成倉(cāng)庫(kù)啟動(dòng)首先我們來(lái)看一下是如何啟動(dòng)的是的掛載點(diǎn),它決定在多大范圍的樹(shù) showImg(https://segmentfault.com/img/remote/1460000012478667?w=1920&h=926...

    崔曉明 評(píng)論0 收藏0
  • BiuJS[v1.0]說(shuō)明文檔(4):$if 指令

    摘要:是一個(gè)輕巧的框架它實(shí)現(xiàn)了數(shù)據(jù)的雙向綁定并提供一些基本的指令幫助你提升效率,比如,,,,是的,如你所見(jiàn),以開(kāi)頭的指令是它的獨(dú)特標(biāo)識(shí)行左右的代碼量,讓應(yīng)用的開(kāi)發(fā)和加載的一瞬完成倉(cāng)庫(kù)指令往下看之前,請(qǐng)大家沐浴更衣,因?yàn)槲乙v的指令了中的已經(jīng)被占用 showImg(https://segmentfault.com/img/remote/1460000012478667?w=1920&h=926...

    _ang 評(píng)論0 收藏0
  • BiuJS[v1.0]說(shuō)明文檔(3):文本編譯

    摘要:如此循環(huán),直到結(jié)束如果循環(huán)結(jié)束之后,比字符串的長(zhǎng)度要小,那說(shuō)明后面還有文本匹配失敗了。 showImg(https://segmentfault.com/img/remote/1460000012478667?w=1920&h=926); BiuJS BiuJS是一個(gè)輕巧的mvvm框架它實(shí)現(xiàn)了數(shù)據(jù)的雙向綁定并提供一些基本的指令幫助你提升效率,比如$for,$model,$if,$cli...

    lucas 評(píng)論0 收藏0
  • Web安全開(kāi)發(fā)規(guī)范手冊(cè)V1.0

    摘要:一背景團(tuán)隊(duì)最近頻繁遭受網(wǎng)絡(luò)攻擊,引起了技術(shù)負(fù)責(zé)人的重視,筆者在團(tuán)隊(duì)中相對(duì)來(lái)說(shuō)更懂安全,因此花了點(diǎn)時(shí)間編輯了一份安全開(kāi)發(fā)自檢清單,覺(jué)得應(yīng)該也有不少讀者有需要,所以將其分享出來(lái)。 一、背景 團(tuán)隊(duì)最近頻繁遭受網(wǎng)絡(luò)攻擊,引起了技術(shù)負(fù)責(zé)人的重視,筆者在團(tuán)隊(duì)中相對(duì)來(lái)說(shuō)更懂安全,因此花了點(diǎn)時(shí)間編輯了一份安全開(kāi)發(fā)自檢清單,覺(jué)得應(yīng)該也有不少讀者有需要,所以將其分享出來(lái)。 二、編碼安全 2.1 輸入驗(yàn)證 ...

    Yuqi 評(píng)論0 收藏0
  • Web安全開(kāi)發(fā)規(guī)范手冊(cè)V1.0

    摘要:一背景團(tuán)隊(duì)最近頻繁遭受網(wǎng)絡(luò)攻擊,引起了技術(shù)負(fù)責(zé)人的重視,筆者在團(tuán)隊(duì)中相對(duì)來(lái)說(shuō)更懂安全,因此花了點(diǎn)時(shí)間編輯了一份安全開(kāi)發(fā)自檢清單,覺(jué)得應(yīng)該也有不少讀者有需要,所以將其分享出來(lái)。 一、背景 團(tuán)隊(duì)最近頻繁遭受網(wǎng)絡(luò)攻擊,引起了技術(shù)負(fù)責(zé)人的重視,筆者在團(tuán)隊(duì)中相對(duì)來(lái)說(shuō)更懂安全,因此花了點(diǎn)時(shí)間編輯了一份安全開(kāi)發(fā)自檢清單,覺(jué)得應(yīng)該也有不少讀者有需要,所以將其分享出來(lái)。 二、編碼安全 2.1 輸入驗(yàn)證 ...

    Ryan_Li 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<