avatar

目录
ES6新特征(基本+常用)

[TOC]

第一章:概述

课程地址:https://www.imooc.com/video/16703
学习vue的过程中出现很多ES6语法,补充学习

1-1:课程介绍

  • ES3 ES5 ES6的对比讲解
  • 常量、作用域、箭头函数、默认参数、对象代理

##1-2:环境搭建

第二章:ES6基础

2-1:常量

Code
1
2
3
4
5
6
7
8
9
10
// ES5 中设置常量的语法
Object.defineProperty(typeof global === "object" ? global : window, "PI2", {
value: 3.1415926,
enumerable: true,
writable: false,
configurable: false
});

// ES6 设置常量的语法
const PI = 3.1415926;

但是下面情况是可以被改变的,如:

Code
1
2
3
4
5
6
7
8
9
10
11
12
const obj={
a:1,
b:2
}
//修改对象的值是可行的
obj.a=3;
// 修改对象是不可行的
obj={
c:1
};

//因为对象是引用类型,const 指向的是对象引用地址,只要地址不变就符合 const 定义。

2-2:作用域

  • 区分 let 和 var
Javascript
1
2
3
4
5
6
7
8
9
10
11
12
var callbacks2=[]
for (var i = 0; i <= 2; i++) {
callbacks2[i] = function () { return i * 2; };
}

console.table([
callbacks2[0]() === 0,//false
callbacks2[1]() === 2,//false
callbacks2[2]() === 4//false
])

// var 声明的变量是没有块作用域的
Javascript
1
2
3
4
5
6
7
8
9
10
11
12
let callbacks = [];
for (let i = 0; i <= 2; i++) {
callbacks[i] = function () { return i * 2; };
}

console.table([
callbacks[0]() === 0,//true
callbacks[1]() === 2,//true
callbacks[2]() === 4//true
])

//let 是块作用域变量
  • 如何隔离一块作用域
Javascript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
//ES5
(function () {
var foo = function () { return 1; }
foo() === 1;
(function () {
var foo = function () { return 2; }
foo() === 2;//这个foo和外边的fool是隔离的
})();
foo() === 1;
})();

//ES6
{
function foo () { return 1 }
foo() === 1
{
function foo () { return 2 }
foo() === 2
}
foo() === 1
}
//块作用域符号 {}

2-3:箭头函数

  • 基本用法
Javascript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//ES5
var evens = [1, 2, 3, 4, 5];
var odds = evens.map(function (v) {
return v + 1;
});
var pairs = evens.map(function (v) {
return {
even: v,
odd: v + 1
};
});
var nums = evens.map(function (v, i) {
return v + i;
});
console.table(evens, odds, pairs, nums)
Javascript
1
2
3
4
5
6
7
8
9
10
11
12
13
//ES6
let evens = [1, 2, 3, 4, 5];
let odds = evens.map(v => v + 1)
let pairs = evens.map(v => ({
even: v,
odd: v + 1
}))
let nums = evens.map((v, i) => v + i)
console.table(evens, odds, pairs, nums)

//上述代码 v => v+1 就是箭头函数, 箭头左侧是函数的参数,
//当只有一个参数的时候可以不用 () ,等有多个参数的时候用 () 。
//箭头右侧是函数体,如何只有一行代码可以省略 {},值就是return 。
  • this 的不一样
    Javascript
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    // ES5、ES3
    var factory=function(){
    this.a='a';
    this.b='b';
    this.c={
    a:'a+',
    b:function(){
    return this.a
    }
    }
    }

    console.log(new factory().c.b());//输出结果是 'a+'

    //this 的引用是函数运行调用的对象
    //运行b()的是c,所以b函数内的this.a this指的是c
Javascript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var factory=function(){
this.a='a';
this.b='b';
this.c={
a:'a+',
b:()=>{
return this.a
}
}
}

console.log(new factory().c.b());//输出结果是 'a+'

//这个时候用的是箭头函数,b 函数中 this 指向的是定义时的对象,也就是 factory 类的实例,所以 this.a 就是构造函数的属性 a ,也就是 'a' 了。
//

2-4:参数

  • 默认参数
Javascript
1
2
3
4
5
6
7
8
9
//ES3\ES5
function f(x, y, z) {
if (y === undefined)
y = 7;
if (z === undefined)
z = 42;
return x + y + z;
};
console.log(f(1));
Javascript
1
2
3
4
5
6
7
//ES6
function f(x, y = 7, z = 42) {
return x + y + z
}
console.log(f(1));
//x 是必选参数,y、z 是可选的
//当输入两个参数的时候第一个参数是x、第二个参数就不会使用默认值

如何让 x 参数成为必选参数呢?不设置这个参数就报错

Javascript
1
2
3
4
5
6
7
8
9
function checkParameter(){
throw new Error('can\'t be empty!')
};

function f(x = checkParameter(),y = 2,z = 3){
return x + y + z
}

console.log(f());
  • 可变参数
Javascript
1
2
3
4
5
6
7
8
9
10
11
12
13
function f(a,b){//可变参数求和
return a+b
}

