ES6+新特性:现代JavaScript的强大功能

ES6+新特性:现代JavaScript的强大功能

今天我们要学习ES6+的新特性!从ES2015开始,JavaScript迎来了翻天覆地的变化,这些新特性让我们的代码更加简洁、优雅和强大。

🎯 本周学习目标

✅ 掌握箭头函数和模板字符串的使用

✅ 深入理解let/const和块级作用域

✅ 学会ES6类和继承语法

✅ 掌握模块化编程思想

✅ 了解其他重要的ES6+特性


🏹 第一部分:箭头函数

1️⃣ 箭头函数基础语法

javascript 复制代码
// 传统函数表达式
const add = function(a, b) {
    return a + b;
};

// 箭头函数
const addArrow = (a, b) => {
    return a + b;
};

// 简化写法(单表达式)
const addSimple = (a, b) => a + b;

// 单参数可以省略括号
const double = x => x * 2;

// 无参数需要空括号
const greet = () => 'Hello World!';

// 返回对象需要用括号包裹
const createUser = (name, age) => ({
    name: name,
    age: age,
    id: Math.random()
});

// 多行箭头函数
const processData = (data) => {
    const processed = data.map(item => item.toUpperCase());
    const filtered = processed.filter(item => item.length > 3);
    return filtered.sort();
};

console.log(add(2, 3));           // 5
console.log(addArrow(2, 3));      // 5
console.log(addSimple(2, 3));     // 5
console.log(double(4));           // 8
console.log(greet());             // 'Hello World!'
console.log(createUser('张三', 25));

2️⃣ 箭头函数的this绑定

javascript 复制代码
// 传统函数的this
const traditionalObj = {
    name: '传统对象',
    methods: {
        regularFunction: function() {
            console.log('Regular function this:', this.name);
            
            // 嵌套函数中的this指向全局对象
            function nested() {
                console.log('Nested function this:', this.name); // undefined
            }
            nested();
        },
        
        arrowFunction: () => {
            // 箭头函数没有自己的this,继承外层作用域
            console.log('Arrow function this:', this.name); // undefined
        }
    }
};

// 箭头函数的this继承
const modernObj = {
    name: '现代对象',
    items: ['item1', 'item2', 'item3'],
    
    // 使用传统函数作为方法
    processItems: function() {
        console.log('Processing items for:', this.name);
        
        // 箭头函数继承外层的this
        this.items.forEach(item => {
            console.log(`${this.name} processing ${item}`);
        });
        
        // 如果使用传统函数,需要bind或保存this
        this.items.forEach(function(item) {
            console.log(`${this.name} processing ${item}`); // this.name是undefined
        }.bind(this));
    },
    
    // 箭头函数作为方法(不推荐)
    arrowMethod: () => {
        console.log('Arrow method this:', this.name); // undefined
    }
};

traditionalObj.methods.regularFunction();
modernObj.processItems();

// 事件处理中的this
class Button {
    constructor(element) {
        this.element = element;
        this.clickCount = 0;
        
        // 箭头函数自动绑定this
        this.element.addEventListener('click', () => {
            this.clickCount++;
            console.log(`Button clicked ${this.clickCount} times`);
        });
        
        // 传统函数需要手动绑定
        this.element.addEventListener('click', function() {
            console.log('Traditional function this:', this); // 指向element
        });
    }
}

3️⃣ 箭头函数的限制

javascript 复制代码
// 1. 不能作为构造函数
const ArrowConstructor = () => {
    this.name = 'test';
};

// new ArrowConstructor(); // TypeError: ArrowConstructor is not a constructor

// 2. 没有arguments对象
function traditionalFunction() {
    console.log('Arguments:', arguments);
}

const arrowFunction = () => {
    // console.log(arguments); // ReferenceError: arguments is not defined
    // 使用剩余参数代替
};

const arrowWithRest = (...args) => {
    console.log('Rest parameters:', args);
};

traditionalFunction(1, 2, 3);
arrowWithRest(1, 2, 3);

// 3. 不能使用yield关键字
// const generatorArrow = () => {
//     yield 1; // SyntaxError
// };

// 4. 没有prototype属性
function regularFunc() {}
const arrowFunc = () => {};

