Bootstrap

JavaScript进阶、es6语法

作用域和作用域链

作用域

作用域指的是在程序中定义变量的区域,这个区域决定了变量的可见性和生命周期。在不同的作用域中,可以定义同名的变量,它们互不影响。作用域可以分为以下几种:

  1. 全局作用域:在这个作用域中定义的变量在整个程序中都是可见的,直到程序结束。

  2. 函数作用域:在函数内部定义的变量只在该函数内部可见,函数执行完毕后,这些变量就会被销毁。

  3. 块作用域:在花括号{}内部定义的变量,只在这些花括号内部可见。例如,在if语句、for循环或者直接使用花括号定义的代码块中或者使用let和const声明的变量。

作用域链

作用域链是一种底层变量的查找机制,在函数执行时,会优先查找当前函数作用域中的变量,如果没有找到则会依次逐级查找父级作用域直到全局作用域。变量只能向上查找,不能向下查找。

垃圾回收机制

内存生命周期

1、内存分配:声明变量、函数、对象时,系统会自动分配内存

2、内存使用:读写内存,即使用变量、函数

3、内存回收:使用完毕,由垃圾回收机制自动回收不再使用的内存

注意

1、全局变量一般不会回收

2、一般情况下局部变量的值,不用了会被自动回收

内存泄漏

程序中分配内存由于某种原因程序未释放或无法释放

去除缓存的两个方法

1、引用计数:这是一种不太常用的垃圾回收方式。是针对值为引用类型数据的变量进行计数,引用一次计数+1。当一个对象的引用次数为0时,该对象被认为是无用的,可以被垃圾回收器回收。

弊端:对象循环引用

2、标记清除:从根部(全局对象)出发定时扫描内存中的对象,凡是能从根部到达的对象,都是需要使用的。那些无法从根部出发触及到的对象标记为不再使用。由垃圾回收机制进行回收。

闭包

什么是闭包

一个函数能够访问其外部函数的作用域(函数嵌套,内层函数 + 外层函数)

闭包的特点

1、访问外部变量:内部函数可以访问和操作外部函数的变量,即使外部函数已经执行完毕。

2、数据封装:闭包可以用来创建私有变量,因为外部函数的变量不会被外部直接访问,只能通过闭包函数(内部函数)进行访问和修改。

3、数据私有化

4、不会被垃圾回收机制回收

function fnA(){
    let a = 1
    function fnB(){
        console.log(a);
    }
    return fnB
}

const fnC = fnA()
fnC()

注意事项

1、内存泄漏:由于闭包会持续引用外部变量,可能会导致内存泄漏,特别是当外部变量是大型对象或者数组时。

2、性能问题:过度使用闭包可能会影响性能,因为它们增加了垃圾回收的复杂性。

变量提升

变量声明被提升

只有var声明的变量,变量在声明时会被提升到当前作用域最前面声明,但在赋值之前它们的值是undefined

let 和 const 不完全提升

var不同,letconst声明的变量不会被提升到作用域的顶部,而是被提升到它们所在代码块的顶部,并且在代码块内形成了一个“暂时性死区”。

函数参数

使用动态参数( arguments 对象)

arguments 对象是一个类数组对象,包含了函数调用时传入的所有参数。它不是真正的数组,所以没有数组的方法,但是可以通过索引访问每个参数。

function sum() {
    var total = 0;
    for (var i = 0; i < arguments.length; i++) {
        total += arguments[i];
    }
    return total;
}

console.log(sum(1, 2, 3, 4)); // 输出:10

使用剩余参数(REST )

ES6 引入了 REST 参数,它允许我们将一个不定数量的参数表示为一个数组。

function sum(...args) {
    return args.reduce((total, num) => total + num, 0);
}

console.log(sum(1, 2, 3, 4)); // 输出:10

展开运算符(...)

允许一个数组或类数组对象在需要多个参数(函数参数)或多个元素(数组元素)的地方被展开

使用场景

合并数组

