Js中This的指向问题

前端萌新自用,仅供参考,错误之处还请指正,谢谢。

与其他语言相比,JavaScript中this的表现有些不同,并且在严格模式和非严格模式下也有差异。

this是什么?

this是函数在运行时产生的内部变量,无法在函数外部被访问,this 不能在执行期间被赋值。在绝大多数情况下,函数的调用方式决定了this的指向(运行时绑定),所以每次调用函数,this的指向都可能不同。

this的指向:

1.全局上下文

无论是否在严格模式下,在全局执行环境中(在任何函数体外部),this都指向全局对象。

(可以使用globalThis获取全局对象,无论是否在全局上下文中)

2.默认绑定

在非严格模式中,在全局环境中定义函数person,this默认绑定到window。(可以这样理解:person()全局模式下省略了window. ,补全后为window.person(),this指向调用的对象所以指向window。) 

var name = '123'
function person() {
    console.log(this)  //window
    return this.name
}

console.log(person())   //123

这里换成let name = '123',在第一次运行时打印空白,改为var后改回let 又打印123,不知道为什么。(let不会绑定全局作用域,所以改为let后,window中并没有name这个变量,所以this.name也就是window.name才没有值)

在严格模式下,如果进入执行环境时,没有设置this的值,则this默认为undefined。

var name = '123'
function person (){
    'use strict';
    console.log(this);    //undefined
    return this.name
}
console.log(person())     //Uncaught TypeError: Cannot read property 'name' of undefined

3.隐式绑定

函数作为某个对象的方法进行调用时,this指向这个对象。

let obj = {
  name:'123',
  getName() {
    return this.name
  }
}

console.log(obj.getName())   //123

而且这样的行为不会受到函数定义方式或者定义位置的影响,无论是在定义对象obj的同时将getName函数定义为成员getName,还是先定义getName函数,之后在附属到obj.a,都是一样的结果。

let obj = {
  name:'123'
}
function getName() {
    return this.name
  }

obj.a = getName

console.log(obj.a())   //123

同样,this的指向只受最近成员引用的影响,下面代码中,将getName方法作为obj.b的c方法,在这次执行期间,函数中的this将指向obj.b。事实证明,这与他是对象 obj的成员没有多大关系,最近的引用才是最重要的。

let obj = {
  name:'123'
}
function getName() {
    return this.name
  }
  
obj.a = getName

obj.b = {
  name:'456',
  c:getName
}

console.log(obj.b.c())   //456

4.new 绑定

通过new关键字生成一个实例对象时,this指向这个实例对象。

    function Animal () {
      this.name = 123
    }
    let a = new Animal()
    console.log(a.name);     //123

构造函数中有return时,会根据return的内容不同而出现变化:

当构造函数中return一个非对象时,this仍然指向实例对象。(a为执行构造函数后的实例对象)

    function Animal () {
      this.name = 123
      return '456'
    }
    let a = new Animal()
    console.log(a.name);  //123
    console.log(a)        //Animal(name:'123')

当构造函数return一个对象时,this指向这个对象。 (a为返回的对象)。

    function Animal () {
      this.name = 123
      return {name:'456'}
    }
    let a = new Animal()
    console.log(a.name);  //456
    console.log(a)        //{name:'456}

虽然null也是一个对象,但是return null,this仍然指向实例对象。

    function Animal () {
      this.name = 123
      return null
    }
    let a = new Animal()
    console.log(a.name);  //123
    console.log(a)        //Animal(name:'123')

5.显式修改

apply、call、bind这三个函数都可以改变调用函数的对象,它们的第一个参数就是改变后调用函数的对象,所以,this指向第一个参数。

  let a ={
    name :'123',
    getName() {
      return this.name
    }
  }
  let b ={
    name :'456'
  }
  console.log(a.getName.call(b));         //456
  console.log(a.getName.apply(b));        //456
  console.log(a.getName.bind(b)());       //456

6.箭头函数

MDN:在箭头函数中,this与封闭词法环境的this保持一致。

我的理解,箭头函数的this指向箭头定义时最近外层的this。下面代码中,箭头函数中的this在定义时就确定了,而输出的不同是由于,箭头函数都指向最近外层中的this,也就是bar中的this,而b=a.bar()中,bar作为a的方法被调用,this指向a,所以箭头函数的this也指向a;b=a.bar,bar并未执行,而是在c()()中执行,这时bar中的this指向window,则箭头函数也指向window。因为bar中this的不同才导致了箭头函数中this的指向不相同。

  let a ={
    name :'123',
    bar: function() {
    var x = (() => this);
    return x;
  }
  }
  let b = a.bar()
  console.log(b());       //{name:'123,bar:f}

  let c = a.bar
  console.log(c()());     //window

MDN中的描述,链接:this - JavaScript | MDN

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值