13. 手写call, apply, bind

手写call

查看答案
Function.prototype.myCall=function(context=window){  // 函数的方法,所以写在Fuction原型对象上
if(typeof this !=="function"){   // 这里if其实没必要,会自动抛出错误
throw new Error("不是函数")
}
const obj=context||window   //这里可用ES6方法,为参数添加默认值,js严格模式全局作用域this为undefined
obj.fn=this      //this为调用的上下文,this此处为函数,将这个函数作为obj的方法
const arg=[...arguments].slice(1)   //第一个为obj所以删除,伪数组转为数组
res=obj.fn(...arg)
delete obj.fn   // 不删除会导致context属性越来越多
return res
}
//用法:f.call(obj,arg1)
function f(a,b){
console.log(a+b)
console.log(this.name)
}
let obj={
name:1
}
f.myCall(obj,1,2) //否则this指向window

obj.greet.call({name: 'Spike'}) //打出来的是 Spike

手写apply(arguments[this, [参数1,参数2…..] ])

查看答案
Function.prototype.myApply=function(context){  // 箭头函数从不具有参数对象!!!!!这里不能写成箭头函数
let obj=context||window
obj.fn=this
const arg=arguments[1]||[]    //若有参数,得到的是数组
let res=obj.fn(...arg)
delete obj.fn
return res
}
function f(a,b){
console.log(a,b)
console.log(this.name)
}
let obj={
name:'张三'
}
f.myApply(obj,[1,2])  //arguments[1]

手写bind

查看答案
this.value = 2
var foo = {
value: 1
};
var bar = function(name, age, school){
console.log(name) // 'An'
console.log(age) // 22
console.log(school) // '家里蹲大学'
}
var result = bar.bind(foo, 'An') //预置了部分参数'An'
result(22, '家里蹲大学') //这个参数会和预置的参数合并到一起放入bar中
// 简单版本
Function.prototype.bind = function(context, ...outerArgs) {
var fn = this;
return function(...innerArgs) {   //返回了一个函数,...rest为实际调用时传入的参数
return fn.apply(context,[...outerArgs, ...innerArgs]);  //返回改变了this的函数,
//参数合并
}