函数是javascript中非常重要的一部分,用途也非常的多,可作为参数、返回值、回调等等,下面有一些函数式编程的重要概念和定义

纯函数

纯函数属于程序设计的名词,其它语言中也是存在的,而在javascript中,符合以下规则即为纯函数。

  • 函数有相同的输入,必定有相同的输出
  • 函数的输出仅与输入有关,与其他隐藏信息无关
  • 不得产生任何的副作用,如 触发事件等

副作用:除了返回函数值以外,还对调用函数产生了其他的影响,如修改全局变量、修改参数或者改变外部存储。

以下几个示例来区分一下纯函数和非纯函数

1、数组方法

var arr1 = [1, 2, 3, 4]
var arr2 = [10, 20, 30, 40] const newArr1 = arr1.splice(1, 3)
const newArr2 = arr2.slice(1, 3) console.log(arr1, newArr1) // [1] [2, 3, 4]
console.log(arr2, newArr2) // [10, 20, 30, 40] [20, 30]

splice 通过下标值和长度操作原数组本身,修改了入参,所以不是纯函数。

slice 通过下标值截取数组,返回一个新的数组,没有副作用,是纯函数。

2、修改入参

var obj = { name: 'alice' }
function foo(info) {
  info.name = 'kiki'
  return info
}
foo(obj) function bar(info) {
  return {
    ...info,
    name: 'kiki'
  }
}
bar(obj)

上面两个函数的作用都是返回一个新的对象,但foo修改了入参,所以foo不是纯函数,bar没有产生任何副作用,满足纯函数的定义。

使用纯函数在开发当中具有一些优点

  • 不用考虑传入的参数是否已经发生了变化
  • 不用考虑函数的操作是否会修改全局、外部的一些变量

这样函数的功能就更加的单一和纯净,可以放心的编写和使用

柯里化

通过函数返回函数的方式,实现多次接收参数并进行统一处理的函数编码形式

function sum(a, b, c) {
  return a + b + c
} // 柯里化写法
function add(a) {
  return function (b) {
    return function (c) {
      return a + b + c
    }
  }
}
sum(1, 2, 3)
add(1)(2)(3)

以上两个函数的执行结果相同,但是调用方式不同,使用柯里化的优点在于使每一个函数的功能更加单一,及逻辑复用

function foo(type, time, message){
  console.log(`${type}:${[time]}:${message}`)
}
foo('error', '2021/10/24', '接口返回数据异常')
foo('error', new Date(), '页面显示错误') // 柯里化写法
function log(type) {
  return function (time) {
    return function (message) {
      console.log(`${type}:${[time]}:${message}`)
    }
  }
} var error = log('error')
error('2021/10/24')('接口返回数据异常')
error(new Date())('页面显示错误')

如以上柯里化代码,复用了【获取类型】部分的函数

组合函数

组合函数不是一种函数类型,只是创建一个新函数将多种功能的函数合并起来

function mul(m) {
  return m * 2
} function square(n) {
  return n * n
} // 组合函数
function compose(m, n) {
  return function (i) {
    return m(n(i))
  }
} var fn = compose(mul, square)
console.log(fn(5))

通过组合函数,就可以将不同功能的函数组合使用

with语句

with语句可以创建一个独立的作用域

with语句的语法是 with(){},with小括号内需要传递一个值,一般为对象,with语句内的变量会从这个小括号里先查找

var message = 'global'
var obj = { name: 'alice', message: 'obj' } function foo() {
  console.log(message)
  with (obj) {
    console.log(message)
  }
}
foo()

以上代码的执行结果如下

目前with语句已经不推荐使用了

eval

eval用于解析字符串及执行代码

var str = "var message = 'global'; console.log(message)"
eval(str)

以上代码执行完成会在控制台上输出 global

目前已经不推荐使用eval,从上述代码,我们可以看出它存在的问题

  • 可读性非常差,也不便于维护
  • eval字符串很可能会在执行的过程中被篡改,容易遭到攻击
  • js代码在解析的过程中可以经过js引擎优化,如果是字符串,就没办法优化

