在 JavaScript 生态系统中,ECMAScript(简称 ES)是其中最重要的一个,因为它定义了 JavaScript 语言的规范。自 1997 年发表第一版以来,已经经历了许多版本更新。其中的一些版本将语言带入了新的方向,而其他版本则旨在解决旧版中存在的缺陷。在本文中,我们将讨论 ES6 到 ES9 中引入的一些新特性。
ES6
ECMAScript 6(简称 ES6,也称作 ES2015)是 JavaScript 语言的最大更新版本之一。它为 JavaScript 提供了许多新特性,扩展了其功能和灵活性。下面是一些 ES6 中重要的新特性。
块级作用域
在 ES6 之前,JavaScript 没有块级作用域。因此,变量和常量作用域只限于函数或全局作用域。ES6 引入了 let 和 const 关键字来声明块级作用域的变量和常量。用 let 和 const 声明的变量和常量在块级作用域中生效,这使得代码更加清晰可读,减少了变量名冲突的问题。
示例代码:
// javascriptcn.com 代码示例 // Before ES6 { var a = 'Hello'; } console.log(a); // 'Hello' // After ES6 { let b = 'World'; } console.log(b); // ReferenceError: b is not defined
箭头函数
箭头函数是一种易于编写和阅读的语法糖。它可以简化函数表达式的写法,并且可以让开发者少写很多单词。它的主要优势在于可以让开发者在代码中更加自然地表达函数的意图。
示例代码:
// Before ES6 var func1 = function(a, b) { return a + b; } // After ES6 var func2 = (a, b) => a + b;
模板字符串
在 ES6 中,我们可以使用模板字符串来包含变量、表达式和换行符。这种语法上的改进使得字符串拼接代码更加美观、直观。
示例代码:
// Before ES6 var str1 = 'Hello, ' + name + '!'; var str2 = 'The result is ' + (a + b) + '.'; // After ES6 var str3 = `Hello, ${name}!`; var str4 = `The result is ${a + b}.`;
迭代器和生成器
ES6 引入了迭代器和生成器的概念,这让编写可复用的代码更加方便。迭代器是一种新的对象类型,可以让我们代码中的集合或序列更加自然地遍历,而不需要自己去维护一个变量然后一个一个元素地访问。生成器是一种函数类型,与普通函数不同之处在于,它可以在需要的时候暂停执行,然后在需要的时候恢复执行,返回一个值。生成器可以被认为是一种可挂起的函数。
示例代码:
// javascriptcn.com 代码示例 // Iterator Example var numbers = [1, 2, 3]; var iterator = numbers[Symbol.iterator](); console.log(iterator.next()); // {value: 1, done: false} console.log(iterator.next()); // {value: 2, done: false} console.log(iterator.next()); // {value: 3, done: false} console.log(iterator.next()); // {value: undefined, done: true} // Generator Example function* generatorFunction() { yield 'Hello'; yield ' '; yield 'World'; } var generator = generatorFunction(); console.log(generator.next()); // {value: 'Hello', done: false} console.log(generator.next()); // {value: ' ', done: false} console.log(generator.next()); // {value: 'World', done: false} console.log(generator.next()); // {value: undefined, done: true}
类和继承
在 ES6 中,我们可以使用 class 关键字来定义一个类。相比于在 ES5 中使用构造函数来定义类,用 class 来定义类更加直观、简单易于理解,并且可以更好地模拟传统面向对象(OOP)的思想。在 ES6 中,类之间的继承也变得更容易。
示例代码:
// javascriptcn.com 代码示例 // Class Example class Person { constructor(name, age) { this.name = name; this.age = age; } introduce() { console.log(`Hello, I'm ${this.name} and I'm ${this.age} years old.`); } } class Teacher extends Person { constructor(name, age, subject) { super(name, age); this.subject = subject; } teach() { console.log(`I'm teaching ${this.subject}.`); } } var person = new Person('Alice', 26); var teacher = new Teacher('Bob', 42, 'Math'); person.introduce(); // Hello, I'm Alice and I'm 26 years old. teacher.introduce(); // Hello, I'm Bob and I'm 42 years old. teacher.teach(); // I'm teaching Math.
Promise 和异步函数
在 ES6 之前,JavaScript 缺乏对异步代码的支持,通过回调函数进行异步编程是一种常见的做法。ES6 引入了 Promise 和异步函数两个新概念。Promise 使得我们能够更加简单、可靠地组织和管理异步操作。异步函数是 Promise 的一种语法糖,它可以让我们更加自然地编写异步代码,避免了繁琐、嵌套的回调函数。
示例代码:
// javascriptcn.com 代码示例 // Promise Example function asyncFunction() { return new Promise((resolve, reject) => { setTimeout(() => resolve('Done!'), 1000); }); } asyncFunction().then(result => console.log(result)); // Async Function Example async function asyncFunction() { await new Promise(resolve => setTimeout(resolve, 1000)); console.log('Hello, World!'); } asyncFunction();
ES7
ES7(也称作 ES2016)是 ECMAScript 2016 的简称,ES7 的更新内容非常少。它引入了两个新特性:
Array.prototype.includes
Array.prototype.includes() 方法是一种用来判断数组是否包含一个值或某个元素的函数。它的语法和 indexOf() 类似。与 indexOf() 不同之处在于,includes() 可以智能地处理 NaN 和其他特殊情况。
示例代码:
var numbers = [1, 2, 3]; console.log(numbers.includes(1)); // true console.log(numbers.includes(0)); // false console.log(numbers.includes(NaN)); // false var strings = ['hello', 'world', '']; console.log(strings.includes('')); // true console.log(strings.includes(undefined)); // false
指数运算符
ES7 也引入了指数运算符。它是一个新的二元运算符(**),它将左边的操作数提高到右边的操作数次幂。
示例代码:
console.log(2 ** 3); // 8 console.log(3 ** 2); // 9 console.log(10 ** -1); // 0.1
ES8
ES8(也称作 ES2017)是 ECMAScript 2017 的简称,它包含了一些新增的特性。
字符串填充
ES8 引入了字符串填充方法 padStart() 和 padEnd()。这两种方法可以让我们轻松地在字符串前面或后面填充任意字符,使得字符串具有指定的长度。
示例代码:
console.log('abc'.padStart(6)); // ' abc' console.log('abc'.padEnd(6)); // 'abc ' console.log('abc'.padStart(6, '-')); // '---abc' console.log('abc'.padEnd(6, '-')); // 'abc---'
Object.entries() 和 Object.values()
ES8 新增了 Object.entries() 和 Object.values() 两个新方法。这两个方法都用来处理对象。Object.entries() 将对象转换为一个二维数组,其中数组的每个成员都是一个键值对(key-value pair)。Object.values() 将对象的值转换为一个由单个值组成的数组。
示例代码:
var obj = {a: 1, b: 2, c: 3}; console.log(Object.entries(obj)); // [['a', 1], ['b', 2], ['c', 3]] console.log(Object.values(obj)); // [1, 2, 3]
异步迭代器
ES8 引入了异步迭代器的概念。异步迭代器是一个可以暂停和重新启动的迭代器,它表现更像是一个异步生成器。一个异步迭代器是一个实现了 next() 方法并返回 Promise 的对象。
示例代码:
// javascriptcn.com 代码示例 async function* asyncGenerator() { var i = 0; while (i < 3) { await new Promise(resolve => setTimeout(resolve, 1000)); yield i++; } } var asyncIterator = asyncGenerator(); (async function() { for await (var value of asyncIterator) { console.log(value); } })(); // 0 1 2
ES9
ES9(也称作 ES2018)是 ECMAScript 2018 的简称,它包含了一些新的特性。
异步迭代器和生成器
ES9 引入了异步迭代器和生成器(Async Iterator 和 Async Generator)的新支持。异步迭代器和生成器允许我们简单地处理异步操作。
示例代码:
// javascriptcn.com 代码示例 async function* fetchCommits(repo) { var page = 1; var url = `https://api.github.com/repos/${repo}/commits?page=${page}&per_page=100`; while (true) { var response = await fetch(url); var body = await response.json(); if (body.length === 0) break; yield body; if (body.length < 100) break; page++; url = `https://api.github.com/repos/${repo}/commits?page=${page}&per_page=100`; } } (async function() { for await (let commits of fetchCommits('babel/babel')) { console.log(commits); } })();
Promise.prototype.finally
ES9 引入了 Promise.prototype.finally() 方法,它允许我们在 Promise 执行完成后执行一些操作,无论 Promise 成功或失败。它的语法上与 Promise.prototype.then() 类似。
示例代码:
fetch('https://api.github.com/repos/jackfranklin/babel-plugin-remove-console') .then(response => response.json()) .catch(error => console.error('Error:', error)) .finally(() => console.log('Done!'));
Rest/Spread 属性
在 ES9 中,Rest/Spread 特性已经正式成为 ECMAScript 的一部分。这些特性可以让我们更加方便地处理函数参数、对象和数组,使得代码看起来更加简洁、可读性更高。
示例代码:
// javascriptcn.com 代码示例 // Rest Example function sumAll(...numbers) { return numbers.reduce((total, number) => total + number); } console.log(sumAll(1, 2, 3)); // 6 console.log(sumAll(10, 20, 30)); // 60 // Spread Example var arr1 = [1, 2, 3]; var arr2 = [4, 5, 6]; var arr3 = [...arr1, ...arr2]; console.log(arr3); // [1, 2, 3, 4, 5, 6] var obj1 = {a: 1}; var obj2 = {b: 2}; var obj3 = {...obj1, ...obj2}; console.log(obj3); // {a: 1, b: 2}
总结
我们已经介绍了几个版本内有关 JavaScript 新特性的完整指南,不管是类、继承、Promise、箭头函数还是 let 和 const,ES6、ES7、ES8 和 ES9 中的所有特性都应该为前端开发人员提供了更多的功能和灵活性。在学习和使用这些新特性时,我们需要时刻关注代码的语法和代码风格,保持良好的编码习惯,这样才能更好地利用这些新特性来提高我们代码的质量水平。
来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/6538d8aa7d4982a6eb1f8589