ES5 函数基础
ES5 函数进阶
参数的默认值
ES5 的方法:使用短路算法
function sayHello(a, b) {
a = a || "welcome"; // 利用短路算法
b = b || "Peggy";
console.log(a, b);
};
sayHello("你好", "佩奇"); // 你好 佩奇
sayHello(null, ""); // welcome Peggy
ES6:
参数=默认值
function sayHello(a = "欢迎", b = "超人") {
console.log(a, b);
}
sayHello(); // 欢迎 超人
sayHello('welcome', 'superman'); // welcome superman
- 当传入的实参值为
undefined
时,就会使用默认值 - 实参需要按顺序传入;不能跳过前面的参数,给后面的参数传参;但可以给前面的参数传入
undefined
show(, '怪兽'); // SyntaxError: Unexpected token ','
show(undefined, '怪兽'); // 欢迎 怪兽
默认参数 & length
funName.length
:形参个数arguments.length
:实参个数
注意:设置了 参数=默认值
的形参,不会被计算进 funName.length
属性
console.log((function (a, b, c) {}).length); // 3
console.log((function (a, b, c = 5) {}).length); // 2
默认参数 & 作用域
如果设置了函数参数默认值,参数进行初始化时,会形成一个单独的作用域。等到初始化结束,这个作用域就会消失
如果不设置参数默认值,则不存在这种说法
let x = 1;
function fun(x, y = x) { // AO { x:2, y:2 }
console.log(x, y);
};
fun(2); // 2 2
上面代码中,y
设置了默认值,所以 (x, y = x)
形成一个作用域,后面的变量 x
指向前面定义的参数 x
let x = 1;
function f(y = x) { // AO { y:1, x:2 }
let x = 2;
console.log(x, y);
}
f() // 2 1
上面代码中,y
设置了默认值,所以 (y = x)
形成一个作用域,先在当前作用域寻找 x
,发现没有定义,就在父级 ( 全局 ) 作用域中寻找。所以这里的变量 x
指向全局变量 x
箭头函数
ES6 允许使用 “箭头” =>
定义函数。箭头函数是一种函数表达式的简洁语法
let sum = (a, b) => {
console.log(a + b);
}
- 完整写法:
let sum = function (a, b) {
console.log(a + b);
}
- 函数里面只有
return
语句时,可以直接写返回值
function show() { return 1; }
// ↓
let show = function () { return 1; }
// ↓
let show = () => 1;
- 只有一个形参时,小括号也可以省略掉:
function show(a) { return a; }
// ↓
let show = a => a;
- 如果返回的是对象,需要用
()
括住,因为{}
会被解释为代码块:
let getTempItem = id => ({ id: id, name: "Temp" });
箭头函数的 this 指向
- 因为箭头函数是表达式,没有
this
,所以获取时,获取到的其实是父级函数的this
- 箭头函数没有
this
,不能用作构造函数!
情况 ①: 正常情况下,对象方法的 this
指向对象本身
var age = 20;
let obj = {
age: 18,
show: function () {
console.log(this.age); // this 指向 obj
}
}
obj.show(); // 18
因为箭头函数是表达式,所以使用箭头函数后,this
会指向 window
var age = 20; // 如果用 let 定义,会获取到 undefined,因为 let 定义的全局变量与 window 无关
let obj = {
age: 18,
show: () => {
console.log(this.age); // this 指向 window
}
}
obj.show(); // 20
情况 ②:正常情况下,构造函数的 this
指向新创建的对象
var a = 11;
function Test() {
this.a = 22;
this.b = function () {
console.log(this.a);
};
this.b();
};
let obj = new Test(); // 22
虽然箭头函数是表达式,但是箭头函数在 Test
内,Test
的 this
指向新对象,所以箭头函数的 this
也指向新对象
var a = 11;
function Test() {
this.a = 22;
this.b = () => {
console.log(this.a); // this 指向新建对象
};
this.b();
};
let obj = new Test(); // 22
情况 ③:正常情况下,添加定时器,定时器内的 this
指向 window
var age = 30;
let obj = {
age: 18,
show: function () { // this 指向 obj
setTimeout(function () { // 添加定时器
console.log(this.age); // this 指向 window
}, 200);
}
};
obj.show(); // 30
使用箭头函数,箭头函数在 show
内,函数 show
的 this
指向对象 obj
,所以箭头函数的 this
也指向对象 obj
let obj = {
age: 18,
show: function () {
setTimeout(() => {
console.log(this.age); // this 指向 obj
}, 200);
}
};
obj.show(); // 18
箭头函数中的
arguments
因为箭头函数是表达式,所以在箭头函数中也没有 arguments
let show = () => {
console.log(arguments);
}
show(1, 2, 3, 4, 5); // ReferenceError: arguments is not defined at show
此时我们可以使用 [reset 参数] 代替 arguments
:
let show = (...a) => {
console.log(a); // [1, 2, 3, 4, 5]
}
show(1, 2, 3, 4, 5);
尾逗号
- ES6 允许函数的最后一个参数 ( 形参 / 实参都可以 ) 后面有尾逗号
- 这使得函数参数与数组、对象的尾逗号规则保持一致
function show(a, b, c, ) {
console.log(a, b, c);
}
show(1, 2, 3, );