• 售前

  • 售后

热门帖子
入门百科

JavaScript this关键字的深入详解

[复制链接]
潘金麟 显示全部楼层 发表于 2021-10-25 19:36:33 |阅读模式 打印 上一主题 下一主题
目录


  • 一、媒介
  • 二、了解this
  • 三、this到底是谁
  • 四、箭头函数this指向
  • 扩展阅读
  • 总结

一、媒介


this关键字是JavaScript中最复杂的机制之一。它是一个很特别的关键字,被自动定义在全部函数的作用域中。对于那些没有投入时间学习this机制的JavaScript开辟者来说,this的绑定不停是一件非常令人困惑的事。


二、了解this


学习this的第一步是明白this既不指向函数自身也不指向函数的词法作用域,你大概被这样的表明误导过,但其实它们都是错误的。随着函数使用场所的不同,this的值会发生变化。但总有一条原则就是 JS中的this代表的是当前举动实行的主体 ,在JS中主要研究的都是函数中的this,但并不是说只有在函数里才有this, this实际上是在函数被调用时发生的绑定,它指向什么完全取决于函数在哪里被调用 。怎样的区分this呢?

三、this到底是谁


这要分情况讨论,常见有五种情况:
1、函数实行时首先看函数名前面是否有".",有的话,"."前面是谁,this就是谁;没有的话this就是window
  1. function fn(){
  2. console.log(this);
  3. }
  4. var obj={fn:fn};
  5. fn();//this->window
  6. obj.fn();//this->obj
  7. function sum(){
  8. fn();//this->window
  9. }
  10. sum();
  11. var oo={
  12. sum:function(){
  13. console.log(this);//this->oo
  14. fn();//this->window
  15. }
  16. };
  17. oo.sum();