console.log('Regular function prototype:', regularFunc.prototype);
console.log('Arrow function prototype:', arrowFunc.prototype); // undefined

📝 第二部分:模板字符串

1️⃣ 基础语法

javascript 复制代码
// 传统字符串拼接
const name = '张三';
const age = 25;
const city = '北京';

const traditionalString = '我叫' + name + ',今年' + age + '岁,住在' + city;
console.log(traditionalString);

// 模板字符串
const templateString = `我叫${name},今年${age}岁,住在${city}`;
console.log(templateString);

// 多行字符串
const multiLine = `
    这是一个
    多行字符串
    可以保持格式
`;
console.log(multiLine);

// 表达式计算
const price = 100;
const tax = 0.1;
const total = `总价:${price * (1 + tax)}元`;
console.log(total);

// 函数调用
const formatDate = (date) => date.toLocaleDateString();
const today = new Date();
const dateString = `今天是:${formatDate(today)}`;
console.log(dateString);

2️⃣ 标签模板

javascript 复制代码
// 标签函数
function highlight(strings, ...values) {
    console.log('Strings:', strings);
    console.log('Values:', values);
    
    return strings.reduce((result, string, i) => {
        const value = values[i] ? `<mark>${values[i]}</mark>` : '';
        return result + string + value;
    }, '');
}

const user = '李四';
const score = 95;
const highlighted = highlight`用户 ${user} 的分数是 ${score}`;
console.log(highlighted);

