CalebCai

学习笔记(二) js中的this指向问题总结

1.普通函数中 this指向window


// 1. 普通函数 this 指向window
function fn() {
            console.log('普通函数的this' + this);
        }
        window.fn();

2.构造函数中 this指向实例对象


// 2. 构造函数 this 指向 ldh 这个实例对象 原型对象里面的this 指向的也是 ldh这个实例对象
function Star(name) {
  this.name
}; Star.prototype.sing
= function() { } var ldh = new Star();

在构造函数中,我们new一个实例的时候,为这个函数开辟了一块内存空间,构造函数中的this也指向了那块新开辟的内存空间,然后new Star中存的是对应的内存地址,将这个内存地址赋值了ldh所以这this指向的了ldh这个实例的对象,原型对象的this也是指向了ldh这个实例对象,总结,不管是构造函数上的this还是原型对象上的this都指向了我们的实例对象ldh

关于构造函数的扩展:

es6之前通过构造函数+原型实现面向对象的编程

1.构造函数有原型对象prototype

2.构造函数原型对象prototype里面有constructor指向构造函数本身

3.构造函数可以通过原型对象添加扩张

4.构造函数创建的实例对象有__proto__属性指向构造函数的原型对象

注:构造函数与类并没有本质上的区别,使用的类的语法可以让代码更具有可读性

类的使用方法:

 // 1. 类的继承
        // class Father {
        //     constructor() {

        //     }
        //     money() {
        //         console.log(100);

        //     }
        // }
        // class Son extends Father {

        // }
        // var son = new Son();
        // son.money();
        class Father {
            constructor(x, y) {
                this.x = x;
                this.y = y;
            }
            sum() {
                console.log(this.x + this.y);

            }
        }
        class Son extends Father {
            constructor(x, y) {
                super(x, y); //调用了父类中的构造函数
            }
        }
        var son = new Son(1, 2);
        var son1 = new Son(11, 22);
        son.sum();
        son1.sum();
// super 关键字调用父类普通函数
        class Father {
            say() {
                return '我是爸爸';
            }
        }
        class Son extends Father {
            say() {
                // console.log('我是儿子');
                console.log(super.say() + '的儿子');
                // super.say() 就是调用父类中的普通函数 say()
            }
        }
        var son = new Son();
        son.say();
        // 继承中的属性或者方法查找原则: 就近原则
        // 1. 继承中,如果实例化子类输出一个方法,先看子类有没有这个方法,如果有就先执行子类的
        // 2. 继承中,如果子类里面没有,就去查找父类有没有这个方法,如果有,就执行父类的这个方法(就近原则)

但是在es6之前,我们需要使用下面的写法

要去改变子类当中的this的指向,使他指向父类构造函数的this

 // 借用父构造函数继承属性
        // 1. 父构造函数
        function Father(uname, age) {
            // this 指向父构造函数的对象实例
            this.uname = uname;
            this.age = age;
        }
        Father.prototype.money = function() {
            console.log(100000);

        };
        // 2 .子构造函数 
        function Son(uname, age, score) {
            // this 指向子构造函数的对象实例
            Father.call(this, uname, age);
            this.score = score;
        }
        // Son.prototype = Father.prototype;  这样直接赋值会有问题,如果修改了子原型对象,父原型对象也会跟着一起变化
        Son.prototype = new Father();
        // 如果利用对象的形式修改了原型对象,别忘了利用constructor 指回原来的构造函数
        Son.prototype.constructor = Son;
        // 这个是子构造函数专门的方法
        Son.prototype.exam = function() {
            console.log('孩子要考试');

        }
        var son = new Son('刘德华', 18, 100);
        console.log(son);
        console.log(Father.prototype);
        console.log(Son.prototype.constructor);

3.对象方法中 this指向该方法所属的对象


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

4.事件绑定方法中 this指向绑定事件对象

 // 4. 绑定事件函数 this 指向的是函数的调用者 btn这个按钮对象
        var btn = document.querySelector('button');
        btn.onclick = function() {
            console.log('绑定时间函数的this:' + this);
        };

 5.定时器函数和立即执行函数 this指向的是window对象

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

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

this的指向可以被改变:

二.  关于call  apply  bind的使用总结

call方法:

1.call方法会调用函数

2.call方法会改变this的指向

// call 方法
        function fn(x, y) {
            console.log('我想喝手磨咖啡');
            console.log(this);
            console.log(x + y);


        }
        var o = {
            name: 'andy'
        };
        // fn();指向的是window对象
        // 1. call() 可以调用函数
        // fn.call();
        // 2. call() 可以改变这个函数的this指向 此时这个函数的this 就指向了o这个对象
        fn.call(o, 1, 2);

 

apply方法:

1.apply方法会调用函数

2.apply方法也会改变内部的this指向,但是他的参数的必须是数组

3.apply主要应用 例:可以利用数学内置对象求最值

var arr=[1,22,3,55,4,66];
Math.max.apply(Math,arr)



# 应用于平铺数组参数

var a = [1,2,3],
    b = [4,5];

Array.prototype.push.apply(a, b); #=> a = [1, 2, 3, 4, 5]

a.push(b); #=> a = [1, 2, 3, [4,5]]

Math.math(null, [1,2,3,4,5]) #=> 5

这代码的意思是首先apply函数先调用一下Math.max的方法,让第一个形参中的this指向max这个方法的调用者Math

 

bind方法:

1.bind不会调用原来的函数,但是会改变原来函数内部的this指向

2.返回的是原函数改变this只会产生的新函数

3.如果有的函数不需要立即调用 但是又想改变内部的this指向

//bind方法
        var btn = document.querySelector('button');
        btn.onclick = function(){
            this.disabled = true;
            //这个this指向的是btn这个绑定的按钮
            setTimeout(()=>{
                this.disabled = false;//这个this指向的是window对象
            }.bind(this),3000)//这个this指向的是btn对象
        }

在箭头函数中,this指向的是其声明时所在的作用域 的this

 

总结:

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

不同点:1.call和apply会立即调用函数,并且改变this的指向

    2.call和apply传递的参数不一样,call传递的是num1,num2,num3.... apply传递的必须是一个数组

    3.bind不会立即调用函数,改变内部this的指向

应用场景:call多用来对父类的继承

     apply经常和数组有关系,可以对数组使用扩展的方法,例如借助数学方法对数组进行求最值

     bind不调用函数,但改变内部this的指向,比如改变定时器内部的this指向

 

posted on 2020-10-21 20:57  CalebCai  阅读(95)  评论(0)    收藏  举报

导航