likes
comments
collection
share

前端八股文攻略,持续更新中~

作者站长头像
站长
· 阅读数 3

HTML + CSS

盒子模型

  • 标准盒模型 由padding + maring + border + content组成

  • IE盒模型 由margin + content(包含border + padding)组成

可以通过box-sizing属性控制盒子模型的模式,默认为content-box,可以设置为boder-box(IE盒模型)

CSS优先级

  1. !important:最高优先级,将覆盖任何其他样式。
  2. style:内联样式。
  3. id:通过ID选择器指定的样式。
  4. 类/伪类/属性:通过类选择器、伪类选择器或属性选择器指定的样式。
  5. 标签:通过标签名指定的样式。
  6. 通配符:通配符选择器指定的样式。

优先级从高到低,高优先级的样式会覆盖低优先级的样式。

隐藏页面元素

  • opacity: 0:元素透明度为0,但仍占据页面空间。
  • display: none:元素不可见,且不占据页面空间。
  • visibility: hidden:元素不可见,但仍占据页面空间。

px,em,rem的区别

  • px:是浏览器的绝对单位。
  • em:相对于父元素的font-size进行单位计算。
  • rem:相对于根元素(html)的font-size进行单位计算。

重排(回流),重绘

  • 重排 指的是当元素的位置、大小或几何形状发生改变时,浏览器需要重新计算元素的几何属性,然后再重新构建页面的过程。
  • 重绘 是指当元素的样式,如背景色、字体颜色等发生改变时,浏览器只需要将新样式绘制在已经计算好的页面上,而不需要改变元素的几何属性。

重排必定引起重绘,在性能优化的过程中,尽量减少重排和重绘的次数,以提高页面的渲染性能。

元素居中

position

<html>  
    <head>  
        <style>  
            .wrap {  
                width: 400px;  
                height: 400px;  
                border: 1px solid #000;  
                position: relative;  
            }  
            .inner {  
                width: 200px;  
                height: 200px;  
                background: blue;  
                position: absolute;  
                top: 0;  
                left: 0;  
                right: 0;  
                bottom: 0;  
                margin: auto;  
            }  
        </style>  
    </head>  
    <body>  
        <div class="wrap">  
            <div class="inner"></div>  
        </div>  
    </body>  
</html>

transform

<!doctype html>  
<html lang="en">  
    <head>  
    <title>Document</title>  
        <style>  
            .wrap {  
                width: 400px;  
                height: 400px;  
                border: 1px solid #000;  
                position: relative;  
            }  
            .inner {  
                width: 200px;  
                height: 200px;  
                background: green;  
                position: absolute;  
                top: 50%;  
                left: 50%;  
                transform: translate(-50%, -50%)  
            }  
        </style>  
    </head>  
    <body>  
        <div class="wrap">  
            <div class="inner"></div>  
        </div>  
    </body>  
</html>

flex

<!doctype html>  
<html lang="en">  
    <head>  
    <title>Document</title>  
    <style>  
        .wrap {  
            width: 400px;  
            height: 400px;  
            border: 1px solid #000;  
            display: flex;  
            align-items: center;  
            justify-content: center;  
        }  
        .inner {  
            width: 200px;  
            height: 200px;  
            background: pink;  
        }  
    </style>  
    </head>  
    <body>  
        <div class="wrap">  
            <div class="inner"></div>  
        </div>  
    </body>  
</html>

JavaScript

JS的三大组成部分

  • ECMAScript:JavaScript的核心语法规范。
  • 文档对象模型(DOM):由页面元素组成,用于操作和处理文档内容。
  • 浏览器对象模型(BOM):允许JavaScript与浏览器进行交互,提供对浏览器环境的访问和操作。

内置对象

  1. String:字符串对象
  2. Boolean:布尔对象
  3. Number:数字对象
  4. Function:函数对象
  5. Object:通用对象
  6. Date:日期对象
  7. Math:数学计算对象

操作数组的方法

不改变原数组的方法

  1. find: 查找元素
  2. findIndex: 查找元素下标
  3. concat: 连接数组
  4. join: 将数组元素连接成字符串
  5. reduce: 对数组元素从左到右进行累积
  6. map: 对数组的每个元素进行操作后返回新数组
  7. filter: 返回满足条件的数组元素
  8. isArray: 判断是否为数组
  9. every: 检测数组所有元素是否符合条件
  10. some: 检测数组是否有元素符合条件
  11. slice: 返回数组的一部分,不改变原数组

改变原数组的方法

  1. pop: 删除数组最后一个元素
  2. push: 在数组末尾添加一个或多个元素
  3. shift: 删除数组的第一个元素
  4. unshift: 在数组开头添加一个或多个元素
  5. sort: 对数组进行排序
  6. reverse: 颠倒数组中元素的顺序
  7. splice: 从数组中添加或删除元素

基本数据类型和引用数据类型的区别

  • 基本数据类型: Number, Boolean, String, undefined, null。存储在内存栈中,保存的是具体的值。
  • 引用数据类型: Object, Function, Array。保存在堆内存中,保存的是值的引用。如果两个变量指向同一引用地址,其中一个修改值时,另一个变量的值也会发生改变。

如何判断数据类型

  • typeof: 用于判断基本数据类型,不适用于复杂数据类型。
  • instanceof: 用于判断复杂数据类型,不适用于基本数据类型。
  • constructor: 可以用于判断基本数据类型和复杂数据类型,但在某些情况下(原型链重写)可能存在问题。
  • Object.prototype.toString.call: 最完美的解决方案,适用于所有数据类型。
