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

資訊專欄INFORMATION COLUMN

JavaScript函數(shù)式編程

animabear / 3542人閱讀

摘要:本文試圖盡可能系統(tǒng)的描述函數(shù)式編程。函數(shù)式編程使用參數(shù)保存狀態(tài),最好的例子就是遞歸??吕锘瘮?shù)有利于指定函數(shù)行為,并將現(xiàn)有函數(shù)組合為新函數(shù)。

JavaScript函數(shù)式編程 摘要

以往經(jīng)??吹健焙瘮?shù)式編程“這一名詞,卻始終沒有花時間去學(xué)習(xí),暑期實習(xí)結(jié)束之后一直忙于邊養(yǎng)老邊減肥,81天成功瘦身30斤+ ,開始回歸正常的學(xué)習(xí)生活。
便在看《JavaScript函數(shù)式編程》這本書,以系統(tǒng)了解函數(shù)式編程的知識。本文試圖盡可能系統(tǒng)的描述JavaScript函數(shù)式編程。當(dāng)然認(rèn)識暫時停留于本書介紹的程度,如有錯誤之處,還請指正。

注:本書采用的函數(shù)式庫Underscore。一下部分代碼運行時,需引入Underscore。

函數(shù)式編程簡介

我們用一句話來直白的描述函數(shù)式編程:

函數(shù)式編程通過使用函數(shù)來將值轉(zhuǎn)換成抽象單元,接著用于構(gòu)建軟件系統(tǒng)。

概括的來說,函數(shù)式編程包括以下技術(shù)

確定抽象,并為其構(gòu)建函數(shù)

利用已有的函數(shù)來構(gòu)建更為復(fù)雜的抽象

通過將現(xiàn)有的函數(shù)傳給其他函數(shù)來構(gòu)建更加復(fù)雜的抽象

注:JavaScript并不僅限于函數(shù)式編程語言,以下是另外3種常用的編程方式。

命令式編程: 通過詳細描述行為的編程方式

基于原型的面向?qū)ο缶幊蹋?基于原型對象及其實例的編程方式

元編程:對JavaScript執(zhí)行模型數(shù)據(jù)進行編寫和操作的編程方式

函數(shù)式編程的一些特性 純函數(shù)

純函數(shù)堅持以下屬性(堅持純度的標(biāo)準(zhǔn)不僅將有助于使程序更容易測試,也更容易推理。)

其結(jié)果只能從它的參數(shù)的值來計算

不能依賴于能被外部操作改變的數(shù)據(jù)

不能改變外部狀態(tài)

不變性 —— 沒有副作用

所謂"副作用"(side effect),指的是函數(shù)內(nèi)部與外部互動(最典型的情況,就是修改全局變量的值),產(chǎn)生運算以外的其他結(jié)果。
函數(shù)式編程強調(diào)沒有"副作用",意味著函數(shù)要保持獨立,所有功能就是返回一個新的值,沒有其他行為,尤其是不得修改外部變量的值。

不修改狀態(tài)

上一點已經(jīng)提到,函數(shù)式編程只是返回新的值,不修改系統(tǒng)變量。因此,不修改變量,也是它的一個重要特點。在其他類型的語言中,變量往往用來保存"狀態(tài)"(state)。不修改變量,意味著狀態(tài)不能保存在變量中。
函數(shù)式編程使用參數(shù)保存狀態(tài),最好的例子就是遞歸。下面的代碼是一個將字符串逆序排列的函數(shù),它演示了不同的參數(shù)如何決定了運算所處的"狀態(tài)"。

function reverse(string) {
    if(string.length == 0) {
      return string;
    } else {
      return reverse(string.substring(1, string.length)) + string.substring(0, 1);
    }
  }
函數(shù)是一等公民

“一等”這個術(shù)語通常用來描述值。當(dāng)函數(shù)被看作“一等公民”時,那它就可以去任何值可以去的地方,很少有限制。比如數(shù)字在Javascript里就是一等公民,同程
作為一等公民的函數(shù)就會擁有類似數(shù)字的性質(zhì)。

