箭头函数:
(1)认识箭头函数:
由于普通函数使用过于麻烦,于是出现了箭头函数,但箭头函数都是匿名函数,故只有将其赋值给变量才能调用,这点不像普通函数即可以声明也可以赋值
const add = (x, y) => {
return x + y;
};
console.log(add(1, 1)); // 2
(2)箭头函数结构:
const/let 函数名 = 参数 => 函数体;
(3)如何将一般函数改写成箭头函数:
// 声明形式
function add() {}
// 声明形式->函数表达式形式
const add = function () {};
// 函数表达式形式->箭头函数
const add = () => {};
箭头函数注意事项:
(1)参数:
// 1.单个参数
// 单个参数可以省略圆括号
const add0 = x => {
return x + 1;
};
console.log(add0(1)); // 2
// 无参数或多个参数不能省略圆括号
const add = () => {
return 1 + 1;
};
console.log(add()); // 2
const add1 = (x, y) => {
return x + y;
};
console.log(add1(1, 1)); // 2
(2)单行函数体:
单行函数体可以省略{}和return,且要省略两个均省略!当是多行函数体时就不要想着再化简了。
// 单行函数体可以同时省略 {} 和 return
const add0 = (x, y) => {
return x + y;
};
const add = (x, y) => x + y;
console.log(add(1, 1)); // 2
(3)单行对象:
将以下代码改成单行函数体:
const add = (x, y) => {
return {
value: x + y
};
};
错误写法:
const add = (x, y) => {
value: x + y
};
console.log(add(1,2); // undefined
错误的原因很简单,就是浏览器把{}的意思理解错误所导致的!(将{}当成函数体的花括号)
正确写法:
const add = (x, y) => ({
value: x + y
});
console.log(add(1,2)); // 3
总结:如果箭头函数返回单行对象,可以在 {} 外面加上 (),让浏览器不再认为那是函数体的花括号,而是对象的花括号。
普通函数和箭头函数的this指向问题:
非箭头函数的this指向
(1)全局作用域中的this指向:console.log(this);
这里的this指向window
(2)普通函数的this指向:
问:下面代码的this指向谁?
function add() {
console.log(this);
}
正确答案:不确定。这里原因很简单,普通函数的this指向只有在函数调用的时候 this 指向才确定,不调用的时候,不知道指向谁。
问2:下面代码调用后的this指向谁?
// 非严格模式:
function add() {
console.log(this);
}
add();
正确答案:window。 在这里按理说不知道谁调用add()这个函数,那么理应应该是undefined才对但为什么是window呢?其实原因很简单,这是在非严格模式下,浏览器将其转化为window.add()所以指向window。这里也可以理解为,全局作用下的对象就是window,上面代码中add()
其实就相当于window.add()
这样就很好理解为什么this指向window了。
下面演示一下上面代码在严格模式下的this指向:
'use strict';
function add() {
console.log(this);
}
add();
在严格模式下this指向的就是undefined。
注意:this 指向和函数在哪儿调用没关系,只和谁在调用有关;没有具体调用对象的话,this 指向 undefined,在非严格模式下,转向 window。
箭头函数的this指向:
要牢记一句话,箭头函数没有this指向:
const calc = {
add: () => {
console.log(this);
}
};
calc.add(); // window
这里this指向window,原因是:箭头函数没有this指向,故this通过作用域链往外找,因为对象没有作用域,于是this找到的就是全局作用域下的this,全局的this指向的是window,所以这里打印出来的是window。
要是换成普通函数那就是calc了:
const calc = {
add:function(){
console.log(this);
}
};
calc.add(); // {add: ƒ}
// 就是谁调用就指向谁
再举个栗子:
const calc = {
add: function () {
// this
const adder = () => {
console.log(this);
};
adder();
}
};
calc.add(); // calc
在这个例子中adder为箭头函数,其没有this,所以this只能通过作用域链往外找,即到了函数add的作用域中,add中的this指向的是calc,因为calc.add()很明显是calc调用了add(),所以这个例子中this指向的就是calc,但将代码稍微改动可就不一样了,具体代码如下:
const calc = {
add: function () {
// this
const adder = () => {
console.log(this);
};
adder();
}
};
const addFn = calc.add;
addFn(); // undefined->window
在这个案例中,this指向的就是window,想必大家也猜到了为什么,原因很简单,add是普通函数,即add中的this是在调用时才确认的,在这里将calc.add赋值给addFn然后调用addFn,然而addFn是在全局中,即addFn()相当于window.add(),所以this指向的就是window(非严格模式下),由上面可知如果是在严格模式下则this指向的是undefined
不适用箭头函数的场景:
(1)作为构造函数:
const Person = () => {};
new Person();
在这里会报错,说Person不是一个构造函数,这里是因为箭头函数没有this指向,而构造函数里面有this,且this指向的是构造函数实例化后的那个对象,而箭头函数本身没this所以这就想悖。
(2)需要 this 指向调用对象的时候:
document.onclick = function () {
console.log(this); // document
};
在这里this指向调用对象document,但改为箭头函数时:
document.onclick = () => {
console.log(this); // winodw
};
因为箭头函数没this所以找到的就是window。
综上:如果你想要 this 指向调用的对象的时候就不要用箭头函数了
(3)需要使用 arguments 的时候:
箭头函数中没有arguments,所以想使用时尽量不要用箭头函数。