小滴课堂22年新版互联网大厂前端高频面试题(9)~持续更新中


前言

小滴课堂,旨在让编程不在难学,让技术与生活更加有趣。 随着互联网+的时代,在线教育技术越来越便捷,小滴课堂依托在线教育时间以及空间上的便利,为广大IT从业者提供了更为方便、快捷的学习交流途径、提供大量高质量的IT在线课程。更多教程请访问xdclass.net(添加VX:xdclass99)

一、说说你对JS中的原型链的理解

回答

(一)思路

  1. 原型( prototype )

(1)是function对象的⼀个属性,它定义了构造函数制造出的对象的公共祖先,通过该构造函数产⽣的对象,可以继承该原型的属性和⽅法,原型也是对象

function Person() {}
Person.prototype.name = '⼤钊';
Person.prototype.a = function () {
  console.log(11);
};

var person1 = new Person();

console.log(person1.name);
person1.a();

(2)作用

  • 构造函数实例化出来的对象可以使⽤公共的属性或者⽅法
  1. 函数对象才有 prototype 属性

  2. 原型链

(1)js里万物皆对象,所以⼀直访问 proto 属性就会产⽣⼀条链条

(2)链条的尽头是null (Object.prototype. proto )

(3)当js引擎查找对象的属性时,会先判断对象本身是否存在该属性

(4)不存在的属性就会沿着原型链往上找

在这里插入图片描述

function Car() {}
Car.prototype.name = '⼤钊';
var car = new Car();
  1. 总结

(1)原型主要是解决继承问题

(2)每个对象拥有⼀个原型对象,通过 proto 指针指向其原型对象,并从中继承⽅法和属性

(3)同时原型对象也可能拥有原型,这样⼀层⼀层,最终指向 null(Object.proptotype.proto指向的是null)

(4)上述的关系被称为原型链,通过原型链⼀个对象可以拥有定义在其他对象中的属性和⽅法

二、说说你对重绘和重排的理解和如何避免?

回答

(一)思路

  1. 重绘
  • 当元素的外观、背景、颜⾊等改变,浏览器会根据元素的新属性重新绘制,使元素呈现新的外观叫做重绘
  1. 重排
  • 当渲染树⼀部分或者全部因为⼤⼩或者边距⽽改变,需要渲染树重新计算的过程叫做重排
  • 重绘不⼀定需要重排,重排必然导致重绘
  1. 避免
  • 在元素的显示隐藏上尽量用 opacity 替代 visibility(重绘)
  • 元素定位时使用 transform 代替top、left(重排)
  • 尽量不使用 table 布局,因为⼀个⼩的改动会造成整个 table 重新布局(重排)
  • 减少直接操作DOM元素(重排)
  • 为元素添加类,样式都在类中改变(重绘)

三、说下vue的响应式原理是如何实现的?

回答

(一)思路

  1. 原理( Object.defineProperty() )
  • 通过⼀个对象代理另⼀个对象属性的读写
Object.defineProperty('代理对象', '代理属性', {
 get() { // getter 当读取’⽬标对象‘的’代理属性‘时,get函数/getter
就会被调⽤,且返回代理属性的值
 return xxx; 
 },
 set(value) { // setter 当修改’⽬标对象‘的’代理属性‘时,set函 数/setter就会被调⽤,且收到修改的值
   xxx;
 },
});
let obj1 = {
  a: 111,
};
let obj2 = {};
Object.defineProperty(obj2, 'a', {
  get() {
    console.log('obj2被读取了');
    return obj1.a;
 },
 set(value) {
   console.log('obj2被修改了');
   obj1.a = value;
 },
});
  1. Vue中应⽤的数据代理

在这里插入图片描述

(1)通过vm对象属性代理 _data 中属性的读写

(2)能更加⽅便的读写vue中data的数据

(3)通过 Object.defineProperty() 把 data 中的属性添加到vm对象上,每个属性都有setter/getter

  1. 连环问
  • 说下vue3的响应式原理是如何实现的,为什么?

(1)Object.defineProperty

  • 无法监听新增属性和删除属性,使⽤this.$set
  • 深层对象的劫持需要递归
  • 劫持数组时需要重写数组原⽣操作⽅法
  • 只是对对象的属性进行劫持

(2)Proxy

  • 概述

    • 正如Proxy的英译"代理"所示,Proxy是ES6为了操作对象引入的API。它不直接作⽤在对象上,而是作为⼀种媒介,如果需要操作对象的话,需要经过这个媒介的同意。
  • 使用方式

let p = new Proxy(target, handler)
//target: 目标对象
//handler: 对对象进行拦截操作的函数,如set、get
  • 使用场景
const house = {
  name: '张三',
  price: '1000',
  phone: '18823139921',
  id: '111',
  state: '**',
};

const houseProxy = new Proxy(house, {
  // 读取代理
  get: function (target, key) {
    switch (key) {
      case 'phone':
        return '抱歉,不能告知'
      default:
        return Reflect.get(target,key);
    }
  },
  // 设置代理
  set: function (target, key, value) {
    if (key === 'id') {
      return Reflect.get(target,key); 
    } else if (key === 'state') {
      return Reflect.set(target,key,value);
    }
  },
});

console.log(houseProxy.price);
console.log(houseProxy.phone);

