js中手写call(不能使用ES6语法)和使用ES6语法对比

1、js手写call(不能使用ES6语法)复杂

//在myCall中通过this拿到调用myCall的原函数,接下来,当函数被调用时,它作为某个对象的方法(前面加了"."),
// this指向这个对象("."前面的对象)改变原函数中this的指向
//将原函数作为context的方法调用时,方法名并不影响功能,但是将方法名写死可能会造成方法名冲突
//传参问题,可以传递n个参数,使用arguments,第二个参数之后的叫剩余参数,将剩余参数传递给`context[uniqueName]`还可以通过`eval`来拼接调用语句
Function.prototype.myCall = function(context){
	if (context === null || context === undefined) {
       // 指定为 null 和 undefined 的 this 值会自动指向window
        context = window 
    } else {
        // 值为原始值(数字,字符串,布尔值)的 this 会指向该原始值的实例对象
        context = Object(context) 
	}
    //this === 原函数,就是调用myCall的函数
    console.log('this',this)
    //手写返回一个不重复函数名
    function mySymbol(obj){
        let unique = (Math.random()+new Date().getTime())
        if(obj.hasOwnProperty(unique)){
            //如果重复,递归调用
            return mySymbol(obj) 
        }else{
            return unique
        }
    }
    let uniqueName = mySymbol(context)
        //获取除了第一个参数外剩余的参数

    let args = []
    for(let i = 1; i < arguments.length; i++){
        args.push('arguments[' + i + ']')
    }
    //将原函数作为context的方法调用
    context[uniqueName] = this
    //调用原函数,若有返回值,存放在result中, eval可以将字符串执行
    let result = eval('context[uniqueName](' + args.join(',') + ')')
    //返回之前,删除函数名
    delete context[uniqueName]
    //返回值
    return result
}

2、js手写call(使用ES6语法)简单

Function.prototype.myCall = function(context,...args){
    if (context === null || context === undefined) {
       // 指定为 null 和 undefined 的 this 值会自动指向window
        context = window 
    } else {
        // 值为原始值(数字,字符串,布尔值)的 this 会指向该原始值的实例对象
        context = Object(context) 
	}
	//生成一个唯一值作为函数名
    let fn = Symbol('唯一的值')
    context[fn] = this
    //使用剩余参数
    let result = context[fn](...args)
    delete context[fn]
    return result
}

你可能感兴趣的:(JavaScript)