函数
函数
1. 函数的声明
1.1 关键字 function
函数就是使用function命令命名的代码区块,便于反复调用。function命令后面是函数名,函数名后面是一对圆括号,里面是传入函数的参数。函
数体放在大括号里面。
//函数的声明
function test() {
//方法体
}
1.2 函数表达式
除了用function命令声明函数,还可以采用变量赋值的写法。
//函数表达式
var test = function() {
//方法体
}
说明:
1.采用函数表达式声明函数时,function命令后面不带有函数名。
2.函数的表达式需要在语句的结尾加上分号,表示语句结束。而函数的声明在结尾的大括号后面不用加分号。总的来说,这两种声
明函数的方式,差别很细微(变量提升),这里可以近似认为是等价的。
1.3 Function构造函数
通过Function构造函数声明。总的来说,这种声明函数的方式非常不直观,几乎无人使用。
var add = new Function("x", "y", "return x + y");
console.log(add(1, 2));
1.4 函数的重复声明
如果多次采用function命令,重复声明同一个函数,则后面的声明会覆盖前面的声明。
function f(){
console.log(1);
}
f(); // 2
function f(){
console.log(2);
}
f(); // 2
2. 形式参数和return语句
调用函数时,要使用圆括号运算符。圆括号之中,可以加入函数的参数。
function add(x,y) {
return x+y;
}
add(1,1) // 2
3. 立即调用的函数表达式(IIFE(Immediately-Invoked Function Expression))
有时,我们需要在定义函数之后,立即调用该函数。这时,你不能在函数的定义之后加上圆括号,这会产生语法错误。产生这个错误的原因
是,Javascript引擎看到function关键字之后,认为后面跟的是函数定义语句,不应该以圆括号结尾。
function(){ /* code */ }();
// SyntaxError: Unexpected token (
解决方法: 圆括号前面的部分不是函数定义语句,而是一个表达式,可以对此进行运算。
(function(){ /* code */ }());
// 或者
(function(){ /* code */ })();
注意,上面的两种写法的结尾,都必须加上分号。
4. 第一等公民
JavaScript的函数与其他数据类型处于同等地位,可以使用其他数据类型的地方就能使用函数。比如,可以把函数赋值给变量和对象的属性,也
可以当作参数传入其他函数,或者作为函数的结果返回。这表示函数与其他数据类型的地方是平等,所以又称函数为第一等公民。
function add(x, y) {
return x + y;
}
// 将函数赋值给一个变量
var fn = add;
console.log(fn(1, 2));
// 将函数作为参数和返回值
function operator(fn) {
return fn;
}
console.log(operator(add)(1, 2));
5. 函数名的提升
JavaScript引擎将函数名视同变量名,所以采用function命令声明函数时,整个函数会被提升到代码头部。所以,下面的代码不会报错。
var sum = add(1, 2);
console.log(sum);
function add(x, y) {
return x + y;
}
表面上,上面代码好像在声明之前就调用了函数add。但是实际上,由于“变量提升”,函数f被提升到了代码头部,也就是在调用之
前已经声明了。但是,如果采用赋值语句定义函数,JavaScript就会报错。
var sum = add(1, 2);
console.log(sum);
var add = function (x, y) {
return x + y;
}
//Uncaught TypeError: add is not a function
如果同时采用function命令和赋值语句声明同一个函数,最后总是采用赋值语句的定义。
var fn = function() {
console.log ("1");
};
function fn() {
console.log("2");
}
fn();
// 1
6. 函数的属性和方法
6.1 name属性:返回紧跟在function关键字之后的那个函数名。
function fn1() {}
console.log(fn1.name);
var fn2 = function() {};
console.log(fn2.name);
var fn3 = function fn3() {};
console.log(fn3.name);
6.2 length属性:返回函数定义中参数的个数。
function fn(x, y) {}
console.log(fn.length);
7. 函数作用域
7.1 定义
作用域(scope)指的是变量存在的范围。Javascript只有两种作用域:一种是全局作用域,变量在整个程序中一直存在;另一种是函数作用域,
变量只在函数内部存在。
(1) 在函数外部声明的变量就是全局变量(global variable),它可以在函数内部读取。
(2) 在函数内部定义的变量,外部无法读取,称为“局部变量”(local variable)。
(3) 函数内部定义的变量,会在该作用域内覆盖同名全局变量。
7.2 函数内部的变量提升
与全局作用域一样,函数作用域内部也会产生“变量提升”现象。var命令声明的变量,不管在什么位置,变量声明都会被提升到函数体的头部。
7.3 函数本身的作用域
函数本身也是一个值,也有自己的作用域。它的作用域绑定其声明时所在的作用域。
var a = 1;
var fn = function() {
console.log(a);
};
function fn1() {
var a = 2;
fn();
}
fn1(); //1
8. 参数
8.1 概述
函数运行的时候,有时需要提供外部数据,不同的外部数据会得到不同的结果,这种外部数据就叫参数。
function square(x) {
return x * x;
}
square(2); //4
square(3); //9
8.2 传递方式
JavaScript的函数参数传递方式是传值传递(passes by value),这意味着,在函数体内修改参数值,不会影响到函数外部。
//原始数据类型
var a = 1;
function fn(a) {
a = 3;
}
fn(a);
console.log(a); //1
//引用类型
var arr = [1, 2, 3];
function fn1(arr) {
arr = [4, 5, 6];
}
fn1(arr);
console.log(arr); //[1, 2, 3]
注意 , 虽然参数本身是传值传递,但是对于复合类型的变量来说,属性值是传址传递(pass by reference),也就是说,属性值是通过
地址读取的。所以在函数体内修改复合类型变量的属性值,会影响到函数外部。
//修改对象的属性值
var obj = {
attr : 1
};
function fn(obj) {
obj.attr = 2;
}
console.log(obj.attr);
//修改数组的元素值
var arr = [1, 2, 3];
function fn(arr) {
arr[0] = 4;
arr[1] = 5;
arr[2] = 6;
}
fn(arr);
console.log(arr.toString());
8.3 arguments对象
1) 由于JavaScript允许函数有不定数目的参数,所以我们需要一种机制,可以在函数体内部读取所有参数。这就是arguments对象的由来。
2) arguments对象包含了函数运行时的所有参数,arguments[0]就是第一个参数,arguments[1]就是第二个参数,依次类推。这个对象只有在函
数体内部,才可以使用。
3) 可以通过arguments对象的length属性,判断函数调用时到底带几个参数。
浙公网安备 33010602011771号