Features: 1. Let and const keywords are used to declare variables; 2. "for...of" loop, iterable data; 3. Iterable, which is any object that implements the iterable protocol; 4. Generator ; 5. Default parameters; 6. Destructuring assignment syntax, which can remove attributes/values from objects/arrays; 7. Remaining/expanded parameters; 8. Arrow functions; 9. Object literals; 10. Class; 11. Map/ Set/WeakMap/WeakSet data structure; 12. Promise.
The operating environment of this tutorial: windows7 system, vue3 version, DELL G3 computer.
ECMAScript 6.0 (hereinafter referred to as ES6) is the next generation standard of the Javascript language, officially released in June 2015. Its goal is to enable the Javascript language to be used to write complex large-scale applications and become an enterprise-level development language.
ECMAScript 6, the so-called modern Javascript, comes with powerful features like block scoping, classes, arrow functions, generatorsand many other useful features.
All necessary functions used in Vue application development to improve the programming experience, improve development efficiency and code quality. Through the Babel
or core-js
integration of Vue CLI
, the code under development can be iterated in strict accordance with the configuration specifications, which is helpful for team collaboration. This article introduces several ES6 features commonly used in Vue application development.
The most basic functions of ES6: let
and const
.
let
is similar to var
, but variables declared using let
are scoped within the block in which they are declared. (Block refers to conditional blocks, for
loop blocks, etc.)
For example, using let
in a conditional block will scope the variable within the block and will not be available outside the block. .
if (true) { let foo = "word"; } console.log(foo); // error
Here, errors are a good thing because it prevents potential errors from occurring during the production process.
If you use var
in the example above (as you would in traditional Javascript code) instead of let
, you will not get the error.
const
is another ES6 keyword used to declare variables. The difference is that variables created by const
cannot be changed after declaration. This feature can effectively avoid the occurrence of BUG. Therefore, when writing code, it is recommended to write pure functions as much as possible (pure A function means that given a fixed input to the function, the output result is fixed and will not be affected by variables outside the function, etc.).
For example:
const a = 2021 a = 2020 // error
There are several ways to create variables, which one should we use?
The best approach is to use const## whenever possible #. Use
let only if you need a variable that needs to be changed later, such as in a
for loop.
for loops in ES6 syntax without even using
let.
for loop looks like this:
const arr = [1, 2, 3]; for (let i = 0; i < arr.length; i++) { const item = arr[i]; console.log(item); }
const arr = [1, 2, 3]; for (const item of arr) { console.log(item); }
for ..in Syntax confusion; they are completely different things.
for..in will get the properties in the array/object, while
for..of will get the actual data you want to iterate over.
iterable protocol:
const twice = { [Symbol.iterator]() { let i = 0; const iterator = { next() { if (i < 2) { return { value: i++, done: false }; } else { return { value: undefined, done: true }; } }, }; return iterator; }, };
for..of loop #twice
Object: <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:js;toolbar:false;">for(const x of twice){
console.log(x)
}</pre><div class="contentsignin">Copy after login</div></div>
This will loop through the
object twice, getting 0
and 1
respectively. In order to create an iterable object, two protocols are actually implemented, the
protocol and the iterator
protocol. In order to meet the requirements of being an iterable object, a method named
is required. <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:js;toolbar:false;">const twice = {
[Symbol.iterator]() {
...
}
}</pre><div class="contentsignin">Copy after login</div></div>
Two new ES6 tricks are applied in method names.
First,
Symbol.iterator is a built-in symbol value, while Symbol
is the base type used in ES6 for creating unique tags/identifiers. Secondly, the square brackets wrapping the property key make it a dynamically computed key. The key here is expression notation. The iterator will be evaluated as, usually it doesn't matter what the actual evaluation is. This unimportant detail is abstracted away.
This is the iterable protocol. Now you still need to deal with the iterator protocol to create iterable objects, since an iterator must be returned from the
[Symbol.iterator] functionThe iterator protocol is simpler. All it takes is an object to have a
method that returns an object with two keys: value
and done
. When you want to stop iteration, just return the object {value: undefined, done: true}
. This is the iterator in the example:
const iterator = { next() { if (i < 2) { return { value: i++, done: false }; } else { return { value: undefined, done: true }; } }, };
In short, there is an object that satisfies both the iterable protocol and the iterator protocol. Such as the following code:
const twice = { [Symbol.iterator]() { let i = 0; const iterator = { next() { if (i < 2) { return { value: i++, done: false }; } else { return { value: undefined, done: true }; } }, }; return iterator; }, };
数组和字符串可以使用
for..of
,进行迭代。这意味着这些内置类型包含与上面的类似的[Symbol.iterator]
方法。
与迭代相关的另一个功能是生成器。
上面的可迭代代码依靠闭包来存储 i
变量。使用 generator
时,不必担心自己构造闭包:
function* twiceGen() { let i = 0; while (i < 2) { yield i; i++; } } const twice = twiceGen();
该代码实现了与可迭代示例相同的行为,但更为简单。
可以与for..of
完全相同地使用它:
for(const item of twice){ console.log(item) }
如你所见,它是一个带有星号(*
)声明的函数。它使用yield
关键字逐个抽取值,就像迭代器的next
方法一样。
生成器是一种多功能工具,基本上,它是一种允许暂停/恢复功能的机制。不必在for..of
中使用上述twice
对象。可以调用它的next
方法。
function* twiceGen() { const i = 0; while (i < 2) { yield i; } } const twice = twiceGen(); twice.next().value; // 0
此时,twiceGen
函数在第一次运行while
循环后暂停。如果再次运行相同的操作,它将恢复并播放循环的第二次运行。
twice.next().value; // 1
生成器的妙处在于它还创建了一个可迭代的迭代器对象。这就是为什么我们能够使用for..of
(可迭代特权)迭代两次并直接调用其next
方法(迭代器特权)的原因。
可能不会立即创建自己的迭代器、生成器,所以让我们来看看其他一些ES6的独创性,它们可以立即使你的代码更加友好。
就像许多其他编程语言一样,现在可以为函数参数设置默认值。
过去是这样实现默认值的:
function addOne(num) { if (num === undefined) { num = 0; } return num + 1; } addOne();
现在可以这样:
function addOne(num = 0) { return num + 1; } addOne();
解构赋值语法是一种 Javascript 表达式。通过解构赋值, 可以将属性/值从对象/数组中取出,赋值给其他变量。
如果要将对象传递给函数,则可以轻松选择对象的属性,然后使用ES6分解语法将它们放在单独的变量中:
function foo({ a, b }) { console.log(a, b); // 1, 2 } foo({ a: 1, b: 2 });
这种解构语法的好处是可以避免创建带有附加代码行的变量。因此不需要像下面这样:
function foo(obj) { const a = obj.a; const b = obj.b; console.log(a, b); // 1, 2 }
同样,还可以在解构语法中设置默认值:
function foo({ a = 0, b }) { console.log(a, b); // 0, 2 } foo({ b: 2 });
解构语法也适用于赋值:
function foo(obj) { const { a, b } = obj; console.log(a, b); // 1, 2 }
当从参数以外的地方获取对象时,这也很有用。
function getObj() { return { a: 1, b: 2 }; } function foo() { const { a, b } = getObj(); console.log(a, b); // 1, 2 }
解构技巧同样也适用数组。
解构参数:
function foo([a, b]) { console.log(a, b); // 1, 2 } foo([1, 2, 3]);
解构赋值:
function foo(arr) { const [a, b] = arr; console.log(a, b); // 1, 2 }
在解构数组时,可以使用 ...
语法来获取数组中的所有其他项。
function foo([a, b, ...c]) { console.log(c); // [3, 4, 5] } foo([1, 2, 3, 4, 5]);
c
现在是一个包含自己的数组,包含了其余的元素:3
,4
,5
。这里的操作就是Rest
操作。
这个语法同样适用于赋值:
function foo(arr) { const [a, b, ...c] = arr; console.log(c); // [3, 4, 5] } foo([1, 2, 3, 4, 5]);
rest
操作符也可以单独使用,无需解构:
function foo(...nums) { console.log(nums); // [1, 2, 3, 4, 5] } foo(1, 2, 3, 4, 5);
在这里,我们将数字作为独立参数传递,而不是作为单个数组传递。但是在函数内部,使用rest
运算符将数字作为单个数组收集。当遍历这些参数时,这很有用。
rest语法 ...
与另一个ES6特性操作符扩展完全相同。
例如,如果要将两个数组合并为一个:
const a = [1, 2]; const b = [3, 4]; const c = [...a, ...b]; console.log(c); // [1, 2, 3, 4]
spread
操作符用于将所有项展开,并将它们放入不同的数组中。
spread
也适用于对象:
const obj = { a: 1, b: 2 }; const obj2 = { ...obj, c: 3 }; console.log(obj2); // { a: 1, b: 2, c: 3 }
现在,第二个对象除了其自身的属性外,还应包含第一个对象的所有内容。
ES6提供了创建函数,对象和类的更简单方法。
箭头函数表达式的语法比函数表达式更简洁,并且没有自己的this
,arguments
,super
或new.target
。箭头函数表达式更适用于那些本来需要匿名函数的地方,并且它不能用作构造函数。
使用箭头语法来创建更简洁的函数:
const addOne = (num) => { return num + 1; };
箭头语法对于创建单行函数更加简洁友好。
const addOne = (num) => num + 1;
此函数将自动返回表达式num +1
的求值作为返回值,不需要显式的使用return
关键字。
如果函数仅接受一个参数,甚至可以省略括号(但是在严格语法上还是建议加上括号):
const addOne = num => num + 1;
但是如果没有任何参数,仍然需要一对空括号:
const getNum = () => 1;
但是,此语法有一个警告,如果我们返回的是对象字面量,则无法使用,会报错:
const getObj = () => { a: 1, b: 2 } // error
这将产生语法错误,因为解析器将假定花括号用于函数块,而不是对象字面量。
为了避免这个错误,必须将对象字面量包装在一对括号中:
const getObj = () => ({ a: 1, b: 2 });
另一件需要记住的事情是,this
关键字不能在箭头函数中使用。它不会出现错误;相反,它只会从周围的范围提供相同的this
引用。
function thatOrThis() { const that = this; const compare = () => { console.log(that === this); // true }; compare(); } thatOrThis();
以上代码给出的值则为:true
ES6也提供了一种更简单的方法来创建对象字面量。
如果在一个对象中放入两个项目,它们的属性键与变量相同,可以用传统的Javascript做这样的事情:
const a = 1; const b = 2; const obj = { a: a, b: b, };
但是在ES6中,语法可以更简单:
const a = 1;const b = 2;const obj = { a, b };
如果把方法放到对象字面量中,可以这样做:
const a = 1; const b = 2; const obj = { a, b, getA() { return this.a; }, getB() { return this.b; }, };
基本上,没有
function
关键字和冒号。
ES6提供了类似于其他面向对象语言的类构造。现在不必依赖于混淆构造函数和原型方式。
class Person { constructor(name, hobby) { this.name = name; this.hobby = hobby; } introduce() { console.log(`大家好,我的名字叫:${this.name},我喜欢${this.hobby}。`); } } const devpoint = new Person("DevPoint", "coding"); devpoint.introduce();
附带说明,introduce
方法中的字符串称为模板字符串,它是使用反引号而不是引号创建的。这样可以使用美元符号和大括号将表达式插入字符串。
与常规字符串拼接相比,模板字符串的好处是它可以跨越多行:
const str = `line 1 line 2 line 3 `; console.log(str);
它被称为模板字符串,因为它对实现模板很有用。
function pStr(text) { return `<p>${text}</p>`; } pStr("Hello world"); // <p>Hello world</p>
一个类可以从另一个类继承(重用现有类的代码):
class Person { constructor(name, hobby) { this.name = name; this.hobby = hobby; } introduce() { console.log(`大家好,我的名字叫:${this.name},我喜欢${this.hobby}。`); } } class ProfessionalPerson extends Person { constructor(name, hobby, profession) { super(name, hobby); // 执行 Person 的构造函数 this.profession = profession; } introduce() { super.introduce(); // 调用 Person 类的方法 console.log(`我的职业是 ${this.profession}。`); } } const devpoint = new ProfessionalPerson("DevPoint", "coding", "程序员"); devpoint.introduce();
这里使用extends
关键字在两个类之间创建继承关系,其中Person
为父类。代码中用了两次super
关键字,第一次是在构造函数中调用父类的构造函数,第二次,像使用对象一样使用它来调用父类的introduce
方法。super
关键字的行为会因使用的位置而异。
在构造函数中使用时,
super
关键字将单独出现,并且必须在使用this
关键字之前使用。如下代码就是有异常的。
class ProfessionalPerson extends Person { constructor(name, hobby, profession) { this.profession = profession; // 这里会出现异常 super(name, hobby); // 执行 Person 的构造函数 } introduce() { super.introduce(); // 调用 Person 类的方法 console.log(`我的职业是 ${this.profession}。`); } }
ES6新增了两种数据结构:Map
和Set
Map
是键-值
对的集合,并且能够记住键的原始插入顺序。
const mapPerson = new Map(); mapPerson.set("name", "DevPoint"); mapPerson.set("profession", "Coding"); const myName = mapPerson.get("name"); console.log(myName); // DevPoint
Map
对象可以使用任何对象类型作为键。看起来是不有点像Object,下面我们可以看看他们的比较:
Map | Object | |
---|---|---|
意外的键 | Map 默认情况不包含任何键,只包含显式插入的键。 | 一个 Object 有一个原型,原型链上的键名有可能和你自己在对象上的设置的键名产生冲突。 |
键的类型 | Map 的键可以是任意值,包括函数、对象或任意基本类型。 | 一个 Object 的键必须是一个 String 或是 Symbol 。 |
键的顺序 | Map 中的 key 是有序的。因此,当迭代的时候,一个 Map 对象以插入的顺序返回键值。 | 一个 Object 的键是无序的 |
Size | Map 的键值对个数可以轻易地通过 size 属性获取 | Object 的键值对个数只能手动计算,需要自己构建方法 |
迭代 | Map 是 iterable 的,所以可以直接被迭代。 | 迭代一个 Object 需要以某种方式获取它的键然后才能迭代。 |
性能 | 在频繁增删键值对的场景下表现更好 | 在频繁添加和删除键值对的场景下未作出优化 |
Set
对象就像一个数组,但是仅包含唯一项。Set
对象是值的集合,可以按照插入的顺序迭代它的元素。 Set
中的元素只会出现一次,即 Set
中的元素是唯一的。
const numbers = new Set(); numbers.add(1); numbers.add(1); console.log(numbers); // Set { 1 }
尽管两次add
是同样的值,程序本身不会出现任何异常,但该集合仍然只包含一项。
让谈谈来学习一点更复杂的知识,WeakMap
和WeakSet
。它们分别是Map
和Set
的弱引用版本。
WeakMap
其键必须是Object
,而值可以是任意的。
WeakSet
对象是一些对象值的集合, 并且其中的每个对象值都只能出现一次,在WeakSet
的集合中是唯一的。
它和 Set
对象的区别有两点:
Set
相比,WeakSet
只能是对象的集合,而不能是任何类型的任意值。WeakSet
持弱引用:集合中对象的引用为弱引用。 如果没有其他的对WeakSet
中对象的引用,那么这些对象会被当成垃圾回收掉。 这也意味着WeakSet
中没有存储当前对象的列表。 正因为这样,WeakSet
是不可枚举的。一旦不再引用WeakMap
的键,便会对其进行垃圾回收(由Javascript运行时从内存中删除)。
let key1 = {}; const key2 = {}; const wm = new WeakMap(); wm.set(key1, 1); wm.set(key2, 2); key1 = null; // 取消引用
在key1
被取消引用之后,它的对应值将被垃圾回收,意味着它将在未来的某个时间点消失。
同样,如果将一个对象添加到WeakSet
中,然后再取消引用它,它也将被垃圾回收。
let item1 = {}; const item2 = {}; const ws = new WeakSet(); ws.add(item1); ws.add(item2); item1 = null; // 取消引用
Promise
对象用于表示一个异步操作的最终完成 (或失败)及其结果值。是ES6的一个常用功能,它是对传统函数回调模式的改进。
一个 Promise 必然处于以下几种状态之一:
pending
): 初始状态,既没有被兑现,也没有被拒绝。fulfilled
): 意味着操作成功完成。rejected
): 意味着操作失败。例如,这是使用传统回调的方式:
setTimeout(function () { const currentTime = new Date(); console.log(currentTime); }, 1000);
这是一个计时器,显示一秒钟后的时间。
这是一个使用相同setTimeout
逻辑的Promise
对象:
const afterOneSecond = new Promise(function (resolve, reject) { setTimeout(function () { const currentTime = new Date(); resolve(currentTime); }, 1000); });
它接受带有两个参数的函数:resolve
和reject
。这两个都是当有返回值时可以调用的函数。调用resolve
函数返回一个值,可以调用reject
函数返回一个错误。
然后,可以使用then
语法将回调函数附加到这个afteronessecond
对象上:
afterOneSecond.then((t) => console.log(t));
promise
相对于传统回调的好处是promise
对象可以被传递。因此,在设置promise
之后,可以自由地将它发送到其他地方,以处理计时器解析后要做的事情。
另一个很酷的事情是,promise可以与多个then子句链接在一起,即promise
的链式调用。
afterOneSecond.then((t) => t.getTime()) .then((time) => console.log(time));
每个
then
子句将其值作为参数返回到下一个then
子句。
下面就来介绍在VUE中,比较实用的ES6的方法或属性。
Object.assign()
方法用于将所有可枚举属性的值从一个或多个源对象分配到目标对象。它将返回目标对象。提供了一种简单的方法来浅克隆现有对象。
const obj1 = { a: 1 } const obj2 = Object.assign({}, obj1)
构造并返回一个新字符串,该字符串包含被连接在一起的指定数量的字符串的副本。
const str = "DevPoint ".repeat(3);console.log(str); // DevPoint DevPoint DevPoint
用来判断当前字符串是否以另外一个给定的子字符串开头(区分大小写),并根据判断结果返回
true
或false
。
const str = "DevPoint".startsWith("D"); const str2 = "DevPoint".startsWith("d"); console.log(str); // true console.log(str2); // false
用来判断当前字符串是否是以另外一个给定的子字符串“结尾”的,根据判断结果返回
true
或false
。
const str = "DevPoint".endsWith("t"); console.log(str); // true
用于判断一个字符串是否包含在另一个字符串中,根据情况返回
true
或false
。
const str = "DevPoint".includes("P"); console.log(str); // true
返回数组中满足提供的过滤函数的第一个元素的值,否则返回
undefined
。
const arrNumbers = [5, 12, 8, 130, 44]; const foundNumbers = arrNumbers.find((number) => number > 10); console.log(foundNumbers); // 12是数组第一个大于10的数
这不是方法而是属性,返回函数实例的名称,每个函数都有一个
name
属性,该属性提供字符串形式的函数名称
// setTimeout.name; // "setTimeout" const weather = () => { console.log("今天天气真好!"); }; const devpoint = () => {}; // 限制回到函数的名称 const enter = (callback) => { const accessName = ["weather"]; if (accessName.includes(callback.name)) { callback(); } }; enter(devpoint); enter(weather);
上述代码只执行了函数 weather
。
ES6的新特征,某种程度上代表的Javascript在未来的态度,这些新的特征让我迫不及待应用到项目中,不断接受新挑战,提升自己技能。
The above is the detailed content of What are the es6 features used in vue?. For more information, please follow other related articles on the PHP Chinese website!