热乎美团前端面经
- 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.// 环形链表判断:
- 说了快慢指针
// 对象是否有循环引用
// 没搞清楚这个题目:
//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
- 手写一个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模式的实现原理
- 监听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 = "";
} };
- 实现数组的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; }
- 判断数据类型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__;
} }#美团##校招##前端工程师##面经#