JavaScript函数的增强知识

news/2024/11/16 10:50:13/

函数属性和arguments以及剩余参数

函数属性name与length

◼ 我们知道JavaScript中函数也是一个对象,那么对象中就可以有属性和方法。
◼ 属性name:一个函数的名词我们可以通过name来访问;

    // 自定义属性foo.message = "Hello Foo"console.log(foo.message)// 默认函数对象中已经有自己的属性// 1.name属性console.log(foo.name)console.log(bar.name)// 将两个函数放到数组中(了解)var fns = [foo, bar]for (var fn of fns) {console.log(fn.name)}

◼ 属性length:属性length用于返回函数参数的个数;
 注意:rest参数是不参与参数的个数的;

    // 2.length属性: 参数的个数function test() {}test(111, 222, 333)console.log(foo.length)console.log(bar.length)console.log(test.length)// 额外补充// function demo(...args) {// }// demo("abc", "cba", "nba")

函数的arguments

◼ arguments 是一个 对应于传递给函数的参数 的 类数组(array-like)对象。
◼ array-like意味着它不是一个数组类型,而是一个对象类型:
 但是它却拥有数组的一些特性,比如说length,比如可以通过index索引来访问传递给函数的参数
 但是它却没有数组的一些方法,比如filter、map等;

function foo(m, n) {// arguments 类似数组对象console.log(arguments)// 1.默认用法:// 通过索引获取内容// console.log(arguments[0])// console.log(arguments[1])// // 遍历// for (var i = 0; i < arguments.length; i++) {//   console.log(arguments[i])// }// for (var arg of arguments) {//   console.log(arg)// }// 2.需求获取所有参数中的偶数// 数组 filter// for (var arg of arguments) {//   if (arg % 2 === 0) {//     console.log(arg)//   }// }// var evenNums = arguments.filter(item => item % 2 === 0)// console.log(eventNums)}foo(10, 25, 32, 41)

arguments转成Array

◼ 在开发中,我们经常需要将arguments转成Array,以便使用数组的一些特性。
 常见的转化方式如下
◼ 转化方式一:
 遍历arguments,添加到一个新数组中;
◼ 转化方式二:较难理解(有点绕),了解即可
 调用数组slice函数的call方法;
◼ 转化方式三:ES6中的两个方法
 Array.from
 [...arguments]

// 2.1.将arguments转成数组方式一:// var newArguments = []// for (var arg of arguments) {//   newArguments.push(arg)// }// console.log(newArguments)// 2.2.将arguments转成数组方式三: ES6中方式// var newArgs1 = Array.from(arguments)// console.log(newArgs1)// var newArgs2 = [...arguments]// console.log(newArgs2)// 2.3.将arguments转成数组方式二: 调用slice方法var newArgs = [].slice.apply(arguments)// var newArgs = Array.prototype.slice.apply(arguments)console.log(newArgs)

箭头函数不绑定arguments

箭头函数是不绑定arguments的,所以我们在箭头函数中使用arguments会去上层作用域查找

 // 1.箭头函数不绑定argumentsvar bar = () => {console.log(arguments)}bar(11, 22, 33)//报错// 2.函数的嵌套箭头函数function foo() {var bar = () => {console.log(arguments)}bar()}foo(111, 222)//正常运行,因为foo有argument

函数的剩余参数

◼ ES6中引用了rest parameter,可以将不定数量的参数放入到一个数组中:
如果最后一个参数是 ... 为前缀的,那么它会将剩余的参数放到该参数中,并且作为一个数组;

也可以一个函数只有剩余参数


◼ 那么剩余参数和arguments有什么区别呢?
 剩余参数只包含那些没有对应形参的实参,而 arguments 对象包含了传给函数的所有实参;
 arguments对象不是一个真正的数组,而rest参数是一个真正的数组,可以进行数组的所有操作;
 arguments是早期的ECMAScript中为了方便去获取所有的参数提供的一个数据结构,而rest参数是ES6中提供并且希望以此来替代arguments的;
◼ 剩余参数必须放到最后一个位置,否则会报错。

 // 剩余参数: rest parametersfunction foo(num1, num2, ...otherNums) {// otherNums数组console.log(otherNums)}foo(20, 30, 111, 222, 333)// 默认一个函数只有剩余参数function bar(...args) {console.log(args)}bar("abc", 123, "cba", 321)// 注意事项: 剩余参数需要写到其他的参数最后

纯函数的理解和应用

◼ 函数式编程中有一个非常重要的概念叫纯函数,JavaScript符合函数式编程的范式,所以也有纯函数的概念;
 在react开发中纯函数是被多次提及的;
 比如react中组件就被要求像是一个纯函数(为什么是像,因为还有class组件),redux中有一个reducer的概念,也是要求必须是一个纯函数;
 所以掌握纯函数对于理解很多框架的设计是非常有帮助的;


◼ 纯函数的维基百科定义:
 在程序设计中,若一个函数符合以下条件,那么这个函数被称为纯函数:
 此函数在相同的输入值时,需产生相同的输出。
 函数的输出和输入值以外的其他隐藏信息或状态无关,也和由I/O设备产生的外部输出无关。
 该函数不能有语义上可观察的函数副作用,诸如“触发事件”,使输出设备输出,或更改输出值以外物件的内容等。


◼ 当然上面的定义会过于的晦涩,所以简单总结一下:
 确定的输入,一定会产生确定的输出;(不能使用闭包,否则全局变量可能会影响值的输出)
 函数在执行过程中,不能产生副作用;


◼ 那么这里又有一个概念,叫做副作用,什么又是副作用呢?
 在计算机科学中,也引用了副作用的概念,表示在执行一个函数时,除了返回函数值之外,还对调用函数产生了附加的影响,比如修改了全局变量,修改参数或者改变外部的存储;
◼ 纯函数在执行的过程中就是不能产生这样的副作用:
 副作用往往是产生bug的 “温床”。

    function sum(num1, num2) {return num1 + num2}// 不是一个纯函数var address = "广州市"function printInfo(info) {console.log(info.name, info.age, info.message)info.flag = "已经打印结束"address = info.address}var obj = {name: "why",age: 18,message: "哈哈哈哈"}printInfo(obj)console.log(obj)if (obj.flag) {}

◼ 我们来看一个对数组操作的两个函数:
         slice:slice截取数组时不会对原数组进行任何操作,而是生成一个新的数组;
         splice:splice截取数组, 会返回一个新的数组, 也会对原数组进行修改;
◼ slice就是一个纯函数,不会修改数组本身,而splice函数不是一个纯函数;

纯函数的作用与优势

为什么纯函数在函数式编程中非常重要呢?
 因为你可以安心的编写和安心的使用;
 你在写的时候保证了函数的纯度,只是单纯实现自己的业务逻辑即可,不需要关心传入的内容是如何获得的或者依赖其他的
外部变量是否已经发生了修改;
 你在用的时候,你确定你的输入内容不会被任意篡改,并且自己确定的输入,一定会有确定的输出;


◼ React中就要求我们无论是函数还是class声明一个组件,这个组件都必须像纯函数一样,保护它们的props不被修改:


柯里化的理解和应用

◼ 柯里化也是属于函数式编程里面一个非常重要的概念。
 是一种关于函数的高阶技术;
 它不仅被用于 JavaScript,还被用于其他编程语言;


◼ 我们先来看一下维基百科的解释:
 在计算机科学中,柯里化(英语:Currying),又译为卡瑞化或加里化;
 是把接收多个参数的函数,变成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数,而且返回结果的新函数的技术;
 柯里化声称 “如果你固定某些参数,你将得到接受余下参数的一个函数”;


◼ 维基百科的结束非常的抽象,我们这里做一个总结:
 只传递给函数一部分参数来调用它,让它返回一个函数去处理剩余的参数;
 这个过程就称之为柯里化;


◼ 柯里化是一种函数的转换,将一个函数从可调用的 f(a, b, c) 转换为可调用的 f(a)(b)(c)。
 柯里化不会调用函数。它只是对函数进行转换。

    // 普通的函数function foo1(x, y, z) {console.log(x + y + z)}// foo1(10, 20, 30)// foo1(20, 33, 55)// 因为foo不是一个柯里化的函数, 所以目前是不能这样调用// 柯里化函数function foo2(x) {return function(y) {return function(z) {console.log(x + y + z)}}}foo2(10)(20)(30)foo2(20)//无输出值,因为只调用了最外层// 另外一种写法: 箭头函数的写法// function foo3(x) {//   return y => {//     return z => {//       console.log(x + y + z)//     }//   }// }// 另外一种写法: 箭头函数的简化写法var foo3 = x => y => z => {console.log(x + y + z)}foo3(10)(20)(30)

柯里化优势(没懂)

◼ 那么为什么需要有柯里化呢?
 在函数式编程中,我们其实往往希望一个函数处理的问题尽可能的单一,而不是将一大堆的处理过程交给一个函数来处理;
 那么我们是否就可以将每次传入的参数在单一的函数中进行处理,处理完后在下一个函数中再使用处理后的结果;

◼ 比如上面的案例我们进行一个修改:传入的函数需要分别被进行如下处理
 第一个参数 + 2
 第二个参数 * 2
 第三个参数 ** 2

 ◼ 另外一个使用柯里化的场景是可以帮助我们可以复用参数逻辑:
 makeAdder函数要求我们传入一个num(并且如果我们需要的话,可以在这里对num进行一些修改);
 在之后使用返回的函数时,我们不需要再继续传入num了

 柯里化案例练习

这里我们在演示一个案例,需求是打印一些日志:
 日志包括时间、类型、信息;

    // 案例一: 打印一些日志// 信息一: 日志的时间// 信息二: 日志的类型: info/debug/feature// 信息三: 具体的信息// 1.没有柯里化的时候做法function logInfo(date, type, message) {console.log(`时间:${date} 类型:${type} 内容:${message}`)}// // 打印日志// logInfo("2022-06-01", "DEBUG", "修复界面搜索按钮点击的bug")// // 又修复了一个bug// logInfo("2022-06-01", "DEBUG", "修复了从服务器请求数据后展示的bug")// logInfo("2022-06-01", "DEBUG", "修复了从服务器请求数据后展示的bug")// logInfo("2022-06-01", "DEBUG", "修复了从服务器请求数据后展示的bug")// logInfo("2022-06-01", "FEATURE", "增加了商品的过滤功能")// 2.对函数进行柯里化: 柯里化函数的做法// var logInfo = date => type => message => {//   console.log(`时间:${date} 类型:${type} 内容:${message}`)// }function logInfo(date) {return function(type) {return function(message) {console.log(`时间:${date} 类型:${type} 内容:${message}`)}}}var logToday = logInfo("2022-06-01")var logTodayDebug = logToday("DEBUG")var logTodayFeature = logToday("FEATURE")// 打印debug日志logTodayDebug("修复了从服务器请求数据后展示的bug")logTodayDebug("修复界面搜索按钮点击的bug")logTodayDebug("修复界面搜索按钮点击的bug")logTodayDebug("修复界面搜索按钮点击的bug")logTodayDebug("修复界面搜索按钮点击的bug")logTodayFeature("新建过滤功能")logTodayFeature("新建搜索功能")
    function sum(num1, num2) {return num1 + num2}sum(5, 10)sum(5, 15)sum(5, 18)// makeAdder函数就是对sum的柯里化function makeAdder(count) {function add(num) {return count + num}return add}// 1.数字和5相加var adder5 = makeAdder(5)adder5(10)adder5(15)adder5(18)// 2.数组和10相加var adder10 = makeAdder(10)adder10(10)adder10(16)adder10(19)// adder5 = null// adder10 = null

柯里化高级-自动科里化函数

with、eval的使用


严格模式的使用


http://www.ppmy.cn/news/249170.html

相关文章

一张壁纸让android手机瘫痪,一张壁纸让你的手机变成砖头机,用安卓手机的用户要小心了...

原标题&#xff1a;一张壁纸让你的手机变成砖头机&#xff0c;用安卓手机的用户要小心了 看到这个题目我相信很多网友都不会相信&#xff0c;觉得设置一张壁纸怎么可能让自己的手机变成砖头机&#xff0c;这也太离谱了吧。 其实事情的原因是这样的&#xff0c;一位来自国外的网…

华为手机怎么导入主题_如何在华为手机上设置主题动态壁纸

许多智能手机现在可以设置动态桌面墙纸&#xff0c;您还可以选择自己喜欢的桌面主题. 很多用户经常使用系统随附的主题界面后会感到呆板&#xff0c;因此他们想自己设置一些不同的主题界面&#xff0c;还可以自定义一些动态锁屏墙纸. 但是&#xff0c;有很多用户想要修改但不知…

android 壁纸尺寸,常见手机壁纸的尺寸是多少

不同的手机屏幕分辨率不一样&#xff0c;对应的屏幕壁纸尺寸大小也不一样&#xff0c;这里改图宝整理了一些市面上常见的手机型号的壁纸尺寸给大家(单位都为像素)&#xff1a; 苹果Apple iPhone6&#xff1a;872 x 1634&#xff1b; iPhone6 Plus:&#xff1a;2706x2706&#x…

android壁纸和手机屏幕之间要怎么对应,安卓Android手机屏幕壁纸分辨率选择技巧...

安卓Android手机屏幕壁纸分辨率选择技巧 现在使用安卓手机的人好多了&#xff0c;一个好的手机壁纸自然是大家的追求&#xff0c;那么要怎么挑选适合自己安卓手机的手机壁纸呢~登博教程小编来教你挑选吧~ 大家先看看对应的壁纸分辨率&#xff1a; 屏幕分辨率为 480320 的Androi…

120帧手机动态壁纸_星空陨石动态壁纸手机版下载-星空陨石动态壁纸app安卓版下载v1.7最新版...

星空陨石动态壁纸app安卓版是一个主打星空陨石坠落主题的手机动态壁纸工具&#xff0c;大家可以把自己的手机桌面设置成各种星空陨石坠落的动画哦。星空陨石动态壁纸app使用起来非常的简单&#xff0c;一键就能替换桌面主题和壁纸&#xff0c;还支持自己DIY制作哦&#xff0c;赶…

爬取手机壁纸

爬取手机壁纸 1. 准备工作 1.1 环境 python3.9 1.2 用到的库 requests、re 1.3 爬虫的过程分析 当人类去访问一个网页时&#xff0c;是如何进行的&#xff1f;   ①打开浏览器&#xff0c;输入要访问的网址&#xff0c;发起请求。   ②等待服务器返回数据&#xff0…

手机壁纸尺寸android,APP设计手抄:5点安卓手机尺寸分辨率知识

想要真正理解一些有用的android安卓APP设计规范和安卓设计尺寸分辨率、屏幕密度、DP、sp等等相关知识,必须需要反复的去设计和理解阅读的。 所以,准备好APP小抄本也是一项不错的记忆能力。 今天,25学堂给大家整理出来了2016年最新的安卓手机的APP设计手抄——7点安卓手机尺寸…

手机透明壁纸

最近看到个一个透明壁纸的应用&#xff0c;感觉很好玩&#xff0c;所以就想弄弄。 完整代码已经传到github上&#xff0c;地址是https://github.com/SZJing/Screen 应用下载地址https://pan.baidu.com/s/1smhfByP 其实他的思路很简单&#xff0c;就是打开手机摄像头的预览&…