在线观看不卡亚洲电影_亚洲妓女99综合网_91青青青亚洲娱乐在线观看_日韩无码高清综合久久

鍍金池/ 教程/ HTML/ Function 模式(上篇)
代碼復(fù)用模式(避免篇)
S.O.L.I.D 五大原則之接口隔離原則 ISP
設(shè)計模式之狀態(tài)模式
JavaScript 核心(晉級高手必讀篇)
設(shè)計模式之建造者模式
JavaScript 與 DOM(上)——也適用于新手
設(shè)計模式之中介者模式
設(shè)計模式之裝飾者模式
設(shè)計模式之模板方法
設(shè)計模式之外觀模式
強(qiáng)大的原型和原型鏈
設(shè)計模式之構(gòu)造函數(shù)模式
揭秘命名函數(shù)表達(dá)式
深入理解J avaScript 系列(結(jié)局篇)
執(zhí)行上下文(Execution Contexts)
函數(shù)(Functions)
《你真懂 JavaScript 嗎?》答案詳解
設(shè)計模式之適配器模式
設(shè)計模式之組合模式
設(shè)計模式之命令模式
S.O.L.I.D 五大原則之單一職責(zé) SRP
編寫高質(zhì)量 JavaScript 代碼的基本要點(diǎn)
求值策略
閉包(Closures)
對象創(chuàng)建模式(上篇)
This? Yes,this!
設(shè)計模式之代理模式
變量對象(Variable Object)
S.O.L.I.D 五大原則之里氏替換原則 LSP
面向?qū)ο缶幊讨话憷碚?/span>
設(shè)計模式之單例模式
Function 模式(上篇)
S.O.L.I.D 五大原則之依賴倒置原則 DIP
設(shè)計模式之迭代器模式
立即調(diào)用的函數(shù)表達(dá)式
設(shè)計模式之享元模式
設(shè)計模式之原型模式
根本沒有“JSON 對象”這回事!
JavaScript 與 DOM(下)
面向?qū)ο缶幊讨?ECMAScript 實現(xiàn)
全面解析 Module 模式
對象創(chuàng)建模式(下篇)
設(shè)計模式之職責(zé)鏈模式
S.O.L.I.D 五大原則之開閉原則 OCP
設(shè)計模式之橋接模式
設(shè)計模式之策略模式
設(shè)計模式之觀察者模式
代碼復(fù)用模式(推薦篇)
作用域鏈(Scope Chain)
Function 模式(下篇)
設(shè)計模式之工廠模式

Function 模式(上篇)

介紹

本篇主要是介紹 Function 方面使用的一些技巧(上篇),利用 Function 特性可以編寫出很多非常有意思的代碼,本篇主要包括:回調(diào)模式、配置對象、返回函數(shù)、分布程序、柯里化(Currying)。

回調(diào)函數(shù)

在 JavaScript 中,當(dāng)一個函數(shù) A 作為另外一個函數(shù) B 的其中一個參數(shù)時,則函數(shù) A 稱為回調(diào)函數(shù),即 A 可以在函數(shù) B 的周期內(nèi)執(zhí)行(開始、中間、結(jié)束時均可)。

舉例來說,有一個函數(shù)用于生成 node

var complexComputation = function () { /* 內(nèi)部處理,并返回一個node*/};
有一個findNodes函數(shù)聲明用于查找所有的節(jié)點(diǎn),然后通過callback回調(diào)進(jìn)行執(zhí)行代碼。  
var findNodes = function (callback) {
var nodes = [];  
var node = complexComputation();  
// 如果回調(diào)函數(shù)可用,則執(zhí)行它
if (typeof callback === "function") {
callback(node);
}  
nodes.push(node);
return nodes;
};

關(guān)于 callback 的定義,我們可以事先定義好來用:

