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

資訊專欄INFORMATION COLUMN

JavaScript 之函數(shù)式編程

bbbbbb / 1822人閱讀

摘要:同步發(fā)布于是個(gè)程序員都知道函數(shù),但是有些人不一定清楚函數(shù)式編程的概念。你的項(xiàng)目沒(méi)用到函數(shù)式編程,不代表項(xiàng)目不好。函數(shù)式編程的對(duì)立面就是命令式編程。函數(shù)式編程只是一個(gè)概念一致編碼方式,并沒(méi)有嚴(yán)格的定義。這里總結(jié)一些常用的函數(shù)式編程應(yīng)用場(chǎng)景。

同步發(fā)布于 https://github.com/xianshanna...

是個(gè)程序員都知道函數(shù),但是有些人不一定清楚函數(shù)式編程的概念。

應(yīng)用的迭代使程序變得越來(lái)越復(fù)雜,那么程序員很有必要?jiǎng)?chuàng)造一個(gè)結(jié)構(gòu)良好、可讀性好、重用性高和可維護(hù)性高的代碼。

函數(shù)式編程就是一個(gè)良好的代碼方式,但是這不代表函數(shù)式編程是必須的。你的項(xiàng)目沒(méi)用到函數(shù)式編程,不代表項(xiàng)目不好。

什么是函數(shù)式編程(FP)?
函數(shù)式編程關(guān)心數(shù)據(jù)的映射,命令式編程關(guān)心解決問(wèn)題的步驟。

函數(shù)式編程的對(duì)立面就是命令式編程。

函數(shù)式編程語(yǔ)言中的變量也不是命令式編程語(yǔ)言中的變量,即存儲(chǔ)狀態(tài)的單元,而是代數(shù)中的變量,即一個(gè)值的名稱。 變量的值是不可變的(immutable),也就是說(shuō)不允許像命令式編程語(yǔ)言中那樣多次給一個(gè)變量賦值。

函數(shù)式編程只是一個(gè)概念(一致編碼方式),并沒(méi)有嚴(yán)格的定義。本人根據(jù)網(wǎng)上的知識(shí)點(diǎn),簡(jiǎn)單的總結(jié)一下函數(shù)式編程的定義(本人總結(jié),或許有人會(huì)不同意這個(gè)觀點(diǎn))。

函數(shù)式編程就是純函數(shù)的應(yīng)用,然后把不同的邏輯分離為許多獨(dú)立功能的純函數(shù)(模塊化思想),然后再整合在一起,變成復(fù)雜的功能。

什么是純函數(shù)?
一個(gè)函數(shù)如果輸入確定,那么輸出結(jié)果是唯一確定的,并且沒(méi)有副作用,那么它就是純函數(shù)。

一般符合上面提到的兩點(diǎn)就算純函數(shù):

相同的輸入必定產(chǎn)生相同的輸出

在計(jì)算的過(guò)程中,不會(huì)產(chǎn)生副作用

那怎么理解副作用呢?

簡(jiǎn)單的說(shuō)就是變量的值不可變,包括函數(shù)外部變量和函數(shù)內(nèi)部變量。

所謂副作用,指的是函數(shù)內(nèi)部與外部互動(dòng)(最典型的情況,就是修改全局變量的值),產(chǎn)生運(yùn)算以外的其他結(jié)果。

這里說(shuō)明一下不可變不可變指的是我們不能改變?cè)瓉?lái)的變量值?;蛘咴瓉?lái)變量值的改變,不能影響到返回結(jié)果。不是變量值本來(lái)就是不可變。

純函數(shù)特性對(duì)比例子

上面的理論描述對(duì)于剛接觸這個(gè)概念的程序員,或許不好理解。下面會(huì)通過(guò)純函數(shù)的特點(diǎn)一一舉例說(shuō)明。

輸入相同返回值相同

純函數(shù)

function test(pi) {
  // 只要 pi 確定,返回結(jié)果就一定確定。
  return pi + 2;
}
test(3);

