javascript中函数就是对象,对象字面值产生的对象连接到Object.prototype,函数对象连接到Function.prototype(Function.prototype也连接到Object.prototype)。函数创建时,附加两个隐藏属性,函数上下文和实现函数的代码。函数和对象的不同之处是函数多一个“调用”属性。
函数可以保存在变量中,函数名可以省略。
函数可以嵌套定义,内部的函数可以访问父函数的参数和变量,内部定义的函数包含到父函数上下文的连接,这被称为闭包。
函数属于一个对象时,这个函数叫做这个对象的方法,方法调用时,还收到两个附加的参数,this和arguments,this指向方法的所属对象,也就是说方法调用时this绑定到其所属对象,arguments包含传入的参数,传入的参数过少,未定义的参数初始化为undefined,过多会自动忽略。
this的用法例子:
var student = {
"age" : 18,
"sayhello" : function()
{
console.log("I am " + this.age);
}
};
student.sayhello();
函数不属于某个对象时,其this被绑定到全局对象,这里javascript语言上就出了个bug,内部函数不属于任何对象,其this被绑定到了全局对象,而实际上显然应该绑定到外部函数的this。解决方法是外部函数定义一个that变量指向this,内部函数使用that。
var student = {
"age" : 18,
"sayhello" : function()
{
var that = this;
inner_sayhello();
function inner_sayhello()
{
console.log("I am " + that.age);
}
}
};
javascript是基于原型的面向对象语言,实际上不应该有构造器的概念,但偏离了主流语言的风格,因此也提供了构造器的概念。
在一个函数前用new调用,将会创建一个连接到该函数prototype成员的新对象,this会被绑定到新对象上。约定这类函数以大写字母开头,像Java的类定义一样。不推荐使用这种构造方式。
function Student(name)
{
this.name = name;
}
Student.prototype.sayhello = function()
{
console.log(this.name);
};
函数也是对象,所以也有方法,apply方法可以手动给函数绑定this和参数数组。
function add(a, b)
{
return a + b;
}
var result = add.apply(null, [1, 2]);
由于函数参数实际上是通过arguments数组(实际上不是数组,而是array-like,包含length属性)传递给函数的,所以可以编写一个无需指定参数个数的函数。例子:
function add()
{
var sum = 0;
for(i = 0; i < arguments.length; i++)
{
sum += arguments[i];
}
return sum;
}
return指示进行返回,如果没有指定返回值,返回undefined,使用new时,函数返回值是this。
异常可以中断函数执行,throw抛出一个异常对象,通常应该包含name和message属性,用于说明异常类型和报错信息,也可以根据需求添加其他属性。
try
{
throw {
"name" : "error name",
"message" : "error message"
};
}
catch(err)
{
console.log(err.name);
console.log(err.message);
}
javascript可以对语言的基本类型扩充功能,上一章的给Object.property添加create()函数就是一个例子。
Javascript并不支持块级作用域,函数区分作用域。
内层函数可以直接访问外层函数的变量,而不是将其复制。即使外层函数已经返回了,而内层函数还未执行完,那么就可能保留着一些变量供内层函数调用。例子:
function out_func()
{
var count = 0;
function in_func()
{
count++;
console.log(count);
setTimeout(in_func, 500);
}
setTimeout(in_func, 500);
return "out_func returned";
}
使用闭包可以避免全局变量,把一些信息隐藏到内层函数中,避免被修改。
让一个方法返回this可以实现链式调用,例子:
var tom = {
"age" : 10,
"growup" : function()
{
this.age++;
return this;
}
};
tom.growup().growup().growup();