【前端开发】五. ES5和ES6对比

发布于:2025-08-07 ⋅ 阅读:(15) ⋅ 点赞:(0)

ES6 核心特性详解(对比ES5)

一、变量声明:let 和 const

ES5 的问题

// 变量提升(hoisting)
console.log(a); // undefined
var a = 10;

// 重复声明
var b = 20;
var b = 30; // 允许重复声明

// 函数作用域
if (true) {
  var c = 40;
}
console.log(c); // 40 - 变量泄漏到外部作用域

ES6 解决方案

// 块级作用域
let d = 10;
// let d = 20; // 报错:Identifier 'd' has already been declared

if (true) {
  let e = 30;
  const PI = 3.14;
  // PI = 3.15; // 报错:Assignment to constant variable
}
// console.log(e); // 报错:e is not defined

// 暂时性死区(TDZ)
// console.log(f); // 报错:Cannot access 'f' before initialization
let f = 50;

二、箭头函数(Arrow Functions)

ES5 函数

var numbers = [1, 2, 3];
var doubled = numbers.map(function(n) {
  return n * 2;
});

var obj = {
  value: 42,
  getValue: function() {
    var self = this; // 需要保存this引用
    setTimeout(function() {
      console.log(self.value); // 42
    }, 100);
  }
};

ES6 箭头函数

const numbers = [1, 2, 3];
const doubled = numbers.map(n => n * 2); // 单行隐式返回

const obj = {
  value: 42,
  getValue() {
    setTimeout(() => {
      console.log(this.value); // 42 - 自动绑定外部this
    }, 100);
  }
};

// 多行函数体
const sum = (a, b) => {
  const result = a + b;
  return result;
};

三、模板字符串(Template Literals)

ES5 字符串拼接

var name = '张三';
var age = 28;
var message = '姓名: ' + name + '\n' +
              '年龄: ' + age + '\n' +
              '明年他就' + (age + 1) + '岁了';
              
var html = '<div class="card">' +
             '<h2>' + name + '</h2>' +
             '<p>年龄: ' + age + '</p>' +
           '</div>';

ES6 模板字符串

const name = '张三';
const age = 28;
const message = `姓名: ${name}
年龄: ${age}
明年他就${age + 1}岁了`;

const html = `
  <div class="card">
    <h2>${name}</h2>
    <p>年龄: ${age}</p>
  </div>
`;

// 标签模板(高级用法)
function highlight(strings, ...values) {
  return strings.reduce((result, str, i) => 
    `${result}${str}<mark>${values[i] || ''}</mark>`, '');
}
const marked = highlight`姓名: ${name},年龄: ${age}`;

四、解构赋值(Destructuring)

ES5 赋值方式

var person = {
  firstName: '李',
  lastName: '四',
  age: 35,
  address: { city: '北京' }
};

var firstName = person.firstName;
var lastName = person.lastName;
var city = person.address.city;

var colors = ['红', '绿', '蓝'];
var firstColor = colors[0];
var thirdColor = colors[2];

ES6 解构赋值

const person = {
  firstName: '李',
  lastName: '四',
  age: 35,
  address: { city: '北京' }
};

// 对象解构
const { firstName="aaa", lastName, address: { city } } = person;

// 重命名
const { firstName: fName } = person;

// 默认值
const { middleName = '无' } = person;

// 数组解构
const colors = ['红', '绿', '蓝'];
const [firstColor, , thirdColor] = colors;

// 交换变量
let x = 1, y = 2;
[x, y] = [y, x]; // x=2, y=1

// 函数参数解构
function printUser({ firstName, lastName }) {
  console.log(`${firstName} ${lastName}`);
}
printUser(person)

五、默认参数和Rest参数

ES5 处理方式

function greet(name) {
  name = name || '访客'; // 默认值处理
  console.log('你好, ' + name);
}
greet()
function sum() {
  var args = Array.prototype.slice.call(arguments);
  return args.reduce(function(acc, val) {
    return acc + val;
  }, 0);
}
sum(1,2,3,4)

ES6 解决方案

// 默认参数
function greet(name = '访客') {
  console.log(`你好, ${name}`);
}

// Rest参数
const sum = (...args) => {
  return args.reduce((acc, val) => acc + val, 0);
};

// 解构结合默认值
function createPerson({ name = '匿名', age = 0 } = {name = '匿名', age = 0}) {
  console.log(`姓名: ${name}, 年龄: ${age}`);
}
createPerson({a:1})
// Spread操作符(与Rest相反)
const arr1 = [1, 2, 3];
const arr2 = [4, 5, 6];
const combined = [...arr1, ...arr2]; // [1,2,3,4,5,6]

六、类(Class)

ES5 面向对象

// 构造函数
function Person(name, age) {
  this.name = name;
  this.age = age;
}
let p1 = new Person("aa",12)
let p2 = new Person()
// 原型方法
Person.prototype.greet = function() {
  console.log('你好, 我是 ' + this.name);
};
p1.greet()
// 继承
function Student(name, age, grade) {
  Person.call(this, name, age); // 调用父类构造函数
  this.grade = grade;
}

// 设置原型链
Student.prototype = Object.create(Person.prototype);
Student.prototype.constructor = Student;

// 子类方法
Student.prototype.study = function() {
  console.log(this.name + '正在学习');
};

