Skip to content

Latest commit

 

History

History
108 lines (92 loc) · 4.62 KB

03.理解函数.md

File metadata and controls

108 lines (92 loc) · 4.62 KB

03.理解函数

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 的新特性。
    • 剩余参数——不与任何形参名相匹配的额外实参可以通过剩余参数来引用。
    • 默认参数——函数调用时,若没传入参数,默认参数可以给函数提供缺省的参数值。