1.声明
1. function aa() {} //function命令
2.var aa = function() {} //函数表达式
3.构造函数:var add = new Function(
'x',
'y',
'return x + y'
);
// 等同于
function add(x, y) {
return x + y;
}
第三种特别不直观,所以几乎无人使用
如果一个函数多次声明,那么后面的就会覆盖前面的
2.递归
函数可以调用自身,这就是递归
3.第一等公民
JS语言把函数看作一种值,与其他值(字符串,数值,布尔等等地位相同),凡是可以使用值的地方,都可以使用函数。
比如,可以把函数赋值给变量和对象的属性,也可以当作参数传入其他函数,或者作为函数的结果返回。函数只是一个可以执行的值,此外并无特殊之处
由于函数与其他数据类型地位平等,所以在 JavaScript 语言中又称函数为第一等公民
4.函数名的提升
JavaScript 引擎将函数名视同变量名,所以使用 function 命令声明函数时,整个函数会像变量声明一样,被提升到代码头部; 所以下面代码不会报错
f();
function f() {}
但是采用赋值语句定义函数就会报错
f();
var f = function (){};
// TypeError: undefined is not a function
以上代码等同于
var f;
f();
f = function () {};
5.函数的属性和方法
name
返回函数的名字
function f1() {}
f1.name // "f1"
var f2 = function () {};
f2.name // "f2"
var f3 = function myName() {};
f3.name // 'myName'
length
获取函数的参数个数
函数的length属性与实际传入的参数个数无关,只反映函数预期传入的参数个数。
function f(a, b) {}
f.length // 2
toString()
返回一个字符串,内容是函数的源码
unction f() {
a();
b();
c();
}
f.toString()
// function f() {
// a();
// b();
// c();
// }
6.函数的作用域
- 作用域:变量存在的范围
ES5中,Javascript只有两种作用域:
1.全局作用域,变量在整个程序中一直存在,所有地方都可以读取;
2.函数作用域,变量只在函数内部存在。
ES6中新增了块级作用域
函数外部声明的变量就是全局变量(global variable),它可以在函数内部读取。
函数内部定义的变量,外部无法读取,称为“局部变量”(local variable)。
函数内部定义的变量,会在该作用域内覆盖同名全局变量
7. 函数内部的变量提升
与全局作用域一样,函数作用域内部也会出现“变量提升”现象,var命令声明的变量,不管在什么位置,变量声明都会被提升到函数体的头部
8.函数本身的作用域
函数本身也是一个值,也有自己的作用域。它的作用域与变量一样,就是其声明时所在的作用域,与其运行时所在的作用域无关。
9.传递方式
- 函数参数如果是原始类型的值(
数值,字符串,布尔值),传递方式是传值传递。这意味着在函数体内部修改参数值,不会影响到函数外部; - 如果函数参数是复合类型的值(
数组、对象、其他函数),传递方式是传址传递(pass by reference)。也就是说,传入函数的原始值的地址,因此在函数内部修改参数,将会影响到原始值。var obj = { p: 1 }; function f(o) { o.p = 2; } f(obj); obj.p // 2
注意,如果函数内部修改的,不是参数对象的某个属性,而是替换掉整个参数,这时不会影响到原始值。
var obj = [1, 2, 3];
function f(o) {
o = [2, 3, 4];
}
f(obj);
obj // [1, 2, 3]
上面代码中,在函数f内部,参数对象obj被整个替换成另一个值。这时不会影响到原始值。
这是因为,形式参数(o)的值实际是参数obj的地
址,重新对o赋值导致o指向另一个地址,保存在原地址上的值当然不受影响。
(可以自己画一下内存图)