北京小米前端实习一面面经
约的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还是得手写下常考的呀!
