前言
能够手撕各种JavaScript原生函数,可以说是进大厂必备!同时对JavaScript源码的学习和实现也能帮助我们快速扎实地提升自己的前端编程能力。
最近很多人和我一样在积极地准备前端面试笔试,所以就整理了一些前端面试笔试中非常容易被问到的原生函数实现和各种前端原理实现,其中部分源码戳这里。
如果还在IT编程的世界里迷茫,不知道自己的未来规划,学习没有动力,东也学一下,西也学习一下,那你可以加入web前端学习交流Q群:733581373, 里面有大神一起交流并走出迷茫。新手可进群免费领取学习资料,分享一些学习的方法和需要注意的小细节,每晚八点也会准时的讲一些前端的小案例项目。
实现一个new操作符
我们首先知道new做了什么:
- 创建一个空的简单JavaScript对象(即{});
- 链接该对象(即设置该对象的构造函数)到另一个对象 ;
- 将步骤(1)新创建的对象作为this的上下文 ;
- 如果该函数没有返回对象,则返回this。
知道new做了什么,接下来我们就来实现它
function create(Con, ...args){
// 创建一个空的对象
this.obj = {};
// 将空对象指向构造函数的原型链
Object.setPrototypeOf(this.obj, Con.prototype);
// obj绑定到构造函数上,便可以访问构造函数中的属性,即this.obj.Con(args)
let result = Con.apply(this.obj, args);
// 如果返回的result是一个对象则返回
// new方法失效,否则返回obj
return result instanceof Object ? result : this.obj;
}
实现一个Array.isArray
思路很简单,就是利用Object.prototype.toString
Array.myIsArray = function(o) {
return Object.prototype.toString.call(Object(o)) === '[object Array]';
};
实现一个Object.create()方法
function create = function (o) {
var F = function () {};
F.prototype = o;
return new F();
};
实现一个EventEmitter
真实经历,最近在字节跳动的面试中就被面试官问到了,要求手写实现一个简单的Event类。
class Event {
constructor () {
// 储存事件的数据结构
// 为查找迅速, 使用对象(字典)
this._cache = {}
}
// 绑定
on(type, callback) {
// 为了按类查找方便和节省空间
// 将同一类型事件放到一个数组中
// 这里的数组是队列, 遵循先进先出
// 即新绑定的事件先触发
let fns = (this._cache[type] = this._cache[type] || [])
if(fns.indexOf(callback) === -1) {
fns.push(callback)
}
return this
}
// 解绑
off (type, callback) {
let fns = this._cache[type]
if(Array.isArray(fns)) {
if(callback) {
let index = fns.indexOf(callback)
if(index !== -1) {
fns.splice(index, 1)
}
} else {
// 全部清空
fns.length = 0
}
}
return this
}
// 触发emit
trigger(type, data) {
let fns = this._cache[type]
if(Array.isArray(fns)) {
fns.forEach((fn) => {
fn(data)
})
}
return this
}
// 一次性绑定
once(type, callback) {
let wrapFun = () => {
callback.call(this);
this.off(type, wrapFun); // 执行完以后立即解绑
};
this.on(type, wrapFun); // 绑定
return this;
}
}
let e = new Event()
e.on('click',function(){
console.log('on')
})
// e.trigger('click', '666')
console.log(e)