//ES5
function f(){
var a = Array.prototype.slice.call(arguments);
var sum = 0;
a.forEach(function(item){
sum+=item*1
})
return sum
}
Javascript
1
2
3
4
5
6
//ES6
function f(...a){
var sum = 0;
a.forEach(item=>{sum+=item*1});
return sum
}
  • 扩展运算符

比如要合并两个数组

Javascript
1
2
3
4
5
6
7
// ES5
var params = [ "hello", true, 7 ];
var other = [ 1, 2 ].concat(params);

// ES6
var params = [ "hello", true, 7 ]
var other = [ 1, 2, ...params ] // [ 1, 2, "hello", true, 7 ]

2-5:代理

什么是对象代理呢?就是不让用户直接访问一个对象,只能通过代理去操作,类似于中介。

Javascript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//ES3
var Person = function() {
let data = {
name: 'es3',
sex: 'male',
age: 15
};
this.get = function(key) {
return data[key];
}
this.set = function(key, value) {
if (key !== 'sex') {
data[key] = value
}
}
}
Javascript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
//ES5
var Person = {
name: 'es5',
age: 15
};
Object.defineProperty(Person, 'sex', {
writable: false,
value: 'male'
});
// 读取姓名,性别,年龄
console.table({name: Person.name, sex: Person.sex, age: Person.age});
// 修改姓名
Person.name = 'es5-cname';
// 修改性别
try {
Person.sex = 'female';
} catch (e) {
console.log(e);
}
console.table({name: Person.name, sex: Person.sex, age: Person.age});
Javascript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
//ES6
let Person = {
name: 'es6',
sex: 'male',
age: 15
}

let proxy = new Proxy(Person, {
get(target, key) {//target就是person,key就是要读的数据
return target[key]
},
set(target, key, value) {
if (key !== 'sex') {
target[key] = value;
}
}
});

//使用
// 读取姓名,性别,年龄
console.table({name: proxy.name, sex: proxy.sex, age: proxy.age});
// 修改性别
try {
proxy.sex='female';
} catch (e) {
console.log(e);
}
console.table({name: proxy.name, sex: proxy.sex, age: proxy.age});

第三章:常用补充

参考:https://www.jianshu.com/p/287e0bb867ae

字符串

  • 基本的字符串格式化
Javascript
1
2
3
4
5
6
//ES5 
var name = 'lux'
console.log('hello' + name)
//es6
const name = 'lux'
console.log(`hello ${name}`) //hello lux

import 和 export

  • 基本用法
Javascript
1
2
3
4
5
6
7
8
9
//使用export命令定义了模块的对外接口以后,其他JS文件就可以通过import命令加载这个模块(文件)

// a.js
var sex="boy";
var echo=function(value){
  console.log(value)
}
export {sex,echo}
//不能写成export sex这样的方式,如果这样就相当于export "boy",外部文件就获取不到该文件的内部变量sex的值
Javascript
1
2
3
4
5
// b.js
//通过import获取a.js文件的内部变量,{}括号内的变量来自于a.js文件export出的变量标识符。
import {sex,echo} from "./a.js"
console.log(sex) // boy
echo(sex) // boy
  • export default
Javascript
1
2
3
4
5
6
7
//export default命令,为模块指定默认输出,这样就不需要知道所要加载模块的变量名

//a.js
var sex="boy";
export default sex(sex不能加大括号)
//原本直接export sex外部是无法识别的,加上default就可以了.但是一个文件内最多只能有一个export default。
//其实此处相当于为sex变量值"boy"起了一个系统默认的变量名default,自然default只能有一个值,所以一个文件内不能有多个export default。
Javascript
1
2
3
4
5
// b.js
//本质上,a.js文件的export default输出一个叫做default的变量,然后系统允许你为它取任意名字。所以可以为import的模块起任何变量名,且不需要用大括号包含
import any from "./a.js"
import any12 from "./a.js"
console.log(any,any12) // boy,boy

Promise

Promise概念介绍

Javascript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
// 1. Promise 是一个 构造函数,既然是构造函数, 那么,我们就可以  new Promise() 得到一个 Promise 的实例;
// 2. 在 Promise 上,有两个函数,分别叫做 resolve(成功之后的回调函数) 和 reject(失败之后的回调函数)
// 3. 在 Promise 构造函数的 Prototype 属性上,有一个 .then() 方法,也就说,只要是 Promise 构造函数创建的实例,都可以访问到 .then() 方法
// 4. Promise 表示一个 异步操作;每当我们 new 一个 Promise 的实例,这个实例,就表示一个具体的异步操作;
// 5. 既然 Promise 创建的实例,是一个异步操作,那么,这个 异步操作的结果,只能有两种状态:
// 5.1 状态1: 异步执行成功了,需要在内部调用 成功的回调函数 resolve 把结果返回给调用者;
// 5.2 状态2: 异步执行失败了,需要在内部调用 失败的回调函数 reject 把结果返回给调用者;
// 5.3 由于 Promise 的实例,是一个异步操作,所以,内部拿到 操作的结果后,无法使用 return 把操作的结果返回给调用者; 这时候,只能使用回调函数的形式,来把 成功 或 失败的结果,返回给调用者;
// 6. 我们可以在 new 出来的 Promise 实例上,调用 .then() 方法,【预先】 为 这个 Promise 异步操作,指定 成功(resolve) 和 失败(reject) 回调函数;