// 实用的标签函数
function sql(strings, ...values) {
    // 简单的SQL注入防护
    const escapedValues = values.map(value => {
        if (typeof value === 'string') {
            return value.replace(/'/g, "''");
        }
        return value;
    });
    
    return strings.reduce((result, string, i) => {
        const value = escapedValues[i] !== undefined ? `'${escapedValues[i]}'` : '';
        return result + string + value;
    }, '');
}

const userId = 123;
const userName = "O'Connor";
const query = sql`SELECT * FROM users WHERE id = ${userId} AND name = ${userName}`;
console.log(query);

// 样式标签函数
function css(strings, ...values) {
    return strings.reduce((result, string, i) => {
        const value = values[i] || '';
        return result + string + value;
    }, '');
}

const primaryColor = '#007bff';
const fontSize = '16px';
const styles = css`
    .button {
        background-color: ${primaryColor};
        font-size: ${fontSize};
        border: none;
        padding: 10px 20px;
    }
`;
console.log(styles);

🔒 第三部分:let、const和块级作用域

1️⃣ var的问题

javascript 复制代码
// var的函数作用域问题
function varProblems() {
    console.log('开始函数执行');
    
    if (true) {
        var x = 1;
    }
    console.log('x在if外部:', x); // 1,var没有块级作用域
    
    // 变量提升问题
    console.log('y在声明前:', y); // undefined,而不是报错
    var y = 2;
    console.log('y在声明后:', y); // 2
    
    // 循环中的问题
    for (var i = 0; i < 3; i++) {
        setTimeout(() => {
            console.log('var循环:', i); // 输出3次3
        }, 100);
    }
}

varProblems();

// var的重复声明问题
var message = '第一次声明';
var message = '第二次声明'; // 不会报错
console.log(message); // '第二次声明'

2️⃣ let和const的改进

javascript 复制代码
// let的块级作用域
function letImprovements() {
    if (true) {
        let x = 1;
        const y = 2;
    }
    // console.log(x); // ReferenceError: x is not defined
    // console.log(y); // ReferenceError: y is not defined
    
    // 暂时性死区
    // console.log(z); // ReferenceError: Cannot access 'z' before initialization
    let z = 3;
    console.log('z:', z);
    
    // 循环中的let
    for (let i = 0; i < 3; i++) {
        setTimeout(() => {
            console.log('let循环:', i); // 输出0, 1, 2
        }, 200);
    }
    
    // 不能重复声明
    let unique = 'first';
    // let unique = 'second'; // SyntaxError: Identifier 'unique' has already been declared
}

letImprovements();

// const的特性
function constFeatures() {
    // 必须初始化
    // const a; // SyntaxError: Missing initializer in const declaration
    
    const PI = 3.14159;
    // PI = 3.14; // TypeError: Assignment to constant variable
    
    // 对象和数组的const
    const user = { name: '张三', age: 25 };
    user.age = 26; // 可以修改属性
    user.city = '北京'; // 可以添加属性
    // user = {}; // TypeError: Assignment to constant variable
    
    const numbers = [1, 2, 3];
    numbers.push(4); // 可以修改数组内容
    numbers[0] = 0; // 可以修改元素
    // numbers = []; // TypeError: Assignment to constant variable
    
    console.log('User:', user);
    console.log('Numbers:', numbers);
    
    // 冻结对象
    const frozenUser = Object.freeze({ name: '李四', age: 30 });
    // frozenUser.age = 31; // 严格模式下会报错,非严格模式下静默失败
    console.log('Frozen user:', frozenUser);
}

constFeatures();

3️⃣ 块级作用域的应用

javascript 复制代码
// 立即执行函数的替代
// 传统IIFE
(function() {
    var privateVar = 'private';
    console.log('IIFE:', privateVar);
})();

// 块级作用域替代
{
    let privateVar = 'private';
    const privateConst = 'constant';
    console.log('Block scope:', privateVar, privateConst);
}
// console.log(privateVar); // ReferenceError

// switch语句中的块级作用域
function switchExample(type) {
    switch (type) {
        case 'A': {
            let message = 'Type A';
            console.log(message);
            break;
        }
        case 'B': {
            let message = 'Type B'; // 不会与上面的message冲突
            console.log(message);
            break;
        }
        default: {
            let message = 'Unknown type';
            console.log(message);
        }
    }
}

switchExample('A');
switchExample('B');

// 循环中的块级作用域
function loopExamples() {
    // for循环的块级作用域
    for (let i = 0; i < 3; i++) {
        let squared = i * i;
        console.log(`${i} squared is ${squared}`);
    }
    // console.log(i); // ReferenceError
    // console.log(squared); // ReferenceError
    
    // for...of循环
    const fruits = ['apple', 'banana', 'orange'];
    for (const fruit of fruits) {
        console.log(`I like ${fruit}`);
    }
    // console.log(fruit); // ReferenceError
    
    // for...in循环
    const person = { name: '王五', age: 28, city: '上海' };
    for (const key in person) {
        console.log(`${key}: ${person[key]}`);
    }
    // console.log(key); // ReferenceError
}

loopExamples();

🏛️ 第四部分:类和继承

1️⃣ ES6类语法

javascript 复制代码
// 传统构造函数
function TraditionalPerson(name, age) {
    this.name = name;
    this.age = age;
}

TraditionalPerson.prototype.greet = function() {
    return `Hello, I'm ${this.name}`;
};

TraditionalPerson.prototype.getAge = function() {
    return this.age;
};

// ES6类语法
class Person {
    // 构造函数
    constructor(name, age) {
        this.name = name;
        this.age = age;
        this._id = Math.random(); // 私有属性约定
    }
    
    // 实例方法
    greet() {
        return `Hello, I'm ${this.name}`;
    }
    
    getAge() {
        return this.age;
    }
    
    // getter和setter
    get id() {
        return this._id;
    }
    
    set age(newAge) {
        if (newAge > 0 && newAge < 150) {
            this._age = newAge;
        } else {
            throw new Error('Invalid age');
        }
    }
    
    get age() {
        return this._age;
    }
    
    // 静态方法
    static createAdult(name) {
        return new Person(name, 18);
    }
    
    static isValidAge(age) {
        return age > 0 && age < 150;
    }
}

// 使用类
const person1 = new Person('张三', 25);
console.log(person1.greet());
console.log('ID:', person1.id);

const adult = Person.createAdult('李四');
console.log(adult.greet());
console.log('Is valid age:', Person.isValidAge(25));

2️⃣ 继承

javascript 复制代码
// 基类
class Animal {
    constructor(name, species) {
        this.name = name;
        this.species = species;
    }
    
    makeSound() {
        return `${this.name} makes a sound`;
    }
    
    move() {
        return `${this.name} moves`;
    }
    
    toString() {
        return `${this.name} is a ${this.species}`;
    }
    
    static getKingdom() {
        return 'Animalia';
    }
}

// 派生类
class Dog extends Animal {
    constructor(name, breed) {
        super(name, 'Dog'); // 调用父类构造函数
        this.breed = breed;
    }
    
    // 重写父类方法
    makeSound() {
        return `${this.name} barks: Woof!`;
    }
    
    // 新增方法
    fetch() {
        return `${this.name} fetches the ball`;
    }
    
    // 调用父类方法
    move() {
        return super.move() + ' by running';
    }
    
    toString() {
        return super.toString() + ` (${this.breed})`;
    }
}

class Cat extends Animal {
    constructor(name, color) {
        super(name, 'Cat');
        this.color = color;
    }
    
    makeSound() {
        return `${this.name} meows: Meow!`;
    }
    
    climb() {
        return `${this.name} climbs the tree`;
    }
    
    move() {
        return super.move() + ' by sneaking';
    }
}

// 使用继承
const dog = new Dog('旺财', 'Golden Retriever');
const cat = new Cat('咪咪', 'Orange');

console.log(dog.toString());
console.log(dog.makeSound());
console.log(dog.fetch());
console.log(dog.move());

console.log(cat.toString());
console.log(cat.makeSound());
console.log(cat.climb());
console.log(cat.move());

// 静态方法继承
console.log('Kingdom:', Dog.getKingdom());

// instanceof检查
console.log('dog instanceof Dog:', dog instanceof Dog);
console.log('dog instanceof Animal:', dog instanceof Animal);
console.log('cat instanceof Dog:', cat instanceof Dog);

3️⃣ 私有字段和方法(ES2022)

javascript 复制代码
class BankAccount {
    // 私有字段
    #balance = 0;
    #accountNumber;
    
    // 静态私有字段
    static #bankName = 'ES6+ Bank';
    
    constructor(accountNumber, initialBalance = 0) {
        this.#accountNumber = accountNumber;
        this.#balance = initialBalance;
    }
    
    // 私有方法
    #validateAmount(amount) {
        return amount > 0 && typeof amount === 'number';
    }
    
    #log(operation, amount) {
        console.log(`${operation}: ${amount}, Balance: ${this.#balance}`);
    }
    
    // 公共方法
    deposit(amount) {
        if (this.#validateAmount(amount)) {
            this.#balance += amount;
            this.#log('Deposit', amount);
            return true;
        }
        return false;
    }
    
    withdraw(amount) {
        if (this.#validateAmount(amount) && amount <= this.#balance) {
            this.#balance -= amount;
            this.#log('Withdraw', amount);
            return true;
        }
        return false;
    }
    
    getBalance() {
        return this.#balance;
    }
    
    getAccountInfo() {
        return {
            accountNumber: this.#accountNumber,
            balance: this.#balance
        };
    }
    
    // 静态私有方法
    static #validateBankCode(code) {
        return code.length === 4;
    }
    
    static createAccount(bankCode, accountNumber) {
        if (this.#validateBankCode(bankCode)) {
            return new BankAccount(`${bankCode}-${accountNumber}`);
        }
        throw new Error('Invalid bank code');
    }
}

