ES5 vs ES6:JavaScript 演进之路

ES5 vs ES6:JavaScript 演进之路

  • JavaScript版本演进
  • [ES5 vs ES6](#ES5 vs ES6)
    • [1. 变量声明对比](#1. 变量声明对比)
    • [2. 函数特性对比](#2. 函数特性对比)
    • [3. 类和对象](#3. 类和对象)
    • [4. 模块化](#4. 模块化)
    • [5. 解构和展开](#5. 解构和展开)
    • [6. 字符串和模板字面量](#6. 字符串和模板字面量)
    • [7. 数组和对象新方法](#7. 数组和对象新方法)
    • [8. Promise和异步编程](#8. Promise和异步编程)
    • [9. 其他新特性](#9. 其他新特性)
  • 总结

JavaScript版本演进

ECMAScript是JavaScript的标准规范。

JavaScript是ECMAScript的一个实现,包含了ECMAScript以及DOM和BOM等额外的功能。

ES5 (ECMAScript 5)

  • 发布时间:2009年12月
  • 主要目标:提高语言的可靠性、安全性和表现力
  • 重要特性:
    1. strict模式:更严格的语法检查
    2. JSON支持:JSON.parse()和JSON.stringify()
    3. 数组方法:forEach, map, filter, reduce, some, every等
    4. 对象属性:getter/setter
    5. Object方法:Object.create(), Object.defineProperty()等

ES6 (ECMAScript 2015)

  • 发布时间:2015年6月
  • 又称:ES2015(开始采用年份命名)
  • 是JavaScript历史上最重要的版本更新
  • 重要意义:
    1. 使JavaScript更适合编写复杂的大型应用程序
    2. 提供更好的模块化支持
    3. 引入类的概念,使面向对象编程更简单
    4. 增强的异步编程能力

版本演进时间线

版本 发布年份 重要特性
ES1 1997 第一个版本
ES2 1998 细微更新
ES3 1999 正则表达式、try/catch
ES4 放弃 过于激进,未发布
ES5 2009 strict模式、JSON支持、新增数组方法
ES6/ES2015 2015 类、模块、箭头函数、Promise等
ES2016 2016 Array.prototype.includes, 指数运算符
ES2017 2017 async/await, Object.values/entries
ES2018 2018 Rest/Spread属性、异步迭代
ES2019 2019 Array.prototype.flat, Object.fromEntries
ES2020 2020 可选链操作符、空值合并运算符
ES2021 2021 String.prototype.replaceAll, Promise.any
ES2022 2022 Top-level await, Class Fields

为什么ES6如此重要?

  1. 开发效率:

    • 简洁的语法(箭头函数、解构赋值)
    • 更好的变量作用域控制(let/const)
    • 模板字符串提高字符串处理效率
  2. 代码质量:

    • 类的支持使面向对象更规范
    • 模块化支持使代码组织更清晰
    • Promise让异步代码更易维护
  3. 性能提升:

    • 更好的内存管理(块级作用域)
    • 优化的数组和对象操作
    • 改进的字符串处理
  4. 生态系统:

    • 统一的模块化标准
    • 更好的工具支持
    • 框架开发的基础

ES5 vs ES6

1. 变量声明对比

特性 ES5 ES6
变量声明 var let, const
变量提升
暂时性死区
块级作用域
重复声明 允许 不允许

示例代码:

javascript 复制代码
// ES5变量声明和提升示例
console.log(x); // 输出: undefined (变量提升,但值未定义)
var x = 1;
var x = 2; // 允许重复声明
console.log(x); // 输出: 2

// ES6变量声明
// console.log(y); // 错误:暂时性死区,不能在声明前访问
let y = 1;
// let y = 2; // 错误:不能重复声明
console.log(y); // 输出: 1

// 块级作用域示例
{
    let blockScoped = 'only available in this block';
    const CONSTANT = 'cannot be reassigned';
    console.log(blockScoped); // 输出: "only available in this block"
    console.log(CONSTANT);    // 输出: "cannot be reassigned"
}
// console.log(blockScoped); // 错误:blockScoped未定义
// console.log(CONSTANT);    // 错误:CONSTANT未定义

// const声明后不能修改引用,但可以修改对象属性
const person = { name: 'John' };
person.name = 'Jane'; // 允许
console.log(person.name); // 输出: "Jane"
// person = {}; // 错误:不能重新赋值

2. 函数特性对比

特性 ES5 ES6
默认参数 需手动检查 直接在参数列表定义
箭头函数
this绑定 动态绑定 词法绑定
参数处理 arguments对象 剩余参数(...rest)

示例代码:

javascript 复制代码
// ES5默认参数
function greetES5(name) {
    // 使用逻辑或运算符设置默认值
    name = name || 'Guest';
    return 'Hello ' + name;
}
console.log(greetES5());      // 输出: "Hello Guest"
console.log(greetES5('John')); // 输出: "Hello John"

// ES6默认参数和箭头函数
const greetES6 = (name = 'Guest') => `Hello ${name}`;
console.log(greetES6());      // 输出: "Hello Guest"
console.log(greetES6('Jane')); // 输出: "Hello Jane"

// ES5 this绑定问题示例
function Counter() {
    var self = this; // 保存this引用
    this.count = 0;
    setInterval(function() {
        self.count++;
        console.log(self.count); // 每秒输出递增的数字
    }, 1000);
}

// ES6箭头函数自动绑定this
class CounterES6 {
    constructor() {
        this.count = 0;
        setInterval(() => {
            this.count++;
            console.log(this.count); // 每秒输出递增的数字
        }, 1000);
    }
}

// 剩余参数示例
// ES5使用arguments
function sumES5() {
    var args = Array.prototype.slice.call(arguments);
    return args.reduce(function(sum, num) {
        return sum + num;
    }, 0);
}
console.log(sumES5(1, 2, 3)); // 输出: 6

// ES6使用剩余参数
const sumES6 = (...numbers) => numbers.reduce((sum, num) => sum + num, 0);
console.log(sumES6(1, 2, 3)); // 输出: 6

3. 类和对象

特性 ES5 ES6
类定义 构造函数 class关键字
继承实现 原型链 extends关键字
静态方法 手动添加 static关键字
构造函数 同名函数 constructor方法

示例代码:

javascript 复制代码
// ES5方式定义类
function Animal(name) {
    // 构造函数内定义实例属性
    this.name = name;
}

// 在原型上定义实例方法
Animal.prototype.speak = function() {
    return this.name + ' makes a sound';
};

// ES5方式创建和使用实例
var dog = new Animal('Dog');
console.log(dog.name);        // 输出: "Dog"
console.log(dog.speak());     // 输出: "Dog makes a sound"

// ES6方式定义类
class AnimalES6 {
    // constructor是类的构造方法
    constructor(name) {
        // 定义实例属性
        this.name = name;
    }
    
    // 类方法直接定义在类中,无需使用prototype
    speak() {
        return `${this.name} makes a sound`;
    }
    
    // static关键字定义静态方法,只能通过类本身调用,不能通过实例调用
    static create(name) {
        return new AnimalES6(name);
    }
}

// ES6方式创建和使用实例
const cat = new AnimalES6('Cat');
console.log(cat.name);        // 输出: "Cat"
console.log(cat.speak());     // 输出: "Cat makes a sound"

// 使用静态方法创建实例
const bird = AnimalES6.create('Bird');
console.log(bird.speak());    // 输出: "Bird makes a sound"

// 继承示例
// ES5继承
function Dog(name, breed) {
    // 调用父类构造函数
    Animal.call(this, name);
    this.breed = breed;
}
// 设置原型链
Dog.prototype = Object.create(Animal.prototype);
Dog.prototype.constructor = Dog;
// 添加子类特有方法
Dog.prototype.bark = function() {
    return this.name + ' barks!';
};

// ES6继承
class DogES6 extends AnimalES6 {
    constructor(name, breed) {
        // 调用父类构造函数
        super(name);
        this.breed = breed;
    }

    // 子类特有方法
    bark() {
        return `${this.name} barks!`;
    }
}

// 使用继承类
const husky = new Dog('Max', 'Husky');
console.log(husky.speak());   // 输出: "Max makes a sound"
console.log(husky.bark());    // 输出: "Max barks!"

const golden = new DogES6('Buddy', 'Golden Retriever');
console.log(golden.speak());  // 输出: "Buddy makes a sound"
console.log(golden.bark());   // 输出: "Buddy barks!"

4. 模块化

特性 ES5 ES6
模块定义 CommonJS/AMD ES Modules
导出语法 module.exports export/export default
导入语法 require() import
动态导入 无原生支持 dynamic import()

示例代码:

javascript 复制代码
// ES5 (CommonJS)
// math.js
module.exports = {
    add: function(a, b) {
        return a + b;
    }
};
// main.js
var math = require('./math');

// ES6
// math.js
export const add = (a, b) => a + b;
export default class Calculator {};
// main.js
import { add } from './math';
import Calculator from './math';

5. 解构和展开

ES6新增特性:

javascript 复制代码
// 数组解构
const [a, b, ...rest] = [1, 2, 3, 4, 5];
console.log(a);    // 输出: 1
console.log(b);    // 输出: 2
console.log(rest); // 输出: [3, 4, 5]

// 对象解构
const person = { name: 'John', age: 30, city: 'New York' };
const { name, age, city: location = 'Unknown' } = person;
console.log(name);     // 输出: "John"
console.log(age);      // 输出: 30
console.log(location); // 输出: "New York"

// 展开运算符 - 数组
const arr1 = [1, 2, 3];
const arr2 = [...arr1, 4, 5];
console.log(arr2); // 输出: [1, 2, 3, 4, 5]

// 展开运算符 - 对象
const obj1 = { foo: 'bar', x: 42 };
const obj2 = { foo: 'baz', y: 13 };
const clonedObj = { ...obj1 };
const mergedObj = { ...obj1, ...obj2 };
console.log(clonedObj);  // 输出: { foo: 'bar', x: 42 }
console.log(mergedObj);  // 输出: { foo: 'baz', x: 42, y: 13 }

// 函数参数中使用展开
const numbers = [1, 2, 3];
console.log(Math.max(...numbers)); // 输出: 3

6. 字符串和模板字面量

特性 ES5 ES6
多行字符串 使用\n和+连接 模板字符串
字符串插值 字符串拼接 ${expression}
Unicode支持 有限 完整支持

示例代码:

javascript 复制代码
// ES5字符串拼接
var name = 'John';
var age = 30;
var message = 'My name is ' + name + ' and I am ' + age + ' years old.\n' +
              'This is a multi-line string.';
console.log(message);

// ES6模板字符串
const name = 'John';
const age = 30;
const message = `My name is ${name} and I am ${age} years old.
This is a multi-line string.`;
console.log(message);

// 模板字符串中的表达式
const a = 10;
const b = 20;
console.log(`Sum is: ${a + b}`); // 输出: "Sum is: 30"
console.log(`${a} is ${a < b ? 'less than' : 'greater than'} ${b}`);
// 输出: "10 is less than 20"

// 带标签的模板字符串
function myTag(strings, ...values) {
    let result = '';
    strings.forEach((string, i) => {
        result += string;
        if (i < values.length) {
            result += values[i].toUpperCase();
        }
    });
    return result;
}
const name = 'john';
console.log(myTag`Hello ${name}!`); // 输出: "Hello JOHN!"

7. 数组和对象新方法

示例代码:

javascript 复制代码
// Array.from() - 将类数组对象转换为数组
const arrayLike = { 0: 'a', 1: 'b', 2: 'c', length: 3 };
const arr = Array.from(arrayLike);
console.log(arr); // 输出: ['a', 'b', 'c']

// Array.of() - 创建新数组
console.log(Array.of(1, 2, 3)); // 输出: [1, 2, 3]
console.log(Array(3));          // 输出: [empty × 3]

// find() 和 findIndex()
const numbers = [1, 2, 3, 4, 5];
const found = numbers.find(num => num > 3);
const foundIndex = numbers.findIndex(num => num > 3);
console.log(found);      // 输出: 4
console.log(foundIndex); // 输出: 3

// includes()
console.log(numbers.includes(3));  // 输出: true
console.log(numbers.includes(6));  // 输出: false

// keys(), values(), entries()
const obj = { a: 1, b: 2 };
console.log(Object.keys(obj));    // 输出: ['a', 'b']
console.log(Object.values(obj));  // 输出: [1, 2]
console.log(Object.entries(obj)); // 输出: [['a', 1], ['b', 2]]

// 数组遍历方法示例
const fruits = ['apple', 'banana', 'orange'];
// forEach
fruits.forEach((fruit, index) => {
    console.log(`${index}: ${fruit}`);
});
// 输出:
// 0: apple
// 1: banana
// 2: orange

// map
const upperFruits = fruits.map(fruit => fruit.toUpperCase());
console.log(upperFruits); // 输出: ['APPLE', 'BANANA', 'ORANGE']

8. Promise和异步编程

Promise 是异步编程的一种解决方案

Promise 可以用来封装各种异步操作,如网络请求、文件读写、定时器等。

通过 Promise,可以将异步操作的结果以同步的方式进行处理和管理。

示例代码:

javascript 复制代码
// 创建一个Promise
function delay(ms) {
    return new Promise(resolve => setTimeout(resolve, ms));
}

// 使用Promise
console.log('开始');
delay(2000)
    .then(() => {
        console.log('2秒后执行'); // 2秒后输出
        return delay(1000);
    })
    .then(() => {
        console.log('再过1秒执行'); // 再过1秒后输出
    })
    .catch(error => {
        console.error('发生错误:', error);
    });

// async/await语法(ES8引入,但常与Promise一起使用)
async function example() {
    try {
        console.log('开始');
        await delay(2000);
        console.log('2秒后执行');
        await delay(1000);
        console.log('再过1秒执行');
    } catch (error) {
        console.error('发生错误:', error);
    }
}

// Promise.all()示例
Promise.all([
    Promise.resolve(1),
    Promise.resolve(2),
    Promise.resolve(3)
])
.then(values => {
    console.log(values); // 输出: [1, 2, 3]
});

9. 其他新特性

javascript 复制代码
// Set数据结构
const set = new Set([1, 2, 2, 3, 3]);
console.log(set.size);        // 输出: 3
console.log([...set]);        // 输出: [1, 2, 3]
set.add(4);
console.log(set.has(4));      // 输出: true
set.delete(4);
console.log(set.has(4));      // 输出: false

// Map数据结构
const map = new Map();
const key = { id: 1 };
map.set(key, 'value');
console.log(map.get(key));    // 输出: "value"
console.log(map.has(key));    // 输出: true
console.log(map.size);        // 输出: 1

// Symbol
const symbol1 = Symbol('description');
const symbol2 = Symbol('description');
console.log(symbol1 === symbol2); // 输出: false

const obj = {
    [symbol1]: 'Hello',
    [symbol2]: 'World'
};
console.log(obj[symbol1]); // 输出: "Hello"
console.log(obj[symbol2]); // 输出: "World"

// 生成器函数
function* numberGenerator() {
    yield 1;
    yield 2;
    yield 3;
}

const gen = numberGenerator();
console.log(gen.next().value); // 输出: 1
console.log(gen.next().value); // 输出: 2
console.log(gen.next().value); // 输出: 3
console.log(gen.next().done);  // 输出: true

总结

ES6相比ES5的主要改进:

  1. 更好的变量声明机制(let/const)
  2. 更简洁的函数语法(箭头函数)
  3. 更强大的面向对象能力(class)
  4. 更现代的模块化系统
  5. 更方便的数据处理(解构/展开)
  6. 更强大的异步编程能力(Promise)
  7. 更丰富的数据结构(Set/Map)
  8. 更完善的标准库

这些改进使JavaScript更加强大和易用,推动了现代Web开发的发展。

相关推荐
加班是不可能的,除非双倍日工资3 小时前
css预编译器实现星空背景图
前端·css·vue3
wyiyiyi4 小时前
【Web后端】Django、flask及其场景——以构建系统原型为例
前端·数据库·后端·python·django·flask
gnip4 小时前
vite和webpack打包结构控制
前端·javascript
excel4 小时前
在二维 Canvas 中模拟三角形绕 X、Y 轴旋转
前端
阿华的代码王国5 小时前
【Android】RecyclerView复用CheckBox的异常状态
android·xml·java·前端·后端
一条上岸小咸鱼5 小时前
Kotlin 基本数据类型(三):Booleans、Characters
android·前端·kotlin
Jimmy5 小时前
AI 代理是什么,其有助于我们实现更智能编程
前端·后端·ai编程
ZXT5 小时前
promise & async await总结
前端
Jerry说前后端5 小时前
RecyclerView 性能优化:从原理到实践的深度优化方案
android·前端·性能优化
画个太阳作晴天5 小时前
A12预装app
linux·服务器·前端