var fortytwo = function(){return 42} // 函數(shù)與數(shù)字一樣可以存儲為變量
var fortytwo = [32, function(){return 42}] // 函數(shù)與數(shù)字一樣可以存儲為數(shù)組的一個元素
var fortytwo = {number: 32, fun: function(){return 42}} // 函數(shù)與數(shù)字一樣可以作為對象的成員變量
32 + (function(){return 42}) () // 函數(shù)與數(shù)字一樣可以在使用時直接創(chuàng)建出來

// 函數(shù)與數(shù)字一樣可以被傳遞給另一個函數(shù)
function weirdAdd(n, f){ return n + f()}
weirdAdd(32, function(){return 42})

// 函數(shù)與數(shù)字一樣可以被另一個函數(shù)返回
return 32;
return function(){return 42}
Applicative編程

Applicative編程是特殊函數(shù)式編程的一種形式。Applicative編程的三個典型例子是map,reduce,filter

函數(shù)A作為參數(shù)提供給函數(shù)B。 (即定義一個函數(shù),讓它接收一個函數(shù),然后調(diào)用它)

_.find(["a","b",3,"d"], _.isNumber) // _.find與_.isNumber都是Underscore中的方法

// 自行實現(xiàn)一個Applicative函數(shù)
function exam(fun, coll) {
  return fun(coll);
}
// 調(diào)用
exam(function(e){
    return e.join(",")
}, [1,2,3])
// 結(jié)果 ”1,2,3“
高階函數(shù)

定義:一個高階函數(shù)應(yīng)該可以執(zhí)行以下至少一項操作。

以一個函數(shù)作為參數(shù)

返回一個函數(shù)作為結(jié)果

以其他函數(shù)為參數(shù)的函數(shù) 關(guān)于傳遞函數(shù)的思考: max,finder,best
// max是一個高階函數(shù)
var people = [{name: "Fred", age: 65}, {name: "Lucy", age: 36}];
_.max(people, function(p) { return p.age }); 
//=> {name: "Fred", age: 65}

但是,在某些方面這個函數(shù)是受限的,并不是真正的函數(shù)式。具體來說,對于_.max而言,比較總是需要通過大于運算符(>)來完成。

不過,我們可以創(chuàng)建一個新的函數(shù)finder。它接收兩個函數(shù):一個用來生成可比較的值,而另一個用來比較兩個值并返回當(dāng)中的”最佳“值。

function finder(valueFun, bestFun, coll) {
  return _.reduce(coll, function(best, current) {
    var bestValue = valueFun(best);
    var currentValue = valueFun(current);

    return (bestValue === bestFun(bestValue, currentValue)) ? best : current;
  });
}

在任何情況下,我們現(xiàn)在都可以用finder來找到不同類型的”最佳“值:

finder(function(e){return e.age}, Math.max, people) 
// => {name: ”Fred", age: 65}

finder(function(e){return e.name}, function(x, y){
    return (x.charAt((0) === "L") ? x : y),people}) // 偏好首字母為L的人
// => {name:"Lucy", age: 36}

縮減一點
函數(shù)finder短小精悍,并且能按照我們預(yù)期來工作,但為了滿足最大程度的靈活性,它重復(fù)了一些邏輯。