复制代码
2、自实行函数中的this永久是window
  1. (function(){ //this->window })();
  2. ~function(){ //this->window }();
复制代码
3、给元素的某一个事件绑定方法,当事件触发的时候,实行对应的方法,方法中的this是当前的元素,除了IE6~8下使用attachEvent(IE一个闻名的bug)
DOM零级事件绑定
  1. oDiv.onclick=function(){
  2. //this->oDiv
  3. };
复制代码
DOM二级事件绑定
  1. oDiv.addEventListener("click",function(){
  2. //this->oDiv
  3. },false);
复制代码
在IE6~8下使用attachEvent,默认的this就是指的window对象
  1. oDiv.attachEvent("click",function(){
  2. //this->window
  3. });
复制代码
我们大多数时候,遇到事件绑定,如下面例子这种,对于IE6~8下使用attachEvent不必太较真
  1. function fn(){
  2. console.log(this);
  3. }
  4. document.getElementById("div1").onclick=fn;//fn中的this就是#divl
  5. document.getElementById("div1").onclick=function(){
  6. console.log(this);//this->#div1
  7. fn();//this->window
  8. };
复制代码
4、在构造函数模式中,类中(函数体中)出现的this.xxx=xxx中的this是当前类的一个实例
  1. function CreateJsPerson(name,age){
  2. //浏览器默认创建的对象就是我们的实例p1->this
  3. this.name=name;//->p1.name=name
  4. this.age=age;
  5. this.writeJs=function(){
  6. console.log("my name is"+this.name +",i can write Js");
  7. };
  8. //浏览器再把创建的实例默认的进行返回
  9. }
  10. var p1=new CreateJsPerson("尹华芝",48);
复制代码
必须要注意一点: 类中某一个属性值(方法),方法中的this必要看方法实行的时候,前面是否有".",才气知道this是谁 。大家不妨看下接下来的这个例子,就可明白是啥意思。
  1. function Fn(){
  2. this.x=100;//this->f1
  3. this.getX=function(){
  4. console.log(this.x);//this->需要看getX执行的时候才知道
  5. }
  6. }
  7. var f1=new Fn;
  8. f1.getX();//->方法中的this是f1,所以f1.x=100
  9. var ss=f1.getX;
  10. ss();//->方法中的this是window ->undefined
复制代码
5.call、apply和bind
我们先来看一个问题,想在下面的例子中this绑定obj,怎么实现?
  1. var obj={name:"浪里行舟"};
  2. function fn(){
  3. console.log(this);//this=>window
  4. }
  5. fn();
  6. obj.fn();//->Uncaught TypeError:obj.fn is not a function
复制代码
如果直接绑定obj.fn(),程序就会报错。这里我们应该用fn.call(obj)就可以实现this绑定obj,接下来我们详细介绍下call方法:
call方法的作用:
①首先我们让原型上的call方法实行,在实行call方法的时候,我们让fn方法中的this变为第一个参数值obj;然后再把fn这个函数实行。
②call还可以传值,在严酷模式下和非严酷模式下,得到值不一样。
  1. //在非严格模式下
  2. var obj={name:"浪里行舟 "};
  3. function fn(num1,num2){
  4. console.log(num1+num2);
  5. console.log(this);
  6. }
  7. fn.call(100,200);//this->100 num1=200 num2=undefined
  8. fn.call(obj,100,200);//this->obj num1=100 num2=200
  9. fn.call();//this->window
  10. fn.call(null);//this->window
  11. fn.call(undefined);//this->window
复制代码
  1. //严格模式下
  2. fn.call();//在严格模式下this->undefined
  3. fn.call(null);// 在严格模式 下this->null
  4. fn.call(undefined);//在严格模式下this->undefined
复制代码
**apply和call方法的作用是如出一辙的,都是用来改变方法的this关键字而且把方法
实行,而且在严酷模式下和非严酷模式下对于第一个参数是null/undefined这种情况的规
律也是一样的。**
两者唯一的区别:call在给fn通报参数的时候,是一个个的通报值的,而apply不是一个个传,而是把要给fn通报的参数值统一的放在一个数组中进利用用。但是也相称子一个个的给fn的形参赋值。 总结一句话:call第二个参数开始接受一个参数列表,apply第二个参数开始接受一个参数数组
  1. fn.call(obj,100,200);
  2. fn.apply(obj,[100,200]);
复制代码
bind:这个方法在IE6~8下不兼容,和call/apply雷同都是用来改变this关键字的 ,但是和这两者有显着区别:
fn.call(obj,1,2);//->改变this和实行fn函数是一起都完成了
  1. fn.bind(obj,1,2);//->只是改变了fn中的this为obj,并且给fn传递了两个参数值1、2,
  2. 但是此时并没有把fn这个函数执行
  3. var tempFn=fn.bind(obj,1,2);
  4. tempFn(); //这样才把fn这个函数执行
复制代码
bind表现了预处理头脑:事先把fn的this改变为我们想要的结果,而且把对应的参数值也准备好,以后要用到了,直接的实行即可。
call和apply直接实行函数,而bind必要再一次调用。
  1. var a ={
  2. name : "Cherry",
  3. fn : function (a,b) {
  4. console.log( a + b)
  5. }
  6. }
  7. var b = a.fn;
  8. b.bind(a,1,2)
复制代码

上述代码没有实行,bind返回改变了上下文的一个函数,我们必须要手动去调用:
  1. b.bind(a,1,2)() //3
复制代码
必须要声明一点:遇到第五种情况(call apply和bind),前面四种全部让步。

四、箭头函数this指向


箭头函数正如名称所示那样使用一个“箭头”(=>)来定义函数的新语法,但它优于传统的函数,主要表现两点: 更简短的函数而且不绑定this 。
  1. var obj = {
  2. birth: 1990,
  3. getAge: function () {
  4. var b = this.birth; // 1990
  5. var fn = function () {
  6. return new Date().getFullYear() - this.birth; // this指向window或undefined
  7. };
  8. return fn();
  9. }
  10. };
复制代码
如今,箭头函数完全修复了this的指向, 箭头函数没有自己的this,箭头函数的this不是调用的时候决定的,而是在定义的时候处在的对象就是它的this 。
换句话说, 箭头函数的this看外层的是否有函数,如果有,外层函数的this就是内部箭头函数的this,如果没有,则this是window 。
  1. <button id="btn1">测试箭头函数this_1</button>
  2. <button id="btn2">测试箭头函数this_2</button>
  3. <script type="text/javascript">
  4. let btn1 = document.getElementById('btn1');
  5. let obj = {
  6. name: 'kobe',
  7. age: 39,
  8. getName: function () {
  9. btn1.onclick = () => {
  10. console.log(this);//obj
  11. };
  12. }
  13. };
  14. obj.getName();
  15. </script>
复制代码

上例中,由于箭头函数不会创建自己的this,它只会从自己的作用域链的上一层继续this。其实可以简化为如下代码:
  1. let btn1 = document.getElementById('btn1');
  2. let obj = {
  3. name: 'kobe',
  4. age: 39,
  5. getName: function () {
  6. console.log(this)
  7. }
  8. };
  9. obj.getName();
复制代码
那如果上一层并不存在函数,this指向又是谁?
  1. <button id="btn1">测试箭头函数this_1</button>
  2. <button id="btn2">测试箭头函数this_2</button>
  3. <script type="text/javascript">
  4. let btn2 = document.getElementById('btn2');
  5. let obj = {
  6. name: 'kobe',
  7. age: 39,
  8. getName: () => {
  9. btn2.onclick = () => {
  10. console.log(this);//window
  11. };
  12. }
  13. };
  14. obj.getName();
  15. </script>
复制代码

上例中,固然存在两个箭头函数,其实this取决于最外层的箭头函数,由于obj是个对象而非函数,所以this指向为Window对象
由于this在箭头函数中已经按照词法作用域绑定了,所以, 用call()或者apply()调用箭头函数时,无法对this进行绑定,即传入的第一个参数被忽略 :
  1. var obj = {
  2. birth: 1990,
  3. getAge: function (year) {
  4. var b = this.birth; // 1990
  5. var fn = (y) => y - this.birth; // this.birth仍是1990
  6. return fn.call({birth:2000}, year);
  7. }
  8. };
  9. obj.getAge(2018); // 28
复制代码
扩展阅读


箭头函数-廖雪峰
JS中的箭头函数与this
this、apply、call、bind

总结

到此这篇关于JavaScript this关键字深入详解的文章就介绍到这了,更多相关JavaScript this关键字内容请搜刮草根技术分享从前的文章或继续欣赏下面的相关文章盼望大家以后多多支持草根技术分享!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x

帖子地址: 

回复

使用道具 举报

分享
推广
火星云矿 | 预约S19Pro,享500抵1000!
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

草根技术分享(草根吧)是全球知名中文IT技术交流平台,创建于2021年,包含原创博客、精品问答、职业培训、技术社区、资源下载等产品服务,提供原创、优质、完整内容的专业IT技术开发社区。
  • 官方手机版

  • 微信公众号

  • 商务合作