本篇内容介绍了“怎么实现call、apply、bind”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!
成都创新互联成都网站建设定制制作,是成都网站建设公司,为成都茶楼设计提供网站建设服务,有成熟的网站定制合作流程,提供网站定制设计服务:原型图制作、网站创意设计、前端HTML5制作、后台程序开发等。成都网站改版热线:13518219792
首先我们来给call下个定义:
call方法在使用一个指定的 this 值和若干个指定的参数值的前提下调用某个函数或方法。
举个例子:
var foo = {
value: 1
};
function bar() {
console.log(this.value);
}
bar.call(foo); // 1
从上面代码的执行结果,我们可以看到,call首先改变了this的指向,使函数的this指向了foo,然后使bar函数执行了。
总结如下:1、call改变函数this指向,2、调用函数
思考一下:我们如何实现上面的效果呢?代码改造如下:
//将bar函数挂载到foo对象上,使其成为foo的方法,用foo.bar来调用var foo = { value:1, bar:function(){ console.log(this.value) }}foo.bar() //1
仔细观察一下我们做了什么,将bar函数挂载到foo对象上,使其成为foo的方法,用foo.bar来调用。
再来看上面代码的执行结果:打印1,有没有什么启发呢?为了模拟call方法,我们可不可以这样做呢:
a、将函数设为某个对象的属性(或者方法)
b、通过该对象的属性调用该函数
c、将该对象上的这个属性(或者方法)
代码如下:
Function.prototype.myCall = function(context) { context = context || window //将函数挂载到对象的fn属性上 context.fn = this //处理传入的参数 const args = [...arguments].slice(1) //通过对象的属性调用该方法 const result = context.fn(...args) //删除该属性 delete context.fn return result}
我们看一下上面的代码:
1、首先我们对参数context做了兼容处理,不传值,context默认值为window。
2、然后我们将函数挂载到context上面,context.fn = this;
3、处理参数,将传入myCall的参数截取,去除第一位,然后转为数组;
4、调用context.fn,此时fn的this指向context;
5、删除对象上的属性 delete context.fn
5、将结果返回。
以此类推,我们顺便实现一下apply,唯一不同的是参数的处理,代码如下:
Function.prototype.myApply = function(context) {
context = context || window
context.fn = this
let result
// myApply的参数形式为(obj,[arg1,arg2,arg3]);
// 所以myApply的第二个参数为[arg1,arg2,arg3]
// 这里我们用扩展运算符来处理一下参数的传入方式
if (arguments[1]) {
result = context.fn(...arguments[1])
} else {
result = context.fn()
}
delete context.fn
return result
}
以上便是call和apply的模拟实现,唯一不同的是对参数的处理方式。
接着再来思考一下bind的实现,在模拟bind的实现之前,先看一下bind的使用案例:
var obj = {a:1};function bar(){ console.log(this.a);}bar.bind(obj)();
我们看到,bind函数虽然也能改变bar函数的this,但是改变后,函数并不会执行,只是返回一个新的函数,想执行就得继续调用,仔细观察第五行代码的写法。
根据上面的使用案例,我们先实现一个简单版本的bind:
Function.prototype.myBind = function(ctx) { return () => { // 要用箭头函数,否则 this 指向错误 return this.call(ctx) }}var obj = {a:1};function bar(){ console.log(this.a);}bar.myBind(obj)();
但是这样比较简陋,函数的参数一多就不能处理了,如下面这种情况:
bar.bind(obj, 2)(2)// orbar.bind(obj)(2, 2)
为了兼容bind调用时满足参数传递的不同方式,代码修改如下:
Function.prototype.myBind = function(ctx, ...argv1) { return (...argv2) => { return this.call(ctx, ...argv1, ...argv2) }}//测试代码var obj = {a:1};function bar(b,c){ console.log(this.a+b+c);}bar.myBind(obj)(20,30);bar.myBind(obj,20,30)();
“怎么实现call、apply、bind”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注创新互联网站,小编将为大家输出更多高质量的实用文章!