写点什么

2023 前端二面经典面试题汇总

作者:loveX001
  • 2023-02-21
    浙江
  • 本文字数:10254 字

    阅读完需:约 34 分钟

如何避免 React 生命周期中的坑

16.3 版本



>=16.4 版本



在线查看https://projects.wojtekmaj.pl/react-lifecycle-methods-diagram(opens new window)



  • 避免生命周期中的坑需要做好两件事:不在恰当的时候调用了不该调用的代码;在需要调用时,不要忘了调用。

  • 那么主要有这么 7 种情况容易造成生命周期的坑

  • getDerivedStateFromProps 容易编写反模式代码,使受控组件与非受控组件区分模糊

  • componentWillMount 在 React 中已被标记弃用,不推荐使用,主要原因是新的异步渲染架构会导致它被多次调用。所以网络请求及事件绑定代码应移至 componentDidMount 中。

  • componentWillReceiveProps 同样被标记弃用,被 getDerivedStateFromProps 所取代,主要原因是性能问题

  • shouldComponentUpdate 通过返回 true 或者 false 来确定是否需要触发新的渲染。主要用于性能优化

  • componentWillUpdate 同样是由于新的异步渲染机制,而被标记废弃,不推荐使用,原先的逻辑可结合 getSnapshotBeforeUpdatecomponentDidUpdate 改造使用。

  • 如果在 componentWillUnmount 函数中忘记解除事件绑定,取消定时器等清理操作,容易引发 bug

  • 如果没有添加错误边界处理,当渲染发生异常时,用户将会看到一个无法操作的白屏,所以一定要添加


“React 的请求应该放在哪里,为什么?” 这也是经常会被追问的问题。你可以这样回答。


对于异步请求,应该放在 componentDidMount 中去操作。从时间顺序来看,除了 componentDidMount 还可以有以下选择:


  • constructor:可以放,但从设计上而言不推荐。constructor 主要用于初始化 state 与函数绑定,并不承载业务逻辑。而且随着类属性的流行,constructor 已经很少使用了

  • componentWillMount:已被标记废弃,在新的异步渲染架构下会触发多次渲染,容易引发 Bug,不利于未来 React 升级后的代码维护。

  • 所以 React 的请求放在 componentDidMount 里是最好的选择


透过现象看本质:React 16 缘何两次求变?


Fiber 架构简析


Fiber 是 React 16 对 React 核心算法的一次重写。你只需要 get 到这一个点:Fiber 会使原本同步的渲染过程变成异步的


在 React 16 之前,每当我们触发一次组件的更新,React 都会构建一棵新的虚拟 DOM 树,通过与上一次的虚拟 DOM 树进行 diff,实现对 DOM 的定向更新。这个过程,是一个递归的过程。下面这张图形象地展示了这个过程的特征:



如图所示,同步渲染的递归调用栈是非常深的,只有最底层的调用返回了,整个渲染过程才会开始逐层返回。这个漫长且不可打断的更新过程,将会带来用户体验层面的巨大风险:同步渲染一旦开始,便会牢牢抓住主线程不放,直到递归彻底完成。在这个过程中,浏览器没有办法处理任何渲染之外的事情,会进入一种无法处理用户交互的状态。因此若渲染时间稍微长一点,页面就会面临卡顿甚至卡死的风险。


而 React 16 引入的 Fiber 架构,恰好能够解决掉这个风险:Fiber 会将一个大的更新任务拆解为许多个小任务每当执行完一个小任务时,渲染线程都会把主线程交回去,看看有没有优先级更高的工作要处理,确保不会出现其他任务被“饿死”的情况,进而避免同步渲染带来的卡顿。在这个过程中,渲染线程不再“一去不回头”,而是可以被打断的,这就是所谓的“异步渲染”,它的执行过程如下图所示:



换个角度看生命周期工作流


Fiber 架构的重要特征就是可以被打断的异步渲染模式。但这个“打断”是有原则的,根据“能否被打断”这一标准,React 16 的生命周期被划分为了 render 和 commit 两个阶段,而 commit 阶段又被细分为了 pre-commit 和 commit。每个阶段所涵盖的生命周期如下图所示:



