写点什么

那些高级前端是如何回答面试题的

作者:loveX001
  • 2023-01-03
    浙江
  • 本文字数:7796 字

    阅读完需:约 26 分钟

TCP 和 UDP 的区别

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:光标显示为何种形态

单行、多行文本溢出隐藏

  • 单行文本溢出


overflow: hidden;            // 溢出隐藏text-overflow: ellipsis;      // 溢出用省略号显示white-space: nowrap;         // 规定段落中的文本不进行换行
复制代码


  • 多行文本溢出


overflow: hidden;            // 溢出隐藏text-overflow: ellipsis;     // 溢出用省略号显示display:-webkit-box;         // 作为弹性伸缩盒子模型显示。-webkit-box-orient:vertical; // 设置伸缩盒子的子元素排列方式:从上到下垂直排列-webkit-line-clamp:3;        // 显示的行数
复制代码


注意:由于上面的三个属性都是 CSS3 的属性,没有浏览器可以兼容,所以要在前面加一个-webkit- 来兼容一部分浏览器。

手写题:实现柯里化

预先设置一些参数


柯里化是什么:是指这样一个函数,它接收函数 A,并且能返回一个新的函数,这个新的函数能够处理函数 A 的剩余参数


function createCurry(func, args) {  var argity = func.length;  var args = args || [];
return function () { var _args = [].slice.apply(arguments); args.push(..._args);
if (args.length < argity) { return createCurry.call(this, func, args); }
return func.apply(this, args); }}
复制代码

isNaN 和 Number.isNaN 函数的区别?

  • 函数 isNaN 接收参数后,会尝试将这个参数转换为数值,任何不能被转换为数值的的值都会返回 true,因此非数字值传入也会返回 true ,会影响 NaN 的判断。

  • 函数 Number.isNaN 会首先判断传入参数是否为数字,如果是数字再继续判断是否为 NaN ,不会进行数据类型的转换,这种方法对于 NaN 的判断更为准确。

对浏览器的理解

浏览器的主要功能是将用户选择的 web 资源呈现出来,它需要从服务器请求资源,并将其显示在浏览器窗口中,资源的格式通常是 HTML,也包括 PDF、image 及其他格式。用户用 URI(Uniform Resource Identifier 统一资源标识符)来指定所请求资源的位置。


HTML 和 CSS 规范中规定了浏览器解释 html 文档的方式,由 W3C 组织对这些规范进行维护,W3C 是负责制定 web 标准的组织。但是浏览器厂商纷纷开发自己的扩展,对规范的遵循并不完善,这为 web 开发者带来了严重的兼容性问题。


浏览器可以分为两部分,shell 和 内核。其中 shell 的种类相对比较多,内核则比较少。也有一些浏览器并不区分外壳和内核。从 Mozilla 将 Gecko 独立出来后,才有了外壳和内核的明确划分。


  • shell 是指浏览器的外壳:例如菜单,工具栏等。主要是提供给用户界面操作,参数设置等等。它是调用内核来实现各种功能的。

  • 内核是浏览器的核心。内核是基于标记语言显示内容的程序或模块。


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

数组去重

使用 indexOf/includes 实现