//  在 finder函數(shù)中
return (bestValue === bestFun(bestValue, currentValue)) ? best : current;
// 在輸入的函數(shù)參數(shù)中
return (x.charAt((0) === "L") ? x : y

你會發(fā)現(xiàn)上述兩者的邏輯是完全相同的。finder的實現(xiàn)可以根據(jù)以下兩個假設(shè)來縮減。

如果第一個參數(shù)比第二個參數(shù)“更好”,比較最佳值的函數(shù)返回為true

比較最佳值的函數(shù)知道如何“分解”它的參數(shù)

在以上假設(shè)的基礎(chǔ)下,我們可以實現(xiàn)一個更簡潔的best函數(shù)。

function best(fun, coll) {
  return _.reduce(coll, function(x, y) {
    return fun(x, y) ? x : y;
  });
}

best(function(x,y) { return x > y }, [1,2,3,4,5]);
//=> 5
關(guān)于傳遞函數(shù)的更多思考:重復(fù),反復(fù)和條件迭代

首先,從一個簡單的函數(shù)repeat開始。它以一個數(shù)字和一個值為參數(shù),將該值進行多次復(fù)制,并放入一個數(shù)組中:

function repeat(times, VALUE) {
  return _.map(_.range(times), function() { return VALUE; });
}

repeat(4, "Major");
//=> ["Major", "Major", "Major", "Major"]

使用函數(shù),而不是值
通過將參數(shù)從值替換為函數(shù),打開了一個充滿可能性的世界。

function repeatedly(times, fun) {
  return _.map(_.range(times), fun);
}

repeatedly(3, function() {
  return Math.floor((Math.random()*10)+1);
});
//=> [1, 3, 8]

再次強調(diào),“使用函數(shù),而不是值”
我們常常會知道函數(shù)應(yīng)該被調(diào)用多少次,但有時候也知道什么時候推出并不取決于“次數(shù)”,而是條件!因此我可以定義另一個名為iterateUntil的函數(shù)。
iterateUntil接收2個參數(shù),一個用來執(zhí)行一些動作,另一個用來進行結(jié)果檢查。

function iterateUntil(fun, check, init) {
  var ret = [];
  var result = fun(init);

  while (check(result)) {
    ret.push(result);
    result = fun(result);
  }

  return ret;
};
返回其他函數(shù)的函數(shù)
function invoker (NAME, METHOD) { // 接收一個方法,并在任何給定的對象上調(diào)用它
  return function(target /* args ... */) {
    if (!existy(target)) fail("Must provide a target");

    var targetMethod = target[NAME];
    var args = _.rest(arguments);

    return doWhen((existy(targetMethod) && METHOD === targetMethod), function() {
      return targetMethod.apply(target, args);
    });
  };
};

var rev = invoker("reverse", Array.prototype.reverse);

_.map([[1,2,3]], rev);
//=> [[3,2,1]]

高階函數(shù)捕獲參數(shù)
高階函數(shù)的參數(shù)是用來“配置”返回函數(shù)的行為的。對于makeAdder而言,它的參數(shù)配置了其返回函數(shù)每次添加數(shù)值的大小

function makeAdder(CAPTURED) {
  return function(free) {
    return free + CAPTURED;
  };
}
var add10 = makeAdder(10);

add10(32);
//=> 42

捕獲變量的好處
用閉包來捕獲增加值,并用作后綴。(但這樣并不具有引用透明)

function makeUniqueStringFunction(start) {
  var COUNTER = start;

  return function(prefix) {
    return [prefix, COUNTER++].join("");
  }
};
var uniqueString = makeUniqueStringFunction(0);

uniqueString("dari");
//=> "dari0"

uniqueString("dari");
//=> "dari1"
由函數(shù)構(gòu)建函數(shù) 函數(shù)式組合的精華

精華:使用現(xiàn)有的零部件來建立新的行為,這些新行為同樣也成為了已有的零部件。

// 接收一個或多個函數(shù),然后不斷嘗試依次調(diào)用這些函數(shù)的方法,直到返回一個非`undefined`的值
function dispatch(/* funs */) {
  var funs = _.toArray(arguments);
  var size = funs.length;

  return function(target /*, args */) {
    var ret = undefined;
    var args = _.rest(arguments);

    for (var funIndex = 0; funIndex < size; funIndex++) {
      var fun = funs[funIndex];
      ret = fun.apply(fun, construct(target, args));

      if (existy(ret)) return ret;
    }

    return ret;
  };
}

var str = dispatch(invoker("toString", Array.prototype.toString),
invoker("toString", String.prototype.toString));

str("a");
//=> "a"

str(_.range(10));
//=> "0,1,2,3,4,5,6,7,8,9"

在這里,我們想做的只是返回一個遍歷函數(shù)數(shù)組,并apply給一個目標(biāo)對象的函數(shù),返回第一個存在的值。dispatch滿足了多態(tài)JavaScript
函數(shù)的定義。這樣簡化了委托具體方法的任務(wù)。例如,在underscore的實現(xiàn)中,你經(jīng)常會看到許多不同的函數(shù)重復(fù)這樣的模式。

確保目標(biāo)的存在

檢查是否有原生版本,如果是則使用它

如果沒有,那么做一些實現(xiàn)這些行為的具體任務(wù)。

做特定類型的任務(wù)(如適用)

做特定參數(shù)的任務(wù)(如適用)

做特定個參數(shù)的任務(wù)(如適用)

同樣的模式也體現(xiàn)在Underscore的函數(shù)_.map()的實現(xiàn)中:

  _.map = _.collect = function(obj, iteratee, context) {
    iteratee = cb(iteratee, context);
    var keys = !isArrayLike(obj) && _.keys(obj),
        length = (keys || obj).length,
        results = Array(length);
    for (var index = 0; index < length; index++) {
      var currentKey = keys ? keys[index] : index;
      results[index] = iteratee(obj[currentKey], currentKey, obj);
    }
    return results;
  };

使用dispatch可以簡化一些這方面的代碼,并且更容易擴展。想象一下,你正在寫一個可以為數(shù)組和字符串類型生成字符描述的
函數(shù)。使用dispatch則可以優(yōu)雅的實現(xiàn):

var str = dispatch(invoker("toString", Array.prototype.toString),
invoker("toString", String.prototype.toString));

str("a");
//=> "a"

str(_.range(10));
//=> "0,1,2,3,4,5,6,7,8,9"
柯里化 Curring

柯里化函數(shù)為每一個邏輯參數(shù)返回一個新函數(shù)。

例如:

// 除法
function divide(n,d){
  return n/d;
}

// 手動柯里化
function curryDivide(n) { 
  return function(d) {
    return n/d;
  };
}

curryDivide是手動柯里化函數(shù),也就是說,我顯示地返回對應(yīng)參數(shù)數(shù)量的函數(shù)。

自動柯里化參數(shù)

// 接收一個函數(shù),并返回一個只接受一個參數(shù)的函數(shù)。
function curry(fun) { // 柯里化一個參數(shù),雖然似乎沒什么用
  return function(arg) {
    return fun(arg);
  };
}

function curry2(fun) { // 柯里化兩個參數(shù)
  return function(secondArg) {
    return function(firstArg) {
        return fun(firstArg, secondArg);
    };
  };
}
function curry3(fun) { // 柯里化三個參數(shù)
  return function(last) {
    return function(middle) {
      return function(first) {
        return fun(first, middle, last);
      };
    };
  };
};

curry2函數(shù)接受一個函數(shù)并將其柯里化成兩個深層參數(shù)的函數(shù)??梢杂盟鼇韺崿F(xiàn)先前定義的除法函數(shù)。

var divide10 = curry2(div)(10) 

divide10(50)
// => 5

柯里化函數(shù)有利于指定JavaScript函數(shù)行為,并將現(xiàn)有函數(shù)“組合”為新函數(shù)。并且使用柯里化比較容易產(chǎn)生流利的函數(shù)式API。

部分應(yīng)用

柯里化函數(shù)逐漸返回消耗參數(shù)的函數(shù),直到所有參數(shù)都耗盡。然而,部分應(yīng)用函數(shù)是一個“部分“執(zhí)行,等待接收剩余的參數(shù)立即執(zhí)行的函數(shù)。

// 部分應(yīng)用一個或兩個已知的參數(shù)
function partial1(fun, arg1) {
  return function(/* args */) {
    var args = construct(arg1, arguments); // construct為拼接數(shù)組,在此代碼略去
    return fun.apply(fun, args);
  };
}

function partial2(fun, arg1, arg2) {
  return function(/* args */) {
    var args = cat([arg1, arg2], arguments); // cat也為拼接數(shù)組,在此代碼略去
    return fun.apply(fun, args);
  };
}

// 部分應(yīng)用任意數(shù)量的參數(shù)
function partial(fun /*, pargs */) {
  var pargs = _.rest(arguments);

  return function(/* arguments */) {
    var args = cat(pargs, _.toArray(arguments));
    return fun.apply(fun, args);
  };
}
通過組合端至端的拼接函數(shù)

一種理想化的函數(shù)式程序是向函數(shù)流水線的一端輸送的一塊數(shù)據(jù),從另一端輸出一個全新的數(shù)據(jù)塊。
!_.isString(name)
這個流水線由_.isString!組成

_.isString接收一個對象,并返回一個布爾值

!接收一個布爾值,并返回一個布爾值

// 通過組合多個函數(shù)及其數(shù)據(jù)轉(zhuǎn)換建立新的函數(shù)
function isntString(str){
return !_.isString(str)
}

isntString(1)
// => true

// 還可以使用Underscore的_.compose函數(shù)實現(xiàn)同樣的功能
// _.compose函數(shù)從右往左執(zhí)行。即最右邊函數(shù)的結(jié)果會被送入其左側(cè)的函數(shù),一個接一個
var isntString = _.compose(function(x) { return !x }, _.isString);

isntString([]);
//=> true
遞歸

理解遞歸對理解函數(shù)式編程來說非常重要,原因有三。

遞歸的解決方案包括使用對一個普通問題子集的單一抽象的使用

遞歸可以隱藏可變狀態(tài)

遞歸是一種實現(xiàn)懶惰和無限大結(jié)構(gòu)的方法

自吸收函數(shù)

在編寫自遞歸函數(shù)時,規(guī)則如下

知道什么時候停止

決定怎樣算一個步驟

把問題分解成一個步驟和一個較小的問題

function myLength(ary) {
  if (_.isEmpty(ary)) // _.isEmpty何時停止 
    return 0; 
  else
    // 進行一個步驟 1+ ;
    return 1 + myLength(_.rest(ary)); // 小一些的問題 _.rest(ary)   
}

尾遞歸
尾遞歸與一般自遞歸的明顯區(qū)別是,”一個步驟“和”縮小的問題“中的元素都要進行遞歸調(diào)用。

function tcLength(ary, n) {
  var l = n ? n : 0;

  if (_.isEmpty(ary))
    return l;
  else
    return tcLength(_.rest(ary), l + 1);
}

tcLength(_.range(10));
//=> 10
相互關(guān)聯(lián)函數(shù)

兩個或多個函數(shù)相互調(diào)用被稱為相互遞歸。下面看一個例子,用謂詞函數(shù)來檢查偶數(shù)和奇數(shù):

function evenSteven(n) {
  if (n === 0)
    return true;
  else
    return oddJohn(Math.abs(n) - 1);
}

function oddJohn(n) {
  if (n === 0)
    return false;
  else
    return evenSteven(Math.abs(n) - 1);
}
// 相互遞歸調(diào)用來回反彈彼此之間遞減某個絕對的值,知道一方或另一方達到0
evenSteven(4)
//  => true
oddJohn(11)
// =>true
對遞歸的改進

盡管遞歸技術(shù)上是可行的,但是因為JavaScript引擎沒有優(yōu)化遞歸調(diào)用,因此,在使用或?qū)戇f歸函數(shù)時,可能會碰到如下錯誤

evenSteven(10000) 
// 棧溢出

遞歸應(yīng)該被看作一個底層操作,應(yīng)該盡可能地避免(很容易造成棧溢出)。普通的共識是,首先是要函數(shù)組合,僅當(dāng)需要的時才使用遞歸和蹦床。

蹦床(tramponline):使用蹦床展平調(diào)用,而不是深度嵌套的遞歸調(diào)用。

首先,看看如何手動修復(fù)evenOlineoddOline使得遞歸調(diào)用不會溢出。一個辦法是返回一個函數(shù),它包裝調(diào)用,而不是直接直接調(diào)用。

function evenOline(n) {
  if (n === 0)
    return true;
  else
    return partial1(oddOline, Math.abs(n) - 1);
}

function oddOline(n) {
  if (n === 0)
    return false;
  else
    return partial1(evenOline, Math.abs(n) - 1);
}

oddOline(3)()() // 返回的只是一個函數(shù)調(diào)用
// => function(){return evenOline(Math.abs(n) - 1)}
oddOline(3)()()() // 將函數(shù)調(diào)用執(zhí)行
// => true
oddOline(10000)()()()... // 10000個()去執(zhí)行返回的函數(shù)調(diào)用
// => true

當(dāng)然,我們不能直接向用戶暴露這個API,可以提高另外一個函數(shù)trampoline,從程序執(zhí)行來進行扁平化處理。

