Vue 源码阅读(七) bind

起源

通过 Class 实现代码

class Demo {
  constructor() {
    this.num = 1
    this.init()
  }

  resize() {
    alert(this.num)
  }

  init() {
    window.addEventListener('resize', this.resize)
  }
}

new Demo()

代码执行后,缩放浏览器,此时弹窗显示 undefined

符合预期!!

通过 Vue 实现的代码

import Vue from 'vue'

new Vue({
  template: '<div></div>',
  data: {
    num: 1
  },
  methods: {
    resize() {
      alert(this.num)
    }
  },
  mounted() {
    window.addEventListener('resize', this.resize)
  }
}).$mount('#app')

缩放浏览器,此时弹框显示 1

不符合预期!!

代码分析

按常理,绑定事件 this.resize 后,将会丢失 this 所指向的上下文,所以第一个代码执行的结果是 undefined

因此猜想,在 Vue 的实现版本中,绑定是一定不是定义在 methods 下的 resize 方法。

源码分析

src/core/instance/state.js#L258

function initMethods (vm: Component, methods: Object) {
  const props = vm.$options.props
  for (const key in methods) {
    // ...
    vm[key] = methods[key] == null ? noop : bind(methods[key], vm)
  }
}

可以看到在 Vue 实例上绑定的方法,都是被 bind 处理过的。

src/shared/util.js#L203

function polyfillBind (fn: Function, ctx: Object): Function {
  function boundFn (a) {
    const l = arguments.length
    return l
      ? l > 1
        ? fn.apply(ctx, arguments)
        : fn.call(ctx, a)
      : fn.call(ctx)
  }

  boundFn._length = fn.length
  return boundFn
}

function nativeBind (fn: Function, ctx: Object): Function {
  return fn.bind(ctx)
}

export const bind = Function.prototype.bind
  ? nativeBind
  : polyfillBind

由此可见, Vue 的实例调用的方法,是经过 bind 后带有上下文的新方法。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值