JavaScript 中最关键的概念是:函数是第一类对象(first-class objects),或者说它们 被称作一等公民(first-class citizens)。函数与对象共存,函数也可以被视为其他任意类 型的 JavaScript 对象。函数和那些更普通的 JavaScript 数据类型一样,它能被变量引用, 能以字面量形式声明,甚至能被作为函数参数进行传递。
- 在集合中存储函数使我们轻易管理相关联的函数。例如,某些特定情况下必须调用的回调函数。
- 记忆让函数能记住上次计算得到的值,从而提高后续调用的性能。
存储唯一函数集合
var store = {
nextId: 1,
cache: {},
add: function(fn) {
if (!fn.id) {
// 仅当函数唯一时,将该函数加入缓存
fn.id = this.nextId++;
this.cache[fn.id] = fn;
return true;
}
}
};
记忆化(memoization)是一种构建函数的处理过程,能够记住上次计算结果。
计算先前得到的值
function isPrime(val) {
if (!isPrime.answers) {
isPrime.answers = {}; // 创建缓存
}
if (isPrime.answers[val] !== undefined) {
// 检查参数中传的值是否已经存储到缓存中
console.log('已缓存');
return isPrime.answers[val];
}
var prime = val !== 0 && val !== 1; // 1 is not a prime
for (var i = 2; i < val; i++) { // 缓存会针对参数中的值 value 来存储该值是否为素数(true 或 false)
if (val % i === 0) {
prime = false;
break;
}
}
console.log('加入缓存');
return isPrime.answers[val] = prime // 存储计算的值
}
isPrime(5) // 加入缓存
isPrime(5) // 已缓存
- 优点:
- 由于函数调用时会寻找之前调用所得到的值,所以用户最终会乐于看到所获得的性能收益。
- 它几乎是无缝地发生在后台,最终用户和页面作者都不需要执行任何特殊请求,也不需要做任何额外初始化,就能顺利进行工作。
- 缺点:
- 任何类型的缓存都必然会为性能牺牲内存。
- 纯粹主义者会认为缓存逻辑不应该和业务逻辑混合,函数或方法只需要把一件事做好。
- 对于这类问题很难做负载测试或估计算法复杂度,因为结果依赖于函数之前的输入。
- 函数定义(function declarations)和函数表达式(function expressions)
function myFun(){ return 1;}
- 立即函数:
(function(){}())
(function(){})()
+function(){}();
-function(){}();
!function(){}();
~function(){}();
- 箭头函数(通常被叫做 lambda 函数)
myArg => myArg*2
- 函数构造函数
new Function('a', 'b', 'return a + b')
- 生成器函数
function* myGen(){ yield 1; }
- 把 JavaScript 看作函数式语言你就能书写复杂代码。
- 作为第一类对象,函数和 JavaScript 中其他对象一样。类似于其他对象类型,函数具有以下功能。
- 通过字面量创建。
- 赋值给变量或属性。
- 作为函数参数传递。
- 作为函数的结果返回。
- 赋值给属性和方法。
- 回调函数是被代码随后“回来调用”的函数,它是一种很常用的函数,特别是在事件处理场景下。
- 函数具有属性,而且这些属性能够被存储任何信息,我们可以利用这个特性来做很多事情;例如:
- 可以在函数属性中存储另一个函数用于之后的引用和调用。
- 可以用函数属性创建一个缓存(记忆),用于减少不必要的计算。
- 有很多不同类型的函数:函数声明、函数表达式、箭头函数以及函数生成器等。
- 函数声明和函数表达式是两种最主要的函数类型。函数声明必须具有函数名,在代码中它也必须作为一个独立的语句存在。函数表达式可以不必有函数名,但此时它就必须作为其他语句的一部分。
- 箭头函数是 JavaScript 的一个新增特性,这个特性让我们可以使用更简洁的方式来定义函数。
- 形参是函数定义时列出的变量,而实参是函数调用时传递给函数的值。
- 函数的形参列表和实参列表长度可以不同。
- 未赋值的形参求值得到undefined。
- 传入的额外实参不会被赋给任何一个命名形参。
- 剩余参数和默认参数是 JavaScript 的新特性。
- 剩余参数——不与任何形参名相匹配的额外实参可以通过剩余参数来引用。
- 默认参数——函数调用时,若没传入参数,默认参数可以给函数提供缺省的参数值。