function trampoline(fun /*, args */) { // 不斷調(diào)用函數(shù)的返回值,知道它不是一個函數(shù)為止
  var result = fun.apply(fun, _.rest(arguments));

  while (_.isFunction(result)) {
    result = result();
  }

  return result;
}

trampoline(oddOline, 10000)
// false

由于調(diào)用鏈的間接性,使用蹦床增加了相互遞歸函數(shù)的一些開銷。然而滿總比溢出要好。同樣,你可能不希望強迫用戶使用trampoline,只是為了避免堆棧溢出。我們可以進一步隱藏其外觀。

function isEvenSafe(n) {
  if (n === 0)
    return true;
  else
    return trampoline(partial1(oddOline, Math.abs(n) - 1));
}

function isOddSafe(n) {
  if (n === 0)
    return false;
  else
    return trampoline(partial1(evenOline, Math.abs(n) - 1));
}
基于流的編程 鏈接

使用jQuery等庫經(jīng)常會使用鏈接,鏈接可以讓我們的代碼更加簡潔,如下是鏈接的實現(xiàn)示例。
鏈接方法的原理在于。每個鏈接的方法都返回統(tǒng)一的宿主對象引用。

function createPerson() {
  var firstName = "";
  var age = 0;

  return {
    setFirstName: function(fn) {
      firstName = fn;
      return this;
    },
    setAge: function(a) {
      age = a;
      return this;
    },
    toString: function() {
      return [firstName, lastName, age].join(" ");
    }
  };
}

