说说你对this的理解

说说你对this的理解

在我的印象中,一直有这么一句话 “谁调用,this指向谁”,但在工作的时候,还是有时候会感到疑惑,所以决定好好的了解一下这个this

这个时候我们不能知道this会指向谁

function fn() {
  console.log(this);
}

下面两种情况,this的指向又不同

function fn() {
    console.log(this);
}
let obj = {fn};

fn(); // window
obj.fn(); // obj

其实this的指向就有这么几种情况:

1. 函数独立调用时,在严格模式下和非严格模式下this指向不一致
 let a = 1
 function test() {
  'use strict';
  let a = 2
  console.log(this.a) // 报错
 }
 test()
 let a = 1
 function test() {
  let a = 2
  console.log(this.a) // 1
 }
 test()

严格模式下this为undefined,非严格模式下指向window

2. 通过对象调用
let o = {
    name:"haha",
    fn:function(){
        console.log(this.name);  // haha
    }
}
o.fn();

数组中调用

function fn() {
  console.log(this)
}

arr[fn, fn2, fn3]

arr[0]() // ??

// answer:arr

// 解析
// 数组也是对象的一种
// arr[0]() 可以看做 arr.0().call(arr)

通过上面可以知道,this的指向在定义时是没法确认的,只有在调用的时候,才能决定

3. 多层调用
let o = {
    name:'aa',
    user:{
        name:'bb',
        fn:function(){
            console.log(this.name); // bb
        }
    }
}
o.user.fn(); // bb

this的指向指向user,是因为,this的指向只看上一级是谁

4. 函数自调用
let o = {
  name:'aa',
  user:{
      name:'bb',
      fn:function(){
          console.log(this.name); // undefined
          console.log(this); //window
      }
  }
}
let fn2 = o.user.fn;
fn2();

this永远指向最后调用它的对象,也就是执行的时候是谁调用的。这里fn2执行的时候相当于window.fn2(),所以它指向的是window。

要记住,严格模式下,函数自调用,this为undefined

5. 函数中有函数自执行
let obj = {
    a: function () {
        console.log(this,77);
    },
    b: function () {
        console.log(this,88) 
        let f = obj.a;
        f();
    }
}

obj.b(); 
// obj,88
// window,77

可以看到第一个输出不出我们所料,但第二个输入让我们有点混乱了。其实第二个输出的情况就是第四种情况,函数自执行,所以相当于window.fn()

6. 构造函数下的this
function Fn(){
    this.name = "haha";
}
var f = new Fn();
console.log(f.name); // haha

为什么这里的this指向了f呢,是因为new做的事情,这里就得说说new做的事情了

//自己定义的new方法
let newMethod = function (Parent, ...rest) {
    // 1.以构造器的prototype属性为原型,创建新对象;
    let child = Object.create(Parent.prototype);
    // 2.将this和调用参数传给构造器执行
    let result = Parent.apply(child, rest);
    // 3.如果构造器没有手动返回对象,则返回第一步的对象
    return typeof result  === 'object' ? result : child;
};

中间有一个 Parent.apply(child, rest); 这里apply将构造函数的this指向了child实例,所以上面Fn的this指向了f。可以看到,new函数里面return有个判断,如果构造函数里面有返回的话,而且返回的是对象,那么,this就指向了构造函数的返回对象。

7. setTimeout、setInterval的this
<div>
    <span id="test">666</span>
  </div>
  <script>
    let q = document.getElementById('test')
    q.addEventListener('click', function (e) {
      console.log(this); // <span id="test">666</span>这个元素
      setTimeout(function () {
        console.log(this); // 这里的this是全局变量window
      }, 200);
    }, false)
  </script>
8. 事件中的this

上面的代码已经说明了,事件中的this指向触发事件的dom节点

9. 箭头函数中的this

箭头函数中没有this,直接把父级作用域的this拿来用

10。 自己指定this指向

call、apply、bind

参考文章:

彻底理解js中this的指向,不必硬背
js new一个对象的过程,实现一个简单的new方法
this揭秘

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值