北京小米前端实习一面面经
约的3.18 上午11点面试,面试官也提前几分钟进入面试房间了,好评
一共面了一个小时
上来是自我介绍,问了点项目上的问题
然后开始提问问题
1. css实现一个扇形
不会
2. css优先级
!important > 内联样式 > id选择器 > 类选择器 > 标签选择器
伪元素、伪类及他们的优先级 ?
3.三栏自适应布局
flex实现了一版,浮动的忘记了,参考下面的
4.js evenLoop
主任务调用栈、宏任务、微任务队列
js程序顺序执行,遇到异步任务放到相应的队列中去,主调用栈执行完了,就去清空微任务队列,再去执行宏任务队列里的任务,若有微任务继续放入微任务队列进行循环
为什么会有宏任务和微任务?
看几个代码的执行输出
async function async1() { console.log("async1 start"); //2 await async2(); console.log("async1 end"); //6 } async function async2() { console.log("async2"); //3 } console.log("script start"); //1 setTimeout(function () { console.log("setTimeout"); //8 }, 0); async1(); new Promise(function (resolve) { console.log("promise1"); //4 resolve(); }).then(function () { console.log("promise2"); //7 }); console.log("script end"); //5 调用栈 script start async1 start async2 promise1 script end 宏任务 setTimeout 微任务 async1 end promise2问async原理知道嘛,回答生成器函数加了自动执行
const a = () => new Promise((resolve) => setTimeout(() => { console.log("a"), resolve(); }, 1e3) ); const b = () => new Promise((resolve) => setTimeout(() => { console.log("b"); resolve(); console.log("bb"); }, 1e3) ); const c = () => new Promise((resolve, reject) => setTimeout(() => { console.log("c"), reject("Oops!"); }, 1e3) ); const d = () => new Promise((resolve, reject) => setTimeout(() => { console.log("d"), resolve("hello"); }, 1e3) ); Promise.resolve() .then(a) .then(b) .then(c) .then(d) .catch(console.error) .finally(() => console.log("always")); a b bb c Oops always
5. js数据类型,判断方法
Mdn上给了八种,Number、Bollean、String、Symbol、BigInt、Null、Undefined、Object
然后说基本数据类型与引用数据类型的区别
判断方法:
typeof 对于null、date、array不能精确识别
instanceof 不能识别基本数据类型
Object.prototype.toString.call()
6.call方法实现
//call 函数实现了两点 //1. 改变了this指向 //2. 函数执行了 //可以给对象增加对应函数,调用函数后再删除掉 Function.prototype.myCall = function(context) { if(typeof this !== "function") { throw new Error(this + "must be a function") } //首先获取参数 let args = [...arguments].slice(1); //arguments 为类数组对象 let result = null; //判断context是否传入,没有则设置为window context = context || window; //this即为要执行的函数 const fnSymbol = Symbol(); context[fnSymbol] = this; //执行函数 result = context[fnSymbol](...args); //手动删除属性 delete context[fnSymbol]; //返回函数执行结果 return result; } var obj = { value: "vortesnail", }; function fn(a, b) { console.log(this.value); console.log(a, b) } fn.call(obj, 1, 2); fn.myCall(obj, 1, 2);
7. let /const /var
var存在问题
1.变量提升 (更准确点是申明提升)
2.变量覆盖
3.没有块级作用域
1.变量提升 (更准确点是申明提升)
2.变量覆盖
3.没有块级作用域
let解决了以上问题
const则是声明常量,不可更改,但const声明的数组、对象的值可以更改,因为是引用类型,地址不变就行
8.vue 双向绑定原理
vue2.x 发布订阅模式 + Object.defineProterty实现
详细问defineProterty
问数组监听怎么实现嘛,回答改写了能改变数组的那七个方法、pop、push、shift、unshift、splice、reverse、sort
直接监听数组下标不行嘛,答约可以,但是性能会浪费,vue 有人提过issue,尤大回复就是因为性能原因没有这样做
vue3 升级为proxy直接代理对象,按需加载,对于data里新增的属性和嵌套深的对象属性的双向绑定都更加快和方便了
9.数组扁平化
//递归解法 function my_faltten(arr) { let ans = []; for(let item of arr) { if(Array.isArray(item)) { let temp = my_faltten(item); for(let it of temp) ans.push(it); }else { ans.push(item); } } return ans; }让再写非递归解法,提示用reduce,不太会,下面链接讲得比较清楚
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/flat
10.v-model原理
<html> <body> <input placeholder="请输入名字" id="username"/><br> 显示值:<p id="uName"></p> <script> let obj = {}; Object.defineProperty(obj, "username",{ get: function() { console.log("取值"); }, set: function(val) { //对象属性劫持,将其值绑定到p元素 console.log("设置值"); document.getElementById("uName").innerText = val; } }) document.getElementById("username").addEventListener("keyup", function() { //监听键盘输入事件,将其值绑定到obj.username obj.username = event.target.value; }) </script> </body> </html>面试官说到v-model只是语法糖,vue源码读过嘛,知不知道它是怎么实现的?真不知道
11.反问环节
公司业务及技术栈
因为css答的不好,问公司css要求很高嘛,答约只是考察基础,所以之后css还是得手写下常考的呀!