目录
16. 严格模式
代码按严格模式解析,JS 在更严格的条件下运行。
好处
- 消除不合理和不严谨之处:
- 禁止不安全语法和用法,如使用未声明变量会成为全局变量。
- 禁止
with
语句,with
语句会动态改变作用域,导致难以追踪错误。
- 提高代码安全性:
eval()
函数不会在其外部作用域引入新的变量或函数。防止潜在代码注入攻击。- 禁止删除不可删除的属性(如对象内置属性)。
- 提高编译器效率:
- 严格模式本身不直接提高运行时的性能,但通过减少潜在的运行错误和异常,使代码清晰和可预测,有助于编译器更有效的优化。
- 严格模式鼓励使用更现代的 JS 特性,在现代 JS 引擎中通常得到更好的优化。
- 为未来版本的JS 铺路:
- 严格模式可以看作是 JS 未来版本的预览,引入了一些新的限制和错误检查,可能成为未来语言规范的正式部分。
坏处
- 不一样的运行结果:
- 严格模式可能会改变某些代码行为。如,对未声明变量赋值会抛出错误,而不像非严格模式下自动成为全局变量。
- 一些函数参数和
this
值在严格模式下也有不同行为。
- 兼容性问题:
- 旧版本JS 中编写的代码可能不完全兼容严格模式。虽然这鼓励了代码现代化和改进,但可能导致在迁移到严格模式时需进行大量重构工作。
- 并非所有JS 环境都完全支持严格模式。
- 学习曲线:
- 理解严格模式的规则和限制需要时间。掌握这些规则将极大提高代码质量和可维护性。
17. ES6+新特性
1.变量声明
- let 和 const:引入块级作用域,不需要立即执行函数。使变量作用域更清晰,避免了
var
导致的变量提升。const
声明常量,赋值后不可改变(对象或数组不可改变其引用,内容可变)。
2.数据类型与数据结构
- Symbol:新的基本数据类型,创建唯一标识符,用于对象属性名,解决属性名冲突问题。
- Set 和 Map:Set类似数组,但成员的值唯一不重复。Map是键值对的集合,一个键可以映射到最多一个值。
3.语言扩展(字符串、数组、正则、对象、函数)
- 模板字符串:使用反引号
`
包裹的字符串,可嵌入表达式,通过${}
语法插值。 - 默认参数、剩余参数:允许函数参数有默认值,使用剩余参数(...)接收不定数量的参数。
- 对象属性的简洁表达:允许直接通过变量名作为对象的属性名,无需使用引号包裹。
- 解构赋值:允许从数组或对象中提取数据,对变量赋值,使数据操作更简洁。
- 箭头函数:提供一种更简洁的函数书写方式,不绑定自己的
this
,arguments
,super
,或new.target
。这些函数表达式更适用于非方法函数,并且它们不能用作构造函数。
4.异步编程
- Promise:表示一个异步操作的最终完成(或失败)及其结果值。
- async/await:建立在Promise上,使异步代码看起来像同步代码,简化异步代码编写理解。
- Generator:函数可暂停执行和恢复执行,使异步编程更加灵活可控。
5.模块化
- import 和 export:支持ES模块(ESM),允许JS代码以模块化的方式组织,每个模块可以导入其他模块导出的功能,同时也支持导出本模块的功能供其他模块使用。
6.类(Class)
- 引入
class
关键字,提供了一种更清晰、更易于理解的方式创建和使用对象。类支持继承、构造函数、方法、getter/setter等面向对象编程的特性。
7.编译与兼容性
- 由于ES6及之后的许多新特性在旧版浏览器中不被支持,实际开发中常使用Babel的 JS 编译器将ES6+代码转译为ES5代码,确保代码能在尽可能多的环境中运行。
18. JS的垃圾回收机制
垃圾回收GC:清理程序不用的内存或者是之前用过了,以后不会再用的内存空间。js 中的垃圾回收机制是确保内存不被无用数据占用的关键过程。js 引擎使用不同策略来管理堆和栈上的内存分配和释放。
栈的垃圾回收:
栈用于存储执行上下文,包括函数调用的局部变量、参数等信息。函数执行完毕后,其执行上下文会从栈中自动弹出,由 js 引擎控制。栈内存的分配和释放(即“垃圾回收”)通过这种方式自动完成,开发者通常不需手动干预。
堆的垃圾回收:
堆是 js 用来存储对象、数组等复杂数据结构的内存区域。由于堆内存的分配和释放更复杂, js 引擎采用垃圾回收机制来管理。
- 引用计数法:
通过追踪每个对象被引用的次数判断对象是否可以被回收。当一个对象没有任何引用指向它时(即引用计数为0),该对象就会被垃圾回收机制回收。存在循环引用问题(两个对象相互引用,但不再被其他对象引用,导致引用计数永不为0,无法被回收)。现代 JS 引擎很少使用该方法。
- 标记清除法:
是大多数 js引擎采用的垃圾回收算法,解决了引用计数法中的循环引用问题,但可能导致内存碎片,影响内存分配效率。该算法分为两阶段:
- 标记阶段:遍历所有从根集合(根集合通常是全局变量和当前执行上下文中的局部变量)可达的对象,为所有活动对象做上标记。
- 清除阶段:遍历堆中的所有对象,回收那些未被标记的对象(即非活动对象)。
- v8引擎的垃圾回收优化:
- 分代收集:将堆分为新、老生代。新生代对象存活时间短,老生代对象存活时间长。V8 对这两个区域采用不同的垃圾回收策略,更频繁地回收新生代区域,以减少每次遍历的时间。
- 并行回收:在新生代中,V8 使用并行回收技术加快垃圾回收过程。多个垃圾回收器线程可同时工作,提高效率。
- 并发标记:在老生代中,V8 使用并发标记减少对主线程的影响。标记过程可以在主线程执行 JS 代码的同时进行,减少垃圾回收的停顿时间。
- 增量标记:为了进一步减少停顿时间,V8 还实现了增量标记。标记过程可以分成多个小块,与主线程的执行交错进行。
19. 无限极目录递归
// 示例数据
const data = [
{
name: 'Item 1',
child: [
{ name: 'Item 1.1' },
{ name: 'Item 1.2', child: [{ name: 'Item 1.2.1' }] }
]
},
{
name: 'Item 2'
}
];
function createTree(data) {
let str = '<ul>';
data.forEach(item => {
str += `<li>${item.name}`;
if(item.child) {
str += createTree(item.child);
}
str += '</li>';
})
str += '</ul>';
return str;
}
document.querySelector('#lists').innerHTML = createTree(data)
// 父组件
<div id="lists">
<Item v-for="(v,i) in items" :key="i" :item="v"></Item>
</div>
// 子组件
<template>
<ul>
<li>{{item.name}}
<Item v-for="(v,i) in item.child" :key="i" :item="v"></Item>
</li>
</ul>
</template>
20. 全选功能实践
checkAllChange(){
this.lists.forEach(item => {
item.check = this.checkALL
})
},
checkChange(){
this.checkALL = this.lists.every(item => item.check)
},