ES6 手册:你需要知道的一切
各位读者好!这篇博客是关于 ES6 的,涵盖了所有与示例相关的主题。在继续阅读之前,我想声明一下,这并非一篇博客文章,只是我的个人笔记,仅供参考,如有拼写错误,敬请谅解 :)
目录
笔记
let/const
在进入正题之前,我们先来了解一下两个概念:
- 全局作用域- 变量在函数外部声明。代码中的每个函数都可以访问此变量。
- 函数范围- 变量在函数内部声明,在函数外部无法访问。
- 块作用域- 简而言之,块作用域是指在 { } 块中声明的变量无法在块外部访问。该块可以是
if
语句、for
循环while
等。
var
:函数/全局作用域。例如:
→ 如你所见, var 既是全局变量,又是函数作用域变量,这经常会造成混淆。所以尽量避免使用它。
var name = 'Jack'; // global scope
function message() {
var msg = 'Hey Jack!' //function scope
}
console.log(msg); // ERROR
msg
上面这行代码会抛出错误,因为函数外部message
(我们记录变量的地方)没有变量。所以它会显示为undefined
。
let
:块作用域。例如:
→let
关键字不能被重新声明:
let x = 1;
let x = 3;
结果:SyntaxError - 重新声明 let x
但是当我们let
在函数内部使用时,它的工作方式如下:
let size = "big";
function box() {
for (let x = 0; x < 7; x++) {
console.log(size);
//Output: ReferenceError - `size` is not defined
let size = "small";
console.log(size);
}
}
box(); // small
console.log(size); //big
当我们在函数内部box()
记录 size 的值时,它会显示一个引用错误。这是因为它let
是块作用域的。
大括号 { } 内的所有内容都是块级作用域。在上述场景中,函数box()
就是一个块。
const
:块作用域。例如:
const
非常相似,let
只是它们不能被改变和重新声明。
const m = 8;
console.log(m); //m = 8
m = 5; // 🚫 this will throw an error
console.log(m);
// Uncaught TypeError: invalid assignment to const 'm'.
}
→ 因此let
,与关键字const
相比,更适合var
用于声明变量。
对象
{ }
对象以键:值对的集合形式写在花括号内。
key
:属性名称
value
:该属性的值
- 创建一个空对象:
const car = {
model: 'Tesla',
color: 'black',
price: 800
}
具体来说 ES6,在 ES6 之前,我们必须同时指定 (key, value),即使两者名称相同。
function Boy(name, age) {
return(
name: name,
age: age
);
}
ES6 帮助我们避免键值对名称重复的情况。所以现在我们的代码看起来是这样的:
function Boy(name, age) {
return(name, age);
}
这
this
是一个关键字。它基本上返回一个指向其所在对象的引用
💡注意:
- 当我们将函数作为对象中的方法调用时,
this
关键字将返回对该对象的引用。👇
const user = {
name: 'Mike';
call() {
console.log(this);
}
}
user.call();
// ⚙️ Output: {name: 'Mike, call: f}
- 但是当我们单独调用该函数时,对象外部
this
会返回全局对象(浏览器窗口),因此我们得到的结果为未定义👇
const user = {
name: 'Mike';
call() {
console.log(this);
}
}
const myCall = user.call;
myCall();
// ⚙️ Output: undefined
箭头函数
- 通常,在 ES6 之前:
const square = function(num) {
return num * num;
}
- 在 ES6 中:
const square = num => num * num;
数组.map()
如果我们有一个数组 -
const colors = ["red", "green", "blue"];
我们要映射对象。现在有两种方法,es6
一种更简洁、更简单。
- 正常情况:
const items1 = colors.map(function (color) {
return "<li>" + color + "</li>";
});
- es6:
const items2 = colors.map((color) => `<li> ${color} </li>`);
对象解构
假设我们有一个名为的对象girl
,它有 3 个键,如下所示:
const girl = {
name: "",
age: "",
country: "",
};
- 通常,我们会做这样的事情来获取值:
const name = girl.name;
const age = girl.age;
const country = girl.country;
- 正如你所见,
girl
每次获取值时,我们都必须重复对象名称。这个问题可以通过对象解构来解决:
const { name, age, country } = girl;
这行代码的作用和之前的代码一样。所以解构使我们的代码更短,更容易理解。
- 如果您想为您的工作使用别名(不同的变量名):
const {country: ctry} = girl;
上面这行代码意味着我们定义了一个名为 的新变量ctry
,并将其设置为country
。
扩展运算符
案例 I - 组合数组
- 如果我们想合并这两个数组:
const one = [1, 2, 3];
const two = [4, 5, 6];
- 没有 ES6:
const combined = one.concat(two);
- 使用 ES6:
const combined = [...one, ...two];
- 如果我们想在中间添加一些东西:
const combined = [...one, '9', '7', ...two ];
- 如果我们想要克隆一个数组:
const myDupli = [...two];
案例 II - 组合物体
- 如果我们想合并这两个对象:
const alpha = { name: 'Shreya' };
const beta = { age: 19 };
- 在 ES6 中:
const combined = {...alpha, ...beta};
- 如果我们想在黑白中添加更多属性:
const gamma = { ...alpha, surName:'Purohit', ...beta, country: 'India'}
- 克隆对象:
const betaV2 = {...beta};
课程
- 我们以一个对象为例
boy
。我们有一个函数run
在它内部被调用。如果将来我们遇到了一些 bug,或者需要修改这个函数以适应不同的对象,那么修改起来就会非常麻烦。
const boy = {
name: "Sam",
run() {
console.log("running...");
},
};
- 为了克服这个问题并使我们的工作更容易,我们使用类:
class Boy {
constructor(name) {
this.name = name;
}
run() {
console.log("running...");
}
}
- 现在我们已经创建了一个类,让我们再次尝试构建我们的对象 -
const boy = new Boy("Samridh");
通过上面的类,我们用一行代码实现了 run 方法。如果有一天我们发现了 bug,我们只需在 Boy 类内部的一个地方进行修改即可。这就是在 JS 中使用类的优势。
遗产
- 如果我们有一个 Boy 类,那么 -
class Boy {
constructor(name) {
this.name = name;
}
run() {
console.log("running");
}
}
- 并且我们想要创建另一个类(具有类似的属性以及一些其自身的特定属性)。我们可以使用关键字
extends
class Girl extends Boy {
eat() {
console.log("eating");
}
}
- 我们刚刚在这里创建了这个类
Girl
。现在让我们用这个创建一个 const -
const myGirl = new Girl("Shreya");
- 大功告成。这段代码的意思就是,现在 const 函数将拥有类的
myGirl
functionseat
++run
属性。所以我们可以像这样使用它:constructor
Boy
myGirl.eat();
myGirl.run();
- 现在假设我们想在
Girl
类中创建另一个构造函数{它是从Boy
类扩展的,因此此类中的构造函数Girl
称为派生类构造函数。 }。 - 我们必须在新的构造函数中调用
super()
构造函数,否则会报错(因为this
在派生类中使用构造函数需要super()
类)。这看起来可能有点令人困惑,我们来看下面的例子——
class Girl extends Boy {
constructor(age) {
this.age = age;
}
eat() {
console.log("eating");
}
}
// *result - Uncaught ReferenceError: must call super constructor before using 'this' in derived class constructor*
- 调用
super()
构造函数:
class Girl extends Boy {
constructor(name, age) {
super(name);
this.age = age;
}
eat() {
console.log("eating");
}
}
const myGirl = new Girl("Shreya");
- 在子类构造函数中,直到被调用
this
时才能使用。super
模块
有时我们会在一个文件中声明多个类。这会使代码变得冗长、混乱和混乱。为了避免这种情况,我们将这些类分成不同的文件,并将它们作为module
主文件导入。这称为模块化。
让我们实际看一下。我们的文件夹如下所示src
:
// src/boy.js
export class Boy {
constructor(name) {
this.name = name;
}
run() {
console.log("running");
}
}
// src/girl.js
import { Boy } from './src/boy';
export class Girl extends Boy {
constructor(name, age) {
super(name);
this.age = age;
}
eat() {
console.log("eating");
}
}
Boy 和 Girl 类在文件夹中都是私有的,为了使用它们,我们使用
export
关键字将它们公开。我们
import
在 girl.js 的第 1 行使用关键字,因为它是该类的扩展版本Boy
。
现在,一半的工作已经完成了。目前,这些类在我们的主app.js
文件中还无法访问。为此,我们需要将它们导入到我们的app.js
文件中。我们可以这样操作:
import { Boy } from './src/boy';
import { Girl } from './src/girl';
默认导出和命名导出
命名导出
- 我们可以从特定模块导出多个对象。这称为命名导出。例如:
export class Car {
constructor(model) {
this.model = model;
}
}
export function add(a, b){
return a + b;
}
- 这里我们导出了一个类
Car
和一个函数add
。
默认导出
- 它基本上是从模块导出的主要对象。通常情况下,我们只需要导出一个对象。让我们看看它是怎样的——
export default class Car {
constructor(model) {
this.model = model;
}
}
💡 现在我们不需要import { Car } from "./car";
相反,我们import Car from "./car";
在默认导出的情况下使用。
Default exports → import Car from "./car";
Named exports → import { Car } from "./car";
👋 呼!你终于看到最后了。希望对你有所帮助。我一有空就会写这类文章。除此之外,我每天还会在推特上分享与 Web 开发相关的内容。我们在那里联系吧!@eyeshreya
文章来源:https://dev.to/shreya/es6-handbook-everything-you-need-to-know-1ea7