this的指向性问题


前言

this是一个抽象化的概念,在不同的场景有着不同的指向,它就像一个魔术变量,有着千变万化,不过只要我们掌握核心,就能很清楚的分辨它具体指向哪里。


一、默认绑定

1 函数直接调用

js非严格模式下,函数在调用时没有任何前缀时,函数里的this默认指向全局变量window。
代码如下(示例):

function fn1() {
    let fn2 = function () {
        console.log(this); //window
        fn3();
    };
    console.log(this); //window
    fn2();
};

function fn3() {
    console.log(this); //window
};

fn1();
2 行内绑定
<div class="box">
        <button type="button" id="btn" onclick="fn()">我是一个按钮</button>
    </div>

    <script>
        function fn() {
            console.log(this); //btn
        }
    </script>

二、隐式绑定

如果函数调用时,前面有调用它的对象,this就隐式绑定在这个对象上

1.对象调用

this在对象中表示当前对象本身。

var obj={
    a:"哈哈哈",
    b:function(){
        console.log(this);
    }
};
obj.b();//Object
2.动态绑定的事件

在动态绑定的事件的回调函数中,this指向当前节点对象
代码如下(示例):

<div class="box">
        <button type="button" id="btn">我是一个按钮</button>
    </div>

    <script>
        var btn = document.getElementById("btn");
        btn.onclick = function () {
            console.log(this); //btn
        }
    </script>

三.this显式绑定

显式绑定是指我们通过call、bind方法改变this的行为,相比隐式绑定,我们能清楚的感知 this 指向变化过程。来看个例子:
代码如下(示例):

let obj1 = {
    name: '加薪*1'
};
let obj2 = {
    name: '加薪*2'
};

var name = '加薪';

function fn() {
    console.log(this.name);
};
fn(); //加薪 指向window
fn.call(obj1); //加薪*1 指向object1
fn.bind(obj2)(); //加薪*2 指向object2

四.new绑定

要想知道js中new以后this指向了谁,必须的知道new做了哪些事:
1.在内存中创建一个新的空对象
2.让this指向这个新的对象
3.执行构造函数里面的代码,给这个新对象添加属性和方法
4.返回这个新对象

function Fn(){
    this.name = '加薪加薪';
};
let obj = new Fn();
obj.name//加薪加薪 this指向被实例化后的对象

五. 箭头函数的this

箭头函数中this指向宿主对象,准确的说,箭头函数中没有this,箭头函数的this指向取决于外层作用域中的this,外层作用域或函数的this指向谁,箭头函数中的this便指向谁。

function fn() {
    return () => {
        console.log(this.name);
    };
}
let obj1 = {
    name: '加2k月薪'
};
let obj2 = {
    name: '加4k月薪'
};
let bar = fn.call(obj1); // fn this指向obj1
bar.call(obj2); //加2k月薪

从第二次结果我们可以看出,再次改变this指向时没有生效,这是为什么呢?
前面说了,箭头函数的this取决于外层作用域的this,fn函数执行时this指向了obj1,所以箭头函数的this也指向obj1。除此之外,箭头函数this还有一个特性,那就是一旦箭头函数的this绑定成功,也无法被再次修改,有点硬绑定的意思。

当然,箭头函数的this也不是真的无法修改,我们知道箭头函数的this就像作用域继承一样从上层作用域找,因此我们可以修改外层函数this指向达到间接修改箭头函数this的目的。

function fn() {
    return () => {
        console.log(this.name);
    };
};
let obj1 = {
    name: '听风是风'
};
let obj2 = {
    name: '时间跳跃'
};
fn.call(obj1)(); // fn this指向obj1,箭头函数this也指向obj1
fn.call(obj2)(); //fn this 指向obj2,箭头函数this也指向obj2

六.定时器

定时器函数中this指向window,示例如下

 var obj = {
            fn: function () {
                var timer = null;
                clearInterval(timer);
                timer = setInterval(function () {
                    console.log(this); //window
                }, 1000)
            }
        }
      obj.fn();

但是如果定时器里使用箭头函数则指向会改变,会指向这个对象本身,和隐式绑定中的对象绑定一样,遵循了箭头函数this’指向宿主对象的原则。

var obj = {
            fn: function () {
                var timer = null;
                clearInterval(timer);
                timer = setInterval(() => {
                    console.log(this);//object
                }, 1000)
            },
        }
        obj.fn();
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值