const getType = (target) => {  
    const typeString = Object.prototype.toString.call(target)  
    const match = typeString.replace(/\[object (\w+)\]/, '$1')  
    return match.toLowerCase()  
}

console.log(getType('123')) // string
console.log(getType([1,2,3])) // array

闭包

闭包的定义: 闭包是指函数嵌套函数的情形,内部函数被外部函数返回并保存下来,形成了对外部函数作用域的引用。这种引用使得内部函数能够访问外部函数的变量和参数,即便外部函数已经执行完毕。

特点:

  • 重复利用变量: 闭包允许内部函数访问外部函数的变量,避免了全局污染,同时提供了一种机制来保护变量不受外界直接访问。
  • 变量持久存在内存中: 由于闭包中的内部函数引用了外部函数的变量,这些变量在内存中得以保留,即使外部函数已经执行完毕。这使得闭包可以用来创建“私有”变量。
  • 潜在内存占用和内存泄漏: 如果闭包被过度使用,即存在大量的未释放内存的闭包,可能会导致浏览器占用内存较多,引发性能问题和潜在的内存泄漏。

使用场景:

  • 防抖与截流: 通过闭包可以保存防抖和截流中需要记忆的变量,确保函数在一定时间内只执行一次。
  • 避免函数污染: 闭包可以用于封装代码,防止函数内部的变量污染全局作用域,实现模块化的开发。

总体而言,闭包在 JavaScript 中是一种强大的机制,合理地使用闭包可以提高代码的可维护性和安全性。但需注意谨慎使用,以避免潜在的性能问题。

内存泄漏

定义: 已被赋值引用类型的变量,没有及时被垃圾回收机制清除和释放,长期占用内存,就容易造成内存泄漏,引起页面卡顿或崩溃。

原因:

  • 过渡闭包
  • 未清除的定时器
  • 未清除的变量或元素引用

解决方案: 尽早将不需要的变量引用置为null,以便及时释放内存。

事件冒泡和事件捕获

  • addEventListener 方法有三个参数,第三个参数用于控制是否是事件捕获。
  • 默认值为 false,即为事件冒泡,会先执行最先触发内部的方法,最后触发外层的方法。
  • 当第三个参数的值为 true 时为事件捕获,事件捕获最先执行外层的方法,最后触发内部的方法。
  • 其中事件捕获的优先级要高于事件冒泡,会先执行事件捕获的方法。
<body>  
    <div id="wrap">  
        <div id="inner">  
            <div id="content">
                <div id="text"></div>  
            </div>  
        </div>  
    </div>  
    <script>  
        const wrap = document.getElementById('wrap')  
        const inner = document.getElementById('inner')  
        const content = document.getElementById('content')  
        const text = document.getElementById('text')  

        wrap.addEventListener('click', () => {  
            console.log('wrap')  
        }, false)  

        inner.addEventListener('click', () => {  
            console.log('inner')  
        }, true)  

        content.addEventListener('click', () => {  
            console.log('content')  
        }, false)  
        
        text.addEventListener('click', () => {  
            console.log('text')  
        }, true)  
    </script>  
</body>

在代码中,当点击最里面的 id 为 text 元素时,innertext 绑定的属于事件捕获,会最先执行,由外到内,然后执行事件冒泡函数 contentwrap。 最终输出的顺序为:inner -> text -> content -> wrap

事件代理(委托): 利用事件冒泡,将事件绑定到父元素,通过事件冒泡传递的方式,实现对子元素的事件监听,减少事件监听器的数量,提高性能。

事件顺序控制: 在一些特定场景下,需要控制事件的执行顺序,可以通过事件捕获和冒泡的不同阶段进行灵活控制。

let、const、var 的区别

  • let:

    • 用于声明块级作用域的变量。
    • 允许变量被重新赋值。
    • 不会被提升作用域顶部。
  • const:

    • 用于声明块级作用域的常量,其值不能被重新赋值。
    • 必须在声明时进行初始化。
    • 不会被提升至作用域顶部。
  • var:

    • 用于声明全局作用域或函数作用域的变量。
    • 允许变量被重新赋值。
    • 会被提升至作用域顶部,但初始化为 undefined。
    • 不具备块级作用域。
// 使用 let
for (let i = 0; i < 5; i++) {
  setTimeout(() => {
    console.log(`let 循环中:${i}`);
  }, 1000);
}

// 使用 const
for (const j = 0; j < 5; j++) {
  // Error: 常量 j 不允许被重新赋值
  setTimeout(() => {
    console.log(`const 循环中:${j}`);
  }, 1000);
}

// 使用 var
for (var k = 0; k < 5; k++) {
  // 输出的是同一个 k,因为 var 不具备块级作用域
  setTimeout(() => {
    console.log(`var 循环中:${k}`);
  }, 1000);
}

在上述例子中,let 声明的变量在每次循环迭代时都会创建一个新的块级作用域,因此能正确捕获循环变量。而 const 声明的常量不允许重新赋值,因此在循环中使用会导致错误。而 var 则在整个函数作用域内都是可见的,因此在 setTimeout 内部访问时输出的是同一个 k 值。推荐使用 letconst,避免使用 var

补充: 使用var时,可以通过创建一个函数作用域来捕获循环变量的值。

// 使用 var
for (var k = 0; k < 5; k++) {
  // 利用立即执行函数创建一个新的函数作用域
  (function (index) {
    setTimeout(() => {
      console.log(`var 循环中:${index}`);
    }, 1000);
  })(k);
}

原型和原型链