# HTML
# 语义化
- 利于 SEO
- 增强可读性
# 哪些是块级元素、哪些是内联元素
- display: block/table; 有 div p h1 table ul ol
- display: inline/inline-block; 有 span a img input button
# CSS
# 布局
# 盒模型的宽度如何计算
offsetWidth = width + padding + border
- box-sizing: content-box; 默认
- box-sizing: border-box; 宽度包含 padding 和 border。注意 (包含边框)
# margin 纵向重叠问题
- 相邻元素的 margin-top 和 margin-bottom 会重叠,上下重叠,取最大值
- 空 p 标签也会重叠
# margin 负值的问题
- margin-top 和 margin-left 取负值,元素会向上、左移动
- margin-right 负值,右侧元素左移,自身不影响
- margin-bottom 取负值,下面的元素上移,自身不影响
# BFC 理解与应用
块级格式化上下文,一个独立的区域,内部元素的渲染不会影响边界以外的元素。
形成条件
- float 不是 none
- position 是 absolute/fixed
- overflow 不是 visible
- display 是 flex inline-block 等
常见应用:清除浮动
# float 布局,以及 clearfix
圣杯布局、双飞翼布局
三栏布局、两栏布局
使用 float 布局
使用 margin 负值
手写 clearfix
:clearfix:after {
content: '';
display: block;
clear: both;
}
.clearfix {
*zoom: 1; /* IE6 */
}
# flex 布局
容器
- flex-direction: row/column;
- justify-content: center/flex-start/flex-end/space-between ;
- align-items: center/flex-start/flex-end;
- flex-wrap: wrap;
子元素
align-self: flex-start/flex-end/center;
align-content: flex-start/flex-end/center;
flex-grow: 1;
flex-shrink: 1;
flex-basis: 100%;
order: 1;
flex: 1;
# absolute 和 relative 分别依据什么定位
- relative: 默认,基于自身定位
- absolute: 基于最近一层的定位元素定位
# 居中对其的实现方式
水平居中
- inline 元素:text-align: center
- block 元素:margin: auto
- absolute 元素:left:50% + margin-left 负值
垂直居中
- inline 元素:line-height 的值等于 height 值
- absolute 元素:top: 50%, left: 50%, margin-top 负值
- absolute 元素:top: 50%, left: 50%, transform(-50%,-50%)
- absolute 元素:top, left, bottom, right = 0 + margin: auto
# 图文样式
# line-hight 如何继承
- 写具体数值,如 30px,则继承该值
- 写比例,如2/1.5, 则继承该比例。最终值 = 当前的 font-size * 该比例。
- 写百分比,如200%,则继承计算出来的值。最终值 = 父级的字体大小 * 200%。和当前的font-size无关。
# 响应式
# rem em px
- px,绝对长度单位,最常用
- em,相对长度单位,相对于父元素,不常用
- rem,相对长度单位,相对于根元素,常用于响应式布局
# 响应式布局的常用方案
media-query,根据不同的屏幕宽度设置根元素 font-size
rem, 基于根元素的相对单位
# vw / wh
# CSS3新特性
# JS
# 变量类型
# typeof 能判断那些类型
- 所有的值类型
- function
- 能判断是否是引用类型(不可细分),即: 不能区分 (null、object、array)
# 值类型和引用类型的区别
值类型:存储在栈中,赋值时复制实际值,比较时也基于实际值。 引用类型:存储在堆中,栈中保存的是引用,赋值时复制引用,比较时基于引用。
null 为特殊的引用类型
function:函数是一种特殊的对象,其定义存储在堆内存中,而在栈内存中存储的是指向这些函数的引用。函数调用:每次调用函数时,会在栈内存中创建一个新的执行上下文,用于管理函数调用期间的局部变量和参数。
# 手写深拷贝
# 类型计算
# 字符串拼接
100 + 10 // 110
100 + '10' // '10010'
true + '10' // 'true10'
# if 语句和逻辑运算
对值进行两次取反, !!
可以判断是否为 falsely 变量。
以下是 falsely 变量。除此之外都是 truly 变量
!!0 === false
!!NaN === false
!!'' === false
!!null === false
!!undefined === false
!false === false
if 语句里面判断的是 falsely 变量
逻辑运算, &&
会返回 第一个 falsely 变量, ||
会返回第一个 truthy 变量
10 && 0 // 0
0 && 10 // 0
'' || 'abc' // abc
!window.abc // true
# 如何使用 === 和 ==
100 == '100' // true
0 == '' // true
0 == false // true
false == '' // true
null == undefined // true
除了 a == null // 相当于 a === null || a === undefined
, 其余的一律使用 ===
# 原型 & 原型链
__proto__ // 隐式原型, 存在于实例对象上
prototype // 显示原型, 存在于构造函数上
先在自身属性和方法上面查找,如果找不到,则自动取 隐式原型(_proto_)上面 查找。隐式原型指向构造函数的 prototype 属性。
# 判断一个变量是不是数组
# 手写一个 jQuery,考虑插件和拓展性
class jQuery {
constructor(selector) {
const result = document.querySelectorAll(selector)
const length = result.length
for (let i = 0; i < length; i++) {
this[i] = result[i];
this.length = length;
this.selector = selector;
}
}
get(index) {
return this[index];
}
each(fn) {
for (let i = 0; i < this.length; i++) {
const elem = this[i];
fn(elem);
}
}
}
// 插件
jQuery..prototype.xxx = function(obj) {}
# class 原型的本质
class 本质是函数
- constructor
# 继承
- extends
- super
# 作用域 & 闭包
# 作用域
- 全局作用域
- 函数作用域
- 块级作用域
- eval 作用域
# 作用域链
一个变量在当前作用域没有定义,去上级作用域一层一层的查找,直到找到为止
# this
# 闭包
- 函数作为参数传递
function print(fn) {
let a = 200
fn()
}
let a = 100
function fn() {
console.log(a)
}
print(fn) // 100 , fn 的作用域是 全局作用域
- 函数作为返回值
//函数作为返回值
function create() {
const a = 100
return function () {
console.log(a)
}
}
const fn = create()
const a = 200
fn() // 100 fn 的作用域为 create 函数作用域
闭包:变量查找是函数定义的地方,向上级作用域查找,不是执行的时候的作用域
闭包的场景
const proxyObj = () => {
const data = {};
return {
get(key) { return data[key] },
set(key, val) { data[key] = val }
}
}
const obj = proxyObj();
obj.set('name', 'zhangsan')
obj.get('name') // zhangsan
# this
普通函数
使用 call、apply、bind 调用
则会绑定到 指定的 this 上
作为对象方法调用
setTimeout 如果方法是一个普通的 function, 里面的 this 是 window。如果是箭头函数,则为上层的 this (当前对象)等
class 中使用
箭头函数
this 的取值是函数执行的时候确定的,不是函数定义的时候确定。
# 异步 & 单线程
# Event Loop
宏任务 (Macrotasks)
宏任务通常涉及较为耗时的操作,或者需要在稍后的时间点执行的任务。常见的宏任务包括:
- 整体脚本执行:整个脚本作为一个宏任务执行。
- 定时器:如
setTimeout
和setInterval
。 - I/O 操作:文件读写、网络请求等。
- UI 渲染:在浏览器环境中,页面的重绘和重排。
requestAnimationFrame
:用于在下一次重绘前调度一个函数调用。- 用户输入事件:如点击、键盘输入等。
MessageChannel
的port.postMessage
:用于跨线程通信。
微任务 (Microtasks)
微任务则是在当前宏任务结束后,下一个宏任务开始之前执行的任务。常见的微任务包括:
Promise
的回调:then
、catch
和finally
回调。MutationObserver
回调:用于观察 DOM 变化的回调。process.nextTick
(仅限 Node.js 环境):在当前操作完成后立即执行。queueMicrotask
:ES2020 引入的新方法,用于手动将一个函数排队为微任务。
Event Loop 工作流程
- 执行同步任务:Event Loop 首先执行所有同步任务,直到调用栈为空。
- 执行微任务:当调用栈清空后,Event Loop 会检查微任务队列,并执行所有微任务,直到微任务队列为空。
- 渲染:在浏览器环境中,如果此时页面需要更新,那么会进行渲染。
- 执行宏任务:然后 Event Loop 会从任务队列中取出下一个宏任务执行,重复上述过程。
微任务 DOM 渲染前触发
宏任务 DOM 渲染后触发
async function async1() {
console.log('async1 start 2') // 2
await async2()
// 后面的代码可以理解为 - 微任务 1
console.log('async1 end 6') // 6
}
async function async2() {
console.log('async2 3') // 3
}
console.log('script start 1') // 1
setTimeout(function () {
console.log('setTimeout 7') // 7
}, 0)
async1()
new Promise(function (resolve) {
// Promise 构造函数是同步的,会里面执行
console.log('promise 4') // 4
// 如果遇到了宏任务,则为异步的。 宏任务 2
setTimeout(() => {
console.log('timeout 2 8') // 8
resolve()
}, 0)
}).then(function () { // 微任务 2,需要等到上面的 setTimeout 执行完毕再执行
console.log('promise2 9') // 9
})
console.log('script end 5') // 5
# Promise
Promise.then() 返回一个 resolve 的 Promise 对象,如果报错则是 reject 的 Promise 对象, 所以可以链式调用
Promise.catch() 正常返回一个 resolve 的 Promise 对象,如果报错则是 reject 的 Promise 对象
Promise 的构造函数是同步的还是异步的
构造函数的执行是同步的:new Promise 构造函数会立即执行传入的执行器函数。
内部的异步操作是异步的:执行器函数内部的异步操作(如 setTimeout、fetch 等)不会阻塞主线程,而是在异步任务完成后调用 resolve 或 reject 函数来改变 Promise 的状态。
# async/await
相当于 Promise.then。 本质是同步的代码写异步, async/await 后面的代码,相当于是放入了 callback 队列中,等执行器函数执行完后,才执行。
async/await
是基于 Promise
的语法糖,使得异步代码看起来更像同步代码,从而提高可读性和可维护性。
async function async1() {
console.log('async1 start 2') // 2
await async2()
// await 的后面,都可以看做是 callback 里的内容,即异步
// 类似,event Loop , setTimeout (cb1)
// setTimeout(function() { console.log ('async1 end' )})
// Promise.resolve().then(() => console.log('async1 end'))
console.log('async1 end 5') // 最后执行 5
}
async function async2() {
console.log('async2 3') //3 重要
}
console.log('script start 1') // 1
async1();
console.log('script end 4') // 4
for of 循环,是异步的 (会等待每一次执行完了后,再执行),但是 for in 循环,是同步的 forEach 是同步的
# DOM
一次性插入多个 DOM,如何考虑性能
# BOM
# 事件
- 冒泡
- 委托
# HTTP
# http 缓存
# http 状态码
# http 常见 headers
# Webpack & Babel
# React
# git
# 浏览器
# 浏览器渲染过程
# XSS、CSRF
# 存储
# window.onload 和 DOMContentLoaded 的区别
React →