Open wsqww opened 3 years ago
/**
* call
* @param {*} ctx
* 1.ctx 存在就使用 ctx window
* 2.使用 Object(ctx) 将 ctx 转换成对象,并通过 ctx.fn 将 this 指向 ctx
* 3.循环参数,注意从 1 开始,第 0 个是上下文,后面才是我们需要的参数
* 4.将参数字符串 push 进 args
* 5.拿到结果返回前,删除掉 fn
*/
Function.prototype.myCall = function (ctx) {
ctx = ctx || window;
const fn = Symbol(); // Symbol属性来确定fn唯一。
const args = [...arguments].slice(1);
// console.log(this);
ctx[fn] = this; // this 在这里是调用 call 的函数
const result = ctx[fn](...args);
delete ctx[fn];
return result;
};
/**
* apply
* @param {*} ctx
* @param {*} args
* 1.apply 无需循环参数列表,传入的 args 就是数组
* 2.但是 args 是可选参数,如果不传入的话,直接执行
*/
Function.prototype.myApply = function (ctx, args) {
ctx = ctx || window;
const fn = Symbol(); // Symbol属性来确定fn唯一。
ctx[fn] = this; // this 是调用 call 的函数 f say() {}
let result;
if (!args) {
// 判断array是否存在
result = ctx[fn]();
} else {
result = ctx[fn](...args);
}
delete ctx[fn];
return result;
};
/**
* bind
* @param {*} ctx
* 1. 改变this指向
* 2. 接受参数列表、
* 3. return 一个函数
* 4. 遇到new这样优先级高于bind方法的时候,bind改变this指向会无效。
*/
/* eslint-disable */
Function.prototype.myBind = function (ctx) {
var self = this; // 因为之后要return一个函数,这里保存一下this防止混乱
var args = Array.prototype.slice.call(arguments, 1); // 获取参数
var fb = function () {
var bindArgs = Array.prototype.slice.call(arguments);
const target = this instanceof fb ? this : ctx;
return self.apply(target, args.concat(bindArgs));
};
var fn = function () {};
fn.prototype = this.prototype; // 让实例可以继承原型
fb.prototype = new fn();
return fb;
};
let Person = {
name: "Tom",
say(a, b) {
this.a = a;
this.b = b;
console.log(this);
console.log(`我叫${this.name}, a: ${this.a}, b: ${this.b}`);
}
};
// call --------------------------------------------------------
let PersonA = {
name: "Tom A"
};
Person.say.myCall(PersonA, "A1", "A2");
// apply --------------------------------------------------------
let PersonB = {
name: "Tom B"
};
Person.say.myApply(PersonB, ["B1", "B2"]);
// bind --------------------------------------------------------
let PersonC = {
name: "Tom C"
};
const fnC = Person.say.myBind(PersonC, "C1");
fnC("C2");
测试代码,点击这里