Web开发

首页 » 常识 » 预防 » 2020Web前端面试题汇总开课吧
TUhjnbcbe - 2023/8/31 20:23:00
白癜风用什么药最好 http://pf.39.net/bdfyy/qsnbdf/140805/4440899.html
Web前端面试题

本文收录了一些在Web前端开发面试中经常会遇到的面试题及答案,希望对大家有所帮助,若有所疏漏欢迎指正。

问题:模拟new

解析:new操作符做了这些事:

它创建了个全新的对象

它会被执行[[Prototype]](也就是proto)链接

它使this指向新创建的对象

通过new创建的每个对象将最终被[[Prototype]]链接到这个函数的prototype对象上

如果函数没有返回对象类型Object(包含Functoin,Array,Date,RegExg,Error),那么new表达式中的函数调用将返回该对象引用

//objectFactory(name,cxk,18)

functionobjectFactory(){

constobj=newObject();

constConstructor=[].shift.call(arguments);

obj.proto=Constructor.prototype;

constret=Constructor.apply(obj,arguments);

returntypeofret===object?ret:obj;

}

问题:实现instanceOf

解析://模拟instanceof

functioninstance_of(L,R){

//L表示左表达式,R表示右表达式

varO=R.prototype;//取R的显示原型

L=L.proto;//取L的隐式原型

while(true){

if(L===null)returnfalse;

if(O===L)

//这重点:当O严格等于L时,返回true

returntrue;

L=L.proto;

}

}

问题:实现Event(eventbus)

解析:eventbus既是node中各个模块的基石,又是前端组件通信的依赖手段之,同时涉及了订阅-发布设计模式,是非常重要的基础。

简单版:

classEventEmeitter

{constructor(){

this._events=this._events

newMap();//储存事件/回调键值对

this._maxListeners=this._maxListeners

10;//设立监听上限

}

}

//触发名为type的事件

EventEmeitter.prototype.emit=function(type,...args)

{lethandler;

//从储存事件键值对的this._events中获取对应事件回调函数

handler=this._events.get(type);

if(args.length0){

handler.apply(this,args);

}else

{handler.call(this);

}

returntrue;

};

//监听名为type的事件

EventEmeitter.prototype.addListener=function(type,fn){

//将type事件以及对应的fn函数放入this._events中储存

if(!this._events.get(type))

{this._events.set(type,fn);

}

};

试版:

classEventEmeitter

{constructor(){

this._events=this._events

newMap();//储存事件/回调键值对

this._maxListeners=this._maxListeners

10;//设立监听上限

}

}

//触发名为type的事件

EventEmeitter.prototype.emit=function(type,...args)

{lethandler;

//从储存事件键值对的this._events中获取对应事件回调函数

handler=this._events.get(type);

if(args.length0){

handler.apply(this,args);

}else

{handler.call(this);

}

returntrue;

};

//监听名为type的事件

EventEmeitter.prototype.addListener=function(type,fn){

//将type事件以及对应的fn函数放入this._events中储存

if(!this._events.get(type))

{this._events.set(type,fn);

}

};

//触发名为type的事件

EventEmeitter.prototype.emit=function(type,...args)

{lethandler;

handler=this._events.get(type);

if(Array.isArray(handler)){

//如果是个数组说明有多个监听者,需要依次此触发里面的函数

for(leti=0;ihandler.length;i++)

{if(args.length0){

handler.apply(this,args);

}else

{handler.call(this);

}

}

}else{

//单个函数的情况我们直接触发即可

if(args.length0)

{handler.apply(this,args);

}else

{handler.call(this);

}

}

returntrue;

};

//监听名为type的事件

EventEmeitter.prototype.addListener=function(type,fn){

consthandler=this._events.get(type);//获取对应事件名称的函数清单

if(!handler)

{this._events.set(type,fn);

}elseif(handlertypeofhandler===function){

//如果handler是函数说明只有个监听者

this._events.set(type,[handler,fn]);//多个监听者我们需要数组储存

}else{

handler.push(fn);//已经有多个监听者,那么直接往数组里push函数即可

}

};

EventEmeitter.prototype.removeListener=function(type,fn)

{consthandler=this._events.get(type);//获取对应事件名称的函数清单

//如果是函数,说明只被监听了次

if(handlertypeofhandler===function)

{this._events.delete(type,fn);

}else{

letpostion;

//如果handler是数组,说明被监听多次要找到对应的函数

for(leti=0;ihandler.length;i++)

{if(handler===fn){

postion=i;

}else

{postion=-

1;

}

}

//如果找到匹配的函数,从数组中清除

if(postion!==-1){

//找到数组对应的位置,直接清除此回调

handler.splice(postion,1);

//如果清除后只有个函数,那么取消数组,以函数形式保存

if(handler.length===1)

{this._events.set(type,

handler[0]);

}

}else

{return

this;

}

}

1