非純函數(shù)

function test(pi) {
  // 隨機(jī)數(shù)返回值不確定
  return pi + Math.random();
}

test(3);
返回值不受外部變量的影響

非純函數(shù),返回值會(huì)被其他變量影響(說(shuō)明有副作用),返回值不確定。

let a = 2;
function test(pi) {
  // a 的值可能中途被修改
  return pi + a;
}
a = 3;
test(3);

非純函數(shù),返回值受到對(duì)象 getter 的影響,返回結(jié)果不確定。

const obj = Object.create(
  {},
  {
    bar: {
      get: function() {
        return Math.random();
      },
    },
  }
);

function test(obj) {
  // obj.a 的值是隨機(jī)數(shù)
  return obj.a;
}
test(obj);

純函數(shù),參數(shù)唯一,返回值確定。

function test(pi) {
  // 只要 pi 確定,返回結(jié)果就一定確定。
  return pi + 2;
}
test(3);
輸入值是不可以被改變的

非純函數(shù),這個(gè)函數(shù)已經(jīng)改變了外面 personInfo 的值了(產(chǎn)生了副作用)。

const personInfo = { firstName: "shannan", lastName: "xian" };

function revereName(p) {
  p.lastName = p.lastName
    .split("")
    .reverse()
    .join("");
  p.firstName = p.firstName
    .split("")
    .reverse()
    .join("");
  return `${p.firstName} ${p.lastName}`;
}
revereName(personInfo);
console.log(personInfo);
// 輸出 { firstName: "nannahs",lastName: "naix" }
// personInfo 被修改了

純函數(shù),這個(gè)函數(shù)不影響外部任意的變量。

const personInfo = { firstName: "shannan", lastName: "xian" };

function reverseName(p) {
  const lastName = p.lastName
    .split("")
    .reverse()
    .join("");
  const firstName = p.firstName
    .split("")
    .reverse()
    .join("");
  return `${firstName} ${lastName}`;
}
revereName(personInfo);
console.log(personInfo);
// 輸出 { firstName: "shannan",lastName: "xian" }
// personInfo 還是原值

那么你們是不是有疑問(wèn),personInfo 對(duì)象是引用類型,異步操作的時(shí)候,中途改變了 personInfo,那么輸出結(jié)果那就可能不確定了。

如果函數(shù)存在異步操作,的確有存在這個(gè)問(wèn)題,的確應(yīng)該確保 personInfo 不能被外部再次改變(可以通過(guò)深度拷貝)。

但是,這個(gè)簡(jiǎn)單的函數(shù)里面并沒(méi)有異步操作,reverseName 函數(shù)運(yùn)行的那一刻 p 的值已經(jīng)是確定的了,直到返回結(jié)果。

下面的異步操作才需要確保 personInfo 中途不會(huì)被改變:

async function reverseName(p) {
  await new Promise(resolve => {
    setTimeout(() => {
      resolve();
    }, 1000);
  });
  const lastName = p.lastName
    .split("")
    .reverse()
    .join("");
  const firstName = p.firstName
    .split("")
    .reverse()
    .join("");
  return `${firstName} ${lastName}`;
}

const personInfo = { firstName: "shannan", lastName: "xian" };

async function run() {
  const newName = await reverseName(personInfo);
  console.log(newName);
}

run();
personInfo.firstName = "test";
// 輸出為 tset naix,因?yàn)楫惒讲僮鞯闹型?firstName 被改變了

修改成下面的方式就可以確保 personInfo 中途的修改不影響異步操作:

// 這個(gè)才是純函數(shù)
async function reverseName(p) {
  // 淺層拷貝,這個(gè)對(duì)象并不復(fù)雜
  const newP = { ...p };
  await new Promise(resolve => {
    setTimeout(() => {
      resolve();
    }, 1000);
  });
  const lastName = newP.lastName
    .split("")
    .reverse()
    .join("");
  const firstName = newP.firstName
    .split("")
    .reverse()
    .join("");
  return `${firstName} ${lastName}`;
}