严格模式

在全局或者函数中通过 "use strict" 来开启严格模式,严格模式下,不允许编写一些松散的代码,浏览器会对代码进行更严格的检测

严格模式对javascript语义做了一些限制

1、严格模式通过【抛出错误】来消除一些原有的【静默】错误

静默错误:比如定义变量没有关键字声明,如 num = 1

2、严格模式在js引擎在执行代码的时候可以进行更多的优化(不需要对特殊的语法进行处理)

如以下代码,通过属性描述符定义name属性为不可修改

var obj = {}
Object.defineProperty(obj, "name", { writable: false })
obj.name = "alice"

非严格模式直接忽略赋值,严格模式下会报错

3、严格模式禁用了在ECMAScript未来版本可能会定义的一些语法

如:

关键字 function var new

保留字 class let const (ES5以前)

保留字在未来有可能升级为关键字

非严格模式下以前可以使用保留字作为变量如var let = "abc"

严格模式下会报错

具体来说,严格模式做了以下限制

1、无法意外的创建全局变量

在非严格模式下,没有通过关键字定义的变量会被添加到全局

严格模式下这样的代码执行会抛出异常 message is not defined

 message = "hello"

2、严格模式会使引起静默失败的赋值操作抛出异常

静默失败:silently fail,不报错也没有任何效果

非严格模式下不报错,严格模式下直接抛出异常 Cannot create property 'message' on boolean 'true'

true.name = "alice"

3、严格模式下删除不可删除的属性会抛出异常

非严格模式下不报错,忽略删除操作,严格模式下直接抛出异常 Cannot delete property 'address' of #

