前端进击的巨人(四):略知函数式编程

系列更文前三篇文章,围绕了一个重要的知识点:"函数"

函数调用栈、函数执行上下文、函数作用域到闭包。可见不理解函数式编程,代码都撸不好。

函数是一等公民

函数与其它数据类型一样,可以作为值赋给变量,作为参数传递或返回值返回,也可以像对象一样给函数创建属性(不推荐给函数加属性,虽然可用)。

函数在实际开发中应用:

  1. 函数声明
  2. 函数表达式
  3. 匿名函数
  4. 自执行函数
// 函数声明
function getName() {
    //...
}

// 函数表达式
var getName = function() {
    //...
}

// 匿名函数
setTimeout(function(){
    //...
}, 1000);

// 自执行函数
(function(){
    //...
})();

何为一等:优先级

函数声明在"执行上下文创建阶段"就会进行声明并赋值,而var声明变量会初始化为undefined,实际赋值会等到"执行上下文执行阶段"。函数表达式使用var来声明,因此它遵循的是变量声明的规则。( 如果函数名与变量重名,函数优先赋值)

"函数声明优先级高于变量声明,函数表达式,自称一等公民。"

// 代码书写:
console.log(getName);
getName();
var getName;
getName = ‘我的名字‘;
function getName(){
    //...
}
console.log(getName);

// 实际执行
var getName;            // 变量名与函数名重名,函数优先赋值
function getName() {
    //...
}
console.log(getName);
getName();
getName = ‘我的名字‘;
console.log(getName);

函数式编程

函数式编程是一种编程思维方式,它建议我们在程序编写时,对复用性高的功能代码进行函数封装,实现代码的高复用性。

新手朋友往往是一块代码多次出现在不同的地方,常见的例子就是ajax请求方法运用,在需要请求后端数据时多次出现一串ajax请求代码。

如果想要对ajax请求统一做异常处理,或管理后端返回状态码,是不是每处代码都要修改???但是如果把ajax请求代码封装成一个函数,接口url和数据data通过参数传递到函数内部处理,后期扩展维护都方便修改,复用性扩展性都更加优秀。

所以实际敲代码过程中,要经常提醒自己运用函数式编程的思维方式,只要有可能出现多次的业务逻辑代码,那么就要考虑是否封装成函数,以便后续统一调用。

function sumScore(list) {
    var totalScore = 0
    for (var i = 0; i < list.length; i++) {
        totalScore += list[i];
    }
    return totalScore;
}

var list = [10, 8, 9, 7];
var totalScore = sumScore(list);    // 计算总分

TIPS: 函数名建议使用动词,如addUser(),sumScore(),getUser()...

纯函数

纯函数:相同的输入对应相同的输出,稳定没有副作用(不改变外部变量的值)

相同的输入,相同的输出

相同的参数传入调用,要有相同的结果输出,概念有点绕,上代码栗子:

function getDate() {
    return new Date();
}
var dateOne = getDate();
var dateTwo = getDate();
var dateThr = getDate();

上述代码中调用了三次getDate(),三次返回的值都不一样。相同的输入并没有相同的输出,所以getDate()并不是一个纯函数。

TIPS:函数中使用new Date(),Math.random(), 异步等都可能造成函数不稳定。

没有副作用(不改变外部环境的值)

部分小伙伴的代码,在函数里面直接修改参数的值,这是一种非常不推荐的做法,这样做会造成代码环境不可控制,污染外部变量环境,一旦出现错误排查起来:心累,三个字心好累。

函数有自己的局部作用域,因此函数中,对需要使用到的变量,管控在自身的作用域下。如果需要修改外部参数的值,通过函数返回值返回给函数调用者。修改外部参数值的操作不在函数内进行,确保对外部环境没有副作用。

TIPS:参数为引用类型时,参数复制的是地址指针,避免修改了引用类型中属性值污染外部环境,如需使用建议手动深拷贝赋值。

function getGirlGift(list) {
    // 避免污染参数为引用类型的list,对list深拷贝
    var newList = JSON.parse(JSON.stringify(list));
    newList.map(girl => {
        girl.gift = girl.age > 18 ? ‘lipstick‘ : ‘chocolates‘;
    });
    return newList;    // 返回新值
}

var girlList = [
    {name: ‘Kelly‘, age: 20},
    {name: ‘Alic‘, age: 16},
    {name: ‘Moon‘, age: 23},
    {name: ‘Nana‘, age: 17}
];