const personInfo = { firstName: "shannan", lastName: "xian" };

// run 不是純函數(shù)
async function run() {
  const newName = await reverseName(personInfo);
  console.log(newName);
}

// 當(dāng)然小先運(yùn)行 run,然后再去改 personInfo 對(duì)象。
run();
personInfo.firstName = "test";
// 輸出為 nannahs naix

這個(gè)還是有個(gè)缺點(diǎn),就是外部 personInfo 對(duì)象還是會(huì)被改到,但不影響之前已經(jīng)運(yùn)行的 run 函數(shù)。如果再次運(yùn)行 run 函數(shù),輸入都變了,輸出當(dāng)然也變了。

參數(shù)和返回值可以是任意類型

那么返回函數(shù)也是可以的。

function addX(y) {
  return function(x) {
    return x + y;
  };
}
盡量只做一件事

當(dāng)然這個(gè)要看實(shí)際應(yīng)用場(chǎng)景,這里舉個(gè)簡(jiǎn)單例子。

兩件事一起做(不太好的做法):

function getFilteredTasks(tasks) {
  let filteredTasks = [];
  for (let i = 0; i < tasks.length; i++) {
    let task = tasks[i];
    if (task.type === "RE" && !task.completed) {
      filteredTasks.push({ ...task, userName: task.user.name });
    }
  }
  return filteredTasks;
}
const filteredTasks = getFilteredTasks(tasks);

getFilteredTasks 也是純函數(shù),但是下面的純函數(shù)更好。

兩件事分開(kāi)做(推薦的做法):

function isPriorityTask(task) {
  return task.type === "RE" && !task.completed;
}
function toTaskView(task) {
  return { ...task, userName: task.user.name };
}
let filteredTasks = tasks.filter(isPriorityTask).map(toTaskView);

isPriorityTasktoTaskView 就是純函數(shù),而且都只做了一件事,也可以多帶帶反復(fù)使用。

結(jié)果可緩存

根據(jù)純函數(shù)的定義,只要輸入確定,那么輸出結(jié)果就一定確定。我們就可以針對(duì)純函數(shù)返回結(jié)果進(jìn)行緩存(緩存代理設(shè)計(jì)模式)。

const personInfo = { firstName: "shannan", lastName: "xian" };

function reverseName(firstName, lastName) {
  const newLastName = lastName
    .split("")
    .reverse()
    .join("");
  const newFirstName = firstName
    .split("")
    .reverse()
    .join("");
  console.log("在 proxyReverseName 中,相同的輸入,我只運(yùn)行了一次");
  return `${newFirstName} ${newLastName}`;
}

const proxyReverseName = (function() {
  const cache = {};
  return (firstName, lastName) => {
    const name = firstName + lastName;
    if (!cache[name]) {
      cache[name] = reverseName(firstName, lastName);
    }
    return cache[name];
  };
})();
函數(shù)式編程有什么優(yōu)點(diǎn)?

實(shí)施函數(shù)式編程的思想,我們應(yīng)該盡量讓我們的函數(shù)有以下的優(yōu)點(diǎn):

更容易理解

更容易重復(fù)使用

更容易測(cè)試

更容易維護(hù)

更容易重構(gòu)

更容易優(yōu)化

更容易推理

函數(shù)式編程有什么缺點(diǎn)?

性能可能相對(duì)來(lái)說(shuō)較差

函數(shù)式編程可能會(huì)犧牲時(shí)間復(fù)雜度來(lái)?yè)Q取了可讀性和維護(hù)性。但是呢,這個(gè)對(duì)用戶來(lái)說(shuō)這個(gè)性能十分微小,有些場(chǎng)景甚至可忽略不計(jì)。前端一般場(chǎng)景不存在非常大的數(shù)據(jù)量計(jì)算,所以你盡可放心的使用函數(shù)式編程??聪律厦嫣岬絺€(gè)的例子(數(shù)據(jù)量要稍微大一點(diǎn)才好對(duì)比):

