这边文章的箭头函数与普通函数的this指向没总结好 见下一篇
let v = v => v
// 等同于
let f = function (f) {
return f
}
console.log(v(5)); //5
2.如果箭头函数的代码块部分 多于一条语句 ,就要使用 大括号 将它们括起来,并且使用 return 语句返回。
let sum = (num1, num2) => {
console.log(12);
return num1 + num2 }
console.log(sum(5,10));
3.由于大括号被解释为代码块(代码块就是整个{}+包裹的内容),所以如果箭头函数 直接返回一个对象 ,必须 在对象外面加上括号 ,否则会报错
let getTempItem = id => ({ id: id, name: 'Temp' })
console.log(getTempItem(1));
4.下面是一种特殊情况,虽然可以运行,但会得到错误的结果。
let foo = () => { a: 1 } // undefined
代码中,原始意图是返回一个对象{ a: 1 },但是由于引擎认为大括号是代码块,所以执行了一行语句a: 1。这时,a可以被解释为语句的标签,因此实际执行的语句是1;,然后函数就结束了,没有返回值。
5.箭头函数可以与变量解构结合使用
let person={
fist:"shi",
last:"li"
}
const full = ({fist, last}) => fist + ' ' + last
console.log(full(person));
//等同于
function full(person){
return person.first + ' ' + person.last
}
6.箭头函数使得表达更加简洁
const isEven = n => n % 2 === 0
console.log(isEven(4)); //true
7.如果箭头函数 不需要参数 或 需要多个参数 ,就使用一个 圆括号 代表参数部分,需要一个参数用不用圆括号都行
注:箭头函数根本没有自己区域的this对象,实际是用的外层代码块(函数内)的 this 对象。
function Timer(){
this.s1 = 0
this.s2 = 0
// 箭头函数
setInterval(() =>
{ this.s1++,
console.log(this)//Timer {s1: 3, s2: 0}
}
1000)
// 普通函数
setInterval(function (){
this.s2++
console.log(this)//windows
}, 1000)
}
var timer = new Timer()
setTimeout(() => console.log('s1: ', timer.s1),3100) //s1: 3
setTimeout(() => console.log('s2: ', timer.s2),3100) //s2: 0
上面代码中,Timer 函数内部设置了两个定时器,分别使用了箭头函数和普通函数。前者的 this 绑定定义时所在的作用域(即 Timer 函数)(其实这个this就是函数代码块的this对象),后者的 this 指向运行时所在的作用域(即全局对象)。所以,3100 毫秒之后,timer.s1 被更新了 3 次,而 timer.s2 一次都没更新。
//更好的说明箭头函数和普通函数。前者的 this 绑定定义时所在的作用域(即 Timer 函数),后者的 this 指向运行时所在的作用域(即全局对象)
console.log(this); //[object Window]
var s2=0
function Timer(){
this.s1 = 0
//两个定时器不属于构造函数模板里,因为this.才属于构造函数的属性和方法
//两个定时器只是用来演示箭头函数与普通函数的this指向问题
// 箭头函数 // this指向上下文函数的this指向
setInterval(() => this.s1++, 1000)
// 普通函数
setInterval(function (){
this.s2++ //this指向全局作用域 没人调用默认全局
}, 1000)
}
var timer = new Timer() //构造函数new时即调用会返回一个新对象,同时定时器会自调用执行
setTimeout(() => console.log('s1: ', timer.s1),3100) //s1: 3
setTimeout(() => console.log('s2: ', s2),3100) //s2: 3
var定义的变量是全局变量或者函数变量
let定义的变量是块级的变量,只在{}区域内有效
虽然this指向全局作用域,但let只在它的块级作用域内有效
let num = 100; // let 声明的是块级变量,不是全局变量
let fun = ()=>{
console.log("箭头函数let num:"+this.num); //undefined
}
fun()
var t=3
function name(params) {
var t=2
console.log(this.t); //3 //this直接指向的就是全局作用域,不会像变量提升那样一层一层的向上找
}
name()
下面这个例子能很好的说明箭头函数根本没有自己 区域的this,用的 this 实际是外层代码块(函数内)的 this 。
let handler = {
id: '12345',
init: function() {
console.log(555);
document.addEventListener('click',
function (event) {
console.log(this); // document文档 //匿名函数没人调用
this.doSomething(event.type)
} ,false
)
},
doSomething: function(type) {
console.log(78878);
console.log('Handling ' + type + 'for ' + this.id)
}
}
handler.init() //this.doSomething is not a function
let handler = {
id: '12345',
init: function() {
document.addEventListener('click',
event => {
console.log(this); //{id: '12345', init: ƒ, doSomething: ƒ} //this指向上下文函数的this指向
this.doSomething(event.type)
},false
)
},
doSomething: function(type) {
console.log(78878);
console.log('Handling ' + type + 'for ' + this.id)
}
}
handler.init() //Handling clickfor 12345
上面代码的 init() 方法中,使用了箭头函数,这导致这个箭头函数里面的this ,总是指向 handler 对象。如果回调函数是普通函数,那么运行this.doSomething() 这一行会报错,因为此时 this 指向 document 对象。
小编跟我说了半天 最后跟我说箭头函数里没this
我自己的代码
let handler = {
id: '12345',
init: function() {
console.log(this); // {id: '12345', init: ƒ}
},
}
handler.init()
箭头函数里确实没this,这个this就是外层代码块的 this对象而已
不适用场合
1.定义对象的方法,且该方法内部包括this。
const cat = {
lives: 9,
jumps: () => {
console.log(this); //windows
this.lives--
}
}
cat.jumps()
const cat = {
lives: 9,
jumps: function () {
console.log(this); //{lives: 9, jumps: ƒ}
this.lives--
}
}
cat.jumps()
这是因为对象不构成单独的作用域,导致 jumps 箭头函数定义时的作用域就是全局作用域。
var s = 21
const obj = {
s: 42,
m: () => console.log(this.s)
}
obj.m() //21
由于上面这个原因,对象的属性方法建议使用function写法定义,不要用箭头函数定义。
var button = document.getElementById('press');
button.addEventListener('click', () => {
this.classList.toggle('on')
})
上面代码运行时,点击按钮会报错,因为 button 的监听函数是一个箭头函数,导致里面的 this 就是全局对象。如果改成普通函数,this 就会动态指向被点击的按钮对象。
总的来说箭头函数里的this指向有不确定性,主要看你外面的代码块,
两种情况:要是构造函数里的一个普通方法(不是this.的方法)或者定义一个对象里面有传统方法function定义的方法时的话箭头函数的this确实只会指向当前的代码块区域中,而普通函数的this确实会指向全局。
但你不能说箭头函数里的this都是指向{}的代码块中,这种想法是错的,特殊情况:上面列举的不适用场合的三种情况就说明箭头函数this不是都指向{}的代码块中 反而相反了,箭头函数里this指向全局,普通函数里的this指向{}代码块内**
注:箭头函数根本没有自己区域的this对象,实际是用的外层代码块(函数内)的 this 对象。 但是有时候不同的定义形式确实会导致箭头函数和普通函数里的this指向不同
构造函数里的this. 方法里面的this指向无论是箭头函数还是普通函数都会指向代码块 ,不是this.的方法的话箭头函数的this指向当前的代码块内,而普通函数的this指向全局。*
function Person(name, age) {
this.name = name;
this.age = age;
(()=>{
console.log(this); //this指向上下文函数的this指向
})();
(function(){
console.log(this); //匿名函数没人调用,this指向全局作用域
})()
this.eating = () =>{
console.log(this); //已调用 Person {name: 'zs', age: 12, eating: ƒ}
console.log(this.name + ' is eating');
}
}
const p1 = new Person('zs', 12);
p1.eating() //已调用