houseProxy.id = '222';
houseProxy.state = '****';
console.log(houseProxy.id);
console.log(houseProxy.state);
  • Reflect(映射)
    • 规范化、语义化
    • ES6规范中为了操作对象更加趋向于编程式(函数式)
    • 减少异常的抛出,因为对象的属性有可能是个getter或者setter
    • Reflect对象的方法与Proxy对象的⽅法⼀⼀对应

四、谈谈对Promise的理解

回答

(一)前置知识

  1. 同步
  • 同步的思想是:所有的操作都做完,才返回给用户。这样⽤户在线等待的时间太长,给用户⼀种卡死了的感觉,这种情况下,用户不能关闭界面,如果关闭了,程序就中断了。
  1. 异步
  • 将⽤户请求放⼊消息队列,并反馈给⽤户,程序已经启动,你可以关闭浏览器了。这就是异步。但是⽤户没有卡死的感觉,会告诉你,你的请求程序已经响应了。你可以关闭界⾯了。

  • 通俗的解释就是打电话和发短信的区别。

  • 打电话时,对方挂了电话,通信也就中断了,而发短信时,无需考虑对⽅在不在线,都能进行通信。

(二)概述

  • Promise是⼀种⽤于解决异步问题的思路、⽅案或者对象⽅式。

(三)原理

  • 在Promise的内部,有⼀个状态管理器的存在,有三种状态:pending、fulfifilled、rejected。

    • Promise 对象初始化状态为 pending。
    • 当调用resolve(成功),会由pending => fulfifilled。
    • 当调用reject(失败),会由pending => rejected.
  • 需要记住的是注意promsie状态 只能由 pending => fulfifilled/rejected, ⼀旦修改就不能再变(记住,⼀定要记住,下⾯会考到)。

  • 当状态为fulfifilled(rejected反之)时,then的成功回调函数会被调⽤,进⽽进⾏操作。Promise.then⽅法每次调⽤,都返回⼀个新的Promise对象 所以可以链式写法(无论resolve还是reject都是这样)。

(四)总结

  • ⾸先,Promise是⼀个对象,如同其字面意思⼀样,代表了未来某时间才会知道结果的时间,不受外界因素的印象。Promise⼀旦触发,其状态只能变为fulfifilled或者rejected,并且已经改变不可逆转。Promise的构造函数接受⼀个函数作为参数,该参数函数的两个参数分别为resolve和reject,其作⽤分别是将Promise的状态由pending转化为fulfifilled或者rejected,并且将成功或者失败的返回值传递出去。then有两个函数作为Promise状态改变时的回调函数,当Promise状态改变时接受传递来的参数并调用相应的函数。then中的回调的过程为异步操作。catch⽅法是对.then(null,rejectFn)的封装(语法糖),用于指定发生错误时的回掉函数。⼀般来说,建议不要再then中定义rejected状态的回调函数,应该使用catch⽅法代替。all和race都是竞速函数,all结束的时间取决于最慢的那个,其作为参数的Promise函数⼀旦有⼀个状态为rejected,则总的Promise的状态就为rejected;而race结束的时间取决于最快的那个,⼀旦最快的那个Promise状态发⽣改变,那个其总的Promise的状态就变成相应的状态,其余的参数Promise还是会继续进行的。

  • 当然在es7时代,也出现了await/async的异步方案,这会是我们以后谈论的。

五、谈谈你对css盒子模型的理解

回答

  • css盒子模型分为标准W3C盒子模型和IE盒子模型
  • css盒子模型组成由外边距(margin)、边框(border)、内边距(padding)和内容(content)。

(一)标准W3C盒⼦模型:

在这里插入图片描述

  1. 如上图,在W3C盒⼦模型中:
  • css设置的宽(width)=内容(content)的宽
  • css设置的高(height)= 内容(content)的高
  1. 也就是我们正常给标签设置的宽高,这个时候是标准的盒子模型。举个例⼦:
<div style="width:100px;height:100px;padding:10px;border:1px solid
#000;margin:10px;">helloworld</div>
  1. 此时div的实际大小应该是这样:
盒子总宽度/高度=width/height+padding+border+margin。

在这里插入图片描述

  1. 从上图可以看到蓝色部分(content内容)的宽⾼就是我们设置的css宽高。

(二)IE盒子模型:

在这里插入图片描述

  1. 如上图,在IE模型中:
  • css设置的宽(width)=内容(content)的宽 + 左右padding + 左右border
  • css设置的高(height)=内容(content)的⾼高+ 上下padding + 上下border
  1. 在这里content的宽是<css设置的宽度的,在同样的例子下:
//这里需要另外加上box-sizing:border-box将标准盒子模型转换为IE盒子模型
<div style="width:100px;height:100px;padding:10px;border:1px solid
#000;margin:10px;box-sizing:border-box">helloworld</div>
  1. 此时div的实际大小应该是:
盒子总宽度/高度=width/height + margin = 内容区宽度/高度 + padding + border + margin

在这里插入图片描述

  1. 如上图,这个时候可以看到content的内容宽高变成了78✖78,⽽不是我们设置的width和height,content⼤⼩可通过上面计算公式那样计算出来。

(三)总结:

  • 讲到这里⼤家应该对两个盒⼦模型的区别有了⼀定了解,具体使用情况可以根据⾃⼰需要进⾏调整,⽐如想在div宽高不变的情况下调整padding,这样可以避免影响到布局。
  • 最后,我们如何转换标准盒⼦和IE盒⼦,这⾥可以运用box-sizing属性来定义,如下图:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值