call实现原理
- 让函数的this指向obj
- 可以在obj内创建一个函数,func赋值给它, obj.func = func;
- 用obj调用该函数 obj.func(…);
- 删除obj.func ```javascript let obj = { name: ‘Alibaba’ };
function func(x, y) { this.total = x + y; return this; }
// func的this指向obj obj.func = func; console.log(obj.func(100, 200)); delete obj.func;
<a name="Moq5s"></a>### call / bind具体实现<a name="oDF17"></a>#### bind & call/apply1. 都是为了改变函数中的**this指向**1. call/apply:**立即**把函数执行1. bind: **不是立即**把函数执行1. 只是预先把**this**和后期需要传递的**参数 存储起来**1. 「**预处理思想** -> 柯理化函数」```javascript// 相当于立即执行函数~ function () {// 非常随机了const createRandom = () => {let ran = Math.random() * new Date();// 随机名字return ran.toString(16).replace('.', '');};/* 内置CALL实现原理 */function change(context, ...params) {// this->要执行的函数func context->要改变的函数中的this指向obj// params->未来要传递给函数func的实参信息{数组} [100,200]// 校验context类型// undefined == null undefined !== null// 这里同时校验 undefined 和 nullcontext == null ? context = window : null; // context 为null / undefined this就指向windowif (!/^(object|function)$/.test(typeof context)) {context = Object(context); // 所有类型,转Object类型}// 临时设置的属性,不能和原始对象冲突,所以我们属性采用唯一值处理let self = this,key = Symbol('KEY'),result;context[key] = self; // 添加方法,this指向contextresult = context[key](...params); // 执行方法delete context[key]; // 删除方法return result;};/* 内置BIND的实现原理 */function bind(context, ...params) {// this->func context->obj params->[100,200]let self = this;// 柯里化return function proxy(...args) {// args->事件触发传递的信息,例如:[ev]params = params.concat(args);return self.call(context, ...params);};};Function.prototype.bind = bind;Function.prototype.change = change;}();// bind & call/apply// 都是为了改变函数中的this指向// + call/apply:立即把函数执行// + bind:不是立即把函数执行,// 只是预先把THIS和后期需要传递的参数存储起来「预处理思想 -> 柯理化函数」function func() {console.log(this, arguments);}var obj = {name: 'Alibaba'};document.body.onclick = func.bind(obj, 100, 200);// bind的原理,其实就是利用闭包的机制,把要执行的函数外面包裹一层函数document.body.onclick = function proxy(ev) {// 最后的目的:把func执行,this改为obj,参数100/200/ev传递给他即可func.call(obj, 100, 200, ev); //曲线救国};let obj = {name:'zhufeng'};function func(x,y){this.total=x+y;return this;}let res = func.change(obj,100,200);//res => {name:'Alibaba',total:300}