createPerson()
  .setFirstName("Mike")
  .setAge(108)
  .toString();

//=> "Mike 108"

惰性鏈

上述鏈接是直接執(zhí)行,然而我們也可以實行惰性鏈,即使其先緩存待執(zhí)行的函數(shù),等到調(diào)用執(zhí)行函數(shù)時一起執(zhí)行。
封裝了一些行為的函數(shù)通常被稱為thunk,存儲在_calls中的thunk期待將作為接受force方法調(diào)用的對象的中間目標(biāo)。

function LazyChain(obj) {
  this._calls  = []; // 用于緩存待執(zhí)行函數(shù)的數(shù)組 thunk
  this._target = obj; // 目標(biāo)對象
}

LazyChain.prototype.invoke = function(methodName /*, args */) { // 將函數(shù)壓入的方法
  var args = _.rest(arguments);

  this._calls.push(function(target) {
    var meth = target[methodName];

    return meth.apply(target, args);
  });

  return this;
};

LazyChain.prototype.force = function() { // 強制執(zhí)行this._calls中的函數(shù)
  return _.reduce(this._calls, function(target, thunk) {
    return thunk(target);
  }, this._target);
};
// 使用,直到force方法被調(diào)用才將 concat, sort,join執(zhí)行
new LazyChain([2,1,3])
    .invoke("concat", [8,5,7,6])
    .invoke("sort")
    .invoke("join"," ")
    .force();

// => "1 2 3 4 5 6 7 8"
管道

鏈接模式有利于給對象的方法調(diào)用創(chuàng)建流程的API,但是對于函數(shù)式API則未必。
方法連接有各種各樣的缺點,包括緊耦合對象的set和get邏輯。主要問題是,函數(shù)鏈經(jīng)常會做調(diào)用之間改變傳遞的共同引用。函數(shù)式API重點在操作值而不是引用。
一下是管道的具體實現(xiàn)