首先我們先賦值 10 萬(wàn)條數(shù)據(jù):

const tasks = [];
for (let i = 0; i < 100000; i++) {
  tasks.push({
    user: {
      name: "one",
    },
    type: "RE",
  });
  tasks.push({
    user: {
      name: "two",
    },
    type: "",
  });
}

兩件事一起做,代碼可讀性不夠好,理論上時(shí)間復(fù)雜度為 o(n),不考慮 push 的復(fù)雜度。

(function() {
  function getFilteredTasks(tasks) {
    let filteredTasks = [];
    for (let i = 0; i < tasks.length; i++) {
      let task = tasks[i];
      if (task.type === "RE" && !task.completed) {
        filteredTasks.push({ ...task, userName: task.user.name });
      }
    }
    return filteredTasks;
  }

  const timeConsumings = [];

  for (let k = 0; k < 100; k++) {
    const beginTime = +new Date();
    getFilteredTasks(tasks);
    const endTime = +new Date();

    timeConsumings.push(endTime - beginTime);
  }

  const averageTimeConsuming =
    timeConsumings.reduce((all, current) => {
      return all + current;
    }) / timeConsumings.length;

  console.log(`第一種風(fēng)格平均耗時(shí):${averageTimeConsuming} 毫秒`);
})();

兩件事分開(kāi)做,代碼可讀性相對(duì)好,理論上時(shí)間復(fù)雜度接近 o(2n)

(function() {
  function isPriorityTask(task) {
    return task.type === "RE" && !task.completed;
  }
  function toTaskView(task) {
    return { ...task, userName: task.user.name };
  }

  const timeConsumings = [];

  for (let k = 0; k < 100; k++) {
    const beginTime = +new Date();
    tasks.filter(isPriorityTask).map(toTaskView);
    const endTime = +new Date();

    timeConsumings.push(endTime - beginTime);
  }

  const averageTimeConsuming =
    timeConsumings.reduce((all, current) => {
      return all + current;
    }) / timeConsumings.length;

  console.log(`第二種風(fēng)格平均耗時(shí):${averageTimeConsuming} 毫秒`);
})();

上面的例子多次運(yùn)行得出耗時(shí)平均值,在數(shù)據(jù)較少和較多的情況下,發(fā)現(xiàn)兩者平均值并沒(méi)有多大差別。10 萬(wàn)條數(shù)據(jù),運(yùn)行 100 次取耗時(shí)平均值,第二種風(fēng)格平均多耗時(shí) 15 毫秒左右,相當(dāng)于 10 萬(wàn)條數(shù)據(jù)多耗時(shí) 1.5 秒,1 萬(wàn)條數(shù)多據(jù)耗時(shí) 150 毫秒(150 毫秒用戶基本感知不到)。

雖然理論上時(shí)間復(fù)雜度多了一倍,但是在數(shù)據(jù)不龐大的情況下(會(huì)有個(gè)臨界線的),這個(gè)性能相差其實(shí)并不大,完全可以犧牲瀏覽器用戶的這點(diǎn)性能換取可讀和可維護(hù)性。

很可能被過(guò)度使用

過(guò)度使用反而是項(xiàng)目維護(hù)性變差。有些人可能寫著寫著,就變成別人看不懂的代碼,自己覺(jué)得挺高大上的,但是你確定別人能快速的看懂不? 適當(dāng)?shù)氖褂貌攀呛侠淼摹?/p>

應(yīng)用場(chǎng)景

概念是概念,實(shí)際應(yīng)用卻是五花八門,沒(méi)有實(shí)際應(yīng)用,記住了也是死記硬背。這里總結(jié)一些常用的函數(shù)式編程應(yīng)用場(chǎng)景。

簡(jiǎn)單使用

