Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

call和apply的模拟实现(javascript) #16

Open
YoursJoker opened this issue Aug 25, 2020 · 0 comments
Open

call和apply的模拟实现(javascript) #16

YoursJoker opened this issue Aug 25, 2020 · 0 comments

Comments

@YoursJoker
Copy link
Owner

javascript系列之 call和apply的模拟实现 篇

call和apply异同

同: 改变函数this指向
异: 传参列表不同(call传参是逐个传递,apply传参是以数组的方式传递)

call

用法例子

var bar = {
    age: 18
}
function foo(name, sex) {
    console.log(name)
    console.log(sex)
    console.log(this.age)
}
foo.call(bar, 'Joker', 'male');//Joker,male,18

注意要点:

  1. call改变了foo中的this指向
  2. 函数foo执行了

call的模拟实现

  1. 将函数添加为所绑定目标的属性
  2. 执行该属性
  3. 删除该属性
Function.prototype.myCall = function (target) {
    target = target || window
    //this 参数可以传 null,undefined,当为 null和undefined 的时候,视为指向 window
    argsLen = arguments.length;
    var args = [];
    for(var i = 1; i < argsLen; i++)
        args.push('arguments[' + i + ']')
    args = args.join(',');
    target.fn = this;//将函数添加为所绑定目标的属性
    var result = eval('target.fn(' + args + ')')//执行该属性
    delete target.fn;//删除该属性
    return result;
}
foo.myCall(bar, 'Joker', 'male');//Joker,male,18

使用ES6的rest参数和扩展运算符更为简便

Function.prototype.myCall = function (target, ...args) {
    target = target || window;
    target.fn = this;
    var result = target.fn(...args)
    delete target.fn;
    return result;
}
foo.myCall(bar, 'Joker', 'male');//Joker,male,18

apply

用法例子

var bar = {
    age: 18
}
function foo(name, sex) {
    console.log(name)
    console.log(sex)
    console.log(this.age)
}
foo.apply(bar, ['Joker', 'male']);//Joker,male,18

同理:

  1. apply改变了foo中的this指向
  2. 函数foo执行了

apply的模拟实现

  1. 将函数添加为所绑定目标的属性
  2. 执行该属性
  3. 删除该属性
Function.prototype.myApply = function (target, argsArr) {
    target = target || window
    //this 参数可以传 null,undefined,当为 null和undefined 的时候,视为指向 window
    target.fn = this;//将函数添加为所绑定目标的属性
    var result;
    if(!argsArr)
        result = target.fn();
    else{
        argsLen = argsArr.length;
        var args = [];
        for(var i = 0; i < argsLen; i++)
            args.push('argsArr[' + i + ']')
        args = args.join(',');
        result = eval('target.fn(' + args + ')')//执行该属性
    }
    delete target.fn;//删除该属性
    return result;
}
foo.myApply(bar, ['Joker', 'male']);//Joker,male,18

使用ES6的扩展运算符更为简便

Function.prototype.myApply = function (target, args) {
    target = target || window;
    target.fn = this;
    var result;
    if(!args)
        result = target.fn();
    else
        result = target.fn(...args);
    delete target.fn;
    return result;
}
foo.myApply(bar, ['Joker', 'male']);//Joker,male,18

call和apply的部分实现参考自冴羽的博客

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant