初探Class、继承、Promise 及 ES6 常用功能


Class - 语法糖

  • Class 在语法上更贴合面向对象的写法
  • Class 实现继承更加易读、易理解
  • 更易于写 java 等后端语言的使用
  • 本质还是语法糖,使用 prototype

ES5中的写法

获取实例对象的原型对象Object.getPrototypeOf(m2)

判断实例与构造函数的原型对象是否有关系MathHandle2.prototype.isPrototypeOf(m2)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function MathHandle2(x, y) {
this.x = x
this.y = y
}
MathHandle2.prototype.add = function () {
return this.x + this.y
}

var m2 = new MathHandle2(1,3)
console.log(m2.add())
console.log(m2.__proto__ === MathHandle2.prototype) //true

// 获取实例对象的原型对象Object.getPrototypeOf()
console.log(Object.getPrototypeOf(m2) === MathHandle2.prototype) //true
// 判断实例与构造函数的原型对象是否有关系isPrototypeOf()
console.log(MathHandle2.prototype.isPrototypeOf(m2)) //true

ES6中的写法

对象实例的隐式原型(属性)指向构造函数的原型对象m.__proto__ === MathHandle.prototype

构造函数的原型对象的constructor属性指回了构造函数本身MathHandle.prototype.constructor === MathHandle

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class MathHandle {   // 构造函数
constructor(x, y) {
this.x = x
this.y = y
}

add() {
return this.x + this.y
}
}

const m = new MathHandle(1, 3)
console.log(m.add()) //4

// 对象实例的隐式原型(属性)指向构造函数的原型对象
console.log(m.__proto__ === MathHandle.prototype) //true

// 构造函数的原型对象的constructor属性指回了构造函数本身
console.log(MathHandle.prototype.constructor === MathHandle) //true

继承

prototype

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function Animal() {
this.eat = function() {
console.log('Animal eat')
}
}
function Dog() {
this.bark = function() {
console.log('Dog bark')
}
}
// 绑定原型,实现继承
Dog.prototype = new Animal()
var hashiqi = new Dog()
hashiqi.eat() // Animal eat
hashiqi.bark() // Dog bark

extends

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class Animal {
constructor(name) {
this.name = name
}
eat() {
console.log('Animal eat!' + this.name)
}
}
class Dog extends Animal {
constructor(name) {
super(name)
this.name = name
}
bark() {
console.log('Dog bark!' + this.name)
}
}

const hashiqi = new Dog('哈士奇')
hashiqi.eat()
hashiqi.bark()

Promise

  • new Promise 实例,而且要 return
  • new Promise 时要传入函数,函数有 resolve、reject 两个函数
  • 成功时执行 resolve(),失败时执行 reject()
  • then 监听结果
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
function loadImg(src) {
var promise = new Promise(function(resolve, reject) {
var img = document.createElement('img')
img.onload = function() {
resolve(img)
}
img.onerror = function() {
reject()
}
img.src = src
})
return promise
}

var src1 = 'https://img3.mukewang.com/5c611772085966af06000338-240-135.jpg'
var src2 = 'https://img2.mukewang.com/5c6b7cff08d6895906000338-240-135.jpg'
var result1 = loadImg(src1)
var result2 = loadImg(src2)

result1.then(function(img) {
console.log('第一张图片', img.src)
return result2 //串联操作
}).then(function(img) {
console.log('第二张图片', img.src)
}).catch(function(ex) { // 统一捕获错误信息
console.log(ex)
})

// Promise.all 接受一个 promise 对象的数组,待全部完成之后,统一执行 success

var result3 = loadImg(src1)
var result4 = loadImg(src2)
Promise.all([result3, result4]).then(function(data) {
console.log(data)
})

// Promise.race 接受一个包含多个 promise 对象的数组,只要有一个完成,就执行 success
Promise.race([result3,result4]).then(function(data) {
console.log('race:', data)
})

ES6常用功能

  • let const
  • 多行字符串、模板变量
  • 解构赋值
  • 块级作用域
  • 函数默认参数
  • 箭头函数
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
85
86
87
88
89
90
91
92
93
// let const
let i = 10;
i = 20; // Uncaught SyntaxError: Identifier 'i' has already been declared
const j = 100
j = 20 // Uncaught TypeError: Assignment to constant variable.

// 多行字符串、模板变量
const name = 'yangtao', age = 27;
const html = `
<div>
<p>${name}</p>
<p>${age}</p>
</div>`;

// 结构赋值
const obj = {a: 100, b: 200}
const {a, b} = obj
// 等同于(对象按照属性)
var obj = {a: 100, b: 200}
var a = obj.a,
b = obj.b;

const arr = ['xxx', 'yyy', 'zzz']
const [x, z] = arr
// 等同于(数组按照索引)
var arr = ['xxx', 'yyy', 'zzz']
var x = arr[0],
z = arr[1];

// 块级作用域
const myObj = {a: 1, b: 2}
for(let item in obj) {
console.log(item)
}
console.log(item)
// 等同于
var myObj = { a: 1, b: 2 };
for (var _item in obj) {
console.log(_item);
}
console.log(item);

// 函数参数
function num(a,b=0) {
}
// 等同于
function num2(a) {
var b = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
}

// 箭头函数
const myarr = [1,3,4]
myarr.map(item => item + 1)
myarr.map((item, index) => console.log(item, index))
// 等同于
var myarr = [1, 3, 4];
myarr.map(function (item) {
return item + 1;
});
myarr.map(function (item, index) {
return console.log(item, index);
});

// this指向很诡异
function fn() {
console.log('real', this) // real {a: 10}

var arr = [1,2,3];
arr.map(function(item) {
console.log(this) // window
})
}
fn.call({a: 10})
// 使用箭头函数修改
function fn() {
console.log('real', this) // real {a: 10}

var arr = [1,2,3];
arr.map(item => console.log(this)) // {a: 10}
}
fn.call({a: 10})
// 等同于
function fn() {
var _this = this;

console.log('real', this); // real {a: 10}

var arr = [1, 2, 3];
arr.map(function (item) {
return console.log(_this);
}); // {a: 10}
}
fn.call({ a: 10 });

关于 JS 众多模块化标准

  • 没有模块化
  • AMD成为标准,require.js(也有CMD)
  • 前端打包工具,是node.js模块化可以被使用
  • ES6出现,想统一现在所有模块化标准
  • nodejs积极支持,浏览器尚未统一

模块化

  • 语法:import export(注意有无default)
  • 环境:babel编译 ES6 语法,模块化可用 webpack 和 rollup
  • 扩展:对模块化标准统一的期待

Rollup

  • rollup 功能单一,webpack 功能强大
  • 参考设计原则和《Linux/Unix设计思想》
  • 工具要尽量功能单一,可集成,可扩展
  • gulp + rollup

 评论