我们先来看下三个阶段各自有哪些特征


  • render 阶段:纯净且没有副作用,可能会被 React 暂停、终止或重新启动。

  • pre-commit 阶段:可以读取 DOM。

  • commit 阶段:可以使用 DOM,运行副作用,安排更新。


总的来说,render 阶段在执行过程中允许被打断,而 commit 阶段则总是同步执行的。


为什么这样设计呢?简单来说,由于 render 阶段的操作对用户来说其实是“不可见”的,所以就算打断再重启,对用户来说也是零感知。而 commit 阶段的操作则涉及真实 DOM 的渲染,所以这个过程必须用同步渲染来求稳

CSS3 中有哪些新特性

  • 新增各种 CSS 选择器 (: not(.input):所有 class 不是“input”的节点)

  • 圆角 (border-radius:8px)

  • 多列布局 (multi-column layout)

  • 阴影和反射 (Shadoweflect)

  • 文字特效 (text-shadow)

  • 文字渲染 (Text-decoration)

  • 线性渐变 (gradient)

  • 旋转 (transform)

  • 增加了旋转,缩放,定位,倾斜,动画,多背景

transition 和 animation 的区别

  • transition 是过度属性,强调过度,它的实现需要触发一个事件(比如鼠标移动上去,焦点,点击等)才执行动画。它类似于 flash 的补间动画,设置一个开始关键帧,一个结束关键帧。

  • animation 是动画属性,它的实现不需要触发事件,设定好时间之后可以自己执行,且可以循环一个动画。它也类似于 flash 的补间动画,但是它可以设置多个关键帧(用 @keyframe 定义)完成动画。

JavaScript 中如何进行隐式类型转换?

首先要介绍ToPrimitive方法,这是 JavaScript 中每个值隐含的自带的方法,用来将值 (无论是基本类型值还是对象)转换为基本类型值。如果值为基本类型,则直接返回值本身;如果值为对象,其看起来大概是这样:


/*** @obj 需要转换的对象* @type 期望的结果类型*/ToPrimitive(obj,type)
复制代码


type的值为number或者string


(1)当typenumber时规则如下:


  • 调用objvalueOf方法,如果为原始值,则返回,否则下一步;

  • 调用objtoString方法,后续同上;

  • 抛出TypeError 异常。


(2)当typestring时规则如下:


  • 调用objtoString方法,如果为原始值,则返回,否则下一步;

  • 调用objvalueOf方法,后续同上;

  • 抛出TypeError 异常。


可以看出两者的主要区别在于调用toStringvalueOf的先后顺序。默认情况下:


  • 如果对象为 Date 对象,则type默认为string

  • 其他情况下,type默认为number


总结上面的规则,对于 Date 以外的对象,转换为基本类型的大概规则可以概括为一个函数:


var objToNumber = value => Number(value.valueOf().toString())objToNumber([]) === 0objToNumber({}) === NaN
复制代码


而 JavaScript 中的隐式类型转换主要发生在+、-、*、/以及==、>、<这些运算符之间。而这些运算符只能操作基本类型值,所以在进行这些运算前的第一步就是将两边的值用ToPrimitive转换成基本类型,再进行操作。


以下是基本类型的值在不同操作符的情况下隐式转换的规则 (对于对象,其会被ToPrimitive转换成基本类型,所以最终还是要应用基本类型转换规则):


  1. +操作符 +操作符的两边有至少一个string类型变量时,两边的变量都会被隐式转换为字符串;其他情况下两边的变量都会被转换为数字。


1 + '23' // '123' 1 + false // 1  1 + Symbol() // Uncaught TypeError: Cannot convert a Symbol value to a number '1' + false // '1false' false + true // 1
复制代码


  1. -*\操作符


NaN也是一个数字


1 * '23' // 23 1 * false // 0 1 / 'aa' // NaN
复制代码


  1. 对于==操作符


操作符两边的值都尽量转成number


3 == true // false, 3 转为number为3,true转为number为1'0' == false //true, '0'转为number为0,false转为number为0'0' == 0 // '0'转为number为0
复制代码


  1. 对于<>比较符


如果两边都是字符串,则比较字母表顺序:


