资讯专栏INFORMATION COLUMN

JavaScript函数式编程

LeanCloud / 957人阅读

摘要:函数式编程的特点函数是第一等公民,因为叫函数式编程,因此函数的地位是最高的,也就是说比起变量函数的地位更高一点。高阶函数是对其他函数进行操作的函数,可以将它们作为参数或返回它们。常见的高阶函数有排序过滤

1:基本概念

函数式编程是一种编程思维方式,并不是一些语法规则,对于复用性高的功能代码进行一定的函数封装,实现了代码的高可复用性(主要目的)。

函数式编程的特点:

函数是第一等公民,因为叫函数式编程,因此函数的地位是最高的,也就是说比起变量函数的地位更高一点。

只用表达式而不用语句,表达式就是声明式的意思,语句就是命令式的,尽量使用表达式或者是声明式的代码来组织逻辑。

没有副作用的代码,也叫做纯函数或者在一些开发框架中也叫作纯主键,纯的意思是输入一定那么输出也一定。

不修改状态。

引用透明。

2:函数是一等公民

理解:函数在整个JavaScript代码里面一般来讲有四种,第一种叫做声明函数、然后是表达式函数、匿名函数以及自执行函数。

为什么函数是一等公民?

函数声明优先级高于变量声明和函数表达式

  console.log(getName);
  
  getName();
  
  var getName;
  getName = "Eric";
  function getName(){
      console.log("function getName");
  }
  
  console.log(getName);
  
  //ƒ getName(){
      console.log("function getName");
    }
  // function getName
  // Eric

函数应用

   //声明函数
   function getName(){
   }
   
   //表达式函数(直接赋给一个变量)
   var getName = function(){
   }
   
   //匿名函数(没有名字)
   setTimeout(function(){
   },1000);
   
   //自执行函数(IIFE)
   (function(){
   })();

3:纯函数

特点:

对于相同的输入,永远会得到相同的输出

  function getNumber(num){
      return num + Math.random();
  }

不改变输入值

  function getGirlGift(list){
      // 输入值改变
      list = list.map(girl => {
          girl.gift = girl.age > 18 ? "big" : "small";
      });
      return list;
  }

不包含副作用(网络、I/O)

  var array = [1,2,3,4,5];
  array.slice(0,3);
  array.slice(0,3);
  // [1, 2, 3]
  
  // 改变原数组
  array.splice(0,3);
  array.splice(0,3);
  // [4, 5]
  
  //网络请求
  asiox.get("https://www.xxxx.com").then(res => {
      
  })
  
  //时间
  function getDate(){
      return new Date();
  }

Array函数举例

  以数组为例,纯与不纯函数有哪些:
  //不纯:调用数组之后改变了原数组。
  array.push();       数组尾部插入
  array.pop();        删除并返回数组最后一个元素
  array.unshift();    数组头部插入
  array.shift();      删除并返回数组第一元素
  array.splice();     删除元素,并向数组添加元素
  array.reverse();    颠倒数组元素的顺序
  array.sort();       排序数组元素
  
  
  //数组纯函数:调用数组的方法不改变原数组。
  array.slice();      数组中返回选定的元素
  array.concat();     连接数组,并发挥新数组
  array.join();       按分隔符连接数组,返回字符串

4:函数柯里化

定义:传递给函数的一部分参数来调用它,让它返回一个函数去处理剩下的参数。

柯里化是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数而且返回结果的新函数的技术。例如:

// 普通的add函数
function add(x, y) {
    return x + y
}
add(1,2);
// 3

// 柯里化改编后
function addX(y) {
    return function (x) {
        return x + y;
    }
}
addX(2)(1);
// 3

// 函数不纯 - 硬编码 - 依赖min参数 
var min = 90; 
var isWell = score => score > min;

// 柯里化改编 
var min = 90; 
var chekoLevel = baseLine => (score => score > baseLine);
var isWell = chekoLevel(90);
// isWell(90)
   false
// isWell(940)
   true

实际上就是把add函数的x,y两个参数变成了先用一个函数接收x然后返回一个函数去处理y参数。现在思路应该就比较清晰了,就是只传递给函数一部分参数来调用它,让它返回一个函数去处理剩下的参数。

一种对参数的缓存

用在一些区分环境的函数预缓存

已获取某些耗时操作结果缓存

5:函数组合

在函数式编程思想之前,出现过一个函数嵌套的现象,函数嵌套是一个函数的执行结果它是另外一个函数的入参,一般来讲是两层,但是两层以上或者更多也是可能的。比如下面的代码,它的意思是function13的结果作为function2的入参,然后function2的结果又作为function1的入参。这样的写法不太好理解而且容易混乱,因此在这个基础上,衍生了函数式编程的另外一个思想,叫做函数组合。

函数组合是通过另外一个函数去组合嵌套函数,但是函数本身的嵌套关系,依赖关系是不会改变的。只不过是通过另外一个函数完成一个组装。

函数嵌套

  function1(function2(function13(x)));

函数组合

  var compose = (function1, function2) => (x => function1(function2(x)));
  
  var function1 = param => param + 1;
  var function2 = param => param + 2;
  var final = compose(function1, function2);
  final(1);
  
  // 4

6:Point Free

不要命名转瞬即逝的中间变量。

var getSplitWord = str => str.toUpperCase().split(" ");

//柯里化封装
var toUpperCase = word => word.toUpperCase();
var split = x => str => str.split(x);
var getSplitWord = compose(split(" "), toUpperCase);
7:声明式代码
var students = [{
    name: "Eric",
    score: 99,
    },
    {
        name: "Iven",
        score: 59,
    }
}];

//命令式
const getWell =students => {
    let result = [];
    for (let i = 0; i < students.length; i++){
        if (students[i].score >= 90){
            result.push(students[i])
        }
    }
    return result;
}

//声明式
const getWell = students => return students.filler(student => students.score >= 90);
8:高阶函数

把函数当参数,把传入的函数做一个封装。

function add(x,y,f){
    return f(x) + f(y);
}

高阶函数是对其他函数进行操作的函数,可以将它们作为参数或返回它们。 简单来说,高阶函数是一个函数,它接收函数作为参数或将函数作为输出返回。

常见的高阶函数有:

Array.map

  var array = [1,2,3];
  array.map(s => s + 1);
  // [2, 3, 4]

Array.sort(排序)

Array.filter(过滤)

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/106011.html

相关文章

  • SegmentFault 技术周刊 Vol.16 - 浅入浅出 JavaScript 函数编程

    摘要:函数式编程,一看这个词,简直就是学院派的典范。所以这期周刊,我们就重点引入的函数式编程,浅入浅出,一窥函数式编程的思想,可能让你对编程语言的理解更加融会贯通一些。但从根本上来说,函数式编程就是关于如使用通用的可复用函数进行组合编程。 showImg(https://segmentfault.com/img/bVGQuc); 函数式编程(Functional Programming),一...

    csRyan 评论0 收藏0
  • 翻译连载 | 附录 C:函数编程函数库-《JavaScript轻量级函数编程》 |《你不知道的J

    摘要:为了尽可能提升互通性,已经成为函数式编程库遵循的实际标准。与轻量级函数式编程的概念相反,它以火力全开的姿态进军的函数式编程世界。 原文地址:Functional-Light-JS 原文作者:Kyle Simpson-《You-Dont-Know-JS》作者 关于译者:这是一个流淌着沪江血液的纯粹工程:认真,是 HTML 最坚实的梁柱;分享,是 CSS 里最闪耀的一瞥;总结,...

    Miracle 评论0 收藏0
  • 每个 JavaScript 工程师都应当知道的 10 个面试题

    摘要:所支持的面向对象编程包括原型继承。发明于年的就是首批支持函数式编程的语言之一,而演算则可以说是孕育了这门语言。即使在今天,这个家族的编程语言应用范围依然很广。 1. 能说出来两种对于 JavaScript 工程师很重要的编程范式么? JavaScript 是一门多范式(multi-paradigm)的编程语言,它既支持命令式(imperative)/面向过程(procedural)编程...

    jone5679 评论0 收藏0
  • 每个 JavaScript 工程师都应当知道的 10 个面试题

    摘要:所支持的面向对象编程包括原型继承。发明于年的就是首批支持函数式编程的语言之一,而演算则可以说是孕育了这门语言。即使在今天,这个家族的编程语言应用范围依然很广。 1. 能说出来两种对于 JavaScript 工程师很重要的编程范式么? JavaScript 是一门多范式(multi-paradigm)的编程语言,它既支持命令式(imperative)/面向过程(procedural)编程...

    YorkChen 评论0 收藏0
  • 每个 JavaScript 工程师都应当知道的 10 个面试题

    摘要:所支持的面向对象编程包括原型继承。发明于年的就是首批支持函数式编程的语言之一,而演算则可以说是孕育了这门语言。即使在今天,这个家族的编程语言应用范围依然很广。 1. 能说出来两种对于 JavaScript 工程师很重要的编程范式么? JavaScript 是一门多范式(multi-paradigm)的编程语言,它既支持命令式(imperative)/面向过程(procedural)编程...

    Gilbertat 评论0 收藏0

发表评论

0条评论

LeanCloud

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<