js学习之函数
(一)函数的创建
(1)将要封装的代码以字符串的形式传递给构造函数
var fun=new Function("console.log('hello');");
// 封装到函数中的代码不会立即执行
// 函数中的代码会在函数调用的时候执行
// 调用函数语法:函数对象()
fun();
// 当调用函数时,函数中封装的代码会按照顺序执行
在实际开发中很少使用构造函数来创建一个函数对象
注意:函数也是一个对象,使用typeof检查一个函数对象时,会返回function\
(2)使用函数声明来创建一个函数
function 函数名([形参1,形参2,形参n]){
}
function fun2(){
console.log("hhh");
}
fun2();
(3) 使用函数表达式来创建函数
var 函数名=function([形参1,形参2,形参n]){
}
var fun3=function(){
console.log("xxx");
};
fun3();
(二)函数的参数
(1)函数参数
- 在调用函数时,可以在()中指定实参(实际参数),实参将会复制给函数中对应的形参
// 定义一个求和函数
function sum(a,b){
console.log(a+b);
}
sum(1,2);
// 调用函数时解析器不会检查实参的类型,
// 所以要注意是否有可能会接收到非法的参数,如果有可能则需要对参数进行类型的检查
// 函数的实参可以是任意的数据类型
sum(123,"hello");
sum(true,false);
// 调用函数时,解析器也不会检查实参的数量
// 多余的实参不会被赋值
// 如果实参的数量少于形参的数量,则没有对应实参的形参将用undefined初始化
sum(123,456,"hello");
// sum(123);123+undefined 输出NaN
- 实参还可以是一个对象,当我们的参数过多时,可以将参数封装到一个对象中,然后通过对象传递
function sayhello(o){
console.log("ws"+o.name+"age:"+o.age+"address:"+address);
}
// 创建一个对象
var obj={
name:"wxy",
age:18,
address:"hzau"
};
sayhello(obj);
- 实参可以是一个函数
function fun(a){
console.log("a="+a);
a(obj);// 输出 ws:wxy age:18 address:hzau
}
fun(sayhello) //输出 "a=function sayHello(o){
"console.log("ws:"+o.name+"age:"+o.age+"address:"+address);
}
fun(function(){alert("hello")});//输出 "a=function(){alert("hello")}" 将一个匿名函数传给形参
(2)默认参数
ES6 默认参数特性允许使用默认值初始化参数。
使用ES6默认参数特性将b默认为0。
function sum(a, b = 0) {
console.log(b); // => 0
return a+b;
}
sum(1); // => 1
sum(1, undefined); // => 1
注意,如果将undefined设置为第二个参数sum(1, undefined), b也将初始化为0。
(三)函数的返回值
- 使用return来设置函数的返回值
- return后的值将会作为函数的执行结果返回
- 可以定义一个变量来接收该结果
- return后的语句都不会执行
- 如果return语句后不跟任何值就相当于返回一个undefined
- 如果函数中不写return,则也会返回undefined
- return后可以跟任意类型的值
function sum(a,b,c){
var d=a+b+c;
return d;
alert("hello")
return;
}
// 调用函数
// 变量result的值就是函数的执行结果
var result=sum(4,7,8);
console.log("result="+result);
var result=alert("hello");
console.log("result="+result);
// alert返回值也是undefined
(四)arguments对象
JS 函数的一个很好的特性是能够用可变参数调用同一个函数。这样可以使用 arguments 对象来获取传入的所有参数。
arguments对象是所有(非箭头)函数中都可用的局部变量。你可以使用arguments对象在函数中引用函数的参数。
例如,对函数的参数求和:
function sumArgs() {
console.log(arguments); // { 0: 5, 1: 6, length: 2 }
let sum = 0;
for (let i = 0; i < arguments.length; i++) {
sum += arguments[i];
}
return sum;
}
sumArgs(5, 6); // => 11
arguments 是一个对应于传递给函数的参数的类数组对象。
箭头函数情况:箭头函数中没有arguments
const sumArgs = () => {
console.log(arguments);
return 0;
};
// throws: "Uncaught ReferenceError: arguments is not defined"
sumArgs();
(五)剩余参数
剩余参数语法允许们我将一个不定数量的参数表示为一个数组。
function sumArgs(...numbers) {
console.log(numbers); // [5, 6]
return numbers.reduce((sum, number) => sum + number);
}
sumArgs(5, 6); // => 11
...numbers是一个剩余参数,它将成为一个由剩余参数组成的真数组[5,6]。由于numbers 是一个数组,所以就可以使用数组自有方法reduce(与类数组对象的参数相反)。
如果不想在剩余参数中收集所有参数,则可以组合常规参数和剩余参数。
function multiplyAndSumArgs(multiplier, ...numbers) {
console.log(multiplier); // 2
console.log(numbers); // [5, 6]
const sumArgs = numbers.reduce((sum, number) => sum + number);
return multiplier * sumArgs;
}
multiplyAndSumArgs(2, 5, 6); // => 22
multiplier 是一个常规参数,它获取第一个参数的值。然后剩下的参数...numbers 接收剩余的参数。
(六)剩余参数和 arguments对象的区别
剩余参数和 arguments对象之间的区别主要有三个:
-
剩余参数只包含那些没有对应形参的实参,而 arguments 对象包含了传给函数的所有实参。
-
arguments对象不是一个真正的数组,而剩余参数是真正的Array实例,也就是说你能够在它上面直接使用所有的数组方法,比如sort,map,forEach或pop。 -
arguments对象还有一些附加的属性 (如callee属性)。