面试十题(4)

1. 介绍下 BFC 及其应用。

BFC 就是块级格式上下文,是页面盒模型布局中的一种 CSS 渲染模式,相当于一个独立的容器,里面的元素和外部的元素相互不影响。

  • 创建 BFC 的方式有:
  1. html 根元素
  2. float 浮动
  3. 绝对定位
  4. overflow 不为 visiable
  5. display 为表格布局或者弹性布局
  • BFC 主要的作用是:
  1. 清除浮动
  2. 防止同一 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?

  1. Object.defineProperty 无法监控到数组下标的变化,导致通过数组下标添加元素,不能实时响应;
  2. Object.defineProperty 只能劫持对象的属性,从而需要对每个对象,每个属性进行遍历,如果,属性值是对象,还需要深度遍历。Proxy 可以劫持整个对象,并返回一个新的对象。
  3. 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)

 

面试十题(4)

上一篇:OCP 063中文考试题库(cuug内部资料)第26题


下一篇:Knife4j快速上手