// 注意:这里 new 出来的 promise, 只是代表 【形式上】的一个异步操作;
// 什么是形式上的异步操作:就是说,我们只知道它是一个异步操作,但是做什么具体的异步事情,目前还不清楚
// var promise = new Promise()


// 这是一个具体的异步操作,其中,使用 function 指定一个具体的异步操作
/* var promise = new Promise(function(){
// 这个 function 内部写的就是具体的异步操作!!!
}) */

const fs = require('fs')

// 每当 new 一个 Promise 实例的时候,就会立即 执行这个 异步操作中的代码
// 也就是说,new 的时候,除了能够得到 一个 promise 实例之外,还会立即调用 我们为 Promise 构造函数传递的那个 function,执行这个 function 中的 异步操作代码;
/* var promise = new Promise(function () {
fs.readFile('./files/2.txt', 'utf-8', (err, dataStr) => {
if (err) throw err
console.log(dataStr)
})
}) */


// 初衷: 给路径,返回读取到的内容
function getFileByPath(fpath) {
return new Promise(function (resolve, reject) {
fs.readFile(fpath, 'utf-8', (err, dataStr) => {

if (err) return reject(err)
resolve(dataStr)

})
})
}

/* getFileByPath('./files/2.txt')
.then(function (data) {
console.log(data + '-------')
}, function (err) {
console.log(err.message)
}) */

使用Promise解决回调地狱

Javascript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
const fs = require('fs')

function getFileByPath(fpath) {
return new Promise(function (resolve, reject) {
fs.readFile(fpath, 'utf-8', (err, dataStr) => {

if (err) return reject(err)
resolve(dataStr)

})
})
}

// 先读取文件1,在读取2,最后读取3
// 注意: 通过 .then 指定 回调函数的时候,成功的 回调函数,必须传,但是,失败的回调,可以省略不传
// 这是一个 错误的示范,千万不要这么用; 硬是把 法拉利,开成了 拖拉机;
/* getFileByPath('./files/1.txt')
.then(function (data) {
console.log(data)

getFileByPath('./files/2.txt')
.then(function (data) {
console.log(data)

getFileByPath('./files/3.txt')
.then(function (data) {
console.log(data)
})
})
}) */

// 读取文件1
// 在上一个 .then 中,返回一个新的 promise 实例,可以继续用下一个 .then 来处理


// 如果 ,前面的 Promise 执行失败,我们不想让后续的Promise 操作被终止,可以为 每个 promise 指定 失败的回调
/* getFileByPath('./files/11.txt')
.then(function (data) {
console.log(data)

// 读取文件2
return getFileByPath('./files/2.txt')
}, function (err) {
console.log('这是失败的结果:' + err.message)
// return 一个 新的 Promise
return getFileByPath('./files/2.txt')
})
.then(function (data) {
console.log(data)

return getFileByPath('./files/3.txt')
})
.then(function (data) {
console.log(data)
}).then(function (data) {
console.log(data)
}) */

// console.log('OKOKOK')



// 当 我们有这样的需求: 哪怕前面的 Promise 执行失败了,但是,不要影响后续 promise 的正常执行,此时,我们可以单独为 每个 promise,通过 .then 指定一下失败的回调;

// 有时候,我们有这样的需求,个上面的需求刚好相反:如果 后续的Promise 执行,依赖于 前面 Promise 执行的结果,如果前面的失败了,则后面的就没有继续执行下去的意义了,此时,我们想要实现,一旦有报错,则立即终止所有 Promise的执行;

getFileByPath('./files/1.txt')
.then(function (data) {
console.log(data)

// 读取文件2
return getFileByPath('./files/22.txt')
})
.then(function (data) {
console.log(data)

return getFileByPath('./files/3.txt')
})
.then(function (data) {
console.log(data)
})
.catch(function (err) { // catch 的作用: 如果前面有任何的 Promise 执行失败,则立即终止所有 promise 的执行,并 马上进入 catch 去处理 Promise中 抛出的异常;
console.log('这是自己的处理方式:' + err.message)
})

演示Jquery中Promise

Javascript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>

<body>

<input type="button" value="获取数据" id="btn">

<script src="./node_modules/jquery/dist/jquery.min.js"></script>

<script>
$(function () {
$('#btn').on('click', function () {
$.ajax({
url: './data.json',
type: 'get',
dataType: 'json'
})
.then(function (data) {
console.log(data)
})
})
});
</script>
</body>

</html>
文章作者: Machine
文章链接: https://machine4869.gitee.io/2018/08/09/15338173277136/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 哑舍
打赏
  • 微信
    微信
  • 支付宝
    支付宝

评论