「前端每日一问(19)」JS 中函数为什么被称为一等公民?
Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情。
本题难度:⭐
JS 中为什么函数被称为一等公民?或者说函数为何是第一类对象?
答:
因为 JavaScript 中函数也是对象,函数拥有对象的所有能力,也因此函数可被作为任意其他类型对象来对待。
当我们说函数是第一类对象(一等公民)的时候,就是说函数也能实现对象的全部功能。
函数也是对象
JS 里,一切皆是对象,函数也不例外,废话不多说,直接测试一下,
对象拥有的能力,函数都有
函数也是对象,对象能做的任何一件事,函数都能做。唯一的区别是函数是可调用的(invokable),即函数会被调用以便执行某项动作。
对象
- 对象可以通过字面量来创建。
const obj = {}
- 对象可以赋值给变量、数组项,或其他对象的属性。
const obj = {} // 赋值给变量
const arr = []
arr.push(obj) // 赋值给数组项
obj.data = {} // 赋值给其他对象的属性
- 对象可以作为函数的入参和出参。
function fn (obj) {
return {
obj
}
}
fn({ name: 'lin'})
- 对象可以动态创建和分配属性。
const obj = {}
obj.name = 'lin'
函数
- 函数可以通过字面量来创建。
function fn () {}
- 函数可以赋值给变量、数组项,或其他对象的属性。
const fn = function () {} // 赋值给变量
const arr = []
arr.push(fn) // 赋值给数组项
const obj = {}
obj.fn = fn // 赋值给其他对象的属性
- 函数可以作为函数的入参和出参,这是JS 为何有闭包的一个重要原因。
function fn (callback) {
return callback()
}
fn(() => {
console.log('hello')
})
- 函数可以动态创建和分配属性。
function fn () {}
fn.name = 'lin'
fn.age = 18
扩展:函数可以分配属性的一些用途
函数唯一标识
给函数设置一个 id 属性,作为唯一标识,在某些情况下可以提高性能,比如,
一个集合中的函数,不希望出现重复函数
const store = {
nextId: 1,
cache: {},
add (fn) {
if (!fn.id) {
fn.id = this.nextId++
this.cache[fn.id] = fn
}
}
}
测试一下,
function fn1 () {}
function fn2 () {}
store.add(fn1)
store.add(fn1) // add了两个相同的函数
store.add(fn2)
console.log(store.cache)
添加了两次 fn1 ,最后存储下来的只有一个,如下图,
这种写法可以用于管理事件发生后需要调用的回调函数集合,已经存在于集合中的函数就不要再存进去了,提高性能。
自记忆函数
通过给函数添加属性来记住一些计算结果,之后再调用的时候就可以不用重新计算了,提高性能,以计算素数为例,
function isPrime (value) {
if (!isPrime.cache) {
isPrime.cache = {} // 给函数添加一个 cache 来记住计算结果
}
if (isPrime.cache[value] !== undefined) {
console.log(`缓存里有${value},直接返回`)
return isPrime.cache[value] // 如果有值就直接返回
}
let prime = value > 1 // 计算
for (let i = 2; i < value; i++) {
if (value % i === 0) {
prime = false
break
}
}
console.log(`缓存里没有${value},存进去`)
return isPrime.cache[value] = prime // 如果是第一次计算,就存值
}
测试一下,
isPrime(3)
isPrime(4)
isPrime(5)
isPrime(5)
isPrime(5) // 多次计算 5
console.log('isPrime.cache :>> ', isPrime.cache)
计算素数只是简单的计算,但如果用于处理复杂的计算,比如动画中的计算、搜索不经常变化的数据、耗时的数学运算等,对性能的提升无疑是巨大的。
小结
给函数添加属性的写法有利有弊:
- 好处是能把属于这个函数的功能集中在一起;
- 坏处是纯粹主义者会认为逻辑混合太多,函数应该只需要把一件事做好
仁者见仁,智者见智,纯粹的函数式编程有人做大量实践,给函数添加属性也有人做大量实践,比如 React 源码中的
FunctionComponent
,也在函数上定义了一大堆属性呢。
对于我们普通开发者而言,平时开发中能用就用,即使用不到,了解一下,开拓视野也挺好的。
结尾
如果我的文章对你有帮助,你的👍就是对我的最大支持^_^
我是阿林,输出洞见技术,再会!
上一篇:
下一篇:
转载自:https://juejin.cn/post/7075089473402306597