call,apply,bind的特点
- 都会改变函数指向;
- call 与apply的都会立即执行,区别是第一个以后的传参形式不同,call是多个单一的参数,如:
xxx.call(this, arg1, arg2, arg3, ...)
, apply是数组,如:xxx.apply(this, [arg1, arg2, arg3, ...])
,bind 和apply类似,但是执行后会return一个新的函数,如:const fn = xxx.bind(this, arg)
, 然后可以调用fn(arg2)
; - 要让所有的函数都能调用call, apply, bind,所以我们需要将call定义到函数原型(Function.ptototype)上;
定义一个对象
const person = {
name: "person",
genName: function () {
console.log("this is ", this);
console.log("arguments is ", [...arguments]);
},
};
手写call
Function.prototype.call2 = function (context) {
const cxt = context || window; // 新的作用域
const arg = [...arguments].slice(1); // 截取第一个参数后面的函数
const key = Symbol(); // 定义一个唯一的key
cxt[key] = this; // this是调用call2的函数
cxt[key](...arg); // 立即执行该函数
delete cxt[key];
};
person.genName();
person.genName.call2(null, "Franklin", "Fu");
// this is {name: 'person', genName: ƒ}
// arguments is []
// this is Window {window: Window, self: Window, document: document, name: '', location: Location, …}
// arguments is ['Franklin', 'Fu']
手写apply
Function.prototype.apply2 = function (context) {
const cxt = context || window;
const arg = [...arguments].slice(1);
const fnName = Symbol();
cxt[fnName] = this;
cxt[fnName](arg);
delete cxt[fnName];
};
person.genName();
person.genName.apply2(null, ["Franklin", "Fu"]);
// this is {name: 'person', genName: ƒ}
// arguments is []
// this is Window {window: Window, self: Window, document: document, name: '', location: Location, …}
// arguments is [[Franklin Fu]]
手写bind
Function.prototype.bind2 = function (context) {
const cxt = context || window;
const arg = [...arguments].slice(1);
const self = this; // this是调用call2的函数,闭包保存
return function () {
// 绑定的函数可能有返回值,所以添加return
return self.apply(cxt, arg.concat([...arguments]));
};
};
const _genName = person.genName.bind2(null, "Franklin");
person.genName();
_genName("Fu");
// this is {name: 'person', genName: ƒ}
// arguments is []
// this is Window {window: Window, self: Window, document: document, name: '', location: Location, …}
// arguments is ['Franklin', 'Fu']
版权声明:本文为qq_32247819原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。