function unique(arr) {    var res = [];    for(var i = 0; i < arr.length; i++) {        if(res.indexOf(arr[i]) === -1) res.push(arr[i]);        // if(!res.includes(arr[i])) res.push(arr[i]);    }    return res;}
复制代码

使用 filter(forEach) + indexOf/includes 实现

// filterfunction unique(arr) {    var res = arr.filter((value, index) => {        // 只存第一个出现的元素        return arr.indexOf(value) === index;    });    return res;}// forEachfunction unique(arr) {    var res = [];    arr.forEach((value) => {        if(!res.includes(value)) res.push(value);    });    return res;}
复制代码

非 API 版本(原生)实现

function unique(arr) {    var res = [];    for(var i = 0; i < arr.length; i++) {        var flag = false;        for(var j = 0; j < res.length; j++) {            if(arr[i] === res[j]) {                flag = true;                break;            }        }        if(flag === false) res.push(arr[i]);    }    return res;}
复制代码

ES6 使用 Set + 扩展运算符(...)/Array.from() 实现

function unique(arr) {    // return [...new Set(arr)];    return Array.from(new Set(arr));}
复制代码

实现一个宽高自适应的正方形

  • 利用 vw 来实现:


.square {  width: 10%;  height: 10vw;  background: tomato;}
复制代码


  • 利用元素的 margin/padding 百分比是相对父元素 width 的性质来实现:


.square {  width: 20%;  height: 0;  padding-top: 20%;  background: orange;}
复制代码


  • 利用子元素的 margin-top 的值来实现:


.square {  width: 30%;  overflow: hidden;  background: yellow;}.square::after {  content: '';  display: block;  margin-top: 100%;}
复制代码

柯里化

题目描述:柯里化(Currying),又称部分求值(Partial Evaluation),是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数而且返回结果的新函数的技术。核心思想是把多参数传入的函数拆成单参数(或部分)函数,内部再返回调用下一个单参数(或部分)函数,依次处理剩余的参数。


实现代码如下:


function currying(fn, ...args) {  const length = fn.length;  let allArgs = [...args];  const res = (...newArgs) => {    allArgs = [...allArgs, ...newArgs];    if (allArgs.length === length) {      return fn(...allArgs);    } else {      return res;    }  };  return res;}
// 用法如下:// const add = (a, b, c) => a + b + c;// const a = currying(add, 1);// console.log(a(2,3))
复制代码

什么是 margin 重叠问题?如何解决?

问题描述: 两个块级元素的上外边距和下外边距可能会合并(折叠)为一个外边距,其大小会取其中外边距值大的那个,这种行为就是外边距折叠。需要注意的是,浮动的元素和绝对定位这种脱离文档流的元素的外边距不会折叠。重叠只会出现在垂直方向


计算原则: 折叠合并后外边距的计算原则如下:


  • 如果两者都是正数,那么就去最大者

  • 如果是一正一负,就会正值减去负值的绝对值

  • 两个都是负值时,用 0 减去两个中绝对值大的那个


解决办法: 对于折叠的情况,主要有两种:兄弟之间重叠父子之间重叠 (1)兄弟之间重叠


  • 底部元素变为行内盒子:display: inline-block

  • 底部元素设置浮动:float

  • 底部元素的 position 的值为absolute/fixed


(2)父子之间重叠


  • 父元素加入:overflow: hidden

  • 父元素添加透明边框:border:1px solid transparent

  • 子元素变为行内盒子:display: inline-block

  • 子元素加入浮动属性或定位

代码输出结果

var friendName = 'World';(function() {  if (typeof friendName === 'undefined') {    var friendName = 'Jack';    console.log('Goodbye ' + friendName);  } else {    console.log('Hello ' + friendName);  }})();
复制代码


输出结果:Goodbye Jack


我们知道,在 JavaScript 中, Function 和 var 都会被提升(变量提升),所以上面的代码就相当于:


var name = 'World!';(function () {    var name;    if (typeof name === 'undefined') {        name = 'Jack';        console.log('Goodbye ' + name);    } else {        console.log('Hello ' + name);    }})();
复制代码


这样,答案就一目了然了。

line-height 的理解及其赋值方式

(1)line-height 的概念:


  • line-height 指一行文本的高度,包含了字间距,实际上是下一行基线到上一行基线距离;

  • 如果一个标签没有定义 height 属性,那么其最终表现的高度由 line-height 决定;

  • 一个容器没有设置高度,那么撑开容器高度的是 line-height,而不是容器内的文本内容;

  • 把 line-height 值设置为 height 一样大小的值可以实现单行文字的垂直居中;

  • line-height 和 height 都能撑开一个高度;


(2)line-height 的赋值方式:


  • 带单位:px 是固定值,而 em 会参考父元素 font-size 值计算自身的行高

  • 纯数字:会把比例传递给后代。例如,父级行高为 1.5,子元素字体为 18px,则子元素行高为 1.5 * 18 = 27px

  • 百分比:将计算后的值传递给后代

三栏布局的实现

三栏布局一般指的是页面中一共有三栏,左右两栏宽度固定,中间自适应的布局,三栏布局的具体实现:


  • 利用绝对定位,左右两栏设置为绝对定位,中间设置对应方向大小的 margin 的值。


.outer {  position: relative;  height: 100px;}
.left { position: absolute; width: 100px; height: 100px; background: tomato;}
.right { position: absolute; top: 0; right: 0; width: 200px; height: 100px; background: gold;}
.center { margin-left: 100px; margin-right: 200px; height: 100px; background: lightgreen;}
复制代码


  • 利用 flex 布局,左右两栏设置固定大小,中间一栏设置为 flex:1。


.outer {  display: flex;  height: 100px;}
.left { width: 100px; background: tomato;}
.right { width: 100px; background: gold;}
.center { flex: 1; background: lightgreen;}
复制代码


  • 利用浮动,左右两栏设置固定大小,并设置对应方向的浮动。中间一栏设置左右两个方向的 margin 值,注意这种方式,中间一栏必须放到最后:


.outer {  height: 100px;}
.left { float: left; width: 100px; height: 100px; background: tomato;}
.right { float: right; width: 200px; height: 100px; background: gold;}
.center { height: 100px; margin-left: 100px; margin-right: 200px; background: lightgreen;}
复制代码


  • 圣杯布局,利用浮动和负边距来实现。父级元素设置左右的 padding,三列均设置向左浮动,中间一列放在最前面,宽度设置为父级元素的宽度,因此后面两列都被挤到了下一行,通过设置 margin 负值将其移动到上一行,再利用相对定位,定位到两边。


.outer {  height: 100px;  padding-left: 100px;  padding-right: 200px;}
.left { position: relative; left: -100px;
float: left; margin-left: -100%;
width: 100px; height: 100px; background: tomato;}
.right { position: relative; left: 200px;
float: right; margin-left: -200px;
width: 200px; height: 100px; background: gold;}
.center { float: left;
width: 100%; height: 100px; background: lightgreen;}
复制代码


  • 双飞翼布局,双飞翼布局相对于圣杯布局来说,左右位置的保留是通过中间列的 margin 值来实现的,而不是通过父元素的 padding 来实现的。本质上来说,也是通过浮动和外边距负值来实现的。


.outer {  height: 100px;}
.left { float: left; margin-left: -100%;
width: 100px; height: 100px; background: tomato;}
.right { float: left; margin-left: -200px;
width: 200px; height: 100px; background: gold;}
.wrapper { float: left;
width: 100%; height: 100px; background: lightgreen;}
.center { margin-left: 100px; margin-right: 200px; height: 100px;}
复制代码

使用 clear 属性清除浮动的原理?

使用 clear 属性清除浮动,其语法如下:


clear:none|left|right|both
复制代码


如果单看字面意思,clear:left 是“清除左浮动”,clear:right 是“清除右浮动”,实际上,这种解释是有问题的,因为浮动一直还在,并没有清除。


官方对 clear 属性解释:“元素盒子的边不能和前面的浮动元素相邻”,对元素设置 clear 属性是为了避免浮动元素对该元素的影响,而不是清除掉浮动。


还需要注意 clear 属性指的是元素盒子的边不能和前面的浮动元素相邻,注意这里“前面的”3 个字,也就是 clear 属性对“后面的”浮动元素是不闻不问的。考虑到 float 属性要么是 left,要么是 right,不可能同时存在,同时由于 clear 属性对“后面的”浮动元素不闻不问,因此,当 clear:left 有效的时候,clear:right 必定无效,也就是此时 clear:left 等同于设置 clear:both;同样地,clear:right 如果有效也是等同于设置 clear:both。由此可见,clear:left 和 clear:right 这两个声明就没有任何使用的价值,至少在 CSS 世界中是如此,直接使用 clear:both 吧。


一般使用伪元素的方式清除浮动:


.clear::after{  content:'';  display: block;   clear:both;}
复制代码


clear 属性只有块级元素才有效的,而::after 等伪元素默认都是内联水平,这就是借助伪元素清除浮动影响时需要设置 display 属性值的原因。

什么是中间人攻击?如何防范中间人攻击?

中间⼈ (Man-in-the-middle attack, MITM) 是指攻击者与通讯的两端分别创建独⽴的联系, 并交换其所收到的数据, 使通讯的两端认为他们正在通过⼀个私密的连接与对⽅直接对话, 但事实上整个会话都被攻击者完全控制。在中间⼈攻击中,攻击者可以拦截通讯双⽅的通话并插⼊新的内容。


攻击过程如下:


  • 客户端发送请求到服务端,请求被中间⼈截获

  • 服务器向客户端发送公钥

  • 中间⼈截获公钥,保留在⾃⼰⼿上。然后⾃⼰⽣成⼀个伪造的公钥,发给客户端

  • 客户端收到伪造的公钥后,⽣成加密 hash 值发给服务器

  • 中间⼈获得加密 hash 值,⽤⾃⼰的私钥解密获得真秘钥,同时⽣成假的加密 hash 值,发给服务器

  • 服务器⽤私钥解密获得假密钥,然后加密数据传输给客户端

IndexedDB 有哪些特点?

IndexedDB 具有以下特点:


  • 键值对储存:IndexedDB 内部采用对象仓库(object store)存放数据。所有类型的数据都可以直接存入,包括 JavaScript 对象。对象仓库中,数据以"键值对"的形式保存,每一个数据记录都有对应的主键,主键是独一无二的,不能有重复,否则会抛出一个错误。

  • 异步:IndexedDB 操作时不会锁死浏览器,用户依然可以进行其他操作,这与 LocalStorage 形成对比,后者的操作是同步的。异步设计是为了防止大量数据的读写,拖慢网页的表现。

  • 支持事务:IndexedDB 支持事务(transaction),这意味着一系列操作步骤之中,只要有一步失败,整个事务就都取消,数据库回滚到事务发生之前的状态,不存在只改写一部分数据的情况。

  • 同源限制: IndexedDB 受到同源限制,每一个数据库对应创建它的域名。网页只能访问自身域名下的数据库,而不能访问跨域的数据库。

  • 储存空间大:IndexedDB 的储存空间比 LocalStorage 大得多,一般来说不少于 250MB,甚至没有上限。

  • 支持二进制储存:IndexedDB 不仅可以储存字符串,还可以储存二进制数据(ArrayBuffer 对象和 Blob 对象)。

实现模板字符串解析

描述:实现函数使得将 template 字符串中的{{}}内的变量替换。


核心:使用字符串替换方法 str.replace(regexp|substr, newSubStr|function),使用正则匹配代换字符串。


实现


function render(template, data) {    // 模板字符串正则 /\{\{(\w+)\}\}/, 加 g 为全局匹配模式, 每次匹配都会调用后面的函数    let computed = template.replace(/\{\{(\w+)\}\}/g, function(match, key) {        // match: 匹配的子串;  key:括号匹配的字符串        return data[key];    });    return computed;}
// 测试let template = "我是{{name}},年龄{{age}},性别{{sex}}";let data = { name: "张三", age: 18}console.log(render(template, data)); // 我是张三,年龄18,性别undefined
复制代码

常见浏览器所用内核

(1) IE 浏览器内核:Trident 内核,也是俗称的 IE 内核;


(2) Chrome 浏览器内核:统称为 Chromium 内核或 Chrome 内核,以前是 Webkit 内核,现在是 Blink 内核;


(3) Firefox 浏览器内核:Gecko 内核,俗称 Firefox 内核;


(4) Safari 浏览器内核:Webkit 内核;


(5) Opera 浏览器内核:最初是自己的 Presto 内核,后来加入谷歌大军,从 Webkit 又到了 Blink 内核;


(6) 360 浏览器、猎豹浏览器内核:IE + Chrome 双内核;


(7) 搜狗、遨游、QQ 浏览器内核:Trident(兼容模式)+ Webkit(高速模式);


(8) 百度浏览器、世界之窗内核:IE 内核;


(9) 2345 浏览器内核:好像以前是 IE 内核,现在也是 IE + Chrome 双内核了;


(10)UC 浏览器内核:这个众口不一,UC 说是他们自己研发的 U3 内核,但好像还是基于 Webkit 和 Trident ,还有说是基于火狐内核。

对 CSSSprites 的理解

CSSSprites(精灵图),将一个页面涉及到的所有图片都包含到一张大图中去,然后利用 CSS 的 background-image,background-repeat,background-position 属性的组合进行背景定位。


优点:


  • 利用CSS Sprites能很好地减少网页的 http 请求,从而大大提高了页面的性能,这是CSS Sprites最大的优点;

  • CSS Sprites能减少图片的字节,把 3 张图片合并成 1 张图片的字节总是小于这 3 张图片的字节总和。


缺点:


  • 在图片合并时,要把多张图片有序的、合理的合并成一张图片,还要留好足够的空间,防止板块内出现不必要的背景。在宽屏及高分辨率下的自适应页面,如果背景不够宽,很容易出现背景断裂;

  • CSSSprites在开发的时候相对来说有点麻烦,需要借助photoshop或其他工具来对每个背景单元测量其准确的位置。

  • 维护方面:CSS Sprites在维护的时候比较麻烦,页面背景有少许改动时,就要改这张合并的图片,无需改的地方尽量不要动,这样避免改动更多的CSS,如果在原来的地方放不下,又只能(最好)往下加图片,这样图片的字节就增加了,还要改动CSS

Promise.resolve

Promise.resolve = function(value) {    // 1.如果 value 参数是一个 Promise 对象,则原封不动返回该对象    if(value instanceof Promise) return value;    // 2.如果 value 参数是一个具有 then 方法的对象,则将这个对象转为 Promise 对象,并立即执行它的then方法    if(typeof value === "object" && 'then' in value) {        return new Promise((resolve, reject) => {           value.then(resolve, reject);        });    }    // 3.否则返回一个新的 Promise 对象,状态为 fulfilled    return new Promise(resolve => resolve(value));}
复制代码


用户头像

loveX001

关注

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

还未添加个人简介

评论

发布
暂无评论
那些高级前端是如何回答面试题的_JavaScript_loveX001_InfoQ写作社区