谈谈对this对象的理解

37 阅读3分钟

定义

  • this是执行上下文的一个属性,它指向最后一次调用这个方法的对象

判断this指向的四种方式

  • 函数调用模式
    • 当一个函数不是一个对象的属性时,直接作为函数来调用,this指向全局对象
  • 方法调用
    • 如果一个函数作为一个对象的方法来调用时,this指向这个对象
  • 构造器调用模式
    • 如果一个函数用new调用时,函数执行前会创建一个对象,this指向这个新创建的对象
  • apply、call、bind调用模式
    • 都可以显示地指定调用函数的this指向
    • apply接收两个参数,一个是this绑定的对象,后面的其余参数是传入函数执行的参数function.apply(thisArg,[argsArr])
    const person = {
       fullName: function(city, country) {
         return this.firstName + " " + this.lastName + "," + city + "," + country;
       }
    }
    const person1 = {
      firstName:"John",
      lastName: "Doe"
    }
    person.fullName.apply(person1, ["Oslo", "Norway"]);//'John Doe,Oslo,Norway'
    Math.max.apply(null, [1,2,3]); // 3
    const arr = [1,2,3];
    const otherArr = [3,4,5];
    arr.push.apply(arr,otherArr);
    console.log(arr); // [1, 2, 3, 3, 4, 5]
    
    • call,调用对象的一个方法,以另一个对象替换当前对象,接收参数序列 function.call([thisObj[,arg1[, arg2[, [,.argN]]]]])
    • call方法可以用来代替另一个对象调用一个方法,可将一个函数的对象上下文从初始的上下文改变为由thisObj指定的新对象
    • call()方法的作用和apply()方法类似,区别就是call()方法接受的是参数列表,而apply()方法接受的是一个参数数组
    function isArray(object){
        return Object.prototype.toString.call(object) == '[object Array]';
        //[object Array]表示该对象的类型是数组
    }
    // 借用Object原型上的toString方法来验证下对象是否是数组?
    function accumulation(){
        return [].reduce.call(arguments,(a,b)=>{return a+b})
    }
    
    • bind
      • bind()方法创建一个新的函数,在bind()被调用的时候,这个新函数的this被指定为bind()的第一个参数,而其余的参数将会作为新函数的参数,供调用的时候使用
      • function bind(thisArg[,arg1[,arg2[, ...]]])
      • 返回一个原函数的拷贝,并拥有指定的this值和初始参数
        const OBJ = {
             petName: 'kyogre',
             qq: '2971411050',
             sayHi: function () {
                 console.log(`我是${this.petName} 很高兴认识你`)
             }
         }
         let sayHi = OBJ.sayHi;
         sayHi(); //我是undifined 很高兴认识你  ps: this非严格模式指向了window window.petName不存在
         let sayHi = OBJ.sayHi.bind(OBJ);
         sayHi(); //我是kyogre 很高兴认识你 ps:通过bind强制绑定sayHi函数内部的this指向OBJ
         //bind后sayHi会永久指向OBJ,使用call也无法更改绑定
    

call、bind、apply区别

  • call传入的是参数列表,apply传入的是数组,也可以是类数组
  • bind返回的是一个改变了this指向的函数,便于稍后调用,不像call和apply会立即调用;bind和call很像,传入的也是参数列表,但是可以多次传入,不需要像call,一次传入
  • 注意:当 bind 返回的函数使用new作为构造函数时,绑定的 this 值会失效,this指向实例对象,但传入的参数依然生效 (new调用的优先级 > bind调用)
// bind 返回的函数 作为普通函数调用
let bindFun = normalFun.myBind(obj, '我是参数传进来的name') // this:obj
bindFun('我是参数传进来的age')
// bind 返回的函数 作为构造函数调用
let bindFun = Person.myBind(obj, '我是参数传进来的name') // this:obj
let a = new bindFun('我是参数传进来的age')               // this:a

-------------------------------------------------------------------------------2024.5.12每日一题