文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

JavaScript数据类型对函数式编程的影响是什么

2023-07-05 05:28

关注

这篇文章主要介绍了JavaScript数据类型对函数式编程的影响是什么的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇JavaScript数据类型对函数式编程的影响是什么文章都会有所收获,下面我们一起来看看吧。

JavaScript中 的数据类型中的可变数据

在 JavaScript 中,数据类型有以下 8 种:

注意点:

在 JavaScript 中,变量是没有类型的,值才有类型。变量可以在任何时候,持有任何值。

原始类型(基本类型)

上面 8 中类型除了 object ,其他都是原始类型,原始类型存储的都是值,其特点有两点:

注意点:

对象类型(引用类型)

而除了原始类型,剩下的 object 就是对象类型,和原始类型的不同点在于:原始类型存储的是值,对象类型存储的是地址。

经典示例:

var c = 1;var d = c;d = 2;console.log(c === d) // falsevar a = {    name: "张三",    age: 20}var b = a;b.age = 21;console.log(a.age === b.age) // true

示例中把变量 a 的值给到了变量 b , b 修改了age 属性,但是 a 的 age 属性也跟着变了,是因为 var b = a 是 a 把对象的引用地址赋值给 b ,这时候 a 和 b 指向的是内存中的同一个数据。

而 c 给 d 的是值,并不是一个引用,相当于复制了一份数据。

因此可以知道原型类型的数据是不可变的,而对象类型的数据是可变的。

JavaScript 为何能会让纯函数变得不纯?

JavaScript 中的对象类型的数据是可变,而可变性,就代表了不确定性,纯函数 中使用了不确性的数据就会导致不纯,因为其违背了 纯函数 的特征:不受外界影响,不影响外界。

下面来看一个例子:

A 同学写了这么一段代码,初始化生成了一个 “zhangsan” 用户。

export const defaultUserInfo = {    name: "名称",    age: 20,    hobby: ["玩耍"]};export function initUser(userTemplate, name, age) {    const newUser = userTemplate;    newUser.name = name;    newUser.age = age;    return newUser;}const zhangsan = userInit(userDefaultInfo, "zhangsan", 21);

然后 B 同学在开发其他页面的时候,看到有初始化用户信息的方法,然后直接复制过去,初始化了一个 “lisi” 用户。

import { defaultUserInfo, initUser } from "xxx模块"。const lisi = userInit(userDefaultInfo, "lisi", 21);

检测的时候看到自己初始化的用户信息正确的就没有去检查之前 A 同学的是否是正确的,上线后发现所有的用户都变成了 lisi 。因为 userDefaultInfo 是一个引用类型,userInit(userDefaultInfo, "xxx", xx) 操作的都是内存中的同一个对象。其原因就是因为 A 和 B 开发者犯了一个错误,把可变数据传递到了 userInit 函数内部进行处理,哪怕进行了浅层拷贝,也出现了问题。究其原因还是因为给函数传递进去了一个 可变数据。

我们校验一个 纯函数 有效性的关键依据,永远是“针对已知的输入,能否给出符合预期的输出”,而上面例子中 initUser 函数没有违背这个规则,但是在可变数据的影响下,让它产生了 副作用,对外界已有的数据造成了影响。

如何解决可变数据的影响?

数据拷贝

从使用函数方的角度来看,既然造成这个问题的原因是因为传递进去的数据是 可变数据 ,那么我就复制一份数据传递给函数内部使用,随便你怎么修改,都不会影响外界其他数据。

比如我们使用前面例子中的 initUser 函数时,先拷贝一份数据:

function copyFunc(object) {    return JSON.parse(JSON.string(object));}const zhangsan = userInit(copyFunc(userDefaultInfo), "zhangsan", 21);const lisi = userInit(copyFunc(userDefaultInfo), "lisi", 21);console.log(zhangsan.name === lisi.name); // false

进行拷贝后的数据传递给 userInit 函数,就不会出现问题了。这里的 copyFunc 只能针对部分数据类型,对不少类型是不支持的,具体可以去看一下 关于JSON.parse(JSON.stringify(obj))实现深拷贝应该注意的坑 这篇文章。

从被调用函数方来看,在使用 object 类型数据时,函数内部尽量不要去修改外界 object 数据(通过参数传递,或者直接使用外界的对象都不建议去修改),修改之前可以拷贝一份再修改。

比如:

export function initUser(userTemplate, name, age) {    const newUser = copyFunc(userTemplate);    newUser.name = name;    newUser.age = age;    return newUser;}

使用不可变数据方案

拷贝的数据比较大的时候,会出现性能问题,因此出现了不可变数据的方案。

现在不可变数据常见的有两种: Immutable.js 和 immer.js 。它们都能实现在操作数据后,返回新的一个数据,而不影响之前的数据。

Immutable.js 实现了持久化数据结构,实现原理说明(引用于immutable.js 和 immer):

因此 Immutable.js 需要严格使用它自定义的操作数据的方法才行。

关于“JavaScript数据类型对函数式编程的影响是什么”这篇文章的内容就介绍到这里,感谢各位的阅读!相信大家对“JavaScript数据类型对函数式编程的影响是什么”知识都有一定的了解,大家如果还想学习更多知识,欢迎关注编程网行业资讯频道。

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