js 中的函数,既不关心参数个数,也不关心参数类型
函数的参数在内部表现为一个数组。函数被调用时总会接收一个数组,但函数并不关心这个数组中包含什么。如果数组中什么也没有,那没问题;如果数组的元素超出了要求,那也没问题
arguments
在使用function关键字定义(非箭头)函数时,可以在函数内部访问arguments对象,从中取得传进来的每个参数值。
箭头函数不行
function doAdd() {
if (arguments.length === 1) {
return arguments[0] + 10;
} else if (arguments.length === 2) {
return arguments[0] + arguments[1];
}
}
console.log(doAdd(1)); //11
console.log(doAdd(1, 2)); //3
参数名与arguments
两者可以同时使用,并且绑定,同步发生变化
它们在内存中还是分开的,只不过会保持同步而已
function doAdd(num1, num2) {
console.log("num1: " + num1);
console.log("num1: " + arguments[0]);
console.log("num2: " + num2);
console.log("num2: " + arguments[1]);
num1 = 10;
console.log("num1_change: " + num1); //10
console.log("num1_change: " + arguments[0]); //10
arguments[1] = 20;
console.log("num2_change: " + num2); //20
console.log("num2_change: " + arguments[1]); //20
}
doAdd(1, 2);
arguments 只和实际传入的参数绑定,与声明时参数个数无关
没有重载
同名函数,后定义覆盖先定义的
参数默认值
在 ES5.1 之前,没有默认值的实现,需要在函数中判断参数是否等于 undefined, 然后手动赋值
ES6 之后,支持定义默认值参数
function say(name = "dc") {
return `你好 ${name}`;
}
console.log(say());
使用函数返回值做默认值
function randNum() {
console.log("获取随机数....");
return Math.floor(Math.random() * 10);
}
function say(name = "dc", num = randNum()) {
return `你好 ${name} ${num}`;
}
console.log(say("dch"));
// undefined 占位,name 仍然使用默认值,
// num 使用确定值,randNum()不会调用
console.log(say(undefined,1)); //你好 dc 1
参数的扩展与收集
扩展
function sum() {
let sum = 0;
for (let i = 0; i < arguments.length; i++) {
sum += arguments[i];
}
return sum;
}
let value = [1, 2, 3, 4, 5];
console.log(sum(...value));
// 扩展参数前后仍然可以使用参数
console.log(sum(1,...value,2));
收集
function sum(...values) {
// 把传进来的参数封装成一个数组到 values 中
return values.reduce((x, y) => x + y, 0);
}
console.log(sum(1, 2, 3));
函数内部
callee
arguments对象其实还有一个callee属性,是一个指向arguments对象所在函数的指针,其用法:
阶乘算法实现1:
function factorial(num) {
if (num <= 1) {
return 1;
}
return num * factorial(num - 1);
}
阶乘算法实现2:
function factorial(num) {
if (num <= 1) {
return 1;
}
return num * arguments.callee(num - 1);
}
算法2 函数内部不使用方法名,而是使用函数指针,避免了函数被覆盖而导致的算法失效
this
- 在标准函数中,this是方法调用的上下文对象
- 在箭头函数中,this定义箭头函数的上下文对象
标准函数:
function sayColor() {
console.log(this.color);
}
window = {
color: "red",
};
window.sayColor = sayColor;
window.sayColor(); // red
o = {
color: "blue",
};
o.sayColor = sayColor;
o.sayColor(); // blue
箭头函数:
let sayColor = () => {
// 顶层,this 是 window
console.log(this.color);
};
Red = {
color: "red",
};
Red.sayColor = sayColor;
Red.sayColor(); // undefined
Blue = {
color: "blue",
};
Blue.sayColor = sayColor;
Blue.sayColor(); // undefined
caller
返回函数的调用者
function inner() {
console.log(inner.caller);
}
function out() {
inner();
}
function out1() {
inner();
}
out(); // [Function: out]
out1(); // [Function: out1]
new.target
ECMAScript 6新增了检测函数是否使用new关键字调用的属性: new.target
如果函数是正常调用的,则new.target的值是undefined;如果是使用new关键字调用的,则new.target将引用被调用的构造函数。
function King() {
if (!new.target) throw "只能通过new 初始化";
console.log(`Success ${new.target}`);
}
new King(); // Succss, [Function: King]
King(); // 只能通过new 初始化
联系方式:dccmmtop@foxmail.com