var girlGiftList = getGirlGift(girlList);
girlList         // 原用girlList不变
girlGiftList     // 每个girl多了gift属性

Array对象的函数(纯与不纯)

// 不纯的函数
array.push();       // 数组尾部插入
array.pop();        // 删除并返回数组最后一个元素
array.unshift();    // 数组头部插入
array.shift();      // 删除并返回数组第一元素
array.splice();     // 删除元素,并向数组添加元素
array.reverse();    // 颠倒数组元素的顺序
array.sort();       // 排序数组元素

// 纯函数
array.slice();      // 数组中返回选定的元素
array.concat();     // 连接数组,并发挥新数组
array.join();       // 按分隔符连接数组,返回字符串

>>更多Array对象方法,参考W3C

纯函数的应用:状态管理Redux,Vuex

流行框架中状态管理就是纯函数的实践应用,引用redux的应用,reducer中返回新的状态数据state,但不能去直接去修改state数据,以下为redux中reducer的例子代码:

export default (state = defaultState, action) => {
    let newState = JSON.parse(JSON.stringify(state));

    switch (action.type) {
        case DELETE_TODO_ITEM:
            newState.list.splice(action.value, 1);
        break;
        case ADD_TODO_ITEM:
            if (newState.inputValue.trim().length) {
                newState.list.push(newState.inputValue);
            }
            newState.inputValue = ‘‘;
        break;
        case INIT_LIST_ACTION:
            newState = action.data
        break;
        default:
        break;
    }

    return newState;
}

"自执行函数 + 闭包" 实现模块化

模块化包括:

  1. 私有变量
  2. 私有方法
  3. 公有变量
  4. 公有方法

上篇中《前端进击的巨人(三):从作用域走进闭包》我们讲解了作用域、闭包的原理机制。

"自执行函数可实现块级作用域,而闭包则可实现外部环境对函数作用域内部数据的访问。"

// 自执行函数 + 闭包实现模块化
(function MakeModule(window) {
    var name = ‘以乐之名‘;
    var age = 28;
    var job = ‘程序员‘;

    function changeJob(newJob) {
        job = newJob;
    }

    function getName() {
        return name;
    }

   window.modulePublic = {
        changeJob: changeJob,
        getName: getName
    }
})(window);

window.modulePublic.getName();
window.modulePublic.changeJob(‘产品经理‘);

对作用域,以及闭包知识还没掌握的小伙伴,可回阅《前端进击的巨人(三):从作用域走进闭包》

高阶函数

高阶函数是一个函数,它接收函数作为参数或将函数作为输出返回

JavaScript中常用的高阶函数:

  1. Array.prototype.map (映射遍历)
  2. Array.prototype.filter (过滤)
  3. Array.prototype.reducer(累计)

除了内置的高阶函数,我们实际开放中,高阶函数应用的最多就是回调函数了。

function getOrder(url, datas, callBack) {
    return $.post(url, datas, callBack(orderInfo));
}

// getOrder就是一个高阶函数,接收callBack函数作为参数

高阶函数的概念很简单,"本身是函数,参数是函数,或返回值是函数"

参考文档:

本文首发Github,期待Star!

https://github.com/ZengLingYong/blog

作者:以乐之名

本文原创,有不当的地方欢迎指出。转载请指明出处。

原文地址:https://www.cnblogs.com/kenz520/p/10335214.html

时间: 2024-09-30 06:41:20

前端进击的巨人(四):略知函数式编程的相关文章

20170917 前端开发周报:JavaScript函数式编程、作用域和闭包

1.用函数式编程对JavaScript进行断舍离 当从业20的JavaScript老司机学会函数式编程时,他扔掉了90%的特性,也不用面向对象了,最后发现了真爱啊!!! https://juejin.im/entry/59b86... 2.JavaScript作用域和闭包 作用域和闭包在JavaScript里非常重要.但是在我最初学习JavaScript的时候,却很难理解.这篇文章会用一些例子帮你理解它们.我们先从作用域开始.作用域 JavaScript的作用域限定了你可以访问哪些变量.有两种作

第四部分 函数式编程应用

虽然函数式编程肯定是优雅的,但是,你可能更感兴趣的是其实用目的:作为一种通用的风格,是有用的,在某些问题域中,它肯定更出色.我们已经看到的例子,比如,第四章绘制饼图的应用程序,和第十一章简单的照片浏览器,这些示例的主要目的,是为了演示特定的概念和技术. 第四部分则不同.在每一章,我们将花大量时间讨论实际问题,使用最适当的 F# 特点和函数式编程来解决.这些代码将使用我们到目前为止学到的多种功能,限制在一章中讨论,会比较复杂. 函数式编程在两个领域有明显优点:异步(asynchronous)和并行