'ca' < 'bd' // false'a' < 'b' // true
复制代码


其他情况下,转换为数字再比较:


'12' < 13 // truefalse > -1 // true
复制代码


以上说的是基本类型的隐式转换,而对象会被ToPrimitive转换为基本类型再进行转换:


var a = {}a > 2 // false
复制代码


其对比过程如下:


a.valueOf() // {}, 上面提到过,ToPrimitive默认type为number,所以先valueOf,结果还是个对象,下一步a.toString() // "[object Object]",现在是一个字符串了Number(a.toString()) // NaN,根据上面 < 和 > 操作符的规则,要转换成数字NaN > 2 //false,得出比较结果
复制代码


又比如:


var a = {name:'Jack'}var b = {age: 18}a + b // "[object Object][object Object]"
复制代码


运算过程如下:


a.valueOf() // {},上面提到过,ToPrimitive默认type为number,所以先valueOf,结果还是个对象,下一步a.toString() // "[object Object]"b.valueOf() // 同理b.toString() // "[object Object]"a + b // "[object Object][object Object]"
复制代码

CSS 预处理器/后处理器是什么?为什么要使用它们?

预处理器, 如:lesssassstylus,用来预编译sass或者less,增加了css代码的复用性。层级,mixin, 变量,循环, 函数等对编写以及开发 UI 组件都极为方便。


后处理器, 如: postCss,通常是在完成的样式表中根据css规范处理css,让其更加有效。目前最常做的是给css属性添加浏览器私有前缀,实现跨浏览器兼容性的问题。


css预处理器为css增加一些编程特性,无需考虑浏览器的兼容问题,可以在CSS中使用变量,简单的逻辑程序,函数等在编程语言中的一些基本的性能,可以让css更加的简洁,增加适应性以及可读性,可维护性等。


其它css预处理器语言:Sass(Scss), Less, Stylus, Turbine, Swithch css, CSS Cacheer, DT Css


使用原因:


  • 结构清晰, 便于扩展

  • 可以很方便的屏蔽浏览器私有语法的差异

  • 可以轻松实现多重继承

  • 完美的兼容了CSS代码,可以应用到老项目中

|| 和 && 操作符的返回值?

|| 和 && 首先会对第一个操作数执行条件判断,如果其不是布尔值就先强制转换为布尔类型,然后再执行条件判断。


  • 对于 || 来说,如果条件判断结果为 true 就返回第一个操作数的值,如果为 false 就返回第二个操作数的值。

  • && 则相反,如果条件判断结果为 true 就返回第二个操作数的值,如果为 false 就返回第一个操作数的值。


|| 和 && 返回它们其中一个操作数的值,而非条件判断的结果


参考 前端进阶面试题详细解答

水平垂直居中的实现

  • 利用绝对定位,先将元素的左上角通过 top:50%和 left:50%定位到页面的中心,然后再通过 translate 来调整元素的中心点到页面的中心。该方法需要考虑浏览器兼容问题。


.parent {    position: relative;} .child {    position: absolute;    left: 50%;    top: 50%;    transform: translate(-50%,-50%);}
复制代码


  • 利用绝对定位,设置四个方向的值都为 0,并将 margin 设置为 auto,由于宽高固定,因此对应方向实现平分,可以实现水平和垂直方向上的居中。该方法适用于盒子有宽高的情况:


.parent {    position: relative;}
.child { position: absolute; top: 0; bottom: 0; left: 0; right: 0; margin: auto;}
复制代码


  • 利用绝对定位,先将元素的左上角通过 top:50%和 left:50%定位到页面的中心,然后再通过 margin 负值来调整元素的中心点到页面的中心。该方法适用于盒子宽高已知的情况


.parent {    position: relative;}
.child { position: absolute; top: 50%; left: 50%; margin-top: -50px; /* 自身 height 的一半 */ margin-left: -50px; /* 自身 width 的一半 */}
复制代码


  • 使用 flex 布局,通过 align-items:center 和 justify-content:center 设置容器的垂直和水平方向上为居中对齐,然后它的子元素也可以实现垂直和水平的居中。该方法要考虑兼容的问题,该方法在移动端用的较多:


