前言
但凡是前端的人应该都被this折磨过,不管是不会用还是用错都会造成很大的麻烦,不论是敲代码还是准备面试时候,都要复习好多次,这次记个笔记方便以后复习。
this的特点
官方解释:
this
被自动定义在所有函数的作用域中,它提供了一种更好的方式来“隐式”的传递对象引用,这样使得我们的API
设计或者函数变得更加简洁,而且还更容易复用。
简单的来讲就是为了在函数作用域内更方便的使用这个函数中的对象内容,
例1:
这里的this就指向的是整体的类中,通过this可以访问类中的内容
例2:
person1
和person2
是两个对象想用一个函数就动态的输出两个对象对应的值。
没有this之前可能想的是给say方法传递参数,但通过this.可以直接通过this.name
,然后改变this的指向(call就是用来改变内容this的指向的)
上面这些可以让你很清晰的理解到this是干什莫的。
但是他this的难点不在这里。难点在于this指向的是什么地方。
this 就是一个对象,
this
是在函数被调用时发生的绑定,它指向什么完全取决于函数在哪里被调用。
常见的this指向
1.普通函数:指向window
在直接定义的普通函数中使用时,this指向的是window层面
let x = 1;
var y = 2;
function f(){
console.log(this.x)
console.log(this.y)
}
f();
//打印 :undefined
//2
首先f的执行环境为window
,所以this
指向window
,this.x
、this.y
等同于window.x
、window.y
。
那为什么this.x
不是1呢?
var
声明的y
变量会被js
引擎挂在到jswindow
属性中,所以window.y
是2。然而es6
中let
声明的变量,不会被挂载到window
属性中,而是会挂载到和Global(window)同级的Script
中。this.x
还是等同于window.x
,但是由于window
上没有x
这个属性,所以就打印undefined
了。、
2.对象方法:指向调用该方法的对象
根据该方法调用时所处的环境,决定指向
let obj1 ={
x:1,
f:function(){
console.log(this.x)
}
}
let obj2 ={
x:2,
f:obj1.f
}
obj1.f() //1
obj2.f()//2
第一个函数f
在``obj1环境下执行,
this指向
obj1,所以
this.x等同于
obj1.x`,打印1。
我相信第一个大家都没问题,第二个就有点疑惑了,有人可能会这样想:obj2.f
明明是调用obj1.f
,f
的运行环境还在obj1
中,应该打印1才是。
但是现在调用的这个方法上层是在obj2的环境中,指向的实际上是obj2的内容
因此,对象方法中this
指向调用该方法的对象。注意:
如果我们调用函数时有多个引用调用,比如obj1.obj2.foo()
。这个时候函数 foo
中的 this
指向哪儿呢?其实不管引用链多长,this
的绑定都由最顶层调用位置确定,即obj1.obj2.foo()
的 this
还是绑定带 obj2
。
如果我们调用函数时有多个引用调用,比如obj1.obj2.foo()
。这个时候函数 foo
中的 this
指向哪儿呢?其实不管引用链多长,this
的绑定都由最顶层调用位置确定,即obj1.obj2.foo()
的 this
还是绑定带 obj1
。
作者:小猪课堂
链接:https://juejin.cn/post/7115390077353590792
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
3.构造函数:指向实例对象
function F(x){
this.x=x
this.f=function(){
console.log(this.x)
}
}
let fn = new F(2)
fn.f()//2
这里的this
指向具体的实例对象,也就是fn
,fn
中存在x
属性:2,this.x
也就是fn.x
,输出2了。
4.绑定事件函数 :指向绑定事件的元素
<button>点击</button>
const btn = document.querySelector("button");
btn.onclick = function () {
console.log(this);
};
//打印<button>点击</button>
5.回调函数
对于回调函数中的this
对象。对于普通函数,this
指向调用时所在的对象(即window
对象)。对于箭头函数,this
指向定义生效时所在的对象。
普通函数:
var id = 10;
function foo() {
setTimeout(function () {
console.log(this.id);
}, 1000);
}
foo(); //10
foo.call({ id: 30 }); //10
上面都输出10,this
指向window
对象,原因是1s后,回调函数执行,此时回调函数所在对象为window
。
箭头函数:
对于普通函数来说,内部的
this
指向函数运行时所在的对象,但是这一点对箭头函数不成立。它没有自己的this
对象,内部的this
就是定义时上层作用域中的this
。也就是说,箭头函数内部的this
指向是固定的,相比之下,普通函数的this
指向是可变的。
var id = 10;
function foo() {
setTimeout(()=> {
console.log(this.id);
}, 1000);
}
foo();//10
foo.call({ id: 30 });//30
第一个回调函数输出10,定义时this
就已经确认了指向,指向window
。
第二个回调函数输出30,与上述不同的是,这个回调函数的this
在定义时已经重新指向为{id:30}
这个对象了。
6.立即调用函数 :window
(function(){console.log(this)})() //window
注意严格模式下this
"use strict";
console.log(this); //window
function f() {
console.log(this); //undefined
}
f();
- 在严格模式下,在全局作用域中,
this
指向window
对象 - 在严格模式下,全局作用域函数中
this
等于undefined