// 使用私有字段
const account = new BankAccount('12345', 1000);
console.log('Initial balance:', account.getBalance());

account.deposit(500);
account.withdraw(200);

// console.log(account.#balance); // SyntaxError: Private field '#balance' must be declared in an enclosing class

const newAccount = BankAccount.createAccount('1234', '67890');
console.log('New account:', newAccount.getAccountInfo());

📦 第五部分:模块化编程

1️⃣ 导出模块

javascript 复制代码
// math.js - 命名导出
export const PI = 3.14159;
export const E = 2.71828;

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

export function multiply(a, b) {
    return a * b;
}

export class Calculator {
    constructor() {
        this.result = 0;
    }
    
    add(value) {
        this.result += value;
        return this;
    }
    
    multiply(value) {
        this.result *= value;
        return this;
    }
    
    getResult() {
        return this.result;
    }
    
    reset() {
        this.result = 0;
        return this;
    }
}

// 批量导出
const subtract = (a, b) => a - b;
const divide = (a, b) => b !== 0 ? a / b : null;

export { subtract, divide };

// 重命名导出
const power = (base, exponent) => Math.pow(base, exponent);
export { power as pow };

// utils.js - 默认导出
export default class StringUtils {
    static capitalize(str) {
        return str.charAt(0).toUpperCase() + str.slice(1);
    }
    
