JavaScript高级手写apply()call()bind()
Posted karshey
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JavaScript高级手写apply()call()bind()相关的知识,希望对你有一定的参考价值。
文章目录
手写之前
我们有一个函数foo。
已知:
- foo的隐式原型是绑定在Function的显式原型上的(Function是一个构造函数)
function foo()
console.log(foo.__proto__===Function.prototype);//true
- apply、call、bind方法是来自Function的原型对象
console.log(Function.prototype.apply);//ƒ apply() [native code]
- 也就是说:在Function的原型对象上添加的属性或方法, 可以被所有的函数获取
apply
获取thisArg, 我们要确保是一个对象类型,要进行边界判断
Function.prototype.MyApply = function(thisArg)
thisArg=(thisArg===undefined||thisArg===null)?window:Object(thisArg);
;
将this绑定到传入的参数thisArg上
我们想实现apply显式绑定,就只能用:默认绑定、隐式绑定、new绑定来实现。(总不能自己实现自己)。
默认绑定肯定不是我们要的,因为显式绑定并不希望帮到window
上。
隐式绑定可以。
new绑定要用到构造函数,略显复杂。
所以我们用隐式绑定。
Function.prototype.MyApply = function(thisArg)
thisArg=(thisArg===undefined||thisArg===null)?window:Object(thisArg);
//这步
//当读取thisArg.fn时返回this,相当于thisArg.fn=this
//这里创建一个属性fn,它的值为this
Object.defineProperty(thisArg,"fn",
configurable:true,//true,否则没法delete
value:this,
);
//隐式绑定:让this指向thisArg
thisArg.fn();
//完成后删除thisArg中的fn属性
delete thisArg.fn;
;
将剩余的其他参数传入thisArg
apply传入的其他参数是一个数组。
function foo(name, age)
console.log(this, name, age); // name: 'kaisa' 'kaisa' 18
Function.prototype.myapply = function (thisArg, arrArgs)
thisArg =thisArg === undefined || thisArg === null ? window : Object(thisArg);
Object.defineProperty(thisArg, "fn",
configurable: true,
value: this,
);
// 通过展开运算符, 将其他参数传入thisArg
thisArg.fn(...arrArgs);
delete thisArg.fn;
;
foo.myapply( name: "kaisa" , ["kaisa", 18]);
call
call传入的其他参数是参数列表。
function foo(name, age)
console.log(this, name, age);
Function.prototype.MyCall = function (thisArg,...arrArgs)
thisArg = (thisArg === undefined || thisArg === null) ? window : Object(thisArg);
Object.defineProperty(thisArg, "fn",
configurable: true,
value: this,
);
thisArg.fn(...arrArgs);
delete thisArg.fn;
;
foo.MyCall(name:"abc","abc", 18);
封装函数实现apply和call
显然,apply和call的函数有重复的代码。因此,我们可以把重复代码封装成一个函数。
function repFn(thisArg,otherArgs,fn)
thisArg= (thisArg===null||thisArg===undefined)?window:Object(thisArg);
Object.defineProperty(thisArg,"fn",
configurable: true,
value: fn,
)
thisArg.fn(...otherArgs);
delete thisArg.fn;
//apply
Function.prototype.MyApply=function(thisArg,otherArgs)
repFn(thisArg,otherArgs,this);
//call
Function.prototype.MyCall=function(thisArg,...otherArgs)
repFn(thisArg,otherArgs,this);
测试:
//测试
function foo1(name,age)
console.log(this,name,age);
function foo2(name,age)
console.log(this,name,age);
foo1.MyApply(name:"apply",["apply",19]) //name: 'apply', fn: ƒ 'apply' 19
foo2.MyCall(name:"call","call",20)//name: 'call', fn: ƒ 'call' 20
bind
bind函数会返回一个新的函数,返回的新函数中可以传参数。
function foo(name,age,height)
console.log(this,name,age,height);
Function.prototype.MyBind=function(thisArg,...otherArgs)
thisArg= thisArg===null||thisArg===undefined?window:Object(thisArg);
Object.defineProperty(thisArg,"fn",
configurable:true,
value:this
)
return (...newArgs) =>
var allArgs=[...otherArgs,...newArgs];
thisArg.fn(...allArgs);
;
;
var newFoo=foo.MyBind(name:"bind","bind");
newFoo(18,1.88);//name: 'bind', fn: ƒ 'bind' 18 1.88
参考
coderwhy的课
手写apply-call-bind
手写 实现call、apply和bind方法 超详细!!!
使用JS简单实现一下apply、call和bind方法
Function
以上是关于JavaScript高级手写apply()call()bind()的主要内容,如果未能解决你的问题,请参考以下文章
前端面试题 ---- 手撕JavaScript call apply bind 函数(超详细)