在面试过程中遇到一些手写API的题目,这也让我对手写API产生兴趣,在实现API的过程中,对于语言的实现有了一些深入的了解,同时也练习了工作中不太常用的API。
在熟练实现这些API时也能为面试打下基础,一劳多得。
new
new的操作:
- 创建一个新对象
- 将对象的原型被赋值为构造函数的原型
- 将构造函数的作用域赋值给新对象(this指向新对象)
- 执行构造函数中的代码(为这个新对象添加属性)
- 返回新对象
new的模拟实现
function myNew(ctor, ...args){
if(typeof ctor !== 'function'){
throw new Error();
}
let obj = new Object();
Object.setPrototypeOf(obj, Object.create(ctor.prototype));
let res = ctor.apply(obj, ...args);
let isObject = typeof res === 'object' && typeof res !== null;
let isFunction = typeof res === 'function';
return isObject || isFunction ? res : obj;
}
call
语法
call的语法表现是接收两个参数,第一个参数表示当前函数执行的上下文对象,第二个参数表示传递给当前函数的参数,参数是一个参数列表的形式。
call根据传递的上下文对象,改变函数执行时的this指向
实现
function _call(context, ...args){
context = context || window;
context.fn = this;
let result = eval('context.fn(...args)');
delete context.fn;
return result;
}
apply
语法
apply与call类似,与call不同的是apply的第二个参数是一个数组,数组的每一项,是被调用的函数的参数
实现
function _apply(context,...args){
context = context || window;
context.fn = this;
let result = eval('context.fn(...args)');
delete context.fn;
return result;
}
bind
语法
bind与call类似,但是bind的返回值是一个改变了this指向后的函数
实现
function _bind(context, ...args){
if(typeof this !== 'function'){
throw new Error();
}
let self = this;
let fbound = function (){
self.apply(this instanceof self ? this : context, args.concat(Array.prototype.slice.call(arguments)));
}
if(this.prototype){
fbound.prototype = Object.create(this.prototype);
}
return fbound;
}