一、为什么会有this的出现
“this关键词是JS中最复杂的机制之一,它是一个很特别的关键字,被自动定义在所有函数的作用域中”根据凯尔辛普森的书中描述,刚开始阅读时我对this的使用都感觉到有点一头雾水,虽然隐隐约约知道this的出现是为了使代码更简洁而且利于复用,同时this单指“这个“单词是非常意味鲜明的,但在各种情况下不同的this指向,反倒是让人觉得这个设计逻辑很反人类。
二、this
首先我们必须理解的就是this是在运行时绑定的,而非在编写时绑定,它的上下文取决于函数调用的各种条件,this的绑定和函数声明的位置没有任何关系,只取决于函数的调用方式,简单来说,只有在函数执行this才会有它的指向,如果函数不执行,则this没有任何意义。
三、this的绑定规则
1、默认绑定
默认绑定下,this默认指向window,什么时候会认为是默认绑定呢?即是函数的独立调用,this默认指向window,以及在全局作用域下this默认指向window。
1 2 3 4 | function test(){ console.log( this === window); } test(); //函数独立调用 this指向window<br><br>var a = 0 l<br>function foo(){<br> console.log(this); //this指向window<br>}<br>var obj = {<br> a:2;<br> foo:foo;<br>}<br>var bar = obj.foo; //bar赋值为对象obj的foo方法 <br>bar(); //独立调用foo函数 |
2、隐式绑定
隐式绑定规则下,this体现为谁调用就指向谁。
1 2 3 4 5 6 7 8 | var a = 888; var obj = { a: 666; foo: function (){ console.log( this ); // obj } } <br> var obj1 ={<br> o:obj;<br>} obj.foo(); //对象obj调用,则指向对象obj<br>obj1.o.foo(); //this指向obj,距离调用自己最近的对象<br> |
3、显式绑定
显式绑定是指通过用call,apply以及bind方法来改变this的行为,相比隐式绑定,this指向变化过程。
call()方法
call()方法的作用:可以调用一个函数,于此同时,改变这个函数内部的this指向,此外call()方法还可以实现继承。
语法:
1 | fn.call(想要 this 指向的地方,函数实参1,函数实参2); //第一个如果不改变this指向,则传null<br>//call()实现this指向的改变<br>const obj1 = {<br> Name:'Essie',<br> Age:23,<br>};<br>function fn(){<br> console.log(this); //window<br> console,log(this.nickname); //undefined<br>}<br>fn.call(this); //this没有改变 函数调用fn(),指向window<br><br>function fn1(a,b){<br> console.log(this); //obj1<br> console.log(this.nickname); //Essie<br> console.log(a+b); //6<br>}<br>fn1.call(obj1,3,3); //this指向obj1对象<br><br>//call()实现继承<br>function Father(Name,Age){<br> this.name = Name;<br> this.age = Age;<br>}<br>function Son(Name,Age){<br> Father.call(this,Name,Age); //call()方法下Son继承了Father里的name和age属性<br>}<br>const son = new Son('Essie',23);<br>console.log(JSON.stringfy(son)); //{"Name":"Essie","Age":23} |
apply()方法
apply()方法作用:调用一个函数,同时改变函数内部的this指向,但apply()方法的应用上,由于apply需要传递数组,所以会有些不同。
语法:
1 | fn.apply(想要 this 指向的地方,[函数实参1,函数实参2]); //第一个参数不改变this指向,传nullconst obj1 = {<br> Name:'Essie',<br> Age:23,<br>};function fn1(a){<br> console.log(this); //obj1<br> console.log(this.nickname); //Essie<br> console.log(a); //6<br>}<br>fn1.apply(obj1,['hello']);//this指向obj1,然后执行fn1()函数<br><br> |
bind()方法
bind()方法不会调用函数,但是可以改变函数内部的this指向,如果不需要立即调用,但又需要改变函数的内部指向, 则bind()是最为合适的。
语法:
1 | 函数 = fn.bind(想要 this 指向的地方,函数实参1,函数实参2); //第一个不改变,则传null<br>bind函数是有返回值的 |
4、new绑定
用new来调用函数u,发生构造函数调用是,执行操作步骤是,首先创建一个全新的对象;新的对象会被执行[Prototype]连接;新对象会绑定到函数调用的this;如果函数没有手动返回对象,则返回创建的新对象。
语法例子
1 2 3 4 5 6 | function foo(a){ this .a = a; } var bar = new foo(2); //new了一个新对象并绑定到foo的this console.log(bar.a); //2 |
四、this绑定优先级
显示绑定>隐式绑定>默认绑定
new绑定>隐式绑定>默认绑定
五、箭头函数的调用
六、原型链中的this
七、主要注意的地方
this指向只在函数执行时才有其实际意义,而且this指向永远不取决于写在哪,而是取决于谁调用。
1、以函数形式独立调用时(普通函数、立即执行函数、setTimeOut)调用,this指向的都是Window全局。
2、以方法形式调用的时候,this指向调用方法的对象
3、以构造函数调用的时候,this指向实例对象
4、以事件绑定函数的形式调用的时,this指向绑定事件的对象
5、使用call、apply调用,this指向指定的对象
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了