jQuery Callbacks

前言

$.Callbacks用來管理函數隊列。採用了觀察者模式,經過add添加操做到隊列當中,經過fire去執行這些操做。實際上$.Callbacks是1.7版本從$.Deferred對象當中分離出來的,主要是實現$.Deferred功能。設計模式

API

$.Callbacks

咱們經過調用$.Callbacks獲取到一個callback實例,以下數組

var cb = $.Callbacks();

看到Callbacks首字母大寫,有些人可能會以爲通常只有對象纔會這樣,所以須要new一個實例,以下閉包

var cb = new $.Callbacks();

實際上這兩種方式均可以,由於Callbacks函數返回值是一個對象,爲何會這樣?看下面一組對比函數

function Cons() {
    this.name = 'this.name';

    return {
        name: 'obj.name'
    };
}

console.log(Cons().name);//obj.name
console.log(new Cons().name);//obj.name

function Cons() {
    this.name = 'this.name';

    return 'str.name';
}

console.log(Cons());//str.name
console.log(new Cons().name);//this.name

當函數的返回值是一個對象時(null除外),new和直接調用二者的返回值是同樣的。可是須要注意了,二者的this指向是不同的。爲了儘量的節省代碼和避免混亂咱們仍是統一採用var cb = $.Callbacks();的方式去調用。this

像這種先調用獲取到實例,而後經過實例進行一系列的操做,很明顯利用了閉包特性。設計

add

向內部隊列添加函數,總有三種參數形式code

單個函數參數

var cb = $.Callbacks();

cb.add(function () {
    console.log('add one');
});

多個函數參數

var cb = $.Callbacks();

cb.add(function () {
    console.log('add one');
}, function () {
    console.log('add two');
});

數組參數

var cb = $.Callbacks();

cb.add([
    function () {
        console.log('add one');
    }, function () {
        console.log('add two');
    }
]);

fire

依次執行隊列裏的函數對象

var cb = $.Callbacks();

cb.add([
    function () {
        console.log('add one');
    }, function () {
        console.log('add two');
    }
]);

cb.fire();
//add one
//add two

fire的參數會傳遞給咱們添加的函數,例如隊列

var cb = $.Callbacks();

cb.add(function (name, age) {
    console.log(name, age);
});

cb.fire('Jacky', 26);//Jacky 26

fireWith

fire調用的時候,咱們添加函數當中的this指向咱們的Callbacks實例,例如rem

var cb = $.Callbacks();

cb.add(function () {
    console.log(this === cb);
});

cb.fire();//true

fireWith就是改變咱們添加函數的context,即this指向,例如

var cb = $.Callbacks();

var obj = {
    name: 'objName'
};

cb.add(function (age) {
    console.log(this.name, age);
});

cb.fireWith(obj, [26]);//objName 26

fireWith第一個參數是咱們的context,第二個參數是咱們須要傳遞的內容數組,注意了是數組!

empty

清空函數隊列

var cb = $.Callbacks();

cb.add(function () {
    console.log('add one');
});

cb.empty();
cb.fire();

has

判斷函數隊列中是否存在某個函數

var cb = $.Callbacks();

function demo() {
    console.log('demo');
}
cb.add(demo);
console.log(cb.has(demo));//true

函數傳遞的都是引用,千萬別出現如下的低級錯誤

var cb = $.Callbacks();

cb.add(function () {
    console.log('demo');
});
cb.has(function () {
    console.log('demo');
});

remove

從內部隊列中移除某些函數

var cb = $.Callbacks();

function demo1() {
    console.log('demo1');
}

function demo2() {
    console.log('demo2');
}

cb.add(demo1, demo2);
cb.remove(demo1, demo2);
cb.fire();

disable

禁用回調列表。這種狀況會清空函數隊列,禁用核心功能。意味着這個回調管理報廢了。

var cb = $.Callbacks();

cb.add(function () {
    console.log('add');
});

cb.disable();
cb.fire();

disabled

回調管理是否被禁用

var cb = $.Callbacks();

cb.add(function () {
    console.log('add');
});

cb.disable();
console.log(cb.disabled());//true

lock

鎖定回調管理,同disable,惟一的差異會在下面表述

locked

回調管理是否被鎖

fired

回調隊列是否執行過

var cb = $.Callbacks();

cb.add(function () {
    console.log('add');
});

cb.fire();//add
console.log(cb.fired());//true

$.Callbacks()

$.Callbacks經過字符串參數的形式支持4種及以上的特定功能。很明顯的一個工廠模式。

once

函數隊列只執行一次。參考如下對比

//不添加參數 
var cb = $.Callbacks();

cb.add(function () {
    console.log('add');
});

cb.fire();//add
cb.fire();//add

//添加參數
var cb = $.Callbacks('once');

cb.add(function () {
    console.log('add');
});

cb.fire();//add
cb.fire();

函數隊列執行過之後,就不會在執行了,不管調用fire多少次。

unique

往內部隊列添加的函數保持惟一,不能重複添加。參考如下對比

//不添加參數
var cb = $.Callbacks();

function demo() {
    console.log('demo');
}
cb.add(demo, demo);

cb.fire();
//demo
//demo

//添加參數
var cb = $.Callbacks('unique');

function demo() {
    console.log('demo');
}
cb.add(demo, demo);

cb.fire();//demo

相同的函數不會被重複添加到內部隊列中

stopOnFalse

內部隊列裏的函數是依次執行的,當某個函數的返回值是false時,中止繼續執行剩下的函數。參考如下對比

//不添加參數
var cb = $.Callbacks();

cb.add([
    function () {
        console.log('add one');
    },
    function () {
        console.log('add two');
    }
]);

cb.fire();
//add one
//add two

//添加參數
var cb = $.Callbacks('stopOnFalse');

cb.add([
    function () {
        console.log('add one');
        return false;
    },
    function () {
        console.log('add two');
    }
]);

cb.fire();//add one

注意了返回值必定要是false,像undefined、null這種做爲返回值是沒有效果的

memory

當函數隊列fire或fireWith一次事後,內部會記錄當前fire或fireWith的參數。當下次調用add的時候,會把記錄的參數傳遞給新添加的函數並當即執行這個新添加的函數。看個例子

var cb = $.Callbacks('memory');

cb.add(function (name) {
    console.log('one', name);
});

cb.fire('Jacky');//first Jacky

cb.add(function (name) {
    console.log('two', name);
});//two Jacky

例如公司領導在9點的時候發了封郵件,要求你們提交本身的年終終結,這就至關於fire操做了,在公司裏的員工收到郵件後,立馬提交了。小李因爲請假,下午纔過來,看到郵件後也提交了本身的年終總結。不須要領導再次發送郵件提醒。

fire或fireWith必定要在disabled或lock前先執行一遍,memory纔會起做用

小結

這四種基本類型能夠相互組合起來使用,例如$.Deferred就使用了once和memory的組合。

jQuery.Callbacks("once memory")

disable和lock的區別

二者惟一的區別就是添加了memory參數,看一下對比

var cb = $.Callbacks('memory');

cb.add(function () {
    console.log('one');
});
cb.fire();
cb.disable();
//cb.lock();
cb.add(function () {
    console.log('two');
});

毫無疑問,disable就是禁用全部功能,不管添加什麼參數。而在memory的狀況下,fire事後在lock,繼續add新的函數依舊會當即執行。

總結

$.Callbacks在一百多行的代碼裏就用到了兩種設計模式,確實經典。固然了這都是純屬我的看法。因爲平時用的不多,很遺憾沒有舉出表明性的例子供你們參考,畢竟我輩的目標是學以至用。

相關文章
相關標籤/搜索