.parent {    display: flex;    justify-content:center;    align-items:center;}
复制代码

一个 tcp 连接能发几个 http 请求?

如果是 HTTP 1.0 版本协议,一般情况下,不支持长连接,因此在每次请求发送完毕之后,TCP 连接即会断开,因此一个 TCP 发送一个 HTTP 请求,但是有一种情况可以将一条 TCP 连接保持在活跃状态,那就是通过 Connection 和 Keep-Alive 首部,在请求头带上 Connection: Keep-Alive,并且可以通过 Keep-Alive 通用首部中指定的,用逗号分隔的选项调节 keep-alive 的行为,如果客户端和服务端都支持,那么其实也可以发送多条,不过此方式也有限制,可以关注《HTTP 权威指南》4.5.5 节对于 Keep-Alive 连接的限制和规则。


而如果是 HTTP 1.1 版本协议,支持了长连接,因此只要 TCP 连接不断开,便可以一直发送 HTTP 请求,持续不断,没有上限; 同样,如果是 HTTP 2.0 版本协议,支持多用复用,一个 TCP 连接是可以并发多个 HTTP 请求的,同样也是支持长连接,因此只要不断开 TCP 的连接,HTTP 请求数也是可以没有上限地持续发送

+ 操作符什么时候用于字符串的拼接?

根据 ES5 规范,如果某个操作数是字符串或者能够通过以下步骤转换为字符串的话,+ 将进行拼接操作。如果其中一个操作数是对象(包括数组),则首先对其调用 ToPrimitive 抽象操作,该抽象操作再调用 [[DefaultValue]],以数字作为上下文。如果不能转换为字符串,则会将其转换为数字类型来进行计算。


简单来说就是,如果 + 的其中一个操作数是字符串(或者通过以上步骤最终得到字符串),则执行字符串拼接,否则执行数字加法。


那么对于除了加法的运算符来说,只要其中一方是数字,那么另一方就会被转为数字。

Cookie 有哪些字段,作用分别是什么

Cookie 由以下字段组成:


  • Name:cookie 的名称

  • Value:cookie 的值,对于认证 cookie,value 值包括 web 服务器所提供的访问令牌;

  • Size: cookie 的大小

  • Path:可以访问此 cookie 的页面路径。 比如 domain 是 abc.com,path 是/test,那么只有/test路径下的页面可以读取此 cookie。

  • Secure: 指定是否使用 HTTPS 安全协议发送 Cookie。使用 HTTPS 安全协议,可以保护 Cookie 在浏览器和 Web 服务器间的传输过程中不被窃取和篡改。该方法也可用于 Web 站点的身份鉴别,即在 HTTPS 的连接建立阶段,浏览器会检查 Web 网站的 SSL 证书的有效性。但是基于兼容性的原因(比如有些网站使用自签署的证书)在检测到 SSL 证书无效时,浏览器并不会立即终止用户的连接请求,而是显示安全风险信息,用户仍可以选择继续访问该站点。

  • Domain:可以访问该 cookie 的域名,Cookie 机制并未遵循严格的同源策略,允许一个子域可以设置或获取其父域的 Cookie。当需要实现单点登录方案时,Cookie 的上述特性非常有用,然而也增加了 Cookie 受攻击的危险,比如攻击者可以借此发动会话定置攻击。因而,浏览器禁止在 Domain 属性中设置.org、.com 等通用顶级域名、以及在国家及地区顶级域下注册的二级域名,以减小攻击发生的范围。

  • HTTP: 该字段包含HTTPOnly 属性 ,该属性用来设置 cookie 能否通过脚本来访问,默认为空,即可以通过脚本访问。在客户端是不能通过 js 代码去设置一个 httpOnly 类型的 cookie 的,这种类型的 cookie 只能通过服务端来设置。该属性用于防止客户端脚本通过document.cookie属性访问 Cookie,有助于保护 Cookie 不被跨站脚本攻击窃取或篡改。但是,HTTPOnly 的应用仍存在局限性,一些浏览器可以阻止客户端脚本对 Cookie 的读操作,但允许写操作;此外大多数浏览器仍允许通过 XMLHTTP 对象读取 HTTP 响应中的 Set-Cookie 头。

  • Expires/Max-size : 此 cookie 的超时时间。若设置其值为一个时间,那么当到达此时间后,此 cookie 失效。不设置的话默认值是 Session,意思是 cookie 会和 session 一起失效。当浏览器关闭(不是浏览器标签页,而是整个浏览器) 后,此 cookie 失效。


