使用箭头函数应该注意什么?
箭头函数没有它自己的this值,箭头函数内的this值==继承==自外围作用域。导致内部的this就是外层代码块的this。正是因为它没有this,所以也就==不能用作构造函数、原型对象、对象里面定义函数、事件回调函数(这四样一般指向外层window,造成本身代码的bug)==。
==简单对象(非函数)是没有执行上下文的!==
箭头函数this的具体含义,应该==继承的是父执行上下文==里面的this
不要在对象里面定义函数,对象里面的行数应该用传统的函数方法
const test = {
array: [1, 2, 3],
sum: () => {
console.log(this === window); // => true
return this.array.reduce((result, item) => result + item);
}
};
test.sum();
//因为 test.sum()是在全局环境下进行调用,此时this指向全局
//改:
const test = {
array: [1, 2, 3],
sum() {
console.log(this === test); // => true
return this.array.reduce((result, item) => result + item);
}
};
test.sum();
不要在对原型对象上定义函数,在对象原型上定义函数也是遵循着一样的规则
Person.prototype.sayName = () => {
console.log(this === window); // => true
return this.name;
};
//也不能这样,也是用传统函数写法解决
不要用箭头定义构造函数
如果使用箭头函数会报错。
显然,箭头函数是不能用来做构造函数。
const Message = (text) => {
this.text = text;
console.log(this === window); // => true,与下面的例子不同这里的箭头函数写在了外层this指向window
};
const helloMessage = new Message('Hello World!');
// Throws "TypeError: Message is not a constructor"
不要用箭头定义事件回调函数
箭头函数在声明的时候就绑定了执行上下文,要动态改变上下文是不可能的,在需要动态上下文的时候它的弊端就凸显出来:
定义事件回调函数
const button = document.getElementById('myButton');
button.addEventListener('click', () => {
console.log(this === window); // => true,this是window,箭头函数当做参数传入,他的this是window
this.innerHTML = 'Clicked button';
});
//解决办法仍然是用传统函数写法解决
const button = document.getElementById('myButton');
button.addEventListener('click', function() {
console.log(this === button); // => true这时this回到Button本身
this.innerHTML = 'Clicked button';
});
关于箭头函数中的this的指向
==箭头函数没有自己的this, 它的this是继承而来;==
==默认指向在定义它时所处的对象(宿主对象--父执行上下文,外层环境),而不是执行时的对象, 定义它的时候,可能环境是window;==
例如这段函数中,this指向的是Person对象,可以看到控制台打印结果,此时的箭头函数所处的宿主对象是Person,所以this指向的是person
普通函数中的this:
下面看这样一段代码,非箭头函数,就指向调用他的window ,settimeout是window全局方法
,打印‘我叫 我今年 岁’
- this总是代表它的直接调用者(js的this是执行上下文), 例如 obj.func ,那么func中的this就是obj
2.在默认情况(非严格模式下,未使用 'use strict'),没找到直接调用者,则this指的是 window (约定俗成)
3.在严格模式下,没有直接调用者的函数中的this是 undefined
4.使用call,apply,bind(ES5新增)绑定的,this指的是 绑定的对象
例子
//以下代码会输出33,11而不是33,22
var x = 11;
var obj = {
x: 22,
methods: {
x: 33,
say: function () { console.log(this.x) },
say2: () => { console.log(this.x) }
}
}
obj.methods.say();//methods调用,methods的x是33
obj.methods.say2();//简单对象没有上下文,this指向object父执行上下文window
//以下代码会输出1,而不是100
var age = 99;
function PersonX() {
this.age = 0;
setTimeout(() => {
this.age++;
console.log(age)
}, 1000);
}
PersonX();
//构造函数作用域里的箭头函数this指向父作用域person,0+1=1