• 手写 call、apply 及 bind 函数


    首先从以下几点来考虑如何实现这几个函数

    • 不传入第一个参数,那么上下文默认为 window
    • 改变了 this 指向,让新的对象可以执行该函数,并能接受参数

    1. 那么我们先来实现 call

     1 Function.prototype.myCall = function(context) {
     2   if (typeof this !== 'function') {
     3     throw new TypeError('Error')
     4   }
     5   context = context || window
     6   context.fn = this
     7   const args = [...arguments].slice(1)
     8   const result = context.fn(...args)
     9   delete context.fn
    10   return result
    11 }

    以下是对实现的分析:

    • 首先 context 为可选参数,如果不传的话默认上下文为 window
    • 接下来给 context 创建一个 fn 属性,并将值设置为需要调用的函数
    • 因为 call 可以传入多个参数作为调用函数的参数,所以需要将参数剥离出来
    • 然后调用函数并将对象上的函数删除

    2. 以上就是实现 call 的思路,apply 的实现也类似,区别在于对参数的处理,所以就不一一分析思路了

     1 Function.prototype.myApply = function(context) {
     2   if (typeof this !== 'function') {
     3     throw new TypeError('Error')
     4   }
     5   context = context || window
     6   context.fn = this
     7   let result
     8   // 处理参数和 call 有区别
     9   if (arguments[1]) {
    10     result = context.fn(...arguments[1])
    11   } else {
    12     result = context.fn()
    13   }
    14   delete context.fn
    15   return result
    16 }

    3. bind 的实现对比其他两个函数略微地复杂了一点,因为 bind 需要返回一个函数,需要判断一些边界问题,以下是 bind 的实现

     1 Function.prototype.myBind = function (context) {
     2   if (typeof this !== 'function') {
     3     throw new TypeError('Error')
     4   }
     5   const _this = this
     6   const args = [...arguments].slice(1)
     7   // 返回一个函数
     8   return function F() {
     9     // 因为返回了一个函数,我们可以 new F(),所以需要判断
    10     if (this instanceof F) {
    11       return new _this(...args, ...arguments)
    12     }
    13     return _this.apply(context, args.concat(...arguments))
    14   }
    15 }

    以下是对实现的分析:

    • 前几步和之前的实现差不多,就不赘述了
    • bind 返回了一个函数,对于函数来说有两种方式调用,一种是直接调用,一种是通过 new 的方式,我们先来说直接调用的方式
    • 对于直接调用来说,这里选择了 apply 的方式实现,但是对于参数需要注意以下情况:因为 bind 可以实现类似这样的代码 f.bind(obj, 1)(2),所以我们需要将两边的参数拼接起来,于是就有了这样的实现 args.concat(...arguments)
    • 最后来说通过 new 的方式,对于 new 的情况来说,不会被任何方式改变 this,所以对于这种情况我们需要忽略传入的 this
    
    
  • 相关阅读:
    flash中网页跳转总结
    as3自定义事件
    mouseChildren启示
    flash拖动条移出flash无法拖动
    需要一个策略文件,但在加载此媒体时未设置checkPolicyFile标志
    Teach Yourself SQL in 10 Minutes
    电子书本地转换软件 Calibre
    Teach Yourself SQL in 10 Minutes
    Teach Yourself SQL in 10 Minutes
    Teach Yourself SQL in 10 Minutes – Page 31 练习
  • 原文地址:https://www.cnblogs.com/anu0823/p/13857387.html
Copyright © 2020-2023  润新知