你真的理解函数式编程吗?

你真的理解函数式编程吗? 大数据以及人工智能越来越流程,你是否可以轻松适应大数据编程,函数式编程在其中起着重要作用,如何从面向对象编程跳槽到函数式编程?你是否觉得函数式各种概念难于理解?本场 Chat 将为你解答.我将为你分享亲身学习和理解关于函数式编程的经验: 高阶函数.闭包.匿名函数等 高阶函数和闭包是啥关系? 柯里化 函数式编程思维 适合人群: 如果你想转人工智能领域,请关注此 Chat 如果你想了解机器学习,请关注此 Chat 如果你正在学习一下机器学习,请购关注 Chat 实录提要:

python学习笔记(四) - 函数式编程

一. 高阶函数 高阶函数:把函数作为参数传入,这样的函数称为高阶函数,函数式编程就是指这种高度抽象的编程范式 def add(x, y, f): return f(x) + f(y) print add(-5, 6, abs) # 11 二.返回函数 aaa 三.匿名函数 aaa 四.装饰器 aaa 五.偏函数 aaa

Scala函数式编程(四)函数式的数据结构 下

前情提要 Scala函数式编程指南(一) 函数式思想介绍 scala函数式编程(二) scala基础语法介绍 Scala函数式编程(三) scala集合和函数 Scala函数式编程(四)函数式的数据结构 上 1.List代码解析 今天介绍的内容,主要是对上一篇介绍的scala函数式数据结构补充,主要讲代码.可以先看看上一节,主要讲的是函数式的list,Scala函数式编程(四)函数式的数据结构 上.这些代码我都放在我的公众号里面,包括函数式的List以及一个函数式的二叉搜索树,关注公众号:哈尔的

前端函数式编程中的各种概念

本文不涉及深层次的解析,仅作为知识点的查阅.因为概念介绍的比较简单,所以只适合有一定基础的人群阅读. 1.什么是函数式编程? 利用函数把运算过程封装起来,通过组合各种函数来计算结果.(将一套业务流程分割成多个功能,每个功能都用函数封装起来,最后实现这个业务其实就是在调用这些功能函数,这就是函数式编程) 2.一些与函数式编程相关的概念 纯函数 - 指的是函数无副作用,相同的输入(函数参数)有相同的输出(函数返回) 闭包 - 存在内.外两层函数,内层函数对外层函数的局部变量进行来引用.(用途:定义一

[原创译书] JS函数式编程 前言

前言 函数式编程是一种能够让你编写更聪明的代码的方式,可以减低复杂度,增强模块化. 它是一种通过灵巧地变化.组合.使用函数达到编写简洁代码的方式. Javascript提供了一个实现这些的超赞的途径.Javascript,这个Internet的脚本语言, 它的核心实际上是一个函数式语言.通过学习如何显露出它作为一个函数式语言的真实身份, 我们可以实现强大的.更易维护的以及更可靠的web应用. 通过这些,Javascript的那些怪癖和缺陷将会立刻变得清晰,并且语言本身也将会无限精彩. 学习如何使

函数式编程入门教程(转)

初涉函数式编程语言python,转载了一篇文章,先简单来了解一下函数式编程的概念. 文章原址:http://www.ruanyifeng.com/blog/2017/02/fp-tutorial.html 函数式编程入门教程 作者: 阮一峰 日期: 2017年2月22日 你可能听说过函数式编程(Functional programming),甚至已经使用了一段时间. 但是,你能说清楚,它到底是什么吗? 网上搜索一下,你会轻松找到好多答案. 与面向对象编程(Object-oriented prog

翻译连载 | 附录 A:Transducing(上)-《JavaScript轻量级函数式编程》 |《你不知道的JS》姊妹篇

原文地址:Functional-Light-JS 原文作者:Kyle Simpson-<You-Dont-Know-JS>作者 关于译者:这是一个流淌着沪江血液的纯粹工程:认真,是 HTML 最坚实的梁柱:分享,是 CSS 里最闪耀的一瞥:总结,是 JavaScript 中最严谨的逻辑.经过捶打磨练,成就了本书的中文版.本书包含了函数式编程之精髓,希望可以帮助大家在学习函数式编程的道路上走的更顺畅.比心. 译者团队(排名不分先后):阿希.blueken.brucecham.cfanlife.d