1.概念
函数是一段可以反复调用的代码块,可以接受参数,不同的参数会返回不同的值。
2.函数的声明
函数有三种声明方法:function命令、函数表达式、Function构造函数
function命令:function命令后跟函数名,函数名后面是一对圆括号,里面传入函数的参数。函数体放在大括号里面。
function print(s) {
console.log(s);
}
函数表达式(Function Expression): 将一个匿名函数赋值给变量
var print = function(s) {
console.log(s);
};
采用函数表达式声明函数时,function命令后面不带有函数名。如果加上函数名,该函数名只在函数体内部有效,在函数体外部无效。
var print = function x(){
console.log(typeof x);
};
x
// ReferenceError: x is not defined
print()
// function
这个x只在函数体内部可用,指代函数表达式本身,其他地方都不可用。这种写法的用处有两个,一是可以在函数体内部调用自身,二是方便除错(除错工具显示函数调用栈时,将显示函数名,而不再显示这里是一个匿名函数)
Function 构造函数
var add = new Function(
'x',
'y',
'return x + y'
);
// 等同于
function add(x, y) {
return x + y;
}
3.函数的重复声明
如果同一个函数被多次声明,后面的声明就回覆盖前面的声明。
4.圆括号运算符,return 语句和递归
函数内部的return语句,表示返回,return语句所带的那个表达式,就是函数的返回值。
函数可以调用自身,这就是递归(recursion)。
例如:通过递归,计算斐波那契数列的代码
function fib(num) {
if (num === 0) return 0;
if (num === 1) return 1;
return fib(num - 2) + fib(num - 1);
}
fib(6) // 8
5.函数的属性和方法
name 属性:返回函数的名字。
function f1() {}
f1.name // "f1"
length 属性:函数的length属性返回函数预期传入的参数个数,即函数定义之中的参数个数。
function f(a, b) {}
f.length // 2
toString() :函数的toString()方法返回一个字符串,内容是函数的源码。
function f() {
a();
b();
c();
}
f.toString()
// function f() {
// a();
// b();
// c();
// }
对于那些原生的函数,toString()方法返回function (){[native code]}。
6.函数作用域
作用域(scope)指的是变量存在的范围。
JavaScript 只有两种作用域:一种是全局作用域,变量在整个程序中一直存在,所有地方都可以读取;另一种是函数作用域,变量只在函数内部存在。
对于顶层函数来说,函数外部声明的变量就是全局变量(global variable),它可以在函数内部读取。
在函数内部定义的变量,外部无法读取,称为“局部变量”(local variable)。
函数内部定义的变量,会在该作用域内覆盖同名全局变量。
7.参数
函数运行的时候,有时需要提供外部数据,不同的外部数据会得到不同的结果,这种外部数据就叫参数。
8.参数的传递方式
函数参数如果是原始类型的值(数值、字符串、布尔值),传递方式是传值传递(passes by value)。在函数体内修改参数值,不会影响到函数外部
函数参数是复合类型的值(数组、对象、其他函数),传递方式是传址传递(pass by reference)。也就是说,传入函数的原始值的地址,因此在函数内部修改参数,将会影响到原始值。
如果函数内部修改的,不是参数对象的某个属性,而是替换掉整个参数,这时不会影响到原始值。
9.arguments 对象
arguments对象包含了函数运行时的所有参数。
通过arguments对象的length属性,可以判断函数调用时到底带几个参数。
arguments很像数组,但它是一个对象。
如果要让arguments对象使用数组方法,真正的解决方法是将arguments转为真正的数组。
下面是两种常用的转换方法:
slice方法和逐一填入新数组
var args = Array.prototype.slice.call(arguments);
// 或者
var args = [];
for (var i = 0; i < arguments.length; i++) {
args.push(arguments[i]);
}
callee 属性:返回它所对应的原函数
var f = function () {
console.log(arguments.callee === f);
}
f() // true