提示:文章篇幅较长,涉及知识点较多,建议收藏后观看。
目录
let 和 const
解构赋值
箭头函数的使用
模板字符串
函数默认参数
展开运算符
对象字面量 与 class
Promise
数组新增方法
对象新增方法
指数函数的中缀形式
let 和 const 的特点:
临时死区:(TDZ) let 和 const 声明的变量不会被提升到作用域顶部,如果在声明之前访问这些变量,会导致报错:
var value = "global";
// 例子1
(function() {
console.log(value);
let value = 'local';
}());
// 例子2
{
console.log(value);
const value = 'local';
};
// 两个例子中,结果并不会打印 "global",而是报错 Uncaught ReferenceError: value is not defined,就是因为 TDZ 的缘故。
解构赋值语法是一个Javascript表达式,这使得可以将数据从数组或对象提取到不同的变量中
const person = {
name: 'little bear',
age: 18,
sex: '男'
}
let { name,age,sex } = person
//数组
let nbaStars=['yaoming','kobe','james','paul']
let [chinaStar,...usaStar] = nbaStars
let [,,,myidol] = nbaStars
console.log(usaStar,chinaStar,myidol)
//["kobe", "james", "paul"] "yaoming" "paul"
// es5
var fn = function(a, b) {
return a + b;
}
// es6 箭头函数写法,当函数直接被return时,可以省略函数体的括号
const fn = (a, b) => a + b;
// es5
var foo = function() {
var a = 20;
var b = 30;
return a + b;
}
// es6
const foo = () => {
const a = 20;
const b = 30;
return a + b;
}
# 使用箭头函数需要注意以下几点:
使用 `` 将整个字符串包裹起来,而在其中使用 ${} 来包裹一个变量或者一个表达式。
// es6
const a = 20;
const b = 30;
const string = `${a}+${b}=${a+b}`;
// es5
var a = 20;
var b = 30;
var string = a + "+" + b + "=" + (a + b);
function add(x = 20, y = 30) {
return x + y;
}
console.log(add());
在ES6中用...来表示展开运算符,它可以将数组方法或者对象进行展开。
数组展开:
const arr1 = [1, 2, 3];
const arr2 = [...arr1, 10, 20, 30];
// 这样,arr2 就变成了[1, 2, 3, 10, 20, 30];
对象展开:
const obj1 = {
a: 1,
b: 2,
c: 3
}
const obj2 = {
...obj1,
d: 4,
e: 5,
f: 6
}
// 结果类似于 const obj2 = Object.assign({}, obj1, {d: 4})
const name = 'Jane';
const age = 20
// es6
const person = {
name,
age
}
// es5
var person = {
name: name,
age: age
};
// es6
const person = {
name,
age,
getName() { // 只要不使用箭头函数,this就还是我们熟悉的this
return this.name
}
}
// es5
var person = {
name: name,
age: age,
getName: function getName() {
return this.name;
}
};
const name = 'Jane';
const age = 20
const person = {
[name]: true,
[age]: true
}
// ES5
// 构造函数
function Person(name, age) {
this.name = name;
this.age = age;
}
// 原型方法
Person.prototype.getName = function() {
return this.name
}
// ES6
class Person {
constructor(name, age) { // 构造函数
this.name = name;
this.age = age;
}
getName() { // 原型方法
return this.name
}
}
babel会将ES6的写法编译成为利用Object.defineProperty实现的方式,包括get,set等。
class Person {
constructor(name, age) { // 构造函数
this.name = name;
this.age = age;
}
getName() { // 这种写法表示将方法添加到原型中
return this.name
}
static a = 20; // 等同于 Person.a = 20
c = 20; // 表示在构造函数中添加属性 在构造函数中等同于 this.c = 20
// 箭头函数的写法表示在构造函数中添加方法,在构造函数中等同于this.getAge = function() {}
getAge = () => this.age
}
继承 extends
相比ES5,ES6的继承就要简单很多:
class Person {
constructor(name, age) {
this.name = name;
this.age = age;
}
getName() {
return this.name
}
}
// Student类继承Person类
class Student extends Person {
constructor(name, age, gender, classes) {
super(name, age);
this.gender = gender;
this.classes = classes;
}
getGender() {
return this.gender;
}
}
/* 在继承的构造函数中,我们必须如上面的例子那么调用一次super方法,
它表示构造函数的继承,与ES5中利用call/apply继承构造函数是一样的功能。 */
// 构造函数中
// es6
super(name, age);
// es5
Person.call(this);
在ajax的原生实现中,利用了onreadystatechange事件,当该事件触发并且符合一定条件时,才能拿到我们想要的数据,之后我们才能开始处理数据。这样做看上去并没有什么麻烦,但是如果这个时候,我们还需要做另外一个ajax请求,这个新的ajax请求的其中一个参数,得从上一个ajax请求中获取,这个时候我们就不得不如下这样做:
var url = 'https://hq.tigerbrokers.com/fundamental/finance_calendar/getType/2017-02-26/2017-06-10';
var result;
var XHR = new XMLHttpRequest();
XHR.open('GET', url, true);
XHR.send();
XHR.onreadystatechange = function() {
if (XHR.readyState == 4 && XHR.status == 200) {
result = XHR.response;
console.log(result);
// 伪代码
var url2 = 'http:xxx.yyy.com/zzz?ddd=' + result.someParams;
var XHR2 = new XMLHttpRequest();
XHR2.open('GET', url, true);
XHR2.send();
XHR2.onreadystatechange = function() {
...
}
}
}
当出现第三个ajax(甚至更多)仍然依赖上一个请求的时候,我们的代码就变成了一场灾难。这场灾难,往往也被称为回调地狱。
因此我们需要一个叫做Promise的东西,来解决这个问题。
当然,除了回调地狱之外,还有一个非常重要的需求:为了我们的代码更加具有可读性和可维护性,我们需要将数据请求与数据处理明确的区分开来。
Promise对象有三种状态,他们分别是:
new Promise(function(resolve, reject) {
if(true) { resolve() };
if(false) { reject() };
})
Promise.all:
Promise.all接收一个Promise对象组成的数组作为参数,当这个数组所有的Promise对象状态都变成resolved或者rejected的时候,它才会去调用then方法。
var url = '...';
var url1 = '...';
function renderAll() {
return Promise.all([getJSON(url), getJSON(url1)]);
}
renderAll().then(function(value) {
console.log(value);
})
Promise.race:
与Promise.all相似的是,Promise.race都是以一个Promise对象组成的数组作为参数,不同的是,只要当数组中的其中一个Promsie状态变成resolved或者rejected时,就可以调用.then方法了。
function renderRace() {
return Promise.race([getJSON(url), getJSON(url1)]);
}
renderRace().then(function(value) {
console.log(value);
})
1. Array.prototype.includes
includes是一个 Array 上很有用的函数,用于快速查找数组中是否包含某个元素。(包括 NaN,所以和 indexOf 不一样)。
2. 字符串追加
提供了两个字符串追加的方法 String.prototype.padStart 和 String.prototype.padEnd,方便我们将一个新的字符串追加到某个字符串的头尾。
'someString'.padStart(numberOfCharcters [,stringForPadding]);
'5'.padStart(10) // ' 5'
'5'.padStart(10, '=*') //'=*=*=*=*=5'
'5'.padEnd(10) // '5 '
'5'.padEnd(10, '=*') //'5=*=*=*=*='
Object.entries(cars).map(([name, count]) => {
console.log(`${name.padEnd(20, '-')} Count:${count.toString().padStart(3, '0')}`)
})
/*
?ambulance--------- Count:003
?car--------------- Count:007
?trucks------------ Count:004
*/
3. Array.prototype.flat() ( ES9 )
Array.prototype.flat() 递归地将嵌套数组拼合到指定深度。默认值为 1,如果要全深度则使用 Infinity 。此方法不会修改原始数组,但会创建一个新数组:
const arr1 = [1, 2, [3, 4]];
arr1.flat(); // [1, 2, 3, 4]
const arr2 = [1, 2, [3, 4, [5, 6]]];
arr2.flat(2); // [1, 2, 3, 4, 5, 6]
const arr3 = [1, 2, [3, 4, [5, 6, [7, 8]]]];
arr3.flat(Infinity); // [1, 2, 3, 4, 5, 6, 7, 8]
flat() 方法会移除数组中的空项:
const arr4 = [1, 2, , 4, 5];
arr4.flat(); // [1, 2, 4, 5]
4. Array.prototype.flatMap() (ES9)
flatMap() 方法首先使用映射函数映射每个元素,然后将结果压缩成一个新数组。它与 Array.prototype.map 和 深度值为 1的 Array.prototype.flat 几乎相同,但 flatMap 通常在合并成一种方法的效率稍微高一些。
const arr1 = [1, 2, 3];
arr1.map(x => [x * 4]); // [[4], [8], [12]]
arr1.flatMap(x => [x * 4]); // [4, 8, 12]
更好的示例:
const sentence = ["This is a", "regular", "sentence"];
sentence.map(x => x.split(" "));
// [["This","is","a"],["regular"],["sentence"]]
sentence.map(item => item.split(' ')).flat(Infinity)
// ["This","is","a","regular", "sentence"]
sentence.flatMap(x => x.split(" "));
// ["This","is","a","regular", "sentence"]
// 可以使用 归纳(reduce) 与 合并(concat)实现相同的功能
sentence.reduce((acc, x) => acc.concat(x.split(" ")), []);
1.Object.values()
Object.values()函数和 Object.keys()很相似,它返回一个对象中自己属性的所有值(通过原型链继承的不算)。
2. Object.entries()
Object.entries()和 Object.keys 相关,不过 entries()函数会将 key 和 value 以数组的形式都返回。这样,使用循环或则将对象转为 Map 就很方便了。
let obj = { 'dsds': 2, 'fsdsg': 3, 'gththt': 4 }
console.log(Object.entries(obj))
/*
(3) [Array(2), Array(2), Array(2)]
0: (2) ["dsds", 2]
1: (2) ["fsdsg", 3]
2: (2) ["gththt", 4]
*/
3.Object.fromEntries (ES9)
将键值对列表转换为 Object 的新方法。
它与已有 Object.entries() 正好相反,Object.entries()方法在将对象转换为数组时使用,它返回一个给定对象自身可枚举属性的键值对数组。
但现在您可以通过 Object.fromEntries 将操作的数组返回到对象中。
const obj = { prop1: 2, prop2: 10, prop3: 15 };
// 转化为键值对数组:
let array = Object.entries(obj);
// [["prop1", 2], ["prop2", 10], ["prop3", 15]]
// 将所有对象属性的值平方:
array = array.map(([key, value]) => [key, value ** 2]);
// [["prop1", 4], ["prop2", 100], ["prop3", 225]]
我们将转换后的数组 array 作为参数传入 Object.fromEntries ,将数组转换成了一个对象:
const newObj = Object.fromEntries(array);
// {prop1: 4, prop2: 100, prop3: 225}
加/减法我们通常都是用其中缀形式,直观易懂。在 ECMAScript2016 中,我们可以使用**来替代 Math.pow。
如果你看到这里并且感觉对你有那么一点帮助的话,请点赞或评论鼓励一下我。