总结js中this的指向问题

我们知道js中有个全局对象就是window,如果在顶层声明一个变量如

var a=1 //就相当于window.a=1

同时有了node以后,js也可以在服务端运行了,官方解释为Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行环境。通俗说node是一个支持js语法的容器,直接写js就可以在node下运行。这里介绍node主要说一下在node中的全局变量叫global,就像window一样有一些js默认的变量和方法。下面只探讨this在浏览器中的指向,有兴趣的也可以把后面的例子在node中跑一下。

this一般在函数中使用比较多,那就从函数说起吧,我们调用的函数一般分为声明式函数,或者是放在对象中作为方法的函数
一、声明式
function demo1(){
    console.log(this)  
}
function demo2(){
    this.num=2
    function demo3(){
          this.num++
          console.log(num)
    }
    return demo3
}
demo1() // 调用demo1函数,这里this很显然指向window
var a=demo2();
a()  // 这里看到会打印出3,应该也很好理解,a变量将demo2函数执行后的的返回值及demo3函数返回,然后执行,此时this依旧指向window
二、对象中的方法调用
var obj1={
      value:3,
      increment:function(){
           this.value++;
           console.log(this,this.value)
      }
}
obj1.increment() //  obj1{value:4,increment:function(){...}},4 ;打印出obj1对象和4,obj1包含一个value值和一个increment方法,也好理解

在看一个例子

var obj2={
      value:4,
      increment:function(){
           this.value++;
           console.log(this,this.value);
           (function(){
                 console.log('这又是啥',this,this.value)
                 this.value=1
           })() 
      },
      print:function(){
            console.log('print',this.value)
      }
}
obj2.increment() 
obj2.print()
var P=obj2.print
P()
// 打印结果出如下
// {value: 5, increment: ƒ, print: ƒ} 
// 5
// 这又是啥 Window 
// undefined
// print 5
// print 1
依次分析:
第一条先执行obj2中的increment方法,跟上一个例子一样,这里的this是指向我obj2对象,所以this.value再执行+1以后为5,后面是一个自执行函数,这里面的this直接指向了window,window的value一开始不存在所以为undefined,后面增加一个全局变量value值为1;然后是第二条直接执行obj2中的方法print,此时的this还是obj2所以值为5,;然后是第三条声明一个变量P指向obj2中的print方法,执行这个方法这是this指向window,所以输出1
总结来说:
使用声明式函数(后面两个对象中的方法也是使用的声明式函数)会自动绑定 this,直接在全局中声明的函数 this会直接指向 window对象
延伸一下,现在我们都经常会用的es6的箭头函数,箭头函数是不会自动绑定this的,默认从上一级继承下来,那不妨把刚才的例子改下看看
例子1改写
var demo1=()=>{
    console.log(this)  
}
var demo2=()=>{
    this.num=2
    function demo3(){
          this.num++
          console.log(num)
    }
    return demo3
}
demo1() // 调用demo1函数,这里this还是指向window,因为之前说的在全局下声明本身就有个this指向window对象
var a=demo2();
a()  // 3,这里也一样
例子2改写
var obj1={
      value:3,
      increment:()=>{
           this.value++;
           console.log(this,this.value)
      }
}
obj1.increment() // 这时候会看到输出window对象和一个NaN
简单说明下:
如前面所说箭头函数不会自动绑定 this,所以执行increment函数中的 this依旧会指向 window,而 window下的 value还不存在,所以为 undefined再执行+1操作所以 value就变成了 NaN
例子3改写
var obj2={
      value:4,
      increment:function(){
           this.value++;
           console.log(this,this.value);
           (function(){
                 console.log('这又是啥',this,this.value)
                 this.value=1
           })() 
      },
      print:function(){
            console.log('print',this.value)
      }
}
obj2.increment() 
obj2.print()
var P=obj2.print
P()
// 打印结果出如下
// Window 
//  NaN
// 这又是啥 Window
// NaN
// print 1
// print 1
简单说明下:
第一个依旧 window对象(this没绑定的嘛),后面的value当然又是没声明.....然后自执行函数也没得说,后面才接着给 windowvalue赋值为1了,后面就两句自然输出两次1了

那么箭头函数怎么绑定this呢,有apply,call和bind这三个方法得嘛,大家应该都知道,具体区别可以查一下

文章来源:北大青鸟学校前端开发小组

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值