有時(shí)候很多人都用到了函數(shù)式的編程思想(最簡(jiǎn)單的用法),但是沒(méi)有意識(shí)到而已。下面的列子就是最簡(jiǎn)單的應(yīng)用,這個(gè)不用怎么說(shuō)明,根據(jù)上面的純函數(shù)特點(diǎn),都應(yīng)該看的明白。

function sum(a, b) {
  return a + b;
}
立即執(zhí)行的匿名函數(shù)

匿名函數(shù)經(jīng)常用于隔離內(nèi)外部變量(變量不可變)。

const personInfo = { firstName: "shannan", lastName: "xian" };

function reverseName(firstName, lastName) {
  const newLastName = lastName
    .split("")
    .reverse()
    .join("");
  const newFirstName = firstName
    .split("")
    .reverse()
    .join("");
  console.log("在 proxyReverseName 中,相同的輸入,我只運(yùn)行了一次");
  return `${newFirstName} ${newLastName}`;
}

// 匿名函數(shù)
const proxyReverseName = (function() {
  const cache = {};
  return (firstName, lastName) => {
    const name = firstName + lastName;
    if (!cache[name]) {
      cache[name] = reverseName(firstName, lastName);
    }
    return cache[name];
  };
})();
JavaScript 的一些 API

如數(shù)組的 forEach、map、reduce、filter 等函數(shù)的思想就是函數(shù)式編程思想(返回新數(shù)組),我們并不需要使用 for 來(lái)處理。

const arr = [1, 2, "", false];
const newArr = arr.filter(Boolean);
// 相當(dāng)于 const newArr = arr.filter(value => Boolean(value))
遞歸

遞歸也是一直常用的編程方式,可以代替 while 來(lái)處理一些邏輯,這樣的可讀性和上手度都比 while 簡(jiǎn)單。

如下二叉樹(shù)所有節(jié)點(diǎn)求和例子:

const tree = {
  value: 0,
  left: {
    value: 1,
    left: {
      value: 3,
    },
  },
  right: {
    value: 2,
    right: {
      value: 4,
    },
  },
};

while 的計(jì)算方式:

function sum(tree) {
  let sumValue = 0;
  // 使用列隊(duì)方式處理,使用棧也可以,處理順序不一樣
  const stack = [tree];

  while (stack.length !== 0) {
    const currentTree = stack.shift();
    sumValue += currentTree.value;

    if (currentTree.left) {
      stack.push(currentTree.left);
    }

    if (currentTree.right) {
      stack.push(currentTree.right);
    }
  }

  return sumValue;
}

遞歸的計(jì)算方式:

function sum(tree) {
  let sumValue = 0;

  if (tree && tree.value !== undefined) {
    sumValue += tree.value;

    if (tree.left) {
      sumValue += sum(tree.left);
    }
    if (tree.right) {
      sumValue += sum(tree.right);
    }
  }

  return sumValue;
}

遞歸會(huì)比 while 代碼量少,而且可讀性更好,更容易理解。

鏈?zhǔn)骄幊?/b>

如果接觸過(guò) jquery,我們最熟悉的莫過(guò)于 jq 的鏈?zhǔn)奖憷恕,F(xiàn)在 ES6 的數(shù)組操作也支持鏈?zhǔn)讲僮鳎?/p>

const arr = [1, 2, "", false];
const newArr = arr.filter(Boolean).map(String);
// 輸出 "1", "2"]

或者我們自定義鏈?zhǔn)?,加減乘除的鏈?zhǔn)竭\(yùn)算:

function createOperation() {
  let theLastValue = 0;
  const plusTwoArguments = (a, b) => a + b;
  const multiplyTwoArguments = (a, b) => a * b;

  return {
    plus(...args) {
      theLastValue += args.reduce(plusTwoArguments);
      return this;
    },
    subtract(...args) {
      theLastValue -= args.reduce(plusTwoArguments);
      return this;
    },
    multiply(...args) {
      theLastValue *= args.reduce(multiplyTwoArguments);
      return this;
    },
    divide(...args) {
      theLastValue /= args.reduce(multiplyTwoArguments);
      return this;
    },
    valueOf() {
      const returnValue = theLastValue;
      // 獲取值的時(shí)候需要重置
      theLastValue = 0;
      return returnValue;
    },
  };
}
const operaton = createOperation();
const result = operation
  .plus(1, 2, 3)
  .subtract(1, 3)
  .multiply(1, 2, 10)
  .divide(10, 5)
  .valueOf();
