首页 > 热乎美团前端面经
头像
小明爱学习
编辑于 2020-12-29 14:14
+ 关注

热乎美团前端面经

  1. js 中 this指向问题:
var a = 1; 
var b = { c: function ()
 { console.log(this.a); }, 
d: () => { console.log(this.a); } };
 b.d.bind({ a: 2 }); 
var fun = b.c; 
fun(); 
b.c(); 
b.d(); 

第一个func应该是隐式类型绑定,this指向window,
window.func() =>1
第三个箭头函数本身不含有this,绑定的是定义时候的上下文,=> 1;
第二个显式绑定,this指向b,b没有a属性打印undefined
2. 事件轮询机制:

console.log(1) 
setTimeout(() => {
 console.log(2) 
Promise.resolve().then(() => {
console.log(3) }) })
 new Promise((resolve) => { 
console.log(4) 
setTimeout(() => { 
console.log(5) resolve(); }, 2);
 }).then(res => { 
console.log(res) }); 

// 1 4 2 3 5 undefined
3. 手写promsie.all

function all(promises){ 
const values = []; 
return new Promise((resolve, reject)=>
 { promises.forEach(
(promise, index)=> 
{ promise.then((value)=>{ 
//values.push(value); 
values[index] = value; 
if(values.length == promises.length){ 
resolve(values); } },
 reason => { reject(reason); })
 })
 }) 
3.// 环形链表判断:
  1. 说了快慢指针
    // 对象是否有循环引用
    // 没搞清楚这个题目:
//line=readline() 
//print(line) 
var a = { b: { c: { d: a } } } 
function refCycle(obj){ 
for(let key in obj){ 
if(obj[key] == obj){ 
return true; } else{ 
refCycle(obj[key]); } 
} } 
console.log(refCycle(a)) 
function fn(object) {
// 首先判断 object 是否存在于 map.keys 中 
if (Array.from(map.keys()).includes(object)) 
{ // 如果存在则取出值并返回 return map.get(object); } 
var cloneObj = {}; 
// 设置 object 为 key,cloneObj 为值 
map.set(object, cloneObj); 
for (var key in object) { 
// 赋予新对象相应的 property 
// 通过递归调用来拷贝 property 的值
 cloneObj[key] = fn(object[key]); 
} 
// 返回新对象 return cloneObj;
 } 
var obj = {}; 
obj.a = obj; 
var map = new Map(); 
fn(obj); 

博客地址: https://blog.csdn.net/weixin_33738982/article/details/91414115?ops_request_misc=%25257B%252522request%25255Fid%252522%25253A%252522160920791616780271113414%252522%25252C%252522scm%252522%25253A%25252220140713.130102334…%252522%25257D&request_id=160920791616780271113414&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2allsobaiduend~default-1-91414115.nonecase&utm_term=%E5%AF%B9%E8%B1%A1%E5%BE%AA%E7%8E%AF%E5%BC%95%E7%94%A8

  1. 手写一个flat函数
    刚开始写了一个版本:
Array.prototype.flat1 = 
function (arr, n){ 
let newArr = new Array(); 
for(let i = 0; i < arr.length; i++)( 
if(typeof(arr[i]) !== "object" && n-- > 0){
 newArr = newArr.concat(this.flat1(arr[i]));
 } else { 
newArr.push(arr[i]); } ) 
return newArr;
 }
 var flat = function(arr, depth){ 
let res = [], depthArg = depth || 1,
 depthNum = 1, 
flatMap = (arr) => { 
arr.map((element, index, array) => 
{ if(Object.prototype.toString(element).slice(8,-1) === "Array") 
{ if(depthNum < depthArg) {
 depthNum++; 
flatMap(element); } else 
{ res.push(element); 
if(index === array.length - 1) 
depthNum = 0; } } }) }; 
flatMap(arr); return res; }; 
let arr = [[1], [[2]], [3]]; 
console.log(flat(arr)); 
// [1,[2], [3]]
5.hash模式和history模式的实现原理
  1. 监听hash的改变:
<!DOCTYPE html> <html lang="en">
 <head> <meta charset="UTF-8"> 
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title>
 </head> <body> <div id="app"> 
<a href="#/home">首页</a> 
<a href="#/about">关于</a> 
</div> <div class="router-view">
</div> <script> 
// 获取router-view的dom const routerViewEl =
 document.getElementsByClassName("router-view")[0];
 // 监听url的改变 window.addEventListener("hashchange", () => 
{ switch (location.hash) { 
case "#/home": 
routerViewEl.innerHTML = "首页";
 break; 
case "#/about": routerViewEl.innerHTML = "关于";
 break; 
default: routerViewEl.innerHTML = ""; } }); // html5 中的history // history接口是HTML5新增加的,它有六种模式改变url而不刷新页面 // replaceState: 替换原来的路径 // pushState: 使用新的路径 // popState: 路径的回退 // go: 向前或向后 forward: 向 1. 获取router-view的dom 
const routerViewEl = 
document.getElementsByClassName("router-view")[0]; 
2.histort新增加api
// 获取所有的a元素,自己来监听a元素的改变 
const aEls = document.getElementsByTagName("a"); 
for (let el of aEls) 
{ el.addEventListener("click", 
e => { e.preventDefault(); 
const href = el.getAttribute("href");
 history.pushState({}, "", href); 
urlChange(); // history.go(-1) 
// history.back(); 
// urlChange(); }) } 
// 执行返回操作时候,依然来到urlChange
 window.addEventListener('popstate', urlChange);
 // window.addEventListener("go", urlChange);
 // window.addEventListener("pushState", urlChange); 
// 监听URL的改变 function urlChange() { 
console.log(location.pathname);
 switch (location.pathname) {
 case "/home": routerViewEl.innerHTML = "首页";
 break; 
case "/about": 
routerViewEl.innerHTML = "关于"; 
break; 
default: routerViewEl.innerHTML = ""; 
} };
  1. 实现数组的slice方法:
Array.prototype.slice = 
function(start, end){ 
let len = this.length; 
let l = start === undefined ? 0 : 
start < 0 ? Math.max(start + len, 0) : 
Math.min(start, len);
 let r = end === undefined ? len : end < 0 ?
 Math.max(end + len, 0) : 
Math.min(end, len); 
const res = []; while(l < r) 
{ res.push(this[l++]);
 } 
return res; }
  1. 判断数据类型3种方法,实现instaneOf
const instance_of = (left, rigth) =>
 { const baseType = ['number', 'string', 'boolean', 'undefined', 'symbol'];
 const RP = right.prototype; 
while(true){ if(left == null) { 
return false; } else if 
(left == RP) { return true; } 
left = left.__proto__; 
} }

更多模拟面试

全部评论

(7) 回帖
加载中...
话题 回帖

推荐话题

相关热帖

近期热帖

近期精华帖

热门推荐