JS中this在【全局、事件绑定、对象定义、构造函数】下的理解
学前端也好久啦,看了很多文档,结合自己的一点经验来讲,对于this,最通俗易懂的理解就是:
函数在哪里调用的,this就指向哪里。
首先看个例子:这里的函数getFullName,在哪里调用呢,是不是需要写成person.getFullName(),所以getFullName里的this是指向person这个大对象~
var person = { firstName: "Penelope", lastName: "Barrymore", getFullName: function () { // 这里就用this指代person console.log(this.firstName + " " + this.lastName); // 当然我们也可以这么写: console.log(person.firstName + " " + person.lastName); } } // 调用函数 person.getFullName()
几种常见的情况:
1 全局环境中的this。
2 在事件绑定中的this。
3 作为构造函数的调用
4 如何灵活修改this指向
第一种:全局下的this
在非严格模式下,全局中的this是指向window的;
先看一个小例子
var x = "1"; console.log(this.x); //1 console.log(this) //window
再看一个函数的例子
var firstname= "lili"; function showname(){ console.log(this.firstname) } showname() //输出的就是lili,此时是在全局中执行这个函数的,所以this指向的就是window
函数在哪里调用的,this就指向哪里。记得这句,就很好理解了呢~
第二种:事件绑定中的this
js中不可避免的就是需要对dom元素进行事件的绑定,那么绑定事件中的this就是被绑定对象本身;
// 这种情况还是一个道理,show事件是在btn点击时被调用的,所以show函数里的this就是这个按钮 Obtn1.onclick = show; function show() { console.log(this); //这里的this就是指向这个Obtn1这个按钮 } // 在按钮的点击事件发生的时候,就会激发相应的事件发生,所以this还是指向Obtn1 Obtn1.onclick = function () { console.log(this); } //再来看看这种方法:这一次有点不同 //目标绑定的点击事件,函数内部输出的this还是指向Obtn1本身, // 但是在这里再去调用函数的话,show函数中的this就不再指向Obtn了,而是指向window,因为这时候调用函数就是在全局中调用了。 Obtn1.onclick = function () { console.log(this) //Obtn1 show() //输出的是window } function show() { console.log(this) }
函数在谁身上触发的,this就指向谁。
第三种:对象定义中的this
var person = { firstName :"Penelope", lastName :"Barrymore", getFullName:function () { console.log (this.firstName + " " + this.lastName); } } // getFullName()是在person内定义的, // 而且执行的时候也是在person调用下才执行,所以这个时候的this是指向person的 person.getFullName(); // Penelope Barrymore
这个还蛮好理解的,
var firstName = "Peter", lastName = "Ally"; function showFullName () { // 这里面的"this"是指向全局的,因为这个函数是在全局中被定义, // 就像 firstName 和 lastName也是在全局中被定义 console.log (this.firstName + " " + this.lastName); } var person = { firstName :"Penelope", lastName :"Barrymore", showFullName:function () { // "this" 在这里其实是指向对象本身的,因为被调用的时候也是基于该对象的。 console.log (this.firstName + " " + this.lastName); } } //我们来看看下面输出的结果吧 showFullName (); // Peter Ally window.showFullName (); // Peter Ally //这种方法就是相当于在全局中调用了该方法,所以指向的是全局。 // "this" 在 the showFullName () 方法里是指向该对象本身的,所以 输出的是以下结果 person.showFullName (); // Penelope Barrymore
函数在谁身上触发的,this就指向谁。
第四种: 构造函数内的this
当一个函数被用来new一个对象的时候,这个函数就被称为构造函数;
那么此时构造函数内的this就会指向该实例化的对象本身;
var age = 3; //这是全局的变量 function test(){ this.age = 18; } var param = new test(); // 构造函数内的this此时指向的就是param console.log(param.age) //输出18 //我们再来做一点点操作; param.age = 19; console.log(param.age ) //输出的是19,所以构造函数中的this就是指向它构造出来的对象
构造函数中的this就是指向它构造出来的对象
改变this的指向
function Fruits() { this.color="yellow", this.say=function(){ console.log("My color is " + this.color); } } function apple(){ this.color="red" } var banana = new Fruits(); var apple1 = new apple(); banana.say(); //My color is yellow //这里相当于将banana.say方法的this指向指到了apple实例化的对象本身,所以输出的就是下面的结果。 banana.say.call(apple1) //My color is red
看一个例子
var user = { name:"lulei", age:10, say:function () { console.log("I am " + this.name,"I am " + this.age +" years old") } } var Obtn = document.querySelector(".btn"); Obtn.onclick = user.say; //此时的this指向的就是Obtnl ,其实我们这么去写的话, // 是会直接输出undefined的;I am I am undefinedyears old
解决方法
Obtn.onclick = user.say.call(user); // I am lulei I am 10years old
这样修改之后,this就会指向该user了;
除了这种方法之外,我们还可以通过创建中间变量的方法来修改this的指向;
建立一个中间变量:
var that= this; var pageFn={ pageNum:1, pageSize:10, getList1:function(){ console.log('getList1',this.pageNum) // }, clickFn:function(){ var Obtn = document.querySelector(".btn"); var that=this // that 代表的是pageFn Obtn.onclick =function(){ console.log(this) // this 此时是Obtn console.log(this.pageNum) // 输出undefined console.log(that.pageNum) // 输出1 that.getList1() // 输出1 相当于执行的是 pageFn.getList1() // this.getList1() // 无法执行 报错 this.getList1 is not a function } } } pageFn.clickFn()  总结:其实this的指向并不是在定义的时候确定的,而是在真正执行的时候决定的;有时候我们会用到匿名函数或者是回调函数,或者是会将该对象或者构造函数的方法借给其他对象使用,this的指向都会发生相对应的变化,但是我们都不用太着急,因为可以使用apply call bind 的方法去修正和更改this的指向;
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)