ES6 (ECMAScript 2015) 的一些特性

349 阅读7分钟

ES6 (ECMAScript 2015) 的一些特性

ECMAScript 2015(简称ES6)是JavaScript语言的重要更新,引入了许多新特性,这些特性使得JavaScript的编写变得更加简洁、高效和现代化。下面是ES6的部分主要特性及其详细介绍:

1. let 和 const

  • let:用于声明变量,作用域仅限于块级作用域(如if语句、循环体等),相比于 var,它避免了变量提升(hoisting)的问题。

    let x = 10;
    if (true) {
        let x = 20; // 块级作用域内的x
        console.log(x); // 输出20
    }
    console.log(x); // 输出10
    
  • const:用于声明常量,常量的值在声明时必须初始化,且不能再被修改。它也遵循块级作用域。

    const pi = 3.14;
    pi = 3.14159; // 报错,不能重新赋值
    

2. 箭头函数 (Arrow Functions)

箭头函数提供了更简洁的函数表达式,并且具有不同的 this 绑定行为。箭头函数的 this 是在定义时绑定的,而不是调用时绑定的。

const add = (a, b) => a + b;
const square = n => n * n;

传统的函数:

function add(a, b) {
return a + b;
}

箭头函数不适用 arguments,不可以作为构造函数。

3. 模板字符串 (Template Literals)

