前言
好久没有更新过博客了,最近项目进度比较紧张,每天都在加班,学习的时间少之又少,目前这家公司的技术栈以尤大大的Vue+饿了吗的elementui为主导,项目中很少会用到 call & bind,昨天复习了一下原型链的知识,感觉比之前的理解又深入了一个层次,两大基类(Function & Object)的概念愈发强烈,今天抛开原型链,来说一说,call & bind。
Call
首先我们先来了解一下他分别干了什么事儿:
参数: context params
将 this 指向 context,params传递给当前调用 call 的函数
函数执行
注意:call 的context不穿值或者传递null,都指向window
知道了他做了什么事儿,那么我们实现起来就很简单了:
// 先将我们自己定义的myCall绑定到 Js的内置类 Function的原型上 Function.prototype.myCall = function( context, ...params ) { // 校验context是否是undefined || null context == null ? context = window : null; // 校验如果 context是基本数据类型的话转化成引用 栗子:context = 1; 那么 Object(context) = Number { 1 },此时 typeof context === 'object' !/^(object|function)$/.test( typeof context) ? context = Object(context) : null; // 定义形参,除了context是一个以外,后面的参数是不固定的,直接rest运算符一步到位 let _this = this, // 养成习惯...保留this指向 result = null, // 接收函数执行的返回结果 KEY = Symbol('KEY') // 使用Symbol定义 KEY,防止与context原有的属性冲突 context[KEY] = _this; // 将当前函数挂载到context中 result = context[KEY](...params); //当前函数作为context中的一个属性的值被调用 delete context[KEY] // 删除context上自己添加的属性,保持与之前的context一直 return result // 返回函数执行的结果 }
Bind
知道call方法的原理以后,bind就很简单了,无外乎不立即执行
Function.ptototype.myBind = function( context, ...outParams ) { // outerParams主要是形参集合 let _this = this; return function( ...innerParams ) { //innerParams 主要是ev对象 this.call(context, ...outParams.concat(...innerParams)) } } doucument.body.onclick = fn.myBind(obj, 10, 20); function fn(x, y, ev) { this.x = 3; this.y = 4; } var obj = { x: 1, y: 2 }