总结: 服务器端可以使用 Set-Cookie 的响应头部来配置 cookie 信息。一条 cookie 包括了 5 个属性值 expires、domain、path、secure、HttpOnly。其中 expires 指定了 cookie 失效的时间,domain 是域名、path 是路径,domain 和 path 一起限制了 cookie 能够被哪些 url 访问。secure 规定了 cookie 只能在确保安全的情况下传输,HttpOnly 规定了这个 cookie 只能被服务器访问,不能使用 js 脚本访问。

隐藏元素的方法有哪些

  • display: none:渲染树不会包含该渲染对象,因此该元素不会在页面中占据位置,也不会响应绑定的监听事件。

  • visibility: hidden:元素在页面中仍占据空间,但是不会响应绑定的监听事件。

  • opacity: 0:将元素的透明度设置为 0,以此来实现元素的隐藏。元素在页面中仍然占据空间,并且能够响应元素绑定的监听事件。

  • position: absolute:通过使用绝对定位将元素移除可视区域内,以此来实现元素的隐藏。

  • z-index: 负值:来使其他元素遮盖住该元素,以此来实现隐藏。

  • clip/clip-path :使用元素裁剪的方法来实现元素的隐藏,这种方法下,元素仍在页面中占据位置,但是不会响应绑定的监听事件。

  • **transform: scale(0,0)**:将元素缩放为 0,来实现元素的隐藏。这种方法下,元素仍在页面中占据位置,但是不会响应绑定的监听事件。

如何根据设计稿进行移动端适配?

移动端适配主要有两个维度:


  • 适配不同像素密度, 针对不同的像素密度,使用 CSS 媒体查询,选择不同精度的图片,以保证图片不会失真;

  • 适配不同屏幕大小, 由于不同的屏幕有着不同的逻辑像素大小,所以如果直接使用 px 作为开发单位,会使得开发的页面在某一款手机上可以准确显示,但是在另一款手机上就会失真。为了适配不同屏幕的大小,应按照比例来还原设计稿的内容。


为了能让页面的尺寸自适应,可以使用 rem,em,vw,vh 等相对单位。

documentFragment 是什么?用它跟直接操作 DOM 的区别是什么?

MDN 中对documentFragment的解释:


DocumentFragment,文档片段接口,一个没有父对象的最小文档对象。它被作为一个轻量版的 Document 使用,就像标准的 document 一样,存储由节点(nodes)组成的文档结构。与 document 相比,最大的区别是 DocumentFragment 不是真实 DOM 树的一部分,它的变化不会触发 DOM 树的重新渲染,且不会导致性能等问题。


当我们把一个 DocumentFragment 节点插入文档树时,插入的不是 DocumentFragment 自身,而是它的所有子孙节点。在频繁的 DOM 操作时,我们就可以将 DOM 元素插入 DocumentFragment,之后一次性的将所有的子孙节点插入文档中。和直接操作 DOM 相比,将 DocumentFragment 节点插入 DOM 树时,不会触发页面的重绘,这样就大大提高了页面的性能。

object.assign 和扩展运算法是深拷贝还是浅拷贝,两者区别

扩展运算符:


let outObj = {  inObj: {a: 1, b: 2}}let newObj = {...outObj}newObj.inObj.a = 2console.log(outObj) // {inObj: {a: 2, b: 2}}
复制代码


Object.assign():


let outObj = {  inObj: {a: 1, b: 2}}let newObj = Object.assign({}, outObj)newObj.inObj.a = 2console.log(outObj) // {inObj: {a: 2, b: 2}}
复制代码


可以看到,两者都是浅拷贝。


  • Object.assign()方法接收的第一个参数作为目标对象,后面的所有参数作为源对象。然后把所有的源对象合并到目标对象中。它会修改了一个对象,因此会触发 ES6 setter。

  • 扩展操作符(…)使用它时,数组或对象中的每一个值都会被拷贝到一个新的数组或对象中。它不复制继承的属性或类的属性,但是它会复制 ES6 的 symbols 属性。

