C4 -- 函数
函数对象
对象字面量产生的对象连接到Object.prototype,函数对象连接到Function.prototype(该原型对象本身连接到Object.prototype)每个函数在创建时会附加两个隐藏属性:函数的上下文和实现函数行为的代码(调用)。
每个函数对象在创建时也随配有一个prototype属性。它的值是一个拥有constructor属性且值即为该函数的对象。
函数可以保存在变量,对象和数组中。函数可以被当作参数传递给其他函数,函数也可以再返回函数。而且,因为函数是对象,所以函数可以拥有方法。
函数的与众不同的地方在于他们可以被调用。
函数字面量
- 保留字 function
- 函数名 可以被省略为匿名函数
- 包围在圆括号里的一组参数,被定义为函数中的变量,在该函数被调用时初始化为实际提供的参数的值。
- 包围在花括号中的一组语句。这些语句是函数的主体,他们在函数被调用时执行。
函数可以被定义在其他函数中。
调用
除了声明时定义的形式参数,每个函数还接收两个附加的参数:this 和 arguments.参数this在面向对象编程中非常重要,它的值取决于调用的模式。在JavaScript中共有四种调用模式:
- 方法调用模式
- 函数调用模式
- 构造器调用模式
- apply调用模式
四种模式在如何调用初始化关键参数this上存在差异。
调用运算符是跟在任何产生一个函数值的表达式之后的一对圆括号。圆括号内可包含零个或者多个用逗号隔开的表达式。每个表达式产生一个参数值。如果实际参数值过多了,超出的值会被忽略;如果实际的参数值过少,缺失的被替换为undefined.对参数值不会进行类型检查:任何类型的值都可以被传递给任何参数。
方法调用模式
当一个函数被保存为对象的一个属性时,我们称它为一个方法。当一个方法被调用时,this被绑定到该对象。
this到对象的绑定发生在调用的时候。
函数调用模式
当一个函数并非一个对象的属性时,那么他就是被当作函数来调用。
以此模式调用函数时,this被绑定到全局对象。
如果该方法定义一个变量that并给它赋值为this,那么内部函数就可以通过那个变量访问到this
构造器调用模式
JavaScript是一门基于原型继承的语言。这意味着对象可以直接从其他对象继承属性,该语言是无类型的。
提供了一套和基于类的语言类似的对象构建语法。
如果在一个函数前面带上new来调用,那么背地里将会创建一个连接到该函数的prototype成员的新对象,同时this也会绑定到那个新对象上。
new前缀也会改变return语句的行为。
一个函数,如果创建的目的就是希望结合new前缀来调用,那么它就被称为构造器函数。他们保存在以大写格式命名的变量里,调用构造器函数时需要在前面加上new.
Apply调用模式
JavaScript是一门函数是的面向对象编程语言,所以函数可以拥有方法。
apply方法让我们构建一个参数数组传递给调用函数,允许我们选择this的值,该方法接受两个参数,第一个是要绑定给this的值,第二个是一个参数数组。
参数
当函数被调用时,会得到一个参数arguments数组,函数可以通过此参数访问所有被他调用时传递给它的参数列表,包括那些没有分配给函数声明时定义的形式参数的多余参数。arguments并不是一个真正的数组,只是一个类似数组的对象。arguments拥有一个length属性,但他没有任何数组的方法。
返回
return语句使函数提前返回。当return被执行了,函数立即返回不执行余下的语句。
一个函数总是会返回一个值,如果没有指定返回值,则返回undefined。
如果函数调用时在前面加上了new前缀,且返回值不是一个对象,则返回this(该新对象)
异常
throw语句抛出一个exception对象,其中的表达式通常是一个对象字面量,包含一个name属性和一个message属性。该exception对象将被传递到一个try语句的catch 从句中。
一个try语句只会有一个捕获所有异常的catch代码块。
扩充类型的功能
JavaScript允许给语言的基本类型扩充功能。通过给Object.prototype添加方法,可以让该方法对所有对像都可用。这样的方式对函数、数组、字符串、数字、正则表达式和布尔值同样适用。
递归
递归函数就是会直接或者间接调用自身的一种函数,将一个问题分解为一组相似的子问题。
返回自身调用的结果,则被称为尾递归。
作用域
作用域控制变量和参数的可见性及生命周期,减少了名称冲突,并且提供了自动内存管理。
函数作用域,定义在函数中的参数和变量在函数外部是不可见的,在内部任何位置定义的变量,在该函数内部任何地方都可见。
最好的做法是在函数体的顶部声明函数中可能用到的所有变量。
闭包
作用域的好处是,内部的函数可以访问定义在他们的外部函数的参数和变量(除了this和rguments).
内部函数拥有比他的外部函数更长的生命周期。
函数可以访问他被创建时所处的上下文环境。
内部函数可以访问外部函数的实际变量而无需复制 。
!p38

回调
发起异步请求,响应到达时触发回调函数
模块
可以使用函数和闭包来构造模块。模块是一个提供接口却隐藏状态与实现的函数或对象。模块模式利用了函数作用域和闭包来创建被绑定对象与私有成员的关联。
模块模式的一般形式是:一个定义了私有变量和函数的函数;利用闭包创建可以访问私有变量和函数的特权函数;最后返回这个特权函数,或者把他们保存到一个可访问的地方。
模块模式也可以用来产生安全的对象。
模块模式通常结合单例模式使用。JavaScript的单例就是用对象字面量表示法创建的对象,对象的属性值可以是可以是数值或函数,并且属性值在该对象的生命周期中不会发生变化。它通常作为工具为程序其他部分提供功能支持。
级联
有一些方法没有返回值,存在一些设置或修改对象的某个状态却不返回任何值的方法,如果这些方法返回值this,就可以启用级联。在一个级联中,可以在单独一条语句中依次调用同一个对象的很多方法。调用方法,每一个都返回这个对象,每次调用返回的结果都可以被下一次调用所用。
柯里化/局部套用
把多参数函数转化为一系列单参数函数并进行调用。
把函数和传递给它的参数结合产生出一个新的函数。
记忆
函数可以把先前操作的结果记录在某个对乡里,从而避免无谓的重复运算。