面试十题(4)
1. 介绍下 BFC 及其应用。
BFC 就是块级格式上下文,是页面盒模型布局中的一种 CSS 渲染模式,相当于一个独立的容器,里面的元素和外部的元素相互不影响。
- 创建 BFC 的方式有:
- html 根元素
- float 浮动
- 绝对定位
- overflow 不为 visiable
- display 为表格布局或者弹性布局
- BFC 主要的作用是:
- 清除浮动
- 防止同一 BFC 容器中的相邻元素间的外边距重叠问题
2. 在 Vue 中,子组件为何不可以修改父组件传递的 Prop?如果修改了,Vue 是如何监控到属性的修改并给出警告的。
-
因为vue设计是单向数据流,数据的流动方向只能是自上往下的方向;但是反过来则不行。这样会防止从子组件意外变更父级组件的状态,从而导致你的应用的数据流向难以理解。额外的,每次父级组件发生变更时,子组件中所有的 prop 都将会刷新为最新的值。这意味着你不应该在一个子组件内部改变 prop。如果你这样做了,Vue 会在浏览器的控制台中发出警告。
-
在initProps的时候,在defineReactive时通过判断是否在开发环境,如果是开发环境,会在触发set的时候判断是否此key是否处于updatingChildren中被修改,如果不是,说明此修改来自子组件,触发warning提示。
-
需要特别注意的是,当你从子组件修改的prop属于基础类型时会触发提示。 这种情况下,你是无法修改父组件的数据源的, 因为基础类型赋值时是值拷贝。你直接将另一个非基础类型(Object, array)赋值到此key时也会触发提示(但实际上不会影响父组件的数据源), 当你修改object的属性时不会触发提示,并且会修改父组件数据源的数据。
3. js 实现sleep函数
- es6 异步处理
// promise
const sleep = time => {
return new Promise(resolve => setTimeout(resolve, time))
}
sleep(1000).then(() => {
console.log('业务代码')
})
// async/await
const sleepPromise = (time) => {
return new Promise((resolve, reject) => {
setTimeout(resolve, time);
})
}
async function sleep (time) {
await sleepPromise(time);
console.log('业务代码')
}
sleep(5000)
// generator
const sleepPromise = (time) => {
return new Promise((resolve, reject) => {
setTimeout(resolve, time);
})
}
function* sleep(time) {
yield sleepPromise(time);
}
sleep(5000).next().value.then(()=>{
console.log('业务代码')
})
- 伪死循环
function sleep(delay) {
var start = (new Date()).getTime();
while ((new Date()).getTime() - start < delay) {
continue;
}
}
console.log('1')
sleep(5000)
console.log('2')
- 定时器+回调函数
function sleep(time, callback) {
setTimeout(callback, time)
}
sleep(time, () => {
console.log('业务代码')
})
4. 双向绑定和 vuex 是否冲突
5. 为什么通常在发送数据埋点请求的时候使用的是 1x1 像素的透明 gif 图片?
- 能够完成整个 HTTP 请求+响应(尽管不需要响应内容)
- 触发 GET 请求之后不需要获取和处理数据、服务器也不需要发送数据
- 跨域友好
- 执行过程无阻塞,只要 new Image 对象就好了,一般情况下也不需要 append 到 DOM 中,通过它的 onerror 和 onload 事件来检测发送状态。
- 相比 XMLHttpRequest 对象发送 GET 请求,性能上更好
- GIF 的最低合法体积最小(最小的 BMP 文件需要 74 个字节,PNG 需要 67 个字节,而合法的 GIF,只需要 43 个字节)
6. 实现 (5).add(3).minus(2) 功能。
- 方法一
Number.prototype.add = function (number) {
if (typeof number !== 'number') {
throw new Error('请输入数字~');
}
return this.valueOf() + number;
};
Number.prototype.minus = function (number) {
if (typeof number !== 'number') {
throw new Error('请输入数字~');
}
return this.valueOf() - number;
};
console.log((5).add(3).minus(2));
- 方法二
// 这里的~写成加号+ 减号- 都可以。但必须是一元表达式
// 匿名函数前面加~一元运算符就会转变成函数表达式,函数表达式后面加()
~ function(){
function add(n){
return this + n
}
function minus(n){
return this - n
}
Number.prototype.add = add
Number.prototype.minus = minus
}()
console.log((5).add(3).minus(2))
- 方法三
function addmin(){
function add(n){
return this + n
}
function minus(n){
return this - n
}
Number.prototype.add = add
Number.prototype.minus = minus
}
addmin()
console.log((5).add(3).minus(2))
7. Vue 的响应式原理中 Object.defineProperty 有什 么缺陷? 为什么在 Vue3.0 采用了 Proxy,抛弃了 Object.defineProperty?
- Object.defineProperty 无法监控到数组下标的变化,导致通过数组下标添加元素,不能实时响应;
- Object.defineProperty 只能劫持对象的属性,从而需要对每个对象,每个属性进行遍历,如果,属性值是对象,还需要深度遍历。Proxy 可以劫持整个对象,并返回一个新的对象。
- Proxy 不仅可以代理对象,还可以代理数组。还可以代理动态增加的属性。
补充回答:Object.defineProperty 本身有一定的监控到数组下标变化的能力,但是在 Vue 中,从性能/体验的性价比考虑,尤大大就弃用了这个特性。
8. div 水平垂直居中
- 方法一
// 父元素
box {
display: flex;
justify-content: center;
align-items: center;
}
- 方法二
// 绝对定位
.div {
width: 200px;
height: 200px;
background: green;
position:absolute;
left:0;
top: 0;
bottom: 0;
right: 0;
margin: auto;
}
- 方法三
// margin 负间距
div {
width:200px;
height: 200px;
background:green;
position: absolute;
left:50%;
top:50%;
margin-left:-100px;
margin-top:-100px;
}
- 方法四
// transform 变形
div {
width: 200px;
height: 200px;
background: green;
position:absolute;
left:50%; /* 定位父级的50% */
top:50%;
transform: translate(-50%,-50%); /*自己的50% */
}
9. 下面代码执行结果及原因
var a = {n:1}
var b = a;
a.x = a = {n:2}
console.log(a.x) // undefined
console.log(b.x) // {n: 2}
考察运算符的优先级,虽然赋值是从右往左,但是.的运算符比=的优先级高。所以先执行a.x = {n: 2}再执行a = {n: 2}
10. 冒泡排序如何实现,时间复杂度是多少, 还可以如何改进?
- 冒泡排序
var a = [11,2,55,123,88,3,67];
function bubbleSort(arr) {
console.time('time')
for (var i = 0; i < arr.length; i++) {
for (var j = 0; j < arr.length - i - 1; j++) {
if (arr[j] > arr[j + 1]){
let temp = arr[j]
arr[j] = arr[j + 1]
arr[j + 1] = temp
}
}
}
console.timeEnd('time')
console.log(arr)
return arr
}
bubbleSort(a)
- 改进冒泡排序
var a = [11,2,55,123,88,3,67];
function bubbleSort1(arr) {
console.time('time')
var i = arr.length - 1;
while(i > 0) {
let pos = 0;
for (var j = 0; j < i; j++) {
if (arr[j] > arr[j + 1]) {
pos = j
let temp = arr[j]
arr[j] = arr[j + 1]
arr[j + 1] = temp
}
}
i = pos
}
console.timeEnd('time')
console.log(arr)
return arr
}
bubbleSort1(a)