js中的函数式编程的更多相关文章

  1. 可爱的 Python : Python中的函数式编程,第三部分

    英文原文:Charming Python: Functional programming in Python, Part 3,翻译:开源中国 摘要:  作者David Mertz在其文章<可爱的 ...

  2. Java 中的函数式编程(Functional Programming):Lambda 初识

    Java 8 发布带来的一个主要特性就是对函数式编程的支持. 而 Lambda 表达式就是一个新的并且很重要的一个概念. 它提供了一个简单并且很简洁的编码方式. 首先从几个简单的 Lambda 表达式 ...

  3. C#中的函数式编程:序言(一)

    学了那么久的函数式编程语言,一直想写一些相关的文章.经过一段时间的考虑,我决定开这个坑. 至于为什么选择C#,在我看来,编程语言分三类:一类是难以进行函数式编程的语言,这类语言包括Java6.C语言等 ...

  4. (数据科学学习手札48)Scala中的函数式编程

    一.简介 Scala作为一门函数式编程与面向对象完美结合的语言,函数式编程部分也有其独到之处,本文就将针对Scala中关于函数式编程的一些常用基本内容进行介绍: 二.在Scala中定义函数 2.1 定 ...

  5. Apache Beam中的函数式编程理念

    不多说,直接上干货! Apache Beam中的函数式编程理念 Apache Beam的编程范式借鉴了函数式编程的概念,从工程和实现角度向命令式妥协. 编程的领域里有三大流派:函数式.命令式.逻辑式. ...

  6. C#中的函数式编程:递归与纯函数(二) 学习ASP.NET Core Razor 编程系列四——Asp.Net Core Razor列表模板页面

    C#中的函数式编程:递归与纯函数(二)   在序言中,我们提到函数式编程的两大特征:无副作用.函数是第一公民.现在,我们先来深入第一个特征:无副作用. 无副作用是通过引用透明(Referential ...

  7. C#中面向对象编程中的函数式编程详解

    介绍 使用函数式编程来丰富面向对象编程的想法是陈旧的.将函数编程功能添加到面向对象的语言中会带来面向对象编程设计的好处. 一些旧的和不太老的语言,具有函数式编程和面向对象的编程: 例如,Smallta ...

  8. 通过代数,数字,欧几里得平面和分形讨论JavaScript中的函数式编程

    本文是对函数式编程范式的系列文章从而拉开了与以下延续一个. 介绍 在JavaScript中,函数只是对象.因此,可以构造函数,作为参数传递,从函数返回或分配给变量.因此,JavaScript具有一流的 ...

  9. Java经典类库-Guava中的函数式编程讲解

    如果我要新建一个java的项目,那么有两个类库是必备的,一个是junit,另一个是Guava.选择junit,因为我喜欢TDD,喜欢自动化测试.而是用Guava,是因为我喜欢简洁的API.Guava提 ...

  10. C#中的函数式编程

    在函数式编程中,可以把函数看作数据.函数也可以作为参数,函数还可以返回函数.比如,LINQ就是基于函数式编程的. 两个例子引出函数式编程 语句式编程可能这样写: string result; ) { ...

随机推荐

  1. 2021-08-06:天际线问题。城市的天际线是从远处观看该城市中所有建筑物形成的轮廓的外部轮廓。给你所有建筑物的位置和高度,请返回由这些建筑物形成的 天际线 。每个建筑物的几何信息由数组 build

    2021-08-06:天际线问题.城市的天际线是从远处观看该城市中所有建筑物形成的轮廓的外部轮廓.给你所有建筑物的位置和高度,请返回由这些建筑物形成的 天际线 .每个建筑物的几何信息由数组 build ...

  2. AcWing 278. 数字组合

    给定 N 个正整数 A1,A2,-,AN,从中选出若干个数,使它们的和为 M,求有多少种选择方案. 输入格式 第一行包含两个整数 N 和 M. 第二行包含 N 个整数,表示 A1,A2,-,AN. 输 ...

  3. 【Python】如何在FastAPI中使用UUID标记日志,以跟踪一个请求的完整生命周期

    为什么要使用uuid标记日志? 在分布式系统中,一个请求可能会经过多个服务,每个服务都会生成自己的日志.如果我们只使用普通的日志记录,那么很难将这些日志串联在一起,以至难以跟踪一个请求的完整生命周期. ...

  4. JavaWeb编程面试题——Spring Boot

    引言 面试题==知识点,这里所记录的面试题并不针对于面试者,而是将这些面试题作为技能知识点来看待.不以刷题进大厂为目的,而是以学习为目的.这里的知识点会持续更新,目录也会随时进行调整. 关注公众号:编 ...

  5. opencv图像显示问题

    opencv 的图像类型都是numpy array.dtype = uint8. 如果是默认的python的int类型的numpy array,即使每个整数都在范围0-255, 图像也不会显示,必须转 ...

  6. P1585 魔法阵 题解

    题意: 题目传送门 可以看做一个人手中有一些宝石,并将宝石分成两组,一组的编号为 1 至 n×m/2,二组为 n×m/2+1 至 n×m+1.当两组两个宝石编号相差为 n×m/2 为一对.现在要遍历一 ...

  7. 一次Mybaits查询的源码分析

    很好奇Mybaits是怎么将xml和mapper对应起来的,用一段比较简单的demo去debug追踪一下源码看看 先用xml配置的方式,看懂了再去看注解的方式是怎么实现的 获取Mapper Mybai ...

  8. 洛谷 P8026 [ONTAK2015] Bajtocja

    简要题意 有 \(d\) 张初始为空的无向图,每张中都有 \(n\) 个点,标号从 \(1\) 到 \(n\),\(m\) 次操作,每次往一张图加一条边,并询问有多少有序数对 \((a, b)\) 使 ...

  9. ClickHouse数据表迁移实战之-remote方式

    1 引言 ClickHouse是一个用于联机分析(OLAP)的列式数据库管理系统(DBMS).我们内部很多的报表.数据看板都基于它进行开发.今天为大家带来remote方式的ClickHouse数据表迁 ...

  10. Java输出100以内的所有质数

    代码如下: public static void main(String[] args) { for(int k=2;k<=100;k++) { boolean flag = true; for ...