-
Notifications
You must be signed in to change notification settings - Fork 14
Open
Description
new
new之后发生了这些事:新对象的原型prototype等于目标的原型prototype,构造函数constructor指向目标,并执行目标函数,隐式返回新对象。
function _new (target, ...args) {
// 利用该api,以target的prototype为原型生成对象,并包含constructor
const context = Object.create(target.prototype);
const ret = target.apply(context, args)
// 若无显式返回对象 则返回context
return ret instanceof Object ? ret : context;
}bind
将函数绑定另一个上下文环境,改变其内部的this指向,同一函数在进行多次bind后,只有第一次bind时能生效,后续无法再改变其上下文。
在日常开发中,有时也有需要不侵入原函数的实现来改变this指向的场景。因此以下模拟一个bind的实现。
function bind (fn, context) {
return function bindWrapper () {
return fn.apply(context, arguments);
}
}apply
将函数以首个参数作为上下文(改变this),执行后续参数数组,并返回结果。
如果要模拟实现,且不使用bind的话,原理上可以将该函数以一个特殊Key值挂载到指定上下文对象上,然后调用后进行delete即可
Function.prototype._apply = function _apply (context, args) {
const fn = this;
// context为null时,应将上下文设为window
context = context || window;
// 随机生成一个key值,可自行替换生成的随机规则,这里暂采用时间戳
const key = +new Date();
context[key] = fn;
// 用eval处理参数的传递
// 保存调用结果,后续返回
const result = eval('context[key](' + args.map((item, idx) =>{
return `arguments[1][${idx}]`
}).join(',') + ')');
delete context[key];
return result;
};call
作用与apply一样,区别就是传递的参数,不以数组的形式,而是以正常传值形式
Function.prototype._call = function _call () {
const fn = this;
const context = arguments[0] || window;
// 截取arguments
const args = new Array(arguments.length - 1);
for (let i = 1; i < arguments.length; i++) {
args[i - 1] = `arguments[${i}]`
}
const key = +new Date();
context[key] = fn;
const result = eval('context[key](' + args.join(',') + ')');
delete context[key];
return result;
}Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels