前端面试复习笔记

根据自己的/身边朋友的/网路上(主要)的面经的总结
以及自己的复习记录,比如开一篇新的文章的话内容又不够多,索性有复习笔记这一模块就直接加在这里了。

client* / scroll* / offset*

* 代表 Height / Width / Left / Top

offset

只读。

offsetHeight / offsetWidth 返回 HTML 元素的 content + border + padding (与 box-sizing 无关) + 滚动条。

offsetLeft / offsetTop 返回元素的 X 和 Y 坐标。指元素距离最近的带有定位的父元素的顶部(或左侧)的距离,如果没有定位则为距离根元素(在标准兼容模式下为 html 元素;在怪异呈现模式下为 body 元素)顶部(或左侧)的距离。

offsetParent 指这些元素相对的祖先元素

client

clientHeight / clientWidth 返回 HTML 元素的 content + padding (与 box-sizing 无关),存在滚动条时,也无滚动条。

clientTop / clientLeft 返回元素的 padding 的外边缘和其 border 的外边缘的水平距离和垂直距离,通常这些值就等于左边和上边的边框宽度。在有滚动条时,并且浏览器将这些滚动条放置在左侧或顶部(…谁会把滚动条放左侧上方),clientLeft 和 clientTop 则会包含滚动条的宽度。

scroll

scrollHeight / scrollWidth 返回元素的 content + padding + (存在的话)溢出内容,因此,如果没有溢出时,这些属性与 clientWidth 和 clientHeight 是相等的。

scrollLeft 和 scrollTop 指的是元素的滚动条的位置,可写的属性,通过设置它们来让元素中的内容滚动。

盒模型

其实一开始觉得盒模型没有什么内容,但是其实可以讲的东西还挺多的。

box-sizing

围绕这个属性展开。

  1. border-box: 对应 IE 盒模型。width/hight = content + padding + border
  2. content-box: 对应 W3C 盒模型。width/hight = content

所以使用 border-box 时,无论 padding 和 border 怎么变化都不会影响元素的尺寸。

margin

虽然两种盒模型跟 margin 没什么关系,但是还是很重要的一个东西。

margin 属性为给定元素设置所有四个(顺序为上右下左)方向的外边距属性的简写。

值的个数可以为 1 个(四向),2 个(分别为纵向 横向),3 个(分别为上 横向 下),4 个(上右下左)

值可以为负值/auto/百分比/宽度值

经典水平居中: margin: 0 auto。

外边框坍陷问题

只发生在 margin-top / margin-bottom 上。

可能发生的情况主要有如下四种:

  1. 父元素无 border-top & padding-rop,与第一个子元素间无内容,父元素和第一个子元素有 margin-top 属性。
  2. 父元素无 border-bottom & padding-bottom,与最后一个子元素间无内容,父元素和第一个子元素有 margin-bottom 属性。
  3. 相邻兄弟元素,分别定义了 margin-bottom & margin-top
  4. 空元素,无 height/border/padding/content,但是有 margin-top & margin-bottom

padding

不能为负值,也是四个方向的 padding 的简写。

也可以有 1/2/3/4 个值。

border

为 border-width border-style border-color 的简写。

border-width & border-style 也是四个方向的简写。

border-style 常用的值

  1. solid 实线
  2. double 双实线
  3. dotted 一系列圆点
  4. dashed 方形虚线
  5. groove 雕刻效果
  6. ridge 浮雕效果
  7. none
  8. hidden

groove 和 dash 相反。

none 和 hidden 如果没有设置背景,则 border-width 都会是 0。
但是!如果是 none 如果和别的边框重叠了,会显示别的边框。如果是 hidden,碰巧也和别的边框重叠了,则那个边框也会被隐藏。

line-height 1.5 和 150% 的区别

区别就在于继承的问题上。150%是根据父元素的字体大小计算出行高,并且子元素依然沿用这个计算后的行高。而 1.5 则是根据子元素自己字体的大小去乘以 1.5 来计算行高。另,1.5em 等也是按照 150%的情况来算的。

水平垂直居中

来源:水平垂直居中

元素定宽高

  1. absolute + 负 margin
  2. absolute + margin: auto -> 可能不好理解,就是子元素 absolute 的同时,top/left/bottom/right=0,margin:auto
  3. absolute + calc()

元素宽高不定

前两个常用

  1. absolute + transfrom: translateY(-50%) + top: 50%
  2. flex + align-items: center
  3. table
  4. grid + align-self: center

flex 和 grid 的区别:
flex 和 align-item 都是容器(flex container)的属性
grid 是容器的属性,而 align-self 为 grid item 的属性

上中下布局,中间自适应

  1. flex

    display:flex;
    width: 100%;
    height: 100%;
    flex-direction: column;
    .top
    height:100px;
    .center
    flex: 1;
    .bottom
    height: 100px;

  2. absolute
    .top,.center,.bottom
    postion:absolute
    .top
    top:0
    height:100px
    .center
    top:100px
    bottom:100px
    .bottom
    bottom:0
    height:100px

  3. table
    虽然也是种方法,但是 table 不建议。处于减少回流考虑

  4. grid

    display: grid;
    height: 100%;
    grid-template-rows: 100px auto 100px;
    grid-template-columns: 150px;

左中右布局,中间自适应

  1. flex
    和上面的差不多

  2. absolute
    和上面的差不多

  3. float
    .left
    float: left;
    width: 100px;
    .right
    float: right;
    width:100px;

  4. table
    虽然也是种方法,但是 table 不建议。处于减少回流考虑

  5. grid

    display: grid;
    width: 100%;
    grid-template-rows: 50px;
    grid-template-columns: 300px auto 300px;

px em rem vw vh vm

em 基于父元素 font-size ,会出现整个页面内 1em 的值不固定
rem 基于根元素的 font-size

vm 就是 vw/vh 里较小的那个。

需要注意 Chrome 强制字体最小 12px

还有一些单位 in / cm / mm / t / pc

基本类型

String / Number / Boolean / Undefined / null / Symbol / Object

Symbol

表示独一无二的值。

1
let bar = Symbol("foo");

需要注意的是 Symbol 前不能有 new ,因为 Symbol 不是对象,是一个类似于字符串的数据类型。

1
2
typeof bar; // 'symbol'
bar.toString(); // "Symbol(bar)"

因为独一无二

1
2
3
4
let foo = Symbol();
let bar = Symbol();

foo === bar; // fasle

不可以与字符串相加,会报错
不可以与数字相加,或者 Number(bar) ,会报错

Symbol 作为属性名时,不能用.运算符,同理,在对象内部,Symbol 值需要在方括号里。

1
2
3
4
5
6
7
8
9
10
11
12
let mySymbol = Symbol();
let myObject = {};
myObject.mySymbol = "hello";
a[mySymbol]; // undefined
a["mySymbol"]; // 'hello'

let obj = {
[mySymbol]: function(arg) {}
};

// 以及调用时
obj[mySymbol](123);

作为属性名不会被 for in / for of 语句中,也不会被 Object.keys() / Object.getOwnPropertyNames() 返回。

可以使用 Object.getOwnPropertySymbols 返回数组,成员为对象所有的用作属性名的 Symbol 值。

Symbol.for(string)

接收字符串为参数,搜索有没有以此作为名称的 Symbol 值,有则返回,没有则新建一个以此为名称的 Symbol 值。

1
2
3
let a = Symbol.for("demo");
let b = Symbol.for("demo");
a === b; // true

Symbol,keyFor()
返回一个已经登记的 Symbol 类型值的 key

1
2
let a = Symbol.for("foo");
Symbol.keyFor(a); // 'foo'

Symbol.hasInstance 对象使用 isntanceof 运算符会调用这个方法
Symbol.isConcatSpreadable 表示对象使用 Array.prototype.concat() 是否可以展开

1
2
3
4
let arr1 = [1, 2];
let arr2 = [2, 3];
arr1[Symbol.isConcatSpreadable] = fasle;
arr2.concat(arr1, 4); // [2,3,[1,2],4]

// To-Do
Symbol.species 指向当前对象的构造函数
Symbol.match 指向一个函数,当执行 str.match(myObject)时如果该属性存在,则会调用它返回该方法的返回值。
Symbol.replace
Symbol.search
Symbol.split
Symbol.iterator 指向对象的默认遍历器方法
Symbol.toPrimitive
Symbol.toStringTag
Symbol.unscopables

Object

Object.assign(target, sources) 新对象,浅拷贝,Object.assign()拷贝的是属性值。假如源对象的属性值是一个对象的引用,那么它也只指向那个引用。 target 也会变。

Object.create(proto[, propertiesObject]) 方法使用指定的原型对象和其属性创建了一个新的对象。

Object.getPrototypeOf() 方法返回指定对象的原型

Object.is() 与 === 运算符的判定方式不一样。=== 运算符(和== 运算符)将数字值 -0 和 +0 视为相等,并认为 Number.NaN 不等于 NaN。

Object.keys() 方法会返回一个由一个给定对象的自身可枚举属性组成的数组,数组中属性名的排列顺序和使用 for…in 循环遍历该对象时返回的顺序一致 。如果对象的键-值都不可枚举,那么将返回由键组成的数组。
Object.values()方法返回一个给定对象自身的所有可枚举属性值的数组,值的顺序与使用 for…in 循环的顺序相同

Object.prototype.isPrototypeOf() 方法用于测试一个对象是否存在于另一个对象的原型链上。

Function

Function.length 返回形参的个数
Function.name 返回函数实例的名称。
Function.prototype.call()
Function.prototype.bind()
Function.prototype.apply()

Number

Number.EPSILON
Number.MAX_SAFE_INTEGER 表示 JavaScript 中最大的安全整数(maxinum safe integer)(253 - 1)。
Number.MAX_VALUE 表示在 JavaScript 里所能表示的最大数值。
Number.MIN_SAFE_INTEGER
Number.MIN_VALUE
Number.NEGATIVE_INFINITY 表示负无穷大。
Number.POSITIVE_INFINITY 表示正无穷大。
Number.NaN 表示“非数字”(Not-A-Number)。和 NaN 相同。

Number.isFinite()
Number.isInteger()
Number.isNaN()
Number.isSafeInteger()
Number.parseFloat()
Number.parseInt() 注意要指明转换的进制

Number.prototype.toFixed(digits) digits 表示小数点后数字的个数;介于 0 到 20 (包括)之间,实现环境可能支持更大范围。如果忽略该参数,则默认为 0。返回值为字符串
Number.prototype.valueOf() 返回一个被 Number 对象包装的原始值。

String

String.length

String.prototype.charAt(index) 0 <= index <= length-1
String.prototype.concat() 方法将一个或多个字符串与原字符串连接合并,形成一个新的字符串并返回。
String.prototype.includes(searchString[, position) 方法用于判断一个 searchString 是否包含在该字符串中,根据情况返回 true 或 false。
String.prototype.indexOf(searchValue[, length]) 方法返回调用它的 String 对象中第一次出现的指定值的索引,从 fromIndex 处进行搜索。如果未找到该值,则返回 -1。
String.prototype.lastIndexOf(searchValue[, length]) 方法返回指定值在调用该方法的字符串中最后出现的位置,如果没找到则返回 -1。length 为需要检索字符串的长度,默认值为 str.length。
String.prototype.match() 方法检索返回一个字符串匹配正则表达式的的结果。
String.prototype.repeat(count) 构造并返回一个新字符串,该字符串包含被连接在一起的指定数量的字符串的副本。count 大于等于 0
String.prototype.replace() 方法返回一个由替换值(replacement)替换一些或所有匹配的模式(pattern)后的新字符串。模式可以是一个字符串或者一个正则表达式,替换值可以是一个字符串或者一个每次匹配都要调用的回调函数。
String.prototype.search() 方法执行正则表达式和 String 对象之间的一个搜索匹配。
String.prototype.slice(beginIndex[, endIndex]) 方法提取某个字符串的一部分,并返回一个新的字符串,且不会改动原字符串。
String.prototype.split() 方法使用指定的分隔符字符串将一个 String 对象分割成字符串数组,以将字符串分隔为子字符串,以确定每个拆分的位置。
String.prototype.startsWith() 方法用来判断当前字符串是否以另外一个给定的子字符串开头,并根据判断结果返回 true 或 false。
String.prototype.substring() 方法返回一个字符串在开始索引到结束索引之间的一个子集, 或从开始索引直到字符串的末尾的一个子集。
String.prototype.toLocaleLowerCase()方法根据任何特定于语言环境的案例映射,返回调用字符串值转换为小写的值。
String.prototype.toLocaleUpperCase()方法根据任何特定于语言环境的案例映射,返回调用字符串值转换为大写的值。
String.prototype.valueOf() 方法返回一个 String 对象的原始值(primitive value)。

Array

Array.from() 方法从一个类似数组或可迭代对象中创建一个新的,浅拷贝的数组实例。
Array.isArray() 用于确定传递的值是否是一个 Array。
Array.of() 方法创建一个具有可变数量参数的新数组实例,而不考虑参数的数量或类型。

Array.prototype.concat() 浅拷贝
Array.prototype.every() 测试一个数组内的所有元素是否都能通过某个指定函数的测试。它返回一个布尔值。若为空数组,此方法在一切情况下都会返回 true
Array.prototype.some()方法测试数组中是不是有元素通过了被提供的函数测试。它返回的是一个 Boolean 类型的值。
Array.prototype.fill(value[, start[, end]])
Array.prototype.filter()创建一个新数组, 其包含通过所提供函数实现的测试的所有元素。
Array.prototype.find() 方法返回数组中满足提供的测试函数的第一个元素的值。否则返回 undefined。
Array.prototype.findIndex(function()) 值 or -1
Array.prototype.indexOf(searchElement) 值 or -1
Array.prototype.flat() 方法会按照一个可指定的深度递归遍历数组,并将所有元素与遍历到的子数组中的元素合并为一个新数组返回。
Array.prototype.join() 方法将一个数组(或一个类数组对象)的所有元素连接成一个字符串并返回这个字符串。如果数组只有一个项目,那么将返回该项目而不使用分隔符。
Array.prototype.map() 返回新数组
Array.prototype.forEach() 不返回新数组
Array.prototype.pop()
Array.prototype.push()
Array.prototype.reduce()
Array.prototype.reduceRight()
Array.prototype.reverse()
Array.prototype.shift()
Array.prototype.unshift()
Array.prototype.slice([begin[, end]]) 方法返回一个新的数组对象,这一对象是一个由 begin 和 end 决定的原数组的浅拷贝(包括 begin,不包括 end)。原始数组不会被改变。
Array.prototype.sort() 用原地算法对数组的元素进行排序,并返回数组。默认排序顺序是在将元素转换为字符串,然后比较它们的 UTF-16 代码单元值序列时构建的

  1. 如果 compareFunction(a, b) 小于 0 ,那么 a 会被排列到 b 之前;
  2. 如果 compareFunction(a, b) 等于 0 , a 和 b 的相对位置不变。备注: ECMAScript 标准并不保证这一行为,而且也不是所有浏览器都会遵守(例如 Mozilla 在 2003 年之前的版本);
  3. 如果 compareFunction(a, b) 大于 0 , b 会被排列到 a 之前。
    Array.prototype.splice(start[, deleteCount[, item1[, item2[, …]]]])
1
2
3
4
5
6
7
var arr1 = [1, 2, [3, 4]];
arr1.flat();
// [1, 2, 3, 4]

var arr2 = [1, 2, [3, 4, [5, 6]]];
arr2.flat();
// [1, 2, 3, 4, [5, 6]]

for in / for of

for in 应用于数组循环返回的是数组的下标和数组的属性和(自定义的)原型上的方法和属性,而 for in 应用于对象循环返回的是对象的属性名和原型中的方法和属性。

所以 for of -> 数组 | for in -> 对象

箭头函数

this 指向定义生效时所在的对象
箭头函数固化 this 不是因为有内部的绑定 this 机制,而是其根本没有 this,所以内部的 this 就是外层代码块的 this

防抖和节流

函数节流与函数防抖

目的:节省计算机资源

防抖 -> (举个例子) setTImeout 当用户不再输入用户名一段时间发送请求判断是否合法
节流 -> 针对频发的监听事件 (举个例子) setTimeout ,scroll 事件每次触发都刷新 setTimeout 直到停止才触发事件。

setTimeout & setInterval

1
2
3
4
5
6
7
8
9
function run() {
//其他代码
setTimeout(function() {
run();
}, 10000);
}
setInterval(function() {
run();
}, 10000);

setTimeout 若 run()需要 100s,则整体需要 110s

setInterval 10s 就会执行一次 run()

1
2
3
setInterval(function() {
run();
}, 100);

若 run()的周期大于 100ms 时,但是又如 150ms 这样的在第二个周期之内,当执行完第一次后他会立即触发第二次
若 run()的周期大于 如 500ms 时,远远大于 100ms,其实根据 setInterval 的机制,他会抛弃掉中间所发生的(舍弃 300、400、500 触发的而运行 200 的那个)

继承方法

JavaScript 常见的六种继承方式

React Diff

  1. Tree diff -> 对树进行分层比较 -> 很少有跨层的移动
  2. Component diff -> 同一组件 -> 比较虚拟 DOM Tree -> 不同组件-> 替换整个组件下的所有子节点
  3. Element diff -> 优化:同一层级的同组子节点添加唯一 key 来区分。

Fiber

React 决定要加载或者更新组件树时,会做很多事,比如调用各个组件的生命周期函数,计算和比对 Virtual DOM,最后更新 DOM 树,这整个过程是同步进行的,

Fiber 是一个优化,思路是增量更新, state 有变化 React 就会计算,也就存在了卡顿的可能。React 制定了一种名为 Fiber 的数据结构,加上新的算法,使得大量的计算可以被拆解,异步化,浏览器主线程得以释放,保证了渲染的帧率。从而提高响应性。

但是增加了优先级之后,因为一个更新过程可能被打断,所以 React Fiber 一个更新过程被分为两个阶段(Phase):第一个阶段 Reconciliation Phase 和第二阶段 Commit Phase。所以除了 ComponentWillUnmoment、ComponentDidMount、ComponentDidUpadate 都有可能被打断

React 组件通信

  1. 父子 props
  2. 子父 props 回调
  3. 跨级 (祖父 -> 子孙) 可以层层的 props 传递,或者 context
  4. 没有嵌套关系 可以自定义事件,Redux

SessionStorage / LocalStorage / Cookie

客户端设置
document.cookie = “=;(可选参数 1);(可选参数 2)”

C -> B 发送带 Set-Cookie 头的请求
Set-Cookie: =;(可选参数 1);(可选参数 2)

可选参数
Expires=:cookie 的最长有效时间,若不设置则 cookie 生命期与会话期相同

Max-Age=:cookie 生成后失效的秒数

Domain=:指定 cookie 可以送达的主机域名,若一级域名设置了则二级域名也能获取。

Path=:指定一个 URL,例如指定 path=/docs,则”/docs”、”/docs/Web/“、”/docs/Web/Http”均满足匹配条件

Secure:必须在请求使用 SSL 或 HTTPS 协议的时候 cookie 才回被发送到服务器

HttpOnly:客户端无法更改 Cookie,客户端设置 cookie 时不能使用这个参数,一般是服务器端使用

0%