不多bb直接上代码,希望对大家伙有少许帮助
本文中涉及到的公用方法
// 原始值
const primitive = {
'string': true,
'number': true,
'symbol': true,
'boolean': true,
'null': true,
'undefined': true,
}
const isFn = v => typeof v === 'function';
const isBrow = () => typeof window !== 'undefined';
const isArray = v => Array.isArray(v);
const isNew = (v, c) => v instanceof c;
const isPrimitive = v => primitive[typeof v];
apply
// apply的实现
Function.prototype.apply1 = function (context) {
// 获取需要被调用的函数
const fn = this;
if (!isFn(fn)) return;
// 获取指定上下文
const ctx = context || global;
// 获取传递过来的参数
let args = [...arguments]
args = args.pop();
if (!isArray(args)) return;
// 将fn 作为对象的属性
ctx.fn = fn;
const res = ctx.fn(...args);
delete ctx.fn
return res;
}
call
Function.prototype.call1 = function (context) {
// 获取需要被调用的函数
const fn = this;
if (!isFn(fn)) return;
// 获取指定上下文
const ctx = context || global;
// 获取传递过来的参数
const args = [...arguments]
args.shift()
// 将fn 作为对象的属性
ctx.fn = fn;
// 执行 fn
const res = ctx.fn(...args)
delete ctx.fn
return res;
}
bind
// bind的实现
Function.prototype.bind1 = function (context) {
// 获取需要被调用的函数
const fn = this;
if (!isFn(fn)) return;
// 获取指定上下文
let ctx = context || global;
// 获取 预置入绑定函数的参数列表
const _args = [...arguments]
_args.shift();
// 利于一个中转函数 来实现继承关系
const temp = function () { };
const f = function () {
// 合并 bind传递的参数 和 调用函数时传递的参数
const args = [..._args, ...arguments]
ctx = isNew(this, f) ? this : ctx
return fn.call1(ctx, ...args)
}
temp.prototype = fn.prototype;
f.prototype = new temp();
return f
}
instanceof
// instanceof的实现
function instanceof1(left, right) {
if (!(left && right)) return;
do {
if (left.__proto__ === right.prototype) return true;
} while (left = left.__proto__)
return false;
}
new
// new的实现
function new1(constructor) {
if (!isFn(constructor)) return;
// 获取参数
const args = [...arguments];
args.shift()
// 创建一个空对象
const obj = {};
// 将obj作为 上下文 调用 构造函数
const res = constructor.call(obj, ...args);
// 实现一个继承关系 让 obj 可以访问到构造函数上面的属性
// 其实可以在 创建obj的时候 利用 Object.create() 来指定它的原型对象为constructor.prototype
obj.__proto__ = constructor.prototype;
return isPrimitive(res) ? obj : res;
}