首页 > 技术文章 > Js中this指向

wueiwn 2021-07-16 17:53 原文

我们在初使用 JavaScript 开发的时候,多多少少会被 this 的指向搞蒙圈,弄不清楚this指向哪一个对象,但是实际上,关于 this 的指向,记住最核心的一句话: 

哪个对象调用函数,函数里面的this指向哪个对象。

对this的讨论,主要分以下几种情况:

一、普通函数调用

1. 普通函数 this 指向window,因为一般情况下普通函数的调用者都是window

二、对象函数调用

2.对象的方法 this指向的是对象 o

var o = {
            sayHi: function() {
                console.log('对象方法的this:' + this);
            }
        }
        o.sayHi(); //this指向的是对象 o

三、构造函数调用

3. 构造函数 this 指向 ldh 这个实例对象 原型对象里面的this 指向的也是 ldh这个实例对象.

var that;
        function Star(uname, age) {
            this.uname = uname,
                this.age = age,
                that = this
        };
        Star.prototype.sing = function() {
            console.log('我会唱歌');
        }
        var ldh = new Star('刘德华', 20);
        console.log(that === ldh); //ture

四、定时器函数调用与立即执行函数调用

 // 5. 定时器函数 this 指向的也是window
        window.setTimeout(function() {
            console.log('定时器的this:' + this);

        }, 1000);
        // 6. 立即执行函数 this还是指向window
        (function() {
            console.log('立即执行函数的this' + this);
        })();

五、ES6中箭头函数的调用

箭头函数不绑定this即箭头函数没有自己的this,如果在箭头函数中使用this,this关键字将指向箭头函数中定义位置中的this

 function fu() {
            console.log(this);
            return () => {
                console.log(this);
            }
        }
        const obj = {
            name: '张三',
            age: 20
        }
        const resfn = fu.call(obj)
        resfn()

效果如下:

六、call()和apply()与bind()调用

6.1 call()函数 第一个作用可以调用函数 第二个可以改变函数内的this 指向,但是call ()的主要作用是可以实现继承
<script>
        var o = {
            name: 'andy',
        }
        function fu(a, b) {
            console.log(this);
            console.log(a + b);
        }
        fu.call(o, 1, 2);
        // call 第一个可以调用函数 第二个可以改变函数内的this 指向
        // call 的主要作用可以实现继承
        function Father(uname, age, sex) {
            this.uname = uname;
            this.age = age;
            this.sex = sex;
        }
        function Son(uname, age, sex) {
            Father.call(this, uname, age, sex);
        }
        var son = new Son('刘德华', 18, '男');
        console.log(son);
    </script>

效果图如下:

6.2apply()也是可以调用函数 ,第二个作用也可以改变函数内部的this指向,但是apply()的第二个参数必须是数组(伪数组)

// 2. apply()  应用 运用的意思
        var o = {
            name: 'andy'
        }

        function fu(arr) {
            console.log(this);
            console.log(arr); //打印的是字符串
        }
        fu.apply(o, ['pink']);
        // 1. 也是调用函数 第二个可以改变函数内部的this指向
        // 2. 但是他的参数必须是数组(伪数组)
        // 3. apply 的主要应用 比如说我们可以利用 apply 借助于数学内置对象求数组最大值 
        // Math.max();
        var arr = [1, 66, 3, 99, 4];
        var max = Math.max.apply(Math, arr);
        var min = Math.min.apply(Math, arr);
        console.log(max, min);

效果如下:

6.3 bind()不会调用原来的函数 ,但是可以改变原来函数内部的this 指向,调用该函数是有返回值的,返回的是原函数改变this之后产生的新函数

 var o = {
            name: 'andy'
        };
        function fn(a, b) {
            console.log(this);
            console.log(a + b);
        };
        var f = fn.bind(o, 1, 2);
        f();

效果如下:

bind函数用的较多,如果有的函数我们不需要立即调用,但是又想改变这个函数内部的this指向此时用bind,比如我们有一个按钮,当我们点击了之后,就禁用这个按钮,3秒钟之后开启这个按钮(类似于60s发送短信验证)

 var btn = document.querySelector("button");
        btn.onclick = function() {
            // var that = this;
            this.disabled = true; // 这个this 指向的是 btn 这个按钮
            setTimeout(function() {
                    // that.disabled = false;定时器函数里面的this 指向的是window
                    this.disabled = false; // 此时定时器函数里面的this 指向的是btn
                }.bind(this), 3000) // 这个this 指向的是btn 这个对象
        }

七、call()和apply()与bind()总结

相同点:都可以改变this指向

不同点: call 和 apply 会调用函数, 并且改变函数内部this指向 ,call传递参数使用逗号隔开传递,apply传递第二个参数使用数组传递, bind 不会调用函数

应用场景: call 经常做继承, apply 经常跟数组有关系. 比如借助于数学对象实现数组最大值最小值 ,bind 不调用函数,但是还想改变this指向. 比如改变定时器内部的this指向

好了,关于js中this的指向问题就介绍到这里啦。如果你发现文中有错误的地方,还希望大佬们指正,共同进步

推荐阅读