HTML + CSS
盒子模型
-
标准盒模型 由padding + maring + border + content组成
-
IE盒模型 由margin + content(包含border + padding)组成
可以通过box-sizing属性控制盒子模型的模式,默认为content-box,可以设置为boder-box(IE盒模型)
CSS优先级
- !important:最高优先级,将覆盖任何其他样式。
- style:内联样式。
- id:通过ID选择器指定的样式。
- 类/伪类/属性:通过类选择器、伪类选择器或属性选择器指定的样式。
- 标签:通过标签名指定的样式。
- 通配符:通配符选择器指定的样式。
优先级从高到低,高优先级的样式会覆盖低优先级的样式。
隐藏页面元素
- opacity: 0:元素透明度为0,但仍占据页面空间。
- display: none:元素不可见,且不占据页面空间。
- visibility: hidden:元素不可见,但仍占据页面空间。
px,em,rem的区别
- px:是浏览器的绝对单位。
- em :相对于父元素的
font-size
进行单位计算。 - rem :相对于根元素(
html
)的font-size
进行单位计算。
重排(回流),重绘
- 重排 指的是当元素的位置、大小或几何形状发生改变时,浏览器需要重新计算元素的几何属性,然后再重新构建页面的过程。
- 重绘 是指当元素的样式,如背景色、字体颜色等发生改变时,浏览器只需要将新样式绘制在已经计算好的页面上,而不需要改变元素的几何属性。
重排必定引起重绘,在性能优化的过程中,尽量减少重排和重绘的次数,以提高页面的渲染性能。
元素居中
position
html
<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
html
<!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
html
<!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与浏览器进行交互,提供对浏览器环境的访问和操作。
内置对象
- String:字符串对象
- Boolean:布尔对象
- Number:数字对象
- Function:函数对象
- Object:通用对象
- Date:日期对象
- Math:数学计算对象
操作数组的方法
不改变原数组的方法
- find: 查找元素
- findIndex: 查找元素下标
- concat: 连接数组
- join: 将数组元素连接成字符串
- reduce: 对数组元素从左到右进行累积
- map: 对数组的每个元素进行操作后返回新数组
- filter: 返回满足条件的数组元素
- isArray: 判断是否为数组
- every: 检测数组所有元素是否符合条件
- some: 检测数组是否有元素符合条件
- slice: 返回数组的一部分,不改变原数组
改变原数组的方法
- pop: 删除数组最后一个元素
- push: 在数组末尾添加一个或多个元素
- shift: 删除数组的第一个元素
- unshift: 在数组开头添加一个或多个元素
- sort: 对数组进行排序
- reverse: 颠倒数组中元素的顺序
- splice: 从数组中添加或删除元素
如何判断数据类型
- typeof: 用于判断基本数据类型,不适用于复杂数据类型。
- instanceof: 用于判断复杂数据类型,不适用于基本数据类型。
- constructor : 可以用于判断基本数据类型和复杂数据类型,但在某些情况下(原型链重写)可能存在问题。
- Object.prototype.toString.call: 最完美的解决方案,适用于所有数据类型。
javascript
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
时为事件捕获,事件捕获最先执行外层的方法,最后触发内部的方法。 - 其中事件捕获的优先级要高于事件冒泡,会先执行事件捕获的方法。
html
<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
元素时,inner
和 text
绑定的属于事件捕获,会最先执行,由外到内,然后执行事件冒泡函数 content
和 wrap
。 最终输出的顺序为:inner -> text -> content -> wrap
。
let、const、var 的区别
-
let:
- 用于声明块级作用域的变量。
- 允许变量被重新赋值。
- 不会被提升作用域顶部。
-
const:
- 用于声明块级作用域的常量,其值不能被重新赋值。
- 必须在声明时进行初始化。
- 不会被提升至作用域顶部。
-
var:
- 用于声明全局作用域或函数作用域的变量。
- 允许变量被重新赋值。
- 会被提升至作用域顶部,但初始化为 undefined。
- 不具备块级作用域。
javascript
// 使用 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 值。推荐使用 let
和 const
,避免使用 var
。