JS_call&apply

2019-06-27  本文已影响0人  anddju

因为call语法和作用与 apply 方法类似。
只有一个区别,call 接受的是一个参数列表,而 apply 接受的是一个包含多个参数的数组
所以放到一起。

MDN#Call
MDN#Apply

call

  1. 将函数设为传入参数的属性
  2. 指定this到函数并传入给定参数执行函数
  3. 如果不传入参数或者参数为null,默认指向为 window / global
  4. 删除参数上的函数
Function.prototype.call = function (context) {
    /** 如果第一个参数传入的是 null 或者是 undefined, 那么指向this指向 window/global */
    /** 如果第一个参数传入的不是null或者是undefined, 那么必须是一个对象 */
    if (!context) {
        //context为null或者是undefined
        context = typeof window === 'undefined' ? global : window;
    }
    context.fn = this; //this指向的是当前的函数(Function的实例)
    let args = [...arguments].slice(1);//获取除了this指向对象以外的参数, 空数组slice后返回的仍然是空数组
    let result = context.fn(...args); //隐式绑定,当前函数的this指向了context.
    delete context.fn;
    return result;
}
/*
  方法2
  原理就是将函数作为传入的上下文参数(context)的属性执行,这里为了防止属性冲突使用了 ES6 的 Symbol 类型
*/
const selfCall = function(context , ...args){
  let func = this;
  context || (context = window)
  if(typeof func !== 'function') throw new TypeError('this is not function');

  let caller = Symbol("caller");
  context[caller] = func;
  let res = context[caller](...args);
  delete context[caller];
  return res
}

手写apply

apply的实现和call很类似,但是需要注意他们的参数是不一样的,apply的第二个参数是数组或类数组.

Function.prototype.apply = function (context, rest) {
    if (!context) {
        //context为null或者是undefined时,设置默认值
        context = typeof window === 'undefined' ? global : window;
    }
    context.fn = this;
    let result;
    if(rest === undefined || rest === null) {
        //undefined 或者 是 null 不是 Iterator 对象,不能被 ...
        result = context.fn(rest);
    }else if(typeof rest === 'object') {
        result = context.fn(...rest);
    }
    delete context.fn;
    return result;
}

如有侵权,请联系我

上一篇 下一篇

猜你喜欢

热点阅读