js封装bind(),call(),apply()

bind(),call(),apply()

三种方都可以用来改变函数this指向,第一个参数都是目标对象,后面的参数不同,返回值野不同。

  1. call(obj, arg1, arg2…):参数依次放入,返回值是调用的方法的返回值。
  2. apply(obj, [arg1, sarg2…]):出第一个参数都需要放入一个数组当中,返回值是调用的方法的返回值。
  3. bind(obj, arg1, arg2…)():参数一次放入,返回值是一个新的函数,需要去执行。
var obj = {
    name : 'xiaoLi',
    age : 20
}
var person = {
    name : 'xiaozhang',
    age : 16,
    showFun : function( hometown, score ){
        return ("name : " + this.name + ",age : " + this.age + ',hometown : ' + hometown + ',score : ' + score);
    }
}
person.showFun();
console.log(person.showFun.apply(obj, ['beijing', 99]));
console.log(person.showFun.call(obj, 'shanghai', 100));
console.log(person.showFun.bind(obj, 'nanjing', 98));

在这里插入图片描述
在封装之前,再写一段关于this的代码,这个是在别人博客上看到的东西。
原文:https://blog.csdn.net/yangwei234/article/details/84451165

var a = 1;
var obj = {
    a: 2,
    fn: function(){
        console.log(this.a);
    }
}
var fn1 = obj.fn;
fn1();/1

我的理解是,这里fn1接收的这个函数体,但是fn1本身是全局声明的,所以调用fn1时,this指向为window,函数中的this.a自然是1。
先给一段基础代码

var person = {
    name : 'zhangsan',
    age : 12
}
var newPerson = {
    name : 'lisi',
    age : 20,
    showFun : function(hometown, score){
        console.log(this.name + ',' + this.age + ',' + hometown + ',' + score)
        return this.name + ',' + this.age + ',' + hometown + ',' + score
    }
}

封装call

Function.prototype.myCall = function(){
    var that = typeof arguments[0] === 'object' ? arguments[0]  : window;
    var newArg = [];
    for( var i = 1, len = arguments.length; i < len; i ++){
        newArg.push(arguments[i])
    }
    that.newFunction = this;
    var result = that.newFunction(...newArg)
    delete that.newFunction;
    return result;
}
newPerson.showFun.myCall(person,'beijing',100)

这里首先要考虑到使用that接收传进来的对象,同时也要判断一下是否是一个对象,如果不是,则that=window。因为方法中会使用一些传入对象的参数,因此需要给这个对象新增方法去执行一次,执行完毕后记得要删除。

封装apply

判断arguments[0]时,typeof和instanceof Object都无法进行准确判断,因此我使用了原型的constructor属性来判断,而第二个参数的判断是做了一个是否传参以及是否是数组的判断。其他的内容与call()没什么区别。

Function.prototype.myApply = function(){
     var that = typeof arguments[0] === 'object' ? arguments[0] : window;
    var newArg = [];
    if(arguments[1] instanceof Array){
        for( var i = 1, len = arguments[1].length; i < len; i ++){
            newArg.push(arguments[i])
        }
    }else{
        arguments[1] = []
    }
    that.newFunction = this;
    var result = that.newFunction(...arguments[1]);
    delete that.newFunction;
    return result;
}
newPerson.showFun.myApply([1,1])

封装bind

前半部分与封装call()相同,不过因为bind返回的是一个函数,所以,要return出一个函数,之前我尝试直接用that来执行方法,但是return出去后无法删除新增的那个方法,影响目标对象,因此使用Object.assign()复制目标对象,这样不会改变目标对象。

Function.prototype.myBind = function(){
    var that = typeof arguments[0] === 'object' ? arguments[0]  : window;
    var newArg = [];
    for(var i = 1,len = arguments.length; i < len; i ++){
        newArg.push(arguments[i])
    }
    var self = {};
    Object.assign(self,that);
    self.newFunction = this;
    function returnFunc(){
        return self.newFunction(...newArg);
    }
    return returnFunc;
}
newPerson.showFun.myBind()();
newPerson.showFun.bind()();
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值