    static reverse(str) {
        return str.split('').reverse().join('');
    }
    
    static truncate(str, length) {
        return str.length > length ? str.slice(0, length) + '...' : str;
    }
}

// 混合导出
export const VERSION = '1.0.0';
export function formatString(str) {
    return str.trim().toLowerCase();
}

// config.js - 配置导出
const config = {
    apiUrl: 'https://api.example.com',
    timeout: 5000,
    retries: 3
};

export default config;
export const { apiUrl, timeout, retries } = config;

2️⃣ 导入模块

javascript 复制代码
// main.js - 导入模块

// 命名导入
import { add, multiply, PI } from './math.js';
console.log('Add:', add(2, 3));
console.log('Multiply:', multiply(4, 5));
console.log('PI:', PI);

// 重命名导入
import { subtract as minus, divide as div } from './math.js';
console.log('Subtract:', minus(10, 3));
console.log('Divide:', div(15, 3));

// 导入所有命名导出
import * as MathUtils from './math.js';
console.log('All math utils:', Object.keys(MathUtils));
console.log('Using namespace:', MathUtils.add(1, 2));

// 默认导入
import StringUtils from './utils.js';
console.log('Capitalize:', StringUtils.capitalize('hello'));
console.log('Reverse:', StringUtils.reverse('world'));

// 混合导入
import config, { apiUrl, timeout } from './config.js';
console.log('Config:', config);
console.log('API URL:', apiUrl);
console.log('Timeout:', timeout);

// 动态导入
async function loadMathModule() {
    try {
        const mathModule = await import('./math.js');
        console.log('Dynamic import:', mathModule.add(5, 5));
        
        const { Calculator } = mathModule;
        const calc = new Calculator();
        const result = calc.add(10).multiply(2).getResult();
        console.log('Calculator result:', result);
    } catch (error) {
        console.error('Failed to load module:', error);
    }
}

loadMathModule();

// 条件导入
async function conditionalImport(useAdvanced) {
    if (useAdvanced) {
        const { default: AdvancedUtils } = await import('./advanced-utils.js');
        return AdvancedUtils;
    } else {
        const { default: BasicUtils } = await import('./basic-utils.js');
        return BasicUtils;
    }
}

// 重新导出
// index.js - 统一导出入口
export { add, multiply, subtract, divide } from './math.js';
export { default as StringUtils } from './utils.js';
export { default as config } from './config.js';

// 重新导出并重命名
export { Calculator as MathCalculator } from './math.js';

3️⃣ 模块化最佳实践

javascript 复制代码
// logger.js - 单例模式模块
class Logger {
    constructor() {
        this.logs = [];
        this.level = 'info';
    }
    
    setLevel(level) {
        this.level = level;
    }
    
    log(message, level = 'info') {
        const timestamp = new Date().toISOString();
        const logEntry = { timestamp, message, level };
        this.logs.push(logEntry);
        
        if (this.shouldLog(level)) {
            console.log(`[${timestamp}] ${level.toUpperCase()}: ${message}`);
        }
    }
    
    shouldLog(level) {
        const levels = ['debug', 'info', 'warn', 'error'];
        return levels.indexOf(level) >= levels.indexOf(this.level);
    }
    
    getLogs() {
        return [...this.logs];
    }
    
    clear() {
        this.logs = [];
    }
}

// 导出单例实例
export default new Logger();

// api.js - API模块
import config from './config.js';
import logger from './logger.js';

class APIClient {
    constructor(baseURL) {
        this.baseURL = baseURL;
        this.defaultHeaders = {
            'Content-Type': 'application/json'
        };
    }
    
