一、函数
函数是⼀段可以反复调⽤的代码块。函数还能接受输⼊的参数,不同的参数会返回不同的值。
函数概述
函数的声明
JavaScript 有三种声明函数的⽅法。
1. function 命令 function命令声明的代码区块,就是⼀个函数。function命令后⾯是函数名,函数名后⾯是⼀对圆括号,⾥⾯是传⼊函数的参数。函数体放在⼤括号⾥⾯。
function print(s) { console.log(s); }
2. 函数表达式 除了⽤function命令声明函数,还可以采⽤变量赋值的写法
var print = function(s) { console.log(s); };
3. Function 构造函数 第三种声明函数的⽅式是Function构造函数。
var add = new Function( 'x', 'y', 'return x + y' ); // 等同于 function add(x, y) { return x + y; }
总的来说,这种声明函数的⽅式⾮常不直观,⼏乎⽆⼈使⽤。
函数的重复声明
如果同⼀个函数被多次声明,后⾯的声明就会覆盖前⾯的声明。
function f() { console.log(1); } f() // 2 function f() { console.log(2); } f() // 2
第⼀等公⺠
JavaScript 语⾔将函数看作⼀种值,与其它值(数值、字符串、布尔值等等)地位相同。凡是可以使⽤值的地⽅,就能使⽤函数。⽐如,可以把函数赋值给变量和对象的属性,也可以当作参数传⼊其他函数,或者作为函数的结果返回。函数只是⼀个可以执⾏的值,此外并⽆特殊之处。
由于函数与其他数据类型地位平等,所以在 JavaScript 语⾔中⼜称函数为第⼀等公⺠。
function add(x, y) { return x + y; } // 将函数赋值给⼀个变量 var operator = add; // 将函数作为参数和返回值 function a(op){ return op; } a(add)(1, 1) // 2
函数名的提升
JavaScript 引擎将函数名视同变量名,所以采⽤function命令声明函数时,整个函数会像变量声明⼀样,被提升到代码头部。所以,下⾯的代码不会报错。
f(); function f() {}
但是,如果采⽤赋值语句定义函数,JavaScript 就会报错。
f(); var f = function (){}; // TypeError: undefined is not a function
不能在条件语句中声明函数
根据 ES5 的规范,不得在⾮函数的代码块中声明函数,最常⻅的情况就是if语句
if (foo) { function x() {} }
函数的属性和⽅法
name 属性
函数的name属性返回函数的名字。
function f1() { } f1.name // "f1"
如果是通过变量赋值定义的函数,那么name属性返回变量名。
var f2 = function () {}; f2.name // "f2"
name属性的⼀个⽤处,就是获取参数函数的名字。
var myFunc = function () {}; function test(f) { console.log(f.name); } test(myFunc) // myFunc
length 属性
函数的length属性返回函数预期传⼊的参数个数,即函数定义之中的参数个数。
function f(a, b) {} f.length // 2
toString()
函数的toString⽅法返回⼀个字符串,内容是函数的源码。
function f() { a(); b(); c(); } f.toString() // function f() { // a(); // b(); // c(); // }
函数作⽤域
定义
作⽤域(scope)指的是变量存在的范围。在 ES5 的规范中
JavaScript 只有两种作⽤域:⼀种是全局作⽤域,变量在整个程序中⼀直存在,所有地⽅都可以读取;
另⼀种是函数作⽤域,变量只在函数内部存在。
ES6 ⼜新增了块级作⽤域
函数外部声明的变量就是全局变量(global variable),它可以在函数内部读取。
var v = 1; function f() { console.log(v); } f() // 1
在函数内部定义的变量,外部⽆法读取,称为“局部变量”(local variable)。
function f(){ var v = 1; } v // ReferenceError: v is not defined
函数内部定义的变量,会在该作⽤域内覆盖同名全局变量。
var v = 1; function f(){ var v = 2; console.log(v); } f() // 2 v // 1
注意,对于var命令来说,局部变量只能在函数内部声明,在其他区块中声明,⼀律都是全局变量。
if (true) { var x = 5; } console.log(x); // 5
函数内部的变量提升
与全局作⽤域⼀样,函数作⽤域内部也会产⽣“变量提升”现象。var命令声明的变量,不管在什么位置,变量声明都会被提升到函数体的头部。
function foo(x) { if (x > 100) { var tmp = x - 100; } }
函数本身的作⽤域
函数本身也是⼀个值,也有⾃⼰的作⽤域。它的作⽤域与变量⼀样,就是其声明时所在的作⽤域,与其运⾏时所在的作⽤域⽆关。
var a = 1; var x = function () { console.log(a); }; function f() { var a = 2; x(); } f() // 1
函数参数
函数运⾏的时候,有时需要提供外部数据,不同的外部数据会得到不同的结果,这种外部数据就叫参数。
function square(x) { return x * x; } square(2) // 4 square(3) // 9
参数的省略
函数参数不是必需的,Javascript 允许省略参数。
function f(a, b) { return a; } f(1, 2, 3) // 1 f(1) // 1 f() // undefined f.length // 2