zl程序教程

您现在的位置是:首页 >  前端

当前栏目

原生js源码之JavaScript的apply方法

2023-09-11 14:21:46 时间

apply方法与call方法非常的相似,call的话是可以多个参数的,apply就只能最多2个参数,第一个参数都是绑定对象,第2个则是一个参数列表,语法如下:

Function.apply(object,args)方法能接收两个参数
object:这个对象将代替Function类里this对象
args:这个是数组,它将作为参数传给Function(args-->arguments)

写个简单例子使用一下apply方法

var person={
    name:"人类",
    sayHi:function(a,b){
        var hi=this.name+" 在向你问好!"+a +" " +b;
        return hi;
    }
}

var pig={
    name:'小猪'
}

console.log(person.sayHi.apply(pig,['真的','很舒服']));

输出:小猪 在向你问好!真的 很舒服

可以看到实参是通过Array的方式传入的

我们就在之前myCall的基础上稍作修改就可以了

Function.prototype.myApply=function(){
    var ret;
    var args=arguments;
    if(args.length==0){
        return this();//window
    }else{
        var context,arg,newArgs;
            context = args[0];//第一个参数是作为上下文
        if(context==null){//处理null 和 undefined
            return this();//window
        }
        if(typeof context!=='object'){
            context = {};
        }
        context[this.name]=this;
        
        var param = args[1]||[];//取到参数数组
        if(!(param instanceof Array)){//当第2个参数不是数组的时候抛出错误
            throw TypeError("CreateListFromArrayLike called on non-object");
        }

        var fn = this.name+"(";
        for(var i=0,len=param.length;i<len;i++){
            arg = param[i];
            if(i===0){
                fn+="'"+arg+"'";
            }else{
                fn+=",'"+arg+"'";
            }
        }
        fn +=")";

        
        ret= eval("context."+fn);
    }
    return  ret;
}

下面来验证一下结果:

 

完整实现如下:

var person={
    name:"人类",
    sayHi:function(a,b){
        return this.name+" 在向你问好!"+a+" "+b;
    }
}

var pig={
    name:'小猪'
}

Function.prototype.myApply=function(){
    var ret;
    var args=arguments;
    if(args.length==0){
        return this();//window
    }else{
        var context,arg,newArgs;
            context = args[0];//第一个参数是作为上下文
        if(context==null){//处理null 和 undefined
            return this();//window
        }
        if(typeof context!=='object'){
            context = {};
        }
        context[this.name]=this;
        
        var param = args[1]||[];//取到参数数组
        if(!(param instanceof Array)){
            throw TypeError("CreateListFromArrayLike called on non-object");
        }

        var fn = this.name+"(";
        for(var i=0,len=param.length;i<len;i++){
            arg = param[i];
            if(i===0){
                fn+="'"+arg+"'";
            }else{
                fn+=",'"+arg+"'";
            }
        }
        fn +=")";
        
        ret= eval("context."+fn);
    }
    return  ret;
}

console.log(person.sayHi.apply(pig));
console.log(person.sayHi.apply());
console.log(person.sayHi.apply(undefined));
console.log(person.sayHi.apply(null));
console.log(person.sayHi.apply(pig,));
//console.log(person.sayHi.apply(pig,'你好啊'));//CreateListFromArrayLike called on non-object
console.log(person.sayHi.apply(pig,['你好啊','大侠']));
console.log(person.sayHi.apply(pig,null));
console.log("-----------------")
console.log(person.sayHi.myApply(pig));
console.log(person.sayHi.myApply());
console.log(person.sayHi.myApply(undefined));
console.log(person.sayHi.myApply(null));
console.log(person.sayHi.myApply(pig,));
//console.log(person.sayHi.myApply(pig,'你好啊'));//CreateListFromArrayLike called on non-object
console.log(person.sayHi.myApply(pig,['你好啊','大侠']));
console.log(person.sayHi.myApply(pig,null));

 

打完收工,欢迎指正!!