要晓得,做前端开发,ES6是recommend的。这首诗适宜先期进阶和备考,紧密结合阮志成同学的ES6国际标准进阶能更深入细致的自学ES6。
产品目录:
一. 块级返回值、块级表达式let、块级自变量const
二. 斜线表达式
三. 组件处置(预设组件/…)
四. 模版字面上量(模版数组)
五. 第一类的扩充
六. 重构表达式
七. 组件(import/export)
八. 类(class/extends)
九. Promise
十. End 非常感谢写作一. 块级返回值、表达式let、自变量const
由两对 { } 区分的句子叫作块句子,这在其它C语言中叫作A43EI235E句子。通常认知的块:
块:由{}主要包括住
if(){}:是两个块
for(){}:是两个块
那些也可认知成块:
两个表达式:表达式返回值
<script>条码:自上而下返回值
2. JS时用var新闻稿的变量是没块级返回值的,多于表达式返回值和自上而下返回值。
var x = 1;
{
var x = 2;
}
console.log(x);
//会输出2,因为块中的var句子与块前面的var句子返回值相同
//在C或Java中,这段代码会输出 1//这代码证明了var没块返回值
3. 相比之下,使用 let 和 const 新闻稿的表达式是有块级返回值的。
let x = 1;
{
let x = 2;
}
console.log(x);
// 输出 1// x被限制在块级返回值中
// 这里将let换成const结果也一样
4. 经典的例子(背住):
var a = [];
for (var i = 0; i < 10; i++) {
a[i] = function () {console.log(i);};
}
a[0](); // 10
a[1](); // 10
a[6](); // 10
/********************/
var a = [];
for (let i = 0; i < 10; i++) {
a[i] = function () {console.log(i);};
}
a[0](); // 0
a[1](); // 1
a[6](); // 6
//第两个中的i是没块级返回值的,自上而下多于两个表达式i,每次循环的{}中的代码都指向同两个i//第二个中的i是有块级返回值的,当前的i只在本轮循环有效,每次循环的{}中的代码都指向不同的i
//值得注意的是:for的()是两个父返回值,{}是两个子返回值
//因为当前的i只在本轮循环有效,所以let定义的i在每次循环都会重新定义一遍,每次都是两个新表达式
5. 补充:
foo(outside); // TypeError: foo is not a function
{
function foo(location) {
console.log(foo is called + location);
}
foo(inside); // 正常工作并且打印 foo is called inside
}
//使用function时也有块级返回值
6. var表达式提升,let表达式暂时性死区:
//var会发生表达式提升现象,将表达式提升到表达式顶部或自上而下顶部
console.log(foo); //输出undefined,不会报错var foo = 2;
//let没这种情况,必须在let新闻稿后调用该表达式 (const和let一样)
//let和const的这种现象称为暂时性死区
//从块开始到let新闻稿之间是“暂存死区”
console.log(bar); //报错ReferenceError
let bar = 2;
7. let的错误
在同两个返回值时用let重复定义两个表达式将引起TypeError
if (x) {
let foo;
let foo; // TypeError thrown.
}
8. const的概念
必须在新闻稿的同一句子中指定它的值const新闻稿创建两个值的只读引用,也就是说只能通过const定义的表达式来读这个值,不能修改这个值,但是如果这个值本身发生了变化,那么const定义的表达式所对应的值也就跟着变化,比如当引动内容是第一类的情况下。两个自变量不能和它所在返回值内的其它表达式或表达式拥有相同的名称。// 下面错误,自变量要求有一个初始值const FOO;
// 下面正确,自变量可以定义成第一类
const MY_OBJECT = {“key”: “value”};
// 下面错误,改变自变量会失败
MY_OBJECT = {“OTHER_KEY”: “value”};
// 第一类属性并不在保护的范围内,下面会成功执行(第一类本身发生变化)
MY_OBJECT.key = “otherValue”;
// 定义两个自变量
const MY_FAV = 20;
// 不能同名,会出错var MY_FAV = 20;
// 也会报错
let MY_FAV = 20;
二. 斜线表达式
基础语法:
//通常语法:
(组件1, 组件2, …, 组件N) => { 表达式新闻稿 }
//相当于:(组件1, 组件2, …, 参数N) =>{ return 表达式; }(组件1, 组件2, …, 组件N) => 表达式(单一)
// 当多于两个组件时,圆括号是可选的:
(单一组件) => {表达式新闻稿}
单一组件 => {表达式新闻稿}
// 没组件的函数应该写成两对圆括号() => {表达式新闻稿}
高级语法:
(*注: 字面上量通常指[1, 2, 3] 或者{name: “mdn”} 这种简洁的构造方式)
*//加括号的表达式体返回第一类字面上表达式:
组件=> ({foo: bar})
//支持剩余组件和预设组件
(组件1, 组件2, …rest) => {表达式新闻稿}
(组件1 = 预设值1,组件2, …, 组件N = 预设值N) => {表达式新闻稿}
//同样支持组件列表重构
let f = ([a, b] = [1, 2], {x: c} = {x: a + b}) => a + b + c;
f(); // 6
例子:
斜线表达式比较适用于原本需要匿名表达式的地方,比如用在数组内置方法map、filter、forEach、reduce的回调表达式中var elements = [
Hydrogen,
Helium,
Lithium,
Beryllium
];
elements.map(function(element) {
return element.length;
}); // 返回数组:[8, 6, 7, 9]
// 上面的普通表达式可以改写成如下的斜线表达式
elements.map((element) => {
return element.length;
}); // [8, 6, 7, 9]
重点注意:
this 第一类的指向是可变的,但是在斜线表达式中,它是固定的。斜线表达式体内的 this 第一类,就是定义时所在的第一类,而不是使用时所在的第一类。三. 组件处置
1. 给表达式设置预设组件值
在ES6以前,我们想要给组件设置预设值得这么做:
function multiply(a, b) {
//JavaScript中表达式的组件预设是undefined
//没值传入或者undefined被传入给b时给b两个预设值 b = (typeof b !== undefined) ? b : 1;
return a * b;
}
multiply(5, 2); // 10
multiply(5); // 5
现在自学了ES6之后就变得很简单:
function multiply(a, b = 1) {
return a * b;
}
multiply(5, 2); // 10
multiply(5); // 5
注意组件的传递是从左到右的:
function f(x = 1, y) {
return [x, y];
}
f(); // [1, undefined]
f(2); // [2, undefined]
2. 剩余组件(…)
剩余组件语法允许我们将两个不定数量的组件表示为两个数组。
语法:
function(a, b, …theArgs) {
…
}
//必须是表达式的最后两个组件以…为前缀
//它是由剩余实参组成的Array数组
//这个例子中的theArgs收集第三个以及之后的所有实参
实例:
function fun1(…theArgs) {
alert(theArgs.length);//可以使用所有数组属性方法
}
fun1(); // 弹出 “0”, 因为theArgs没元素
fun1(5); // 弹出 “1”, 因为theArgs多于两个元素
3. 展开运算符(…)
展开语法, 可以在表达式调用/数组构造时, 将数组表达式或者string在语法层面展开;还可以在构造字面上量第一类时, 将第一类表达式按key-value的方式展开。
(注: 字面上量通常指[1, 2, 3] 或者{name: “mdn”} 这种简洁的构造方式)
在表达式调用时使用展开语法:function sum(x, y, z) {
return x + y + z;
}
const numbers = [1, 2, 3];
console.log(sum(…numbers));//6
/****下例表示可以多次使用****/
function myFunction(v, w, x, y, z) { }
var args = [0, 1];
myFunction(–1, …args, 2, …[3]);
构造字面上量数组时使用展开语法:/****构造字面上量数组或连接数组****/
var parts = [shoulders, knees];
var lyrics = [head, …parts, and, toes];
// [“head”, “shoulders”, “knees”, “and”, “toes”]var arr = […parts, …lyrics];
/****支持浅拷贝(一维数组)****/
var arr = [1, 2, 3];
var arr2 = […arr];
arr2.push(4);
// arr2 此时变成 [1, 2, 3, 4]
// arr 不受影响
构造字面上量第一类时使用展开语法:var obj1 = { foo: bar, x: 42 };
var obj2 = { foo: baz, y: 13 };
var clonedObj = { …obj1 };
// 浅拷贝
// 克隆后的第一类: { foo: “bar”, x: 42 }
var mergedObj = { …obj1, …obj2 };
// 合并后的第一类: { foo: “baz”, x: 42, y: 13 }
四. 模版字面上量(模版数组)
由反引号 ` 来代替单引号 或者双引号 ” 。
单行数组:`string text`
多行数组(注意回车也包含在内)`string text line 1
string text line 2`
console.log(`string text line 1
string text line 2`);//不再用”+”或”\”连接两行数组
插入表达式:`string text ${expression} string text`
var a = 5;
var b = 10;
console.log(`a + b is ${a + b}`);//不再用”+”连接表达式
带条码的模版数组:条码使我们可以用表达式来解析模版数组。
直接看例子:
var person = Mike;
var age = 28;
function myTag(strings, personExp, ageExp) {
var str0 = strings[0]; // “that ”
var str1 = strings[1]; // ” is a ”
var ageStr;
if (ageExp > 99){
ageStr = centenarian;
} else {
ageStr = youngster;
}
return str0 + personExp + str1 + ageStr;
}
var output = myTag`that ${ person } is a ${ age }`;
console.log(output);
// that Mike is a youngster
原始数组:在条码表达式的第两个组件中,存在两个特殊的属性raw ,我们可以通过它来访问模版数组的原始数组,而不经过特殊字符的替换。
例子:
function tag(strings) {
console.log(strings.raw[0]);
}
tag`string text line 1\n string text line 2`;
// logs “string text line 1 \n string text line 2”
五. 第一类的扩充
创建第一类时可以简化方法和重名的键值对//通常情况
var name=“pan”;
var age=20;
var people = {
name: name,
age: age,
getName: function() {
console.log(this.name)
}
};
//ES6简化后
var name=“pan”;
var age=20;
var people = {
name,
age,
getName(){
console.log(this.name)
}
};
计算属性名(属性名可以用表达式)var i = 0;
var a = {
[“foo” + ++i]: i,
[“foo” + ++i]: i,
[“foo” + ++i]: i
};
console.log(a.foo1); // 1
console.log(a.foo2); // 2
console.log(a.foo3); // 3
__proto__当定义的 属性:值 为 __proto__:值 时,不会创建名为__proto__的属性。
但当值为第一类时,将更改原型(因为__proto__原本指向原型)。
所以不建议使用这个属性名(避免更改__proto__的指向)。六. 重构表达式
重构表达式语法是一种 Javascript 表达式,它使得将值从数组,或属性从第一类,提取到不同的表达式中,成为可能。
目的就是将数组中的值或第一类中的属性方便的提取到其它表达式中重构数组语法:var x, y;
[x, y] = [1, 2, 3];
console.log(x); // 1
console.log(y); // 2
//或者:
var [x, y] = [1, 2, 3];
console.log(x); // 1
console.log(y); // 2
小技巧(不用临时表达式也能交换表达式):
var a = 1;
var b = 3;
//等价于[a,b]=[3,1]
[a, b] = [b, a];
console.log(a); // 3
console.log(b); // 1
重构第一类语法:var o = {p: 42, q: true};
var {p, q} = o;
console.log(p); // 42
console.log(q); // true
注意:第一类重构与数组重构有两个重要的不同点,数组的元素是按次序排列的,表达式的取值由它的位置决定;而第一类的属性没次序,表达式必须与属性同名,才能取到正确的值。七. 组件(import/export)
组件功能主要由两个命令构成:export和import。export命令用于规定组件的对外接口,import命令用于输入其它组件提供的功能。
S 文件,里面使用export命令输出表达式。
导出export// profile.js
var firstName = Michael;
var lastName = Jackson;
var year = 1958;
export {firstName, lastName, year};
//上面代码是profile.js文件,保存了用户信息,
//ES6将其视为两个组件,里面用export命令对外部输出了三个表达式。
//除了这种普通表达式,输出的表达式还可以是两个表达式。
//另外,export句子输出的接口,与其对应的值是动态绑定关系,
//即通过该接口,可以取到组件内部实时的值。
//最后,export/import命令不能在块级作用域内,可以在自上而下返回值任何位置。
导入importimport句子只能在新闻稿了type=”module”的script的条码中使用。
动态导入:import(),它不需要依赖type=”module”的script条码。
按照一定的条件或者按需加载组件的时候,动态import()是非常有用的。
而静态的import是初始化加载的最优选择。// main.js
import {firstName, lastName, year} from ./profile.js;
function setName(element) {
element.textContent = firstName + + lastName;
}
//上面代码的import命令,用于加载profile.js文件,并从中输入表达式。//import命令接受两对大括号,里面指定要从其它组件导入的表达式名。
//大括号里面的表达式名,必须与被导入组件(profile.js)对外接口的名称相同。
注意:import句子会执行所加载的组件import ./lodash.js;
//执行lodash组件,但是不输入任何值
整体导入:import * as myModule from ./my-module.js;//不用加大括号{}
//将my-module里面输出的表达式/表达式,
//输入到myModule这个第一类中作为属性/方法。
//通过myModule.属性名/myModule.方法()来调用。
预设导出/导入预设值:告别使用import命令的时候,用户需要晓得所要加载的表达式名或表达式名的现状//先用export default语法预设导出
//既然是预设输出,那么两个模版只能使用一次
export default function foo() {
console.log(foo);
}
//导入预设值
import customName from ./default.js;//不用加大括号{}
customName(); // foo
八. 类
ES6 中引入的 JavaScript 类实质上是 JavaScript 现有的基于原型的继承的语法糖。类语法不会为JavaScript引入新的面向第一类的继承模型。
如何创建类:class Rectangle {
constructor(height, width) { //构造方法
this.height = height;
this.width = width;
}
}
//或者
let Rectangle = class {
constructor(height, width) { //构造方法
this.height = height;
this.width = width;
}
};
如何使用类:class Rectangle {
// constructor
constructor(height, width) {
this.height = height;
this.width = width;
}
// Getter
get area() {
return this.calcArea()
}
// Method
calcArea() {
return this.height * this.width;
}
}
const square = new Rectangle(10, 10);
console.log(square.area);
// 100
类的静态方法:不能通过两个类实例调用静态方法(这里和Java语法有区别)class Point {
constructor(x, y) {
this.x = x;
this.y = y;
}
static distance(a, b) { //static语法
const dx = a.x – b.x;
const dy = a.y – b.y;
return Math.hypot(dx, dy);
}
}
const p1 = new Point(5, 5);
const p2 = new Point(10, 10);
//直接通过类名调用
console.log(Point.distance(p1, p2));
类的继承(extends)class Animal {
constructor(name) {
this.name = name;
}
speak() {
console.log(this.name + makes a noise.);
}
}
class Dog extends Animal {
constructor(name) {
super(name); // 调用超类构造表达式
}
speak() {
console.log(this.name + barks.);
}
}
var d = new Dog(Mitzie);
// Mitzie barks.
d.speak();
调用父类方法(super)class Cat {
constructor(name) {
this.name = name;
}
speak() {
console.log(this.name + makes a noise.);
}
}
class Lion extends Cat {
speak() {
super.speak();
console.log(this.name + roars.);
}
}
九. Promise 第一类
这部分内容是重难点,说是面试必考的知识点也不过分,因为它不易简单的进行归纳,所以我推荐读到这里的朋友去细读 阮志成Promise ,进行系统的自学这部分内容。
给两个面试考点:Promise、Promise.all、Promise.race分别怎么用?
十. End 非常感谢写作
欢迎感兴趣的知友关注我以及我的专栏,这里面存放的都是我自学前端路上遇到的一些重要知识点~