1. 判断调用对象是否为函数,即使我们是定义在函数的原型上的,
但是可能出现使用 call 等方式调用的情况。
2. 判断传入上下文对象是否存在,如果不存在,则设置为 window 。
3. 处理传入的参数,截取第一个参数后的所有参数。
4. 将函数作为上下文对象的一个属性。
5. 使用上下文对象来调用这个方法,并保存返回结果。
6. 删除刚才新增的属性。
7. 返回结果。
call 函数实现
Function . prototype. mycall = function ( context) {
/ / 首先 判断调用对象是否为函数
if ( typeof this ! == "function" ) {
throw new TypeError( "Error" ) ;
}
/ / 思路,改变要执行函数里的this, 并且执行函数返回结果
/ / 1. 判断传this了没有,没有指向window
context = context | | window;
/ / 看看有没有传参数,把参数拿出来
let ars = [ . . . arguments] . slice( 1) ;
/ / 因为要拿到真正执行代码函数 fn. mycall
/ / 所以this就是fn
context. fn = this;
let result = context. fn( . . . ars)
delete context. fn;
return result;
}
function fn( ) {
console. log( this) ;
}
fn. mycall( { } )
apply 函数实现
Function . prototype. myApply = function ( context) {
/ / 判断调用对象是否为函数
if ( typeof this ! == "function" ) {
throw new TypeError( "Error" ) ;
}
let result = null;
/ / 判断 context 是否存在,如果未传入则为 window
context = context | | window;
/ / 将函数设为对象的方法
context. fn = this;
/ / 调用方法
if ( arguments[ 1] ) {
result = context. fn( . . . arguments[ 1] ) ;
} else {
result = context. fn( ) ;
}
/ / 将属性删除
delete context. fn;
return result;
} ;
bind 函数实现
bind 函数的实现步骤:
1. 判断调用对象是否为函数,即使我们是定义在函数的原型上的,
但是可能出现使用 call 等方式调用的情况。
2. 保存当前函数的引用,获取其余传入参数值。
3. 创建一个函数返回
4. 函数内部使用 apply 来绑定函数调用
,需要判断函数作为构造函数的情况,
这个时候需要传入当前函数的 this 给 apply 调用,
其余情况都传入指定的上下文对象。
Function . prototype. mybind = function ( context) {
if ( typeof this ! == 'function' ) {
return new TypeError( '不是函数' )
}
let fn = this
let args = [ . . . arguments] . slice( 1) ;
return function Fn( ) {
/ / 如果函数式构造函数,this就等于他自己
fn. apply( this instanceof Fn ?
this : context, args. concat( [ . . . arguments] ) )
}
}
mybind( context)