为什么 0.1+0.2 ! == 0.3,如何让其相等

在开发过程中遇到类似这样的问题:


let n1 = 0.1, n2 = 0.2console.log(n1 + n2)  // 0.30000000000000004
复制代码


这里得到的不是想要的结果,要想等于 0.3,就要把它进行转化:


(n1 + n2).toFixed(2) // 注意,toFixed为四舍五入
复制代码


toFixed(num) 方法可把 Number 四舍五入为指定小数位数的数字。那为什么会出现这样的结果呢?


计算机是通过二进制的方式存储数据的,所以计算机计算 0.1+0.2 的时候,实际上是计算的两个数的二进制的和。0.1 的二进制是0.0001100110011001100...(1100 循环),0.2 的二进制是:0.00110011001100...(1100 循环),这两个数的二进制都是无限循环的数。那 JavaScript 是如何处理无限循环的二进制小数呢?


一般我们认为数字包括整数和小数,但是在 JavaScript 中只有一种数字类型:Number,它的实现遵循 IEEE 754 标准,使用 64 位固定长度来表示,也就是标准的 double 双精度浮点数。在二进制科学表示法中,双精度浮点数的小数部分最多只能保留 52 位,再加上前面的 1,其实就是保留 53 位有效数字,剩余的需要舍去,遵从“0 舍 1 入”的原则。


根据这个原则,0.1 和 0.2 的二进制数相加,再转化为十进制数就是:0.30000000000000004


下面看一下双精度数是如何保存的:


  • 第一部分(蓝色):用来存储符号位(sign),用来区分正负数,0 表示正数,占用 1 位

  • 第二部分(绿色):用来存储指数(exponent),占用 11 位

  • 第三部分(红色):用来存储小数(fraction),占用 52 位


对于 0.1,它的二进制为:


0.00011001100110011001100110011001100110011001100110011001 10011...
复制代码


转为科学计数法(科学计数法的结果就是浮点数):


1.1001100110011001100110011001100110011001100110011001*2^-4
复制代码


可以看出 0.1 的符号位为 0,指数位为-4,小数位为:


1001100110011001100110011001100110011001100110011001
复制代码


那么问题又来了,指数位是负数,该如何保存呢?


IEEE 标准规定了一个偏移量,对于指数部分,每次都加这个偏移量进行保存,这样即使指数是负数,那么加上这个偏移量也就是正数了。由于 JavaScript 的数字是双精度数,这里就以双精度数为例,它的指数部分为 11 位,能表示的范围就是 0~2047,IEEE 固定双精度数的偏移量为 1023


  • 当指数位不全是 0 也不全是 1 时(规格化的数值),IEEE 规定,阶码计算公式为 e-Bias。 此时 e 最小值是 1,则 1-1023= -1022,e 最大值是 2046,则 2046-1023=1023,可以看到,这种情况下取值范围是-1022~1013

  • 当指数位全部是 0 的时候(非规格化的数值),IEEE 规定,阶码的计算公式为 1-Bias,即 1-1023= -1022。

  • 当指数位全部是 1 的时候(特殊值),IEEE 规定这个浮点数可用来表示 3 个特殊值,分别是正无穷,负无穷,NaN。 具体的,小数位不为 0 的时候表示 NaN;小数位为 0 时,当符号位 s=0 时表示正无穷,s=1 时候表示负无穷。


对于上面的 0.1 的指数位为-4,-4+1023 = 1019 转化为二进制就是:1111111011.


所以,0.1 表示为:


0 1111111011 1001100110011001100110011001100110011001100110011001
复制代码


说了这么多,是时候该最开始的问题了,如何实现 0.1+0.2=0.3 呢?


对于这个问题,一个直接的解决方法就是设置一个误差范围,通常称为“机器精度”。对 JavaScript 来说,这个值通常为 2-52,在 ES6 中,提供了Number.EPSILON属性,而它的值就是 2-52,只要判断0.1+0.2-0.3是否小于Number.EPSILON,如果小于,就可以判断为 0.1+0.2 ===0.3