    async request(endpoint, options = {}) {
        const url = `${this.baseURL}${endpoint}`;
        const config = {
            headers: { ...this.defaultHeaders, ...options.headers },
            ...options
        };
        
        logger.log(`Making request to ${url}`, 'debug');
        
        try {
            const response = await fetch(url, config);
            
            if (!response.ok) {
                throw new Error(`HTTP ${response.status}: ${response.statusText}`);
            }
            
            const data = await response.json();
            logger.log(`Request successful: ${url}`, 'info');
            return data;
        } catch (error) {
            logger.log(`Request failed: ${error.message}`, 'error');
            throw error;
        }
    }
    
    get(endpoint, params = {}) {
        const queryString = new URLSearchParams(params).toString();
        const url = queryString ? `${endpoint}?${queryString}` : endpoint;
        return this.request(url);
    }
    
    post(endpoint, data) {
        return this.request(endpoint, {
            method: 'POST',
            body: JSON.stringify(data)
        });
    }
}

// 导出配置好的实例
export default new APIClient(config.apiUrl);

// 也导出类,允许创建新实例
export { APIClient };

// app.js - 应用入口
import api from './api.js';
import logger from './logger.js';
import { Calculator } from './math.js';

class App {
    constructor() {
        this.calculator = new Calculator();
        this.init();
    }
    
    async init() {
        logger.log('Application starting...', 'info');
        
        try {
            // 使用API
            const data = await api.get('/users');
            logger.log(`Loaded ${data.length} users`, 'info');
            
            // 使用计算器
            const result = this.calculator.add(10).multiply(2).getResult();
            logger.log(`Calculation result: ${result}`, 'info');
            
            logger.log('Application initialized successfully', 'info');
        } catch (error) {
            logger.log(`Application initialization failed: ${error.message}`, 'error');
        }
    }
}

// 启动应用
new App();

💡 本周总结

🎯 核心知识点

  1. 箭头函数:简洁语法、this绑定、使用限制
  2. 模板字符串:字符串插值、多行字符串、标签模板
  3. let/const:块级作用域、暂时性死区、常量特性
  4. 类和继承:class语法、继承机制、私有字段
  5. 模块化:导入导出、动态导入、模块组织

📝 最佳实践

✅ 优先使用const,需要重新赋值时使用let

✅ 在对象方法中谨慎使用箭头函数

✅ 使用模板字符串进行字符串拼接

✅ 用class语法替代构造函数

✅ 合理组织模块,保持单一职责

🤔 思考题

  1. 箭头函数什么时候不适合使用?
  2. 如何实现真正的私有属性?
  3. 模块化有什么优势?如何避免循环依赖?

📚 下周预告

下周我们将进行 JavaScript实战项目,综合运用所学知识!

内容包括:

  • 项目架构设计
  • 代码组织和模块化
  • 调试技巧和工具使用
  • 性能优化基础

🎉 写在最后

ES6+的新特性让JavaScript变得更加现代化和强大,掌握它们是成为优秀前端开发者的必经之路!

如果这篇文章对你有帮助:

👍 请点个赞 ,让更多人看到

🔄 转发分享 ,帮助更多学习ES6+的朋友

💬 评论区留言,分享你最喜欢的ES6+特性


关于作者

每周更新实用的前端教程,从入门到进阶

关注我,一起在前端的道路上成长!


#JavaScript #ES6 #箭头函数 #模板字符串 #类和继承 #模块化

相关推荐
jiaway9 小时前
【C语言】第二课 位运算
c语言·开发语言·算法
IT北辰9 小时前
初学者也能懂!用Python做房屋销售数据分析,从0到1上手实战(附源码和数据)
开发语言·python·数据分析
蓝倾9769 小时前
1688拍立淘接口对接实战案例
java·开发语言·数据库·python·电商开放平台·开放api接口
或与且与或非9 小时前
Rust+slint实现一个登录demo
开发语言·rust·状态模式
Vae_Mars9 小时前
C语言中的关键字
c语言·开发语言
小高00710 小时前
🚄 前端人必收:5 分钟掌握 ES2025 超实用语法
前端·javascript·面试
怀旧,10 小时前
【C++】17. AVL树实现
java·开发语言·c++
画个逗号给明天"10 小时前
C/C++关键字——union
c语言·开发语言·c++
乌萨奇也要立志学C++10 小时前
【C++详解】C++11(四) 包装器:function、bind、STL中⼀些变化
开发语言·c++