JavaScript语言精粹(重读二)
函数
所谓编程,就是讲一组需求分解成一组函数与数据结构的技能
函数对象
- 对象字面量产生的对象连接到
Object.prototype
- 函数对象连接到
Function.prototype
(原型对象本身连接到Object.prototype
) - 每个函数创建时会有两个隐藏属性
- 函数上下文
- 实现函数的行为代码
每个函数对象创建时随配一个prototype属性,它的值有一个construtor尚属性,且为该函数的对象。
因为函数也是对象,它可以像任何其他值一样被使用。函数可以保存在变量,数组,对象中
函数与众不同之处在于他们可以被调用。
函数字面量
var add = function (a, b) {
return a + b;
}
- 一共四个部分
- 保留字function
- 函数名,可以省略。可以通过函数名递归调用自己,以及供调试工具来识别函数。如果没有函数名那就叫做匿名函数(anonymous)
- 参数,多个参数都逗号隔开
- 函数主体,包含中一对花括号中。在调用函数的时候执行。
函数可以定义在其他函数内部,内部函数可以方位自己的参数和变量还能方位外层函数的参数和变量。通过函数字面量创建的函数对象包含一个连接到外部上下文的连接,这个就称为闭包
调用
调用的时候,还会传递两个附加的参数:this和arguments。
参数this在面向对象编程中非常重要,它的值取决于调用的模式。js中一共有四种调用模式:方法调用,函数调用,构造器调用,和apply调用。这些调用模式在初始化官关键参数this存在差异。
- 当实际参数个数与形参个数不匹配的时候不会导致运行时错误。
- 实参过多,参数的参数会被忽略
- 实参过少,缺省的值被替换为undefiend
- 对类型不会做任何检查
调用模式
方法调用模式:当一个函数被保持为一个对象的属性时,称为方法。当方法调用的的时候this绑定到该对象。
函数调用模式:当一个函数并非对象属性是,它就当做一个函数来调用:var sum = add(3, 4);
此时this绑定到全局对象。如果该有内部函数,那么内部函数里面的this指向哪里呢。这是设计的缺陷,内部函数的this绑定了错误的值,但是可以通过如下代码修正,添加一个that变量
myObject.double = function() {
var that = this; // 解决方法
var helper = fucntion () {
that.value = add(that.value, that.vaulue);
}
helper();
}
myObject.double();
构造器调用模式:如果在一个函数前面带上new来调用你,那么会默认创建一个连接到该函数prototype成员的新对象。同事this会绑定到那个新对象上。函数创建的目的是希望结合new前缀来调用那他称为构造函数。
// 创建以构造函数,构造一个带有status属性的对象
var Quo = function (string) {
this.status = string
};
// 给Quo所有实例提供一个get_status的公共方法
Quo.prototype.get_status = function () {
return this.status;
}
// 构造一个Quo实例
var myQuo = new Quo ("con");
Apply调用模式:apply方法让我们构建一个参数数组传递给调用函数,允许我们选择this的值。第一个参数绑定this的值,第二传递参数数组。
参数
当函数调用,会得到一个额外的参数arguments
数组。可以通过这个参数获得调用时的参数列表,包括那些没有被分配给函数声明时定义的形参多余参数。
var sum function () {
var i,sum = 0;
for(i = 0; i < arguments.length; i += 1) {
sum += arguments[i];
}
return sum;
}
arguments并不是一个真正的数组
返回
一个函数总是会有返回一个值,如果没指定返回值,则返回undefined。如果函数调用时在前加上new,则返回值不是一个对象,而是返回this(新对象)