怎么实现call、apply、bind

本篇内容介绍了“怎么实现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”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注创新互联网站,小编将为大家输出更多高质量的实用文章!


网站题目:怎么实现call、apply、bind
链接URL:http://ybzwz.com/article/jisgdg.html