一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第9天,点击查看活动详情。
this
概要
1.this是什么?
- 任何函数本质上都是通过对象来调用,如果没有直接指定对象,那就是window
- 所有函数的内部都有一个变量this
- this就是调用当前这个函数的对象
2.如何确定this的值? - test() : this是window
- p.test() : this是p
- new test() : this是新创建的对象
- p.call(obj) : this是obj(apply、bind这些可以改变this指向)
例题:
function Person(color) {
console.log(this);
this.color = color;
this.getColor = function () {
console.log(this);
return this.color;
};
this.setColor = function (color) {
console.log(this);
this.color = color;
};
};
Person('red'); this是谁? 👉 window
var p = new Person('yellow');👉
this是谁? 其实和p没关联,this指向的是Person对象,只是new 了一个对象后,让p指向Person对象,所以this是p也没错
p.getColor(); this是谁?👉 p
var obj = {};
p.setColor.call(obj, "black"); this是谁?👉 obj
var test = p.setColor; test(); this是谁?👇
首先p.setColor得到这个函数,然后赋值给test变量,那么这就是一个函数表达式,然后又因为test是全局变量嘛,全局变量会自动成为window对象的成员,这句代码也就相当于window.test(),所以是window调用的,指向的是window
👇function fun1() {
function fun2() {
console.log(this);
}
fun2();
}
fun1();👇👇👇
this还是window,因为所有JavaScript全局对象、函数以及变量均自动成为window对象的成员,fun2()也就等同于window.fn2()
常见的this指向
核心:this指向问题 一般情况下this的最终指向的是那个调用它的对象
1.全局作用域或者普通函数中this指向全局对象window(注意定时器里面的this指向window)
见如下代码:
console.log(this); //window
function fn() {
console.log(this); //window
}
fn(); //因为这是简写,完整的是window.fn(),所以是指向window
window.setTimeout(function () {
console.log(this); //也是指向window
}, 1000);
2.方法调用中谁调用this就指向谁
见以下代码
var o = {
sayHi: function () {
console.log(this); //this指向o这个对象
}
}
o.sayHi();
var btn = document.querySelector('button');
btn.onclick = function () {
console.log(this); //this指向这个button按钮。监听事件方法注册事件也是一样的
}
3.构造函数中,this指向构造函数的实例
function Fun() {
console.log(this);
}
var fun = new Fun();
之前我们讨论过new的执行过程,new先划分了一块空间,然后构造函数中的this全部指向这个空间,而这个对象实例化后赋值给了fun变量,所以this指向的是这个变量fun。
其他补充
window
- 所有浏览器都支持window对象。他表示浏览器窗口。
- 所有JavaScript全局对象、函数以及变量均自动成为window对象的成员。
- 全局变量是window对象的属性
- 全局函数是window对象的方法 而且window是默认特性,可以省略不写
function fun3() {
console.log(this);
}
关于以上代码,解析器在调用函数时,每次都会向函数内部传递一个隐含的参数,这个隐含的参数就是this,这也就是为什么能直接log this的原因0 0
this指向的是一个对象,这个对象我们称为 函数执行的 上下文对象
根据函数的调用方式不同,this会指向不同的对象(谁调用指向谁)
- 以函数形式调用时,this指向永远是window
- 以方法形式调用时,this指向调用方法的对象
严格模式中的this
严格模式下this指向问题
① 以前在全局作用域函数中的this指向window对象
② 严格模式下全局作用域中函数中的this是undefined
③ 以前构造函数时不加new也可以调用,当普通函数,this指向全局对象
比如
function Star(){
this.sex = '男';
}
Star();直接调用,相当于window调用,this是window,也就为window添加了个sex属性
④ 严格模式下,如果构造函数不加new调用,this会报错
⑤ new 实例化的构造函数指向创建的对象实例
⑥ 定时器中的this指向还是window
⑦ 事件、对象还是指向调用者
ES6箭头函数的this指向
ES6中的this,是静态的, this 始终指向函数声明时所在作用域下的this的值
function getName() {
console.log(this.name);
}👇
普通函数在全局作用域下自动成为window的方法,this指向window
let getName2 = () => {
console.log(this.name);
}👇
上面箭头函数是全局作用域下声明的,所以this指向的是window,而箭头函数中的this是静态的,声明时指向的是window,后面不管怎么样this都指向window
//设置window对象的name属性
window.name = '你好呀';
const school = {
name: "我很好"
}
直接调用
getName(); //你好呀
getName2(); //你好呀
call方法调用
getName.call(school); // "我很好"
getName2.call(school); // "你好呀",getName2是个箭头函数,this是静态的,哪怕现在是让它临时成为school对象的方法让school来调用,this指向还是window
其他例题:
以前是在外面保存this的值到变量里面,在放到定时器中使用,现在利用箭头函数中this的静态特性,可以像下面代码一样写
ad.addEventListener('click', function () { //监听事件函数的this指向的是ad
setTimeout(() => {
this.style.background = 'pink';
}, 2000);
})
注意! 箭头函数没有自己的this,它的this指向父级的this也就是函数的this,而这个函数的this是谁调用函数就指向谁,所以箭头函数的this也是ad
总结:
- 箭头函数适合与this无关的回调。定时器、数组的方法回调
- 箭头函数不适合与this有关的回调。事件回调,对象的方法(只说不适合,没说不能,某些情况是可以做为对象的方法的)
总之,箭头函数中是没有this的!在箭头函数里边写的this,它会沿着作用域去找外边的this