// 定義callback
var hide = function (node) {
node.style.display = "none";
}; 
// 查找node,然后隱藏所有的node
var hiddenNodes = findNodes(hide);
也可以直接在調(diào)用的時候使用匿名定義,如下:  
// 使用匿名函數(shù)定義callback
var blockNodes = findNodes(function (node) {
node.style.display = 'block';
});

我們平時用的最多的,估計就數(shù) jQuery 的 ajax 方法的調(diào)用了,通過在 done/faild 上定義 callback,以便在 ajax 調(diào)用成功或者失敗的時候做進(jìn)一步處理,代碼如下(本代碼基于 jquery1.8 版):

var menuId = $("ul.nav").first().attr("id");
var request = $.ajax({
  url: "script.php",
  type: "POST",
  data: {id : menuId},
  dataType: "html"
});  
//調(diào)用成功時的回調(diào)處理
request.done(function(msg) {
  $("#log").html( msg );
});  
//調(diào)用失敗時的回調(diào)處理
request.fail(function(jqXHR, textStatus) {
  alert( "Request failed: " + textStatus );
});

配置對象

如果一個函數(shù)(或方法)的參數(shù)只有一個參數(shù),并且參數(shù)為對象字面量,我們則稱這種模式為配置對象模式。例如,如下代碼:

var conf = {
    username:"shichuan",
    first:"Chuan",
    last:"Shi"
};
addPerson(conf);

則在 addPerson 內(nèi)部,就可以隨意使用 conf 的值了,一般用于初始化工作,例如 jquery 里的 ajaxSetup 也就是這種方式來實現(xiàn)的:

// 事先設(shè)置好初始值
$.ajaxSetup({
   url: "/xmlhttp/",
   global: false,
   type: "POST"
 });  
// 然后再調(diào)用
 $.ajax({ data: myData });

另外,很多 jquery 的插件也有這種形式的傳參,只不過也可以不傳,不傳的時候則就使用默認(rèn)值了。

返回函數(shù)

返回函數(shù),則是指在一個函數(shù)的返回值為另外一個函數(shù),或者根據(jù)特定的條件靈活創(chuàng)建的新函數(shù),示例代碼如下:

var setup = function () {
    console.log(1);
    return function () {
        console.log(2);
    };
};  
// 調(diào)用setup 函數(shù)
var my = setup(); // 輸出 1
my(); // 輸出 2
// 或者直接調(diào)用也可
setup()();

或者你可以利用閉包的特性,在 setup 函數(shù)里記錄一個私有的計數(shù)器數(shù)字,通過每次調(diào)用來增加計數(shù)器,代碼如下:

var setup = function () {
    var count = 0;
    return function () {
        return ++count;
    };
};   
// 用法
var next = setup();
next(); // 返回 1
next(); // 返回 2
next(); // 返回 3

偏應(yīng)用

這里的偏應(yīng)用,其實是將參數(shù)的傳入工作分開進(jìn)行,在有的時候一系列的操作可能會有某一個或幾個參數(shù)始終完全一樣,那么我們就可以先定義一個偏函數(shù),然后再去執(zhí)行這個函數(shù)(執(zhí)行時傳入剩余的不同參數(shù))。

舉個例子,代碼如下:

var partialAny = (function (aps) {
    // 該函數(shù)是你們自執(zhí)行函數(shù)表達(dá)式的結(jié)果,并且賦值給了partialAny變量
    function func(fn) {
        var argsOrig = aps.call(arguments, 1);
        return function () {
            var args = [],
                argsPartial = aps.call(arguments),
                i = 0;  
            // 變量所有的原始參數(shù)集,
            // 如果參數(shù)是partialAny._ 占位符,則使用下一個函數(shù)參數(shù)對應(yīng)的值
            // 否則使用原始參數(shù)里的值
            for (; i < argsOrig.length; i++) {
                args[i] = argsOrig[i] === func._
                            ? argsPartial.shift()
                            : argsOrig[i];
            }  
            // 如果有任何多余的參數(shù),則添加到尾部
            return fn.apply(this, args.concat(argsPartial));
        };
    }  
    // 用于占位符設(shè)置
    func._ = {};  
    return func;
})(Array.prototype.slice);

