前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >快速搞懂call,apply和bind

快速搞懂call,apply和bind

作者头像
LamHo
发布2022-09-26 10:43:36
1570
发布2022-09-26 10:43:36
举报
文章被收录于专栏:小前端看世界小前端看世界

call与apply

call和apply相信很多人用过,或者看源码看到过,在这里简单说说他们之间的关系。首先call和apply都是改变this指向的api。他的区别仅仅只是call和apply的第二位参数起的差别。

代码语言:javascript
复制
function callTest() { console.log(this); }
function applyTest() { console.log(this); }

const obj = {};

callTest.call(obj, arg1, arg2, arg3...);
applyTest.apply(obj, [arg1, arg2, arg3]);

那么如果有一个问题,call和apply之间,那个性能更高,你会怎么觉得呢?

按照函数的调用方式来说,一般都是采用多个参数传入的方式(arg1,arg2,arg3)。那么实际上call和apply之间,其实是call的性能更好。为什么呢?

其实在底层运行上,apply在调用apply的时候,还需要对传入的第二个参数进行解构赋值。

代码语言:javascript
复制
applyTest.apply(obj, [arg1, arg2, arg3]);

function apply() {
    this.call(obj, [...arguments]);
}

所以从运行的效率的角度上来说,call少了一次解构赋值,运行效率会比apply会更高。

bind原理

我使用bind大概也是因为我用react的缘故。在对组件的onClick绑定事件的时候,往往this的执行是存在问题的,因为我们onClick的事件很多时候是需要调用this.setState的。

代码语言:javascript
复制
class App extends Component {

    constructor() {
        this.state = {
            text: '1'
        }
    }
  
    clickHandle() {
        this.setState({
            text: '2'
        })
    }

    render () {
        return (
            <div onClick={this.clickHandle}>{this.state.text}</div>
        )
    }
}

如果我们这样写的话,那么在clickHandle函数中,this的执行就并非App这个class的实例了,而且event对象,这个时候setState就会报错。

如果我们如下修改

代码语言:javascript
复制
render () {
    return (
        <div onClick={() => {this.clickHandle()}}>{this.state.text}</div>
    )
}

那么这个时候就能正常运行,但是这里会有一个性能问题,当我们足够多的组件的时候,通过这样绑定事件回调是会存在性能问题,因为在每一次render的时候,我们使用箭头函数是一个匿名函数,所以每一次都会重新声明一次函数,导致性能下降,所以这个时候就可以使用bind来解决这个问题了。

代码语言:javascript
复制
class App extends Component {

    constructor() {
        this.state = {
            text: '1'
        }
        this.clickHandle = this.clickHandle.bind(this);
    }

    clickHandle() {
        this.setState({
            text: '2'
        })
    }

    render () {
        return (
            <div>OMG-CLI</div>
        )
    }
}

bind的作用实际就是将当前的函数的this进行绑定,而且放在constructor中进行绑定也是有原因的,因为constructor只会在class初始化的时候执行,所以函数也只需要进行一次绑定就可以了。那么有不少面试题里面都会有叫你使用js来实现bind。其实也很简单。

代码语言:javascript
复制
Function.prototype.bind = function() {
    // 保存当前调用bind的函数指针
    const self = this;
    // 获取第一个传入参数,你要绑定的this指针
    const context = Array.prototype.shift.call(arguments);
    // 将传入的参数转为数组
    const args = Array.prototype.slice.call(arguments);
    // 返回一个函数,通过闭包来保存调用函数的指向,this的指针以及传入的参数
    return function() {
        self.apply(context, [].concat.call(args, [].slice.call(arguments)));
    }
}

所以bind的实现也是相当简单的,只要清楚call和apply以及bind的原理,即可手写一个bind出来。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2020-02-25,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • call与apply
  • bind原理
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档