this的概念
- this是
作用域
中的参数 - 解析器在每次调用函数的时候都会向函数内部传递进一个隐含的参数,这个隐含的参数就是this;
- this指向的是一个对象,函数执行的上下文对象;
- 根据函数的调用方式的不同,this会指向不同的对象
call实现原理
- call会立即执行函数
- 所谓的改变this,就是把需要改变this的函数挂载到context对象的临时fn
- 然后调用context里边的临时fn,这样就会把this指向context
- 为了保证不改变原来的对象,最后需要删除临时fn
Function.prototype.newCall = function (context,...arg) {
const ctx = context || window; // 没传或者传null默认是window
ctx.fn = this // 将call方法的目标函数挂到目标对象身上
const res = ctx.fn(...args)// 执行fn并传参,这时候this已经执行context了,因为fn是contex调用的
delete context.fn // 删除fn,不污染原对象
return res
}
function test(name) {
console.log(name + this.age + '岁了');
}
const obj = { age: 23 }
test.newCall(obj, 'sea')// sea23岁了
apply实现原理
与call的实现原理相同,就是传参的方式略微不同。传的是一个数组。
Function.prototype.newApply = function (context, arr=[]) {
const ctx = context || window;
ctx.fn = this // 将apply方法的目标函数挂到目标对象身上
const res = ctx.fn(arr)
delete context.fn
return res
}
bind实现原理
- bind不会立即执行函数,所以需要返回一个待执行的函数从而产生闭包
- 参数传递,由于参数的不确定性,用数组更好
Function.prototype.myBind = function (context, ...arg) {
const ctx = context || window;
ctx.fn = this; // 重要! this就是当前执行的函数. 给对象添加一个函数,那么这个函数内部的this就指向这个对象了
return function () {
const res = ctx.fn(...arg,...arguments); // 执行这个函数
delete ctx.fn;
return res;
};
};
var test = function(a,b){
console.log('作用域绑定 '+ this.value)
console.log('testBind参数传递 '+ a.value2)
console.log('调用参数传递 ' + b)
}
var obj = {value:'ok'}
var newFn = test.myBind(obj,{value2:'also ok'})
newFn ('hello bind')