function pipeline(seed /*, args */) {
  return _.reduce(_.rest(arguments),
                  function(l,r) { return r(l); },
                  seed);
};
pipeline(42, function(n){return -n},function(n){return n+1})
// => -41
寫在最后

本文更多的是對《JavaScript函數(shù)式編程》一書的摘要,并透過一段段代碼試圖闡述函數(shù)式編程的思想。
希望以后的工作中能夠吸取函數(shù)式編程的好,并慢慢對其加深理解。從書中獲取知識,最終還是要落于實踐中去的。
同時,希望能夠通過這篇文章幫助不了解函數(shù)式編程的小伙伴建立系統(tǒng)的認(rèn)識。

WilsonLiu"s blog首發(fā)地址:http://blog.wilsonliu.cn

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

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

相關(guān)文章

  • SegmentFault 技術(shù)周刊 Vol.16 - 淺入淺出 JavaScript 函數(shù)編程

    摘要:函數(shù)式編程,一看這個詞,簡直就是學(xué)院派的典范。所以這期周刊,我們就重點引入的函數(shù)式編程,淺入淺出,一窺函數(shù)式編程的思想,可能讓你對編程語言的理解更加融會貫通一些。但從根本上來說,函數(shù)式編程就是關(guān)于如使用通用的可復(fù)用函數(shù)進行組合編程。 showImg(https://segmentfault.com/img/bVGQuc); 函數(shù)式編程(Functional Programming),一...

    csRyan 評論0 收藏0
  • 翻譯連載 | 附錄 C:函數(shù)編程函數(shù)庫-《JavaScript輕量級函數(shù)編程》 |《你不知道的J

    摘要:為了盡可能提升互通性,已經(jīng)成為函數(shù)式編程庫遵循的實際標(biāo)準(zhǔn)。與輕量級函數(shù)式編程的概念相反,它以火力全開的姿態(tài)進軍的函數(shù)式編程世界。 原文地址:Functional-Light-JS 原文作者:Kyle Simpson-《You-Dont-Know-JS》作者 關(guān)于譯者:這是一個流淌著滬江血液的純粹工程:認(rèn)真,是 HTML 最堅實的梁柱;分享,是 CSS 里最閃耀的一瞥;總結(jié),...

    Miracle 評論0 收藏0
  • 每個 JavaScript 工程師都應(yīng)當(dāng)知道的 10 個面試題

    摘要:所支持的面向?qū)ο缶幊贪ㄔ屠^承。發(fā)明于年的就是首批支持函數(shù)式編程的語言之一,而演算則可以說是孕育了這門語言。即使在今天,這個家族的編程語言應(yīng)用范圍依然很廣。 1. 能說出來兩種對于 JavaScript 工程師很重要的編程范式么? JavaScript 是一門多范式(multi-paradigm)的編程語言,它既支持命令式(imperative)/面向過程(procedural)編程...

    jone5679 評論0 收藏0
  • 每個 JavaScript 工程師都應(yīng)當(dāng)知道的 10 個面試題

    摘要:所支持的面向?qū)ο缶幊贪ㄔ屠^承。發(fā)明于年的就是首批支持函數(shù)式編程的語言之一,而演算則可以說是孕育了這門語言。即使在今天,這個家族的編程語言應(yīng)用范圍依然很廣。 1. 能說出來兩種對于 JavaScript 工程師很重要的編程范式么? JavaScript 是一門多范式(multi-paradigm)的編程語言,它既支持命令式(imperative)/面向過程(procedural)編程...

    YorkChen 評論0 收藏0
  • 每個 JavaScript 工程師都應(yīng)當(dāng)知道的 10 個面試題

    摘要:所支持的面向?qū)ο缶幊贪ㄔ屠^承。發(fā)明于年的就是首批支持函數(shù)式編程的語言之一,而演算則可以說是孕育了這門語言。即使在今天,這個家族的編程語言應(yīng)用范圍依然很廣。 1. 能說出來兩種對于 JavaScript 工程師很重要的編程范式么? JavaScript 是一門多范式(multi-paradigm)的編程語言,它既支持命令式(imperative)/面向過程(procedural)編程...

    Gilbertat 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<