const array1 = [1, 2];
const array2 = [3, 4];
const combinedArray = [...array1, ...array2]; // [1, 2, 3, 4]

求数组最大/小值

const arr= [1, 2, 3];
console.log(Math.max(...arr));
console.log(Math.min(...arr));

复制数组

const originalArray = [1, 2, 3];
const copiedArray = [...originalArray];

插入元素到数组中

const array = [1, 2, 4];
const newArray = [0, ...array, 5]; // [0, 1, 2, 4, 5]

在函数中传递参数

const args = [1, 2, 3];
function sum(a, b, c) {
    return a + b + c;
}
const result = sum(...args); // 6

new 操作符一起使用

const dateFields = [2024, 11, 14];
const date = new Date(...dateFields);

对象复制和合并

const obj1 = { a: 1, b: 2 };
const obj2 = { b: 3, c: 4 };
const combinedObj = { ...obj1, ...obj2 }; // { a: 1, b: 3, c: 4 }

注意

1、展开运算符只能展开可迭代对象,这意味着它不能直接用于非可迭代对象,如普通对象(除非使用对象的[Symbol.iterator]属性)。

2、展开运算符会创建数组或对象的浅拷贝,这意味着如果数组或对象中包含嵌套的数组或对象,只有第一层会被展开。

3、在函数参数中使用展开运算符时,如果参数是undefinednull,它们会被当作空数组处理。

箭头函数

箭头函数是ES6中引入的一种新的函数定义方式,它提供了一种更简洁的函数写法。箭头函数的语法比传统的函数表达式更简洁,并且没有自己的thisargumentssupernew.target。可以替代匿名函数

基本语法

没有参数或一个参数

// 没有参数
const func = () => {
    // 函数体
};

// 一个参数
const func = x => {
    return x;
};

多个参数

const func = (x, y) => {
    return x + y;
};

隐式返回

const func = x => x * x;

箭头函数的特点

1、this值的继承: 箭头函数不绑定自己的this值,它会捕获其所在上下文的this值作为自己的this值,这使得箭头函数非常适合用于回调函数。

2、没有arguments对象: 箭头函数没有自己的arguments对象,但可以通过剩余参数(...args)来访问函数参数。

3、不能作为构造函数: 箭头函数不能用作构造函数,尝试这样做会抛出错误。

4、没有new.target: 箭头函数内部没有new.target属性,这个属性通常用于确定函数是否作为构造函数被调用。

5、不绑定super: 箭头函数不绑定super,因此不能在箭头函数中使用super关键字。

6、不创建ArrayObject: 在箭头函数中使用ArrayObject字面量时,它们不会被特殊处理,例如[]{}会被当作普通表达式。

数组解构

数组解构是ES6中引入的一个特性,它允许我们通过一个简洁的语法将数组中的值赋给多个变量。这种语法形式类似于对象解构,但是专门用于数组。

基本用法

1、赋值运算符:左侧的 [ ] 用于批量声明变量,右侧数组的单元值将被赋值给左侧的变量

2、变量的顺序对应数组单元值的位置依次进行赋值操作

基本解构

const arr = [1, 2, 3];
const [a, b, c,d] = arr;
console.log(a); // 1
console.log(b); // 2
console.log(c); // 3
console.log(d); // undefined

忽略某些元素

如果你不想为数组中的每个元素都创建一个变量,可以使用下划线 _ 或者任意无效标识符来忽略它们

const arr = [1, 2, 3, 4];
const [a, , , d] = arr;
console.log(a); // 1
console.log(d); // 4

重命名变量

在解构时,你可以为变量指定新的名字,不必与数组中的元素顺序对应。

const arr = [1, 2, 3];
const [x, y, z] = arr;
console.log(x); // 1
console.log(y); // 2
console.log(z); // 3

默认值

如果数组中的某个元素是undefined,可以为解构的变量提供一个默认值。

const arr = [1, undefined, 3];
const [a, b = 2, c] = arr;
console.log(a); // 1
console.log(b); // 2
consol
;