使用方式如下:

// 定義處理函數(shù)
function hex(r, g, b) {
    return '#' + r + g + b;
}  
//定義偏函數(shù), 將hex的第一個參數(shù)r作為不變的參數(shù)值ff
var redMax = partialAny(hex, 'ff', partialAny._, partialAny._);  
// 新函數(shù)redMax的調(diào)用方式如下,只需要傳入2個參數(shù)了:
console.log(redMax('11', '22')); // "#ff1122"

如果覺得 partialAny._太長,可以用__代替哦。

var __ = partialAny._;
var greenMax = partialAny(hex, __, 'ff');
console.log(greenMax('33', '44'));
var blueMax = partialAny(hex, __, __, 'ff');
console.log(blueMax('55', '66'));
var magentaMax = partialAny(hex, 'ff', __, 'ff');
console.log(magentaMax('77')); 

這樣使用,就簡潔多了吧。

Currying

Currying 是函數(shù)式編程的一個特性,將多個參數(shù)的處理轉(zhuǎn)化成單個參數(shù)的處理,類似鏈?zhǔn)秸{(diào)用。

舉一個簡單的 add 函數(shù)的例子:

function add(x, y) {
    var oldx = x, oldy = y;
    if (typeof oldy === "undefined") { // partial
        return function (newy) {
            return oldx + newy;
        }
    }
    return x + y;
}

這樣調(diào)用方式就可以有多種了,比如:

// 測試
typeof add(5); // "function"
add(3)(4); // 7  
// 也可以這樣調(diào)用
var add2000 = add(2000);
add2000(10); // 2010

接下來,我們來定義一個比較通用的 currying 函數(shù):

// 第一個參數(shù)為要應(yīng)用的function,第二個參數(shù)是需要傳入的最少參數(shù)個數(shù)
function curry(func, minArgs) {
    if (minArgs == undefined) {
        minArgs = 1;
    }  
    function funcWithArgsFrozen(frozenargs) {
        return function () {
            // 優(yōu)化處理,如果調(diào)用時沒有參數(shù),返回該函數(shù)本身
            var args = Array.prototype.slice.call(arguments);
            var newArgs = frozenargs.concat(args);
            if (newArgs.length >= minArgs) {
                return func.apply(this, newArgs);
            } else {
                return funcWithArgsFrozen(newArgs);
            }
        };
    }  
    return funcWithArgsFrozen([]);
}

這樣,我們就可以隨意定義我們的業(yè)務(wù)行為了,比如定義加法:

var plus = curry(function () {
    var result = 0;
    for (var i = 0; i < arguments.length; ++i) {
        result += arguments[i];
    }
    return result;
}, 2);

使用方式,真實多種多樣哇。

plus(3, 2) // 正常調(diào)用
plus(3) // 偏應(yīng)用,返回一個函數(shù)(返回值為3+參數(shù)值)
plus(3)(2) // 完整應(yīng)用(返回5)
plus()(3)()()(2) // 返回 5
plus(3, 2, 4, 5) // 可以接收多個參數(shù)
plus(3)(2, 3, 5) // 同理

如下是減法的例子

var minus = curry(function (x) {
    var result = x;
    for (var i = 1; i < arguments.length; ++i) {
        result -= arguments[i];
    }
    return result;
}, 2);

或者如果你想交換參數(shù)的順序,你可以這樣定義

var flip = curry(function (func) {
    return curry(function (a, b) {
        return func(b, a);
    }, 2);
});

總結(jié)

JavaScript 里的 Function 有很多特殊的功效,可以利用閉包以及 arguments 參數(shù)特性實現(xiàn)很多不同的技巧,下一篇我們將繼續(xù)介紹利用 Function 進(jìn)行初始化的技巧。