使用方法,apply、call、bind的第一个参数是要指向的对象,后面的参数是要传递的值,其中注意的是bind要返回调用。
1、实现改变函数this指向的主要原理是通过对象进行调用,因为对象调用会将函数的this指向这个函数;
2、将被改写的函数挂载到Function 的函数上去,这样才能成功调用改写的函数。
call改写
Function.prototype.mycall=function(obj,...args){
// 这里的this指调用mycall的函数
if(obj == null || typeof obj == undefined){
obj = window
}
let fn = this
// 将fn挂载到obj对象上去
// 这里要注意,如果添加的属性与这个对象重名,则会污染对象,这里使用一个比较保险的方法是通过使用
// es6中的symbol,添加一个独一无二的key值
let key = Symbol('key')
obj[key] = fn
// 删除变更fn,否则会占用内存空间
delete fn
// 调用fn函数,此时fn中的this会指向obj
let res = obj[key](...args)
delete obj[key]
return res
}
apply
的实现方式与call差不多,唯一的区别就是传参不同,call的传参方式是单个值,而apply传参的方式是以数组的形式进行传参
obj = {name:'alice',age:18}
Function.prototype.myapply=function(obj,arg){
// 这里的this指调用mycall的函数
// 判断传递的参数是否为数组
if(!(arg instanceof Array)) throw ("'arg' is not a array")
if(obj == null || typeof obj == undefined){
obj = window
}
let fn = this
// 将fn挂载到obj对象上去
// 这里要注意,如果添加的属性与这个对象重名,则会污染对象,这里使用一个比较保险的方法是通过使用
// es6中的symbol,添加一个独一无二的key值
let key = Symbol('key')
obj[key] = fn
// 删除变更fn,否则会占用内存空间
delete fn
// 调用fn函数,此时fn中的this会指向obj
let res = obj[key](...args)
delete obj[key]
return res
}
bind
Function.prototype.mybind=function(obj){
// 这里的this指调用mycall的函数
// 判断传递的参数是否为数组
if(obj == null || typeof obj == undefined){
obj = window
}
let fn = this
// 将fn挂载到obj对象上去
// 这里要注意,如果添加的属性与这个对象重名,则会污染对象,这里使用一个比较保险的方法是通过使用
// es6中的symbol,添加一个独一无二的key值
let key = Symbol('key')
obj[key] = fn
// 删除变更fn,否则会占用内存空间
delete fn
// 利用闭包返回函数
return function(...args){
let res = obj[key](...args) // 调用fn函数,此时fn中的this会指向obj
delete obj[key]
return res
}