使用反引号(`)来定义字符串,可以轻松进行字符串插值和多行字符串。

const name = "World";
const greeting = `Hello, ${name}!`;
console.log(greeting); // 输出: Hello, World!

也支持多行字符串:

const message = `This is a
multiline string.`;

4. 解构赋值 (Destructuring Assignment)

解构赋值允许从数组或对象中提取值,并将其赋给变量,语法更加简洁。

  • 数组解构:

    const arr = [1, 2, 3];
    const [a, b] = arr;
    console.log(a, b); // 输出: 1 2
    
  • 对象解构:

    const obj = { x: 10, y: 20 };
    const { x, y } = obj;
    console.log(x, y); // 输出: 10 20
    

5. 默认参数值 (Default Parameters)

可以为函数参数指定默认值,若调用时没有传入该参数,则使用默认值。

function greet(name = "Guest") {
console.log(`Hello, ${name}!`);
}
greet(); // 输出: Hello, Guest!
greet("Alice"); // 输出: Hello, Alice!

6. 扩展运算符 (Spread Operator)

扩展运算符 ... 可以将数组或对象解构为单个元素,也可以将多个元素合并到一个新数组或对象中。

  • 数组:

    const arr1 = [1, 2];
    const arr2 = [3, 4];
    const combined = [...arr1, ...arr2];
    console.log(combined); // 输出: [1, 2, 3, 4]
    
  • 对象:

    const obj1 = { a: 1, b: 2 };
    const obj2 = { c: 3, d: 4 };
    const combinedObj = { ...obj1, ...obj2 };
    console.log(combinedObj); // 输出: { a: 1, b: 2, c: 3, d: 4 }
    

7. 剩余参数 (Rest Parameters)

剩余参数允许函数接受一个不定数量的参数,并将其作为数组处理。

function sum(...numbers) {
return numbers.reduce((acc, num) => acc + num, 0);
}
console.log(sum(1, 2, 3)); // 输出: 6

8. 类 (Classes)

ES6引入了面向对象的类(class),这使得定义类和创建对象的语法更加直观。

class Person {
constructor(name, age) {
 this.name = name;
 this.age = age;
}

greet() {
 console.log(`Hello, I'm ${this.name} and I'm ${this.age} years old.`);
}
}

const person = new Person("Alice", 30);
person.greet(); // 输出: Hello, I'm Alice and I'm 30 years old.

9. 模块化 (Modules)

ES6引入了原生的模块化支持,使用 importexport 来导入和导出模块。

  • 导出:

    // person.js
    export const name = "Alice";
    export function greet() {
      console.log("Hello!");
    }
    
  • 导入:

    // app.js
    import { name, greet } from './person.js';
    greet(); // 输出: Hello!
    console.log(name); // 输出: Alice
    

10. Promise

ES6引入了 Promise,它是处理异步操作的一种新方式,提供了更优雅的解决方案,避免了回调地狱。

const fetchData = new Promise((resolve, reject) => {
  const success = true;
  if (success) {
    resolve("Data fetched successfully");
  } else {
    reject("Error fetching data");
  }
});

fetchData
  .then((result) => console.log(result)) // 成功时执行
  .catch((error) => console.log(error)); // 失败时执行

11. Symbol

Symbol 是一种新的基本数据类型,它是唯一且不可变的。通常用于对象的属性名,以避免属性名的冲突。

const sym = Symbol('description');
const obj = {
[sym]: 'value'
};
console.log(obj[sym]); // 输出: value

12. 迭代器与生成器 (Iterators & Generators)

  • 迭代器:每个对象都可以通过迭代器来遍历。

  • 生成器:生成器函数(使用 function* 定义)可以控制函数的执行流程,通过 yield 暂停和恢复函数的执行。

    function* generator() {
      yield 1;
      yield 2;
      yield 3;
    }
    const gen = generator();
    console.log(gen.next().value); // 输出: 1
    console.log(gen.next().value); // 输出: 2
    

13. Set 和 Map

  • Set:一种新的数据结构,类似于数组,但是其元素是唯一的。

    const set = new Set([1, 2, 3, 3]);
    console.log(set); // 输出: Set { 1, 2, 3 }
    
  • Map:一种新的数据结构,类似于对象,但是键可以是任意类型。

    const map = new Map();
    map.set('name', 'Alice');
    map.set(1, 'number');
    console.log(map.get('name')); // 输出: Alice
    

14. Array Buffers 和 Typed Arrays

ES6 引入了 ArrayBufferTypedArray,它们为高效处理二进制数据提供了支持,主要用于处理 Web APIs,如文件读取、WebSockets 等。

Array BuffersTyped Arrays 是 ES6 中引入的两个特性,它们为高效地处理二进制数据提供了支持,尤其在处理图像、音频、视频、文件读取、网络请求等低级数据操作时非常有用。它们通常用于需要直接操作内存数据的场景,如 Web APIs(例如文件读取、WebSockets)、WebGL 等。

  • ArrayBuffer

    ArrayBuffer 是一个用于表示通用的、固定长度的二进制数据缓冲区。你可以通过它创建一个包含原始二进制数据的缓冲区。

    • 创建和使用 ArrayBuffer
    // 创建一个包含 16 个字节的 ArrayBuffer
    const buffer = new ArrayBuffer(16); 
    
    // 创建一个 DataView 来读取和写入 ArrayBuffer 数据
    const view = new DataView(buffer);
    
    // 向位置 0 写入一个 32 位整数 (4 字节)
    view.setInt32(0, 123456789);
    
    // 从位置 0 读取这个整数
    const value = view.getInt32(0);
    console.log(value); // 输出: 123456789
    

在上面的例子中:

  • ArrayBuffer 创建了一个包含 16 字节的缓冲区。

  • 使用 DataView 来操作这个缓冲区的数据,DataView 提供了多种方法来读写不同类型的二进制数据(如 getInt32, setInt32, getFloat32 等)。

    • Typed Arrays

    Typed Arrays 是 JavaScript 中的数组类型,提供了对 ArrayBuffer 的视图,可以更高效地操作数组数据。每种 Typed Array 对应一个特定的二进制数据类型(如 Int8ArrayUint16ArrayFloat32Array 等)。

    创建和使用 Typed Array

    // 创建一个包含 5 个元素的 32 位浮点数数组 (Float32Array)
    const buffer = new ArrayBuffer(5 * 4); // 5 个 4 字节元素 (Float32)
    const typedArray = new Float32Array(buffer);
    
    // 向数组中写入数据
    typedArray[0] = 10.5;
    typedArray[1] = 20.25;
    typedArray[2] = 30.75;
    typedArray[3] = 40.1;
    typedArray[4] = 50.5;
    
    // 输出整个数组
    console.log(typedArray); // 输出: Float32Array(5) [10.5, 20.25, 30.75, 40.1, 50.5]
    

在这个例子中:

  • 我们创建了一个 ArrayBuffer,它可以容纳 5 个 Float32 元素(每个元素 4 字节)。

  • 然后使用 Float32Array 来访问这个缓冲区中的数据,Float32Array 是一个 Typed Array,专门处理 32 位的浮点数。

常见的 Typed Array 类型

  • Int8Array:8 位带符号整数数组。

  • Uint8Array:8 位无符号整数数组。

  • Int16Array:16 位带符号整数数组。

  • Uint16Array:16 位无符号整数数组。

  • Int32Array:32 位带符号整数数组。

  • Uint32Array:32 位无符号整数数组。

  • Float32Array:32 位浮点数数组。

  • Float64Array:64 位浮点数数组。 -结合 Typed ArrayArrayBuffer 的常见使用场景

    • 读取文件数据

      使用 ArrayBufferTyped Array 来读取二进制文件(例如图像、音频文件等)。

      // 假设你有一个文件上传表单
      const fileInput = document.querySelector('input[type="file"]');
      fileInput.addEventListener('change', handleFileSelect);
      
      function handleFileSelect(event) {
          const file = event.target.files[0];
          const reader = new FileReader();
      
          // 读取文件为 ArrayBuffer
          reader.readAsArrayBuffer(file);
      
          reader.onload = function() {
              // 文件数据读取完成
              const arrayBuffer = reader.result;
      
              // 将 ArrayBuffer 转换为 Uint8Array 以便操作
              const typedArray = new Uint8Array(arrayBuffer);
      
              // 现在可以对 typedArray 进行处理,例如:
              console.log(typedArray);  // 输出文件的二进制数据
          };
      }
      

      在这个例子中:

      • 通过 FileReader 将文件读取为 ArrayBuffer
      • 然后用 Uint8Array 来访问和操作这个文件数据,Uint8Array 是一个 Typed Array,它允许我们按字节处理文件内容。

      WebSockets 中的二进制数据

      ArrayBufferTyped Array 也可以在 WebSockets 中用来发送和接收二进制数据。

      const socket = new WebSocket('wss://example.com/socket');
      
      // 当连接建立时,发送二进制数据
      socket.onopen = function() {
          const buffer = new ArrayBuffer(8);
          const view = new DataView(buffer);
          view.setInt32(0, 123);
          view.setInt32(4, 456);
      
          socket.send(buffer);  // 发送 ArrayBuffer 数据
      };
      
      // 当接收到二进制数据时
      socket.onmessage = function(event) {
          const arrayBuffer = event.data;
          const typedArray = new Int32Array(arrayBuffer);
          console.log(typedArray);  // 输出接收到的 Int32Array 数据
      };
      

      在这个例子中:

      • 使用 WebSocket 发送一个包含 8 字节数据的 ArrayBuffer
      • 当接收到数据时,通过 Int32Array 来访问二进制数据。

    使用 ArrayBufferTyped Array 与 WebGL

    ArrayBufferTyped Array 在 WebGL 中非常常见,它们被用来操作像素数据、着色器数据等。

    // 创建一个包含 3 个浮点数的数组
    const vertices = new Float32Array([0.0, 1.0, 0.0, -1.0, -1.0, 0.0, 1.0, -1.0, 0.0]);
    
    // 使用 WebGL 来操作数据
    const gl = canvas.getContext('webgl');
    
    // 创建一个缓冲区对象
    const buffer = gl.createBuffer();
    
    // 绑定缓冲区并传入数据
    gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
    gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
    
    // 设置顶点属性指针并启用它
    gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 0, 0);
    gl.enableVertexAttribArray(0);
    
    // 绘制
    gl.drawArrays(gl.TRIANGLES, 0, vertices.length / 3);
    

    在这个例子中:

    • 我们使用 Float32Array 来存储 WebGL 需要的顶点数据。
    • 使用 gl.bufferData() 把数据上传到 WebGL 的缓冲区。
    • 通过 gl.vertexAttribPointer()gl.enableVertexAttribArray() 设置顶点属性指针,并绘制三角形。