console.log(result);

當(dāng)然上面的例子不完全都是函數(shù)式編程,因?yàn)?valueOf 的返回值就不確定。

高階函數(shù)

高階函數(shù)(Higher Order Function),按照維基百科上面的定義,至少滿足下列一個(gè)條件的函數(shù)

函數(shù)作為參數(shù)傳入

返回值為一個(gè)函數(shù)

簡(jiǎn)單的例子:

function add(a, b, fn) {
  return fn(a) + fn(b);
}
function fn(a) {
  return a * a;
}
add(2, 3, fn); // 13

還有一些我們平時(shí)常用高階的方法,如 map、reduce、filter、sort,以及現(xiàn)在常用的 redux 中的 connect 等高階組件也是高階函數(shù)。

柯里化(閉包)
柯里化(Currying),又稱部分求值(Partial Evaluation),是把接受多個(gè)參數(shù)的函數(shù)變換成接受一個(gè)單一參數(shù)(最初函數(shù)的第一個(gè)參數(shù))的函數(shù),并且返回接受余下的參數(shù)而且返回結(jié)果的新函數(shù)的技術(shù)。

柯里化的作用以下優(yōu)點(diǎn):

參數(shù)復(fù)用

提前返回

延遲計(jì)算/運(yùn)行

緩存計(jì)算值

柯里化實(shí)質(zhì)就是閉包。其實(shí)上面的立即執(zhí)行匿名函數(shù)的例子就用到了柯里化。

// 柯里化之前
function add(x, y) {
  return x + y;
}

add(1, 2); // 3

// 柯里化之后
function addX(y) {
  return function(x) {
    return x + y;
  };
}

addX(2)(1); // 3
高階組件

這是組件化流行后的一個(gè)新概念,目前經(jīng)常用到。ES6 語(yǔ)法中 class 只是個(gè)語(yǔ)法糖,實(shí)際上還是函數(shù)。

一個(gè)簡(jiǎn)單例子:

class ComponentOne extends React.Component {
  render() {
    return 

title

; } } function HocComponent(Component) { Component.shouldComponentUpdate = function(nextProps, nextState) { if (this.props.id === nextProps.id) { return false; } return true; }; return Component; } export default HocComponent(ComponentOne);

深入理解高階組件請(qǐng)看這里。

無(wú)參數(shù)風(fēng)格(Point-free)

其實(shí)上面的一些例子已經(jīng)使用了無(wú)參數(shù)風(fēng)格。無(wú)參數(shù)風(fēng)格不是沒(méi)參數(shù),只是省略了多余參數(shù)的那一步??聪旅娴囊恍├泳秃苋菀桌斫饬?。

范例一:

const arr = [1, 2, "", false];
const newArr = arr.filter(Boolean).map(String);
// 有參數(shù)的用法如下:
// arr.filter(value => Boolean(value)).map(value => String(value));

范例二:

const tasks = [];
for (let i = 0; i < 1000; i++) {
  tasks.push({
    user: {
      name: "one",
    },
    type: "RE",
  });
  tasks.push({
    user: {
      name: "two",
    },
    type: "",
  });
}
function isPriorityTask(task) {
  return task.type === "RE" && !task.completed;
}
function toTaskView(task) {
  return { ...task, userName: task.user.name };
}
tasks.filter(isPriorityTask).map(toTaskView);

范例三:

