# 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)

宏任务通常涉及较为耗时的操作,或者需要在稍后的时间点执行的任务。常见的宏任务包括:

  • 整体脚本执行:整个脚本作为一个宏任务执行。
  • 定时器:如 setTimeoutsetInterval
  • I/O 操作:文件读写、网络请求等。
  • UI 渲染:在浏览器环境中,页面的重绘和重排。
  • requestAnimationFrame:用于在下一次重绘前调度一个函数调用。
  • 用户输入事件:如点击、键盘输入等。
  • MessageChannelport.postMessage:用于跨线程通信。

微任务 (Microtasks)

微任务则是在当前宏任务结束后,下一个宏任务开始之前执行的任务。常见的微任务包括:

  • Promise 的回调thencatchfinally 回调。
  • MutationObserver 回调:用于观察 DOM 变化的回调。
  • process.nextTick(仅限 Node.js 环境):在当前操作完成后立即执行。
  • queueMicrotask:ES2020 引入的新方法,用于手动将一个函数排队为微任务。

Event Loop 工作流程

  1. 执行同步任务:Event Loop 首先执行所有同步任务,直到调用栈为空。
  2. 执行微任务:当调用栈清空后,Event Loop 会检查微任务队列,并执行所有微任务,直到微任务队列为空。
  3. 渲染:在浏览器环境中,如果此时页面需要更新,那么会进行渲染。
  4. 执行宏任务:然后 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 的区别

上次更新: 11/6/2024, 4:10:52 PM