大伙儿肯定感觉有点诧异,啥?js函数调用一下,还能体验到美感?
是的,下面给各位展示一下js函数调用的美感。
0-背景铺垫
js作为一门饱受争议的编程语言,爱也好,烦也罢,诞生几十年来,她发展成为了web世界的统治性语言,没有哪门语言能撼动其在web前端世界的地位,尤其在ES5,ES6等大改版后,更是脱胎换骨,再加上后来微软重磅出品的typescript的无缝而强大的类型加持,可以说古老的js愈发焕发出强劲的蓬勃生机。
1-主角登场
铺垫完了背景,现在请出今天的主角:函数。大家觉得js发展到现在最核心的特性是啥呢?(此处需要停顿思考几秒钟......)。我很认同jquery框架的作者的观点,他认为js最核心最重要的特性就是函数(这里也安利一下他的那本著名的经典书籍《JavaScript忍者秘籍(第2版)》,亲测,真香!)
很多人可能会说,就这?函数这种烂大街的概念,哪一门编程语言没有函数?这么说是看到了表象,基本上所有编程语言都有函数,但是js的函数跟其他语言的函数有很大的区别。有啥区分呢?大家听过函数式编程这个概念吧,那么什么是函数式呢?一言以蔽之,就是js中的函数跟值一样,可以传给别人,别人也可以返回一个函数,简言之,就是可以跟变量一样传来传去。因为这个特性,js中函数被称作是一等公民。函数是英文function的翻译,这个翻译堪称经典,函,蕴函的意思,数,是指某个值,函数,就是蕴函着某一个数,亦即不是立即给出一个值,而是在未来某一些情况下可以计算推导出一个值来。在程序的世界里,本质都是数值的流转与解析,为啥有直接给值,还要间接求值呢?大家可以好好玩味一下,下面开始讲述js的函数如下的几大应用场景,让大家体会js函数这种间接求值的一等公民的魅力。
2-应用场景
2.1、返回一份独立的数据
这个在vue中有多处应用到,一是组件中data要写成一个函数,而不是一个对象,二是配置props的时候,如果默认值是对象,不能直接写对象,需要写成一个函数。这都是利用里函数调用时创建一个新的封闭的作用域,方便返回新数据的特性。
export default {
name: 'MyComponent',
props: {
option: {
type: Object,
default: () => ({id: 1, value: 123}) // props默认值为对象时,需要是一个函数
}
}
data(){ // 组件中 data 需要是一个函数
return {
state: 1
}
}
}
2.2、传递参数
参数传递非常重要,是一个系统的血脉所在,为了传递参数,有时需要构造一层函数调用,外层函数接收参数,返回给里层函数,这在react中事件绑定需要传参时经常碰到,这里深刻的体现了函数作为一等公民的属性。
// react中事件绑定传参
const handleFuc = () => {
return (item) => {
// handle item
}
}
const dom = arr.map(item => {
return <div onclick=(item) => handleFuc(item)></div>
})
在事件发布订阅模式中,通过函数调用传参也是一种典型场景
// 触发事件,并传递payload
emitter.emit('some-event', payload)
2.3、封装逻辑,并能像值一样传递
没有函数,我们能写代码吗?可以写,但是离开了这个抽象和封装工具,写起来会非常繁琐和痛苦。我们把一段代码,封装起来,并且取一个名字,等遇到需要相同处理场景的时候,我们只需要拿出这个名字,调用他,而不用再把代码重新写一遍,这是编程语言的伟大发明创造,为编写现代大型强大的软件提供了决定性武器。而js中,函数定义好之后,还能存起来,后面需要触发的时候,再拿出来执行,这是发布订阅模式这种前端最重要的设计模式的核心。如果说函数是编程世界中的导弹,那js中的函数,就是导弹中的王者,能指哪儿打哪儿,足够灵活。js的函数,不仅能存在于内存中,还能序列化为字符串,持久化存贮起来,要用的时候,用eval将这个串字符串激活还原成一个能调用的函数。虽然在很多开发规范中,不推荐用eval,但是在某些场景下,使用eval还原一个函数,那是真香!
const func = () => {
console.log('Hello , 我是一个函数')
}
const funcStr = func.toString() // 函数冷冻为字符串
const aliveFunc = eval(funcStr) // eval激活唤醒函数
aliveFunc() // 调用激活的函数
2.4 创建对象
在js中,我们new 一个函数,可以创造一个对象,神奇吧,这对于正统的面向对象语言像java,或者面向过程的语言像c,这是不可思议的。在js中,函数扮演了类的角色,在es6这个版本中,虽然出现了class这个关键词,向正统的面向对象语言靠拢了,但是本质上在js中class是语法糖,本质上还是函数。
2.5 延迟计算
为啥需要延迟计算,有一个场景是,在mock数据的时候。在开发mock工具的时候,我深刻的体会到了这一点。mock数据的时候,需要随机值,因为值是随机的,需要mock引擎执行的时候,才调用random,生成随机值,不能提前执行random,不然就不会产生多样的随机值。下面贴一段之前做fig-mock的一段代码(gitee.com/wcc0077/fig…
module.exports = {
// 配置成数组, 指定生成的数目
goods:[
() => ({
id: id(), // 要mock的数据项, 统一为mockjs中Random成员函数的调用,可以参照上方的key函数
title:ctitle(),
detail:cparagraph()
}),
5
],
// 配置成函数, 默认生成20条数据
users:() => ({
id: id(),
name: cname()
}),
}
3-结语
不知大家感受到js函数的调用之美没有,可能可意会难言传,大家可以多多体会。但是函数作为js中最最核心的特性,大家应该能达成共识,多多领悟函数,拥抱react倡导的函数式编程范式,应该是前端er上升到高段位的一个武功秘籍。