// 比如,現(xiàn)成的函數(shù)如下:
var toUpperCase = function(str) {
  return str.toUpperCase();
};
var split = function(str) {
  return str.split("");
};
var reverse = function(arr) {
  return arr.reverse();
};
var join = function(arr) {
  return arr.join("");
};

// 現(xiàn)要由現(xiàn)成的函數(shù)定義一個(gè) point-free 函數(shù)toUpperCaseAndReverse
var toUpperCaseAndReverse = _.flowRight(
  join,
  reverse,
  split,
  toUpperCase
); // 自右向左流動(dòng)執(zhí)行
// toUpperCaseAndReverse是一個(gè)point-free函數(shù),它定義時(shí)并無(wú)可識(shí)別參數(shù)。只是在其子函數(shù)中操縱參數(shù)。flowRight 是引入了 lodash 庫(kù)的組合函數(shù),相當(dāng)于 compose 組合函數(shù)
console.log(toUpperCaseAndReverse("abcd")); // => DCBA
無(wú)參數(shù)風(fēng)格優(yōu)點(diǎn)?

參風(fēng)格的好處就是不需要費(fèi)心思去給它的參數(shù)進(jìn)行命名,把一些現(xiàn)成的函數(shù)按需組合起來(lái)使用。更容易理解、代碼簡(jiǎn)小,同時(shí)分離的回調(diào)函數(shù),是可以復(fù)用的。如果使用了原生 js 如數(shù)組,還可以利用 Boolean 等構(gòu)造函數(shù)的便捷性進(jìn)行一些過(guò)濾操作。

無(wú)參數(shù)風(fēng)格缺點(diǎn)?

缺點(diǎn)就是需要熟悉無(wú)參數(shù)風(fēng)格,剛接觸不可能就可以用得得心應(yīng)手的。對(duì)于一些新手,可能第一時(shí)間理解起來(lái)沒(méi)那沒(méi)快。

參考文章

Learn the fundamentals of functional programming?—?for free, in your inbox

Make your code easier to read with Functional Programming

從高階函數(shù)--->高階組件

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

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

相關(guān)文章

  • 函數(shù)編程組合

    摘要:在函數(shù)式編程的組合中,我們是從右到左執(zhí)行的,上述的例子中我們借助函數(shù)實(shí)現(xiàn)組合,當(dāng)然,我們也可以用自己的方式實(shí)現(xiàn)。小結(jié)函數(shù)式編程隨著多核的發(fā)展,開(kāi)始再次出現(xiàn)在我們的視野中,有時(shí)候也會(huì)擔(dān)心過(guò)于吹捧函數(shù)式,反而落入俗套。 程序的本質(zhì)是什么?數(shù)據(jù)結(jié)構(gòu)+算法?。?!我想這也是很多程序員給出的答案,我自己也認(rèn)可這一觀點(diǎn),當(dāng)我們了解了某一門編程語(yǔ)之后,接下來(lái)我們面對(duì)的往往是數(shù)據(jù)結(jié)構(gòu)和算法的學(xué)習(xí)。而現(xiàn)在...

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

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

    Miracle 評(píng)論0 收藏0
  • JavaScript函數(shù)編程錯(cuò)誤處理,強(qiáng)壯代碼

    摘要:可當(dāng)我們進(jìn)行函數(shù)式編程時(shí),這樣的方式會(huì)遇到困難,難點(diǎn)在于如何停止。而在函數(shù)式編程中,數(shù)據(jù)在管道中流動(dòng),上一個(gè)函數(shù)的返回值會(huì)傳給下一個(gè)函數(shù),除非報(bào)錯(cuò),事先寫好的流程是停不下來(lái)的。 以下代碼會(huì)用到函數(shù)組合函數(shù)compose,只要知道compose是干什么的就足夠了,如果好奇具體的實(shí)現(xiàn),可以看《JavaScript函數(shù)式編程之函數(shù)組合函數(shù)compose和pipe的實(shí)現(xiàn)》 在寫命令式的代碼時(shí),...

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

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

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

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

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

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

0條評(píng)論

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