目录
- 函数的意义
- 函数的作用
- 函数三种声明方式
- 形参和实参
- arguments对象
- 函数的重复声明
- 函数的返回值
函数的意义
函数是一段反复可以调用的代码块。
函数的作用
- 代码复用
- 让代码变得更可靠,更稳定
- 增加代码安全程度
- 创建函数作用域,避免变量污染
函数声明方式
在js
中有三种函数的声明方式:
1. function命令
function命令声明的代码区块,就是一个函数。function命令后面就是函数名,函数名后面是一对圆括号,里面是传入函数的参数,函数体放在打括号里面。
例如:
function fn1() {
// code...
}
上面的代码定义了一个fn1
函数,我们想要使用这个函数,只需要通过fn1()
这种形式即可执行其中相应的代码段。
这就叫做函数的声明(Function Declaration)
。
2. 函数表达式
采用变量赋值的方式。
示例:
var fn1 = function() {
console.log('hello,world!');
}
这种写法是将一个匿名函数
赋值给变量。这时,这个匿名函数又称为函数表达式(Function Expression),因为赋值语句的等号右侧只能放表达式。
采用函数表达式声明函数时,function命令后面不带有函数名。如果加上函数名,该函数名只在函数体内部有效,在函数体外部无效。
例如:
var fn1 = function test() {
console.log(typeof test);
};
fn1(); // 通过这种调用方式可以顺利执行代码
test(); // 通过这种调用方式则会出现not defined 错误。
在实际开发的过程中,上面的这种在使用函数表达式写法并且同时给函数设置名字的做法其实很常见。
这么做的目的有两个:
- 可以非常方便的在函数体内部调用自身
- 方便除错,除错工具显示函数调用栈时,将显示函数名,而不再显示这里是一个匿名函数
var f = function f() {};
需要注意的是,函数的表达式需要在语句的结尾加上分号,表示语句结束。而函数的声明在结尾的大括号后面不用加分号。
3. Function 构造函数
例如:
var add = new Function (
'x',
'y',
'return x + y'
);
console.log(add);
上面这个通过构造函数创建的代码与下面的代码大体是相等的:
function add(x,y) {
return x + y;
}
上面通过构造函数创建函数的代码中,Function构造函数接受三个参数,除了最后一个参数是add函数的“函数体”,其他参数都是add函数的参数。
你可以传递任意数量的参数给Function构造函数,只有最后一个参数会被当做函数体,如果只有一个参数,该参数就是函数体。
var foo = new Function(
'return "hello world";'
);
// 等同于
function foo() {
return 'hello world';
}
总的来说,这种声明函数的方式非常不直观,几乎无人使用。
圆括号运算符
在我们调用函数的时候,要使用圆括号运算符。圆括号之中,可以加入函数的参数。
例如:
function fn1() {
console.log("hello,world!");
}
fn1();
在上面的案例中,函数名后面紧跟一对圆括号,就会调用这个函数。
我们也可以通过在调用函数的时候传递参数从而实现数据的传递。
function sayHello(name) {
console.log("你好,"+name);
}
sayHello("张三");
一般情况下,我们将函数名后面的括号里面的参数称之为形参
,而在调用函数时使用的圆括号里面传递的参数,我们称之为实参
。
形参和实参
/ *
* 定义一个用来求两个数和的函数
* 可以在函数的()中指定一个或多个形参(形式参数)
* 多个形参之间使用 ,隔开,声明形参就相当于在函数内部声明了对应的变量,但是并不赋值
*
/
function sum(a,b) {
console.log(a+b);
}
/*
* 在调用函数时,可以在()中指定实参(实际参数)
* 实参将会赋值给函数中对应的形参
/
/*
* 在调用函数时,解析器不会检查实参的类型,
* 所以要注意,是否有可能会接收到非法的参数,如果有可能则需要对参数进行类型的检查
函数的实参可以是任意类型的数据类型
/
// sum(123,"hello"); // "123hello"
// sum(true,false); // 1
/*
* 调用函数时,解析器也不会检查实参的数量,
* 多余实参不会被赋值
* 如果实参的数量小于形参的数量,则没有对应实参的形参将是undefined
*/
// sum(123,234,"hello","hsdf",true,null);
// sum(123);
arguments对象
arguments
(ar gei men ci)对象包含了函数运行时所有的参数(实参),arguments[0]
就是第一个参数,arguments[1]
就是第二个参数,以此类推。
需要注意的是,这个对象只有在函数体内部才能使用。
function f1() {
// 获取传入的实参
console.log(arguments[0]);
console.log(arguments[1]);
console.log(arguments[2]);
console.log(arguments[3]);
}
f1(1,2,3,4);// 1 2 3 4
在正常的模式下,arguments对象可以在运行的时候进行修改。
var f = function(a, b) {
arguments[0] = 3;
arguments[1] = 2;
return a + b;
}
f(1, 1) // 5
上面代码中,函数f调用时传入的参数,在函数内部被修改成3和2。
严格模式下,arguments对象与函数参数不具有联动关系。也就是说,修改arguments对象不会影响到实际的函数参数。
var f = function(a, b) {
'use strict'; // 开启严格模式
arguments[0] = 3;
arguments[1] = 2;
return a + b;
}
f(1, 1) // 2
上面代码中,函数体内是严格模式,这时修改arguments对象,不会影响到真实参数a和b。
length属性
通过arguments
对象的length
属性,可以判断函数调用时到底带几个参数。
function f() {
return arguments.length;
}
f(1, 2, 3); // 3
f(1); // 1
f(); // 0
与数组的关系 -- 类数组对象
需要注意的是,虽然arguments
很像数组,但它是一个对象。数组专有的方法(比如slice
和forEach
),不能在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属性
arguments对象带有一个callee
属性,返回它所对应的原函数。
var f = function () {
console.log(arguments.callee === f);
}
f() // true
可以通过arguments.callee
,达到调用函数自身的目的。这个属性在严格模式里面是禁用的,因此不建议使用。
函数重复声明
当在js代码中出现函数重复声明的情况(也就是函数名相同),那么后面的函数会把前面的函数给覆盖掉。
function fn1() {
console.log(1111);
}
function fn1() {
console.log(2222);
}
fn1(); // 2222
函数返回值
-
return语句
在js
函数体内的return
语句,表示返回。
JavaScript 引擎遇到return语句,就直接返回return后面的那个表达式的值,后面即使还有语句,也不会得到执行。也就是说,return语句所带的那个表达式,就是函数的返回值。return语句不是必需的,如果没有的话,该函数就不返回任何值,或者说返回undefined。
例如:
function fn1(){
var name = "zhangsan";
var age = 19;
return name + "今年" + age + "岁!";
}
上面的案例中我们在函数体内设置了一个返回值。返回值会将表达式的结果从函数体内返回到函数体的外部,让我们可以在函数外部访问。
那么该如何访问函数的返回值呢?
例如:
function fn1(){
var name = "zhangsan";
var age = 19;
return name + "今年" + age + "岁!";
}
// 可以直接打印调用函数的语句。就可以在调用函数的同时还打印出返回值
console.log(fn1());
// 也可以直接将返回值赋值给一个变量
var return_value = fn1(); // 函数在执行的同时也将返回值赋值给了变量return_value
console.log(return_value);
如果函数内没有返回值,但是我们偏偏还来打印,那么结果将返回undefined。
function fn1(){
var name = "zhangsan";
var age = 19;
}
console.log(fn1()); // undefined
var return_value = fn1();
console.log(return_value);//undefined