this的改变者(call apply bind)

341 阅读1分钟

三者区别及用法

bindcallapply
(this,param1,param2,param3,...)(this,param1,param2,param3,...)(this,[param1,param2,param3,...])
返回的是fn的拷贝,改变了this的指向,保留了fn的参数fn的执行结果fn的执行结果
不立即执行立即执行立即执行

bind使用场景

let user = {
  data:[
    {name:'张三',age:'18'},
    {name:'王五',age:'25'},
  ],
  getUserAge(name){
    let {age=''} = this.data.find(item=>item.name === name) || {}
    console.log(age)
  }
}
user.getUserAge('王五')

如果不执行call,apply,bind 此时的this-->user;age-->'25'

let person = {
  data:[
    {name:'李四',age:'20'}
  ]
}

person需要getUserAge方法,不需要重新定义注入,直接借用user的即可

person.getUserAge = user.getUserAge.bind(person,'李四')
person.getUserAge() //此时的this-->person;age-->'20'

call使用场景

  Object.prototype.toString.call 检验类型

  let argArray = {
    0:'王权',
    1:'富贵',
    length:2
  }

  Array.prototype.push.call(argArray,'星星','竹海') // { '0': '王权', '1': '富贵', '2': '星星', '3': '竹海', length: 4 }

apply使用场景

const arr = [0,1,22,66,2,11]
const max = Math.max.apply(Math,arr)
const min = Math.min.apply(Math,arr)
  

拓展:

new 关键字

不用关键字new

创建一个构造函数
function Person(name,age){
  this.name = name;
  this.age = age;
}

添加方法
Person.prototype.sayHi = function () {
  console.log(this.name)
}

调用
const person1 = Person('夏有凉风',18)
console.log(person1,'person') // undefined
console.log(window.name) // this -->  window  '夏有凉风'

关键字new
const person2 = new Person('冬有雪',88)
console.log(person2,'person') // Person { name: '冬有雪', age: 88 }
person2.sayHi() // '冬有雪'

实现new 
1.创建一个新的对象
2.新对象[[Prototype]]被赋值位为构造函数的prototype属性
3.构造函数内部的this被赋值为新对象
4.给新对象添加属性
5.返回新的对象
function _new(fn,arguments){
  cosnt newObj = {}
  newObj._proto_ = fn.prototype; // prototype是函数属性  _proto_ 对象的属性
  fn.apply(newObj,arguments)
  return newObj
}

注意点:如果构造函数返回了非空的对象

function Person(name,age){
  this.name = name;
  this.age = age;
  return {car:'奔奔'}
}

const person2 = new Person('冬有雪',88) // { car: '奔奔' }

此时new 返回的就是该非空的对象


整合:
function _new(fn,...args){
  cosnt newObj = Object.create(fn.prototype)
  const res = fn.apply(newObj,args)
  return res instabceof Object ? res : newObj
}