ES6 类语法

class Person {
  // 构造函数
  constructor(name, age) {
    this.name = name;
    this.age = age;
  }

  // 实例方法
  greet() {
    console.log(`你好, 我是 ${this.name}`);
  }

  // 静态方法
  static info() {
    console.log('这是一个Person类');
  }
}

class Student extends Person {
  constructor(name, age, grade) {
    super(name, age); // 调用父类构造函数
    this.grade = grade;
  }

  // 重写方法
  greet() {
    super.greet(); // 调用父类方法
    console.log(`我是${this.grade}年级学生`);
  }

  study() {
    console.log(`${this.name}正在学习`);
  }

  // Getter/Setter
  get studentInfo() {
    return `${this.name}-${this.grade}年级`;
  }
  
  set studentInfo(value) {
    [this.name, this.grade] = value.split('-');
  }
}

七、模块化(Modules)

ES5 模块化(CommonJS)

// math.js
module.exports = {
  add: function(a, b) { return a + b; },
  PI: 3.14
};

// app.js
var math = require('./math.js');
console.log(math.add(2, 3));

ES6 模块化

// math.js
export function add(a, b) {
  return a + b;
}

export const PI = 3.14;

// 默认导出
export default function multiply(a, b) {
  return a * b;
}

// app.js
import { add, PI } from './math.js';
import multiply from './math.js'; // 导入默认导出

console.log(add(2, 3)); // 5
console.log(multiply(2, 3)); // 6

// 重命名导入
import { PI as piValue } from './math.js';

// 全部导入
import * as math from './math.js';
console.log(math.PI);

八、Promise 和异步处理

ES5 回调地狱(Callback Hell)

function fetchData(callback) {
  setTimeout(function() {
    callback(null, '数据');
  }, 1000);
}

fetchData(function(err, data) {
  if (err) {
    console.error(err);
  } else {
    console.log('第一步:', data);
    fetchData(function(err, data2) {
      if (err) {
        console.error(err);
      } else {
        console.log('第二步:', data2);
        // 更多嵌套...
      }
    });
  }
});

ES6 Promise

function fetchData() {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      Math.random() > 0.5 
        ? resolve('数据') 
        : reject(new Error('请求失败'));
    }, 1000);
  });
}

fetchData()
  .then(data => {
    console.log('第一步:', data);
    return fetchData();
  })
  .then(data => {
    console.log('第二步:', data);
  })
  .catch(err => {
    console.error('错误:', err.message);
  });

// Promise.all - 并行处理
Promise.all([fetchData(), fetchData()])
  .then(results => {
    console.log('所有结果:', results);
  });

// Promise.race - 竞速
Promise.race([fetchData(), fetchData()])
  .then(firstResult => {
    console.log('第一个结果:', firstResult);
  });

ES7 async/await

async function processData() {
  try {
    const data1 = await fetchData();
    console.log('第一步:', data1);
    
    const data2 = await fetchData();
    console.log('第二步:', data2);
    
    const [result1, result2] = await Promise.all([fetchData(), fetchData()]);
    console.log('并行结果:', result1, result2);
  } catch (err) {
    console.error('错误:', err.message);
  }
}

processData();

九、其他重要特性

1. 对象字面量增强

// ES5
var name = '张三';
var age = 30;
var person = {
  name: name,
  age: age,
  sayHello: function() {
    console.log('你好');
  }
};

// ES6
const name = '张三';
const age = 30;
const person = {
  name,   // 属性简写
  age,    // 属性简写
  sayHello() {  // 方法简写
    console.log('你好');
  },
  // 计算属性名
  [prefix + 'Info']: '用户信息'
};

2. 迭代器和生成器

// 迭代器
const iterable = {
  [Symbol.iterator]() {
    let step = 0;
    return {
      next() {
        step++;
        if (step <= 5) {
          return { value: step, done: false };
        }
        return { done: true };
      }
    };
  }
};

for (const value of iterable) {
  console.log(value); // 1,2,3,4,5
}

// 生成器
function* idGenerator() {
  let id = 1;
  while (true) {
    yield id++;
  }
}

const gen = idGenerator();
console.log(gen.next().value); // 1
console.log(gen.next().value); // 2

3. 新增数据结构

// Set - 唯一值集合
const set = new Set();
set.add(1);
set.add(2);
set.add(1); // 重复值被忽略
console.log(set.size); // 2

// Map - 键值对集合
const map = new Map();
map.set('name', '张三');
map.set('age', 30);
console.log(map.get('name')); // 张三

// WeakSet 和 WeakMap - 弱引用集合

十、ES6+ 兼容性和转换

1. Babel 转译

# 安装Babel
npm install @babel/core @babel/cli @babel/preset-env --save-dev

# .babelrc 配置
{
  "presets": ["@babel/preset-env"]
}

# 转译文件
npx babel src -d dist

2. Polyfill 服务

<!-- 使用polyfill.io动态提供polyfill -->
<script src="https://polyfill.io/v3/polyfill.min.js?features=es6,es7"></script>

3. 浏览器支持情况

  • 现代浏览器(Chrome、Firefox、Edge)基本支持ES6
  • IE11需要转译
  • 使用 Can I use 检查特性支持


网站公告

今日签到

点亮在社区的每一天
去签到