function numberepsilon(arg1,arg2){                     return Math.abs(arg1 - arg2) < Number.EPSILON;        }        
console.log(numberepsilon(0.1 + 0.2, 0.3)); // true
复制代码

new 一个构造函数,如果函数返回 return {}return nullreturn 1return true 会发生什么情况?

如果函数返回一个对象,那么 new 这个函数调用返回这个函数的返回对象,否则返回 new 创建的新对象

画一条 0.5px 的线

  • 采用 transform: scale()的方式,该方法用来定义元素的 2D 缩放转换:


transform: scale(0.5,0.5);
复制代码


  • 采用 meta viewport 的方式


<meta name="viewport" content="width=device-width, initial-scale=0.5, minimum-scale=0.5, maximum-scale=0.5"/>
复制代码


这样就能缩放到原来的 0.5 倍,如果是 1px 那么就会变成 0.5px。viewport 只针对于移动端,只在移动端上才能看到效果

浏览器是如何对 HTML5 的离线储存资源进行管理和加载?

  • 在线的情况下,浏览器发现 html 头部有 manifest 属性,它会请求 manifest 文件,如果是第一次访问页面 ,那么浏览器就会根据 manifest 文件的内容下载相应的资源并且进行离线存储。如果已经访问过页面并且资源已经进行离线存储了,那么浏览器就会使用离线的资源加载页面,然后浏览器会对比新的 manifest 文件与旧的 manifest 文件,如果文件没有发生改变,就不做任何操作,如果文件改变了,就会重新下载文件中的资源并进行离线存储。

  • 离线的情况下,浏览器会直接使用离线存储的资源。

常用的正则表达式有哪些?

// (1)匹配 16 进制颜色值var regex = /#([0-9a-fA-F]{6}|[0-9a-fA-F]{3})/g;
// (2)匹配日期,如 yyyy-mm-dd 格式var regex = /^[0-9]{4}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$/;
// (3)匹配 qq 号var regex = /^[1-9][0-9]{4,10}$/g;
// (4)手机号码正则var regex = /^1[34578]\d{9}$/g;
// (5)用户名正则var regex = /^[a-zA-Z\$][a-zA-Z0-9_\$]{4,16}$/;
复制代码

CSS 中可继承与不可继承属性有哪些

一、无继承性的属性


  1. display:规定元素应该生成的框的类型

  2. 文本属性


  • vertical-align:垂直文本对齐

  • text-decoration:规定添加到文本的装饰

  • text-shadow:文本阴影效果

  • white-space:空白符的处理

  • unicode-bidi:设置文本的方向


  1. 盒子模型的属性:width、height、margin、border、padding

  2. 背景属性:background、background-color、background-image、background-repeat、background-position、background-attachment

  3. 定位属性:float、clear、position、top、right、bottom、left、min-width、min-height、max-width、max-height、overflow、clip、z-index

  4. 生成内容属性:content、counter-reset、counter-increment

  5. 轮廓样式属性:outline-style、outline-width、outline-color、outline

  6. 页面样式属性:size、page-break-before、page-break-after

  7. 声音样式属性:pause-before、pause-after、pause、cue-before、cue-after、cue、play-during


二、有继承性的属性


  1. 字体系列属性


  • font-family:字体系列

  • font-weight:字体的粗细

  • font-size:字体的大小

  • font-style:字体的风格


  1. 文本系列属性


  • text-indent:文本缩进

  • text-align:文本水平对齐

  • line-height:行高

  • word-spacing:单词之间的间距

  • letter-spacing:中文或者字母之间的间距

  • text-transform:控制文本大小写(就是 uppercase、lowercase、capitalize 这三个)

  • color:文本颜色


  1. 元素可见性


  • visibility:控制元素显示隐藏


  1. 列表布局属性


  • list-style:列表风格,包括 list-style-type、list-style-image 等


  1. 光标属性


  • cursor:光标显示为何种形态


用户头像

loveX001

关注

还未添加个人签名 2022-09-01 加入

还未添加个人简介

评论

发布
暂无评论
2023前端二面经典面试题汇总_JavaScript_loveX001_InfoQ写作社区