1
2
3
4
function Animal (name, age) {
this.name = name;
this.age = age;
}
构造函数的缺点
- 不看函数体, 无法知道是普通函数还是构造函数
- 构造函数当做普通函数执行, 会产生全局变量.
es6 class
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class Animal {
}
console.log(typeof Animal);/ function
babel翻译
"use strict";
/ 可以看出 这个函数的作用,就是为了让构造函数只能用 new 的方式进行调用
function _classCallCheck(instance, Constructor) {
if(!(instance instanceof Constructor)) {
throw new TypeError("Cannot call a class as a function");
}
}
var Animal = function Animal() {
_classCallCheck(this, Animal);
};
- 只能通过 new 进行调用
1 2Animal();/ 报错 new Animal();/ 不报错- 在同一个块级作用域下,不允许重复声明
- 先定义后使用, 也就是有暂时性死区(TDZ)
constructor ``` class Animal { /注意在这里定义函数 不能出现 function (){} 只能用es6声明函数的方法 constructor(name, age = 18){ this.name = name; this.age = age; } }
1
console.log(Animal.prototype.constructor == Animal);/ true ``` > * 可知 class {} 这个大括号不是 对象, 是一种语法糖 > * 语义化很好, 类名, 构造函数 两个概念分了开来. > * 疑问? 在 这个类里定义的函数, 是在这个类的 原型上定义嘛? > 是的
为什么用原型?
- 增加代码复用性
- 节省空间
1
2
3
4
5
6
7
8
9
10
11
12
13
class Animal {
constructor(name, age = 18){
this.name = name;
this.age = age;
}
/ 相当于定义在原型上.
showName () {
console.log(this.name);
}
}
let dog = new Animal('dog',2);
console.log(dog.showName == Animal.prototype.showName);/true
可知, 在class{ } 里定义的函数, 就是定义在原型上的.
什么是静态属性,静态方法? 就像 jq里的工具方法 对应的是 实例方法, 原型链上的方法. 例子
Object.is()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Animal {
constructor(name, age = 18){
this.name = name;
this.age = age;
}
showName () {
console.log(this.name);
}
/ 相当于 Animal.createInstance 在Animal 函数上进行定义
static createInstance (name,age) {
return new Animal(name,age)
}
static a = 123/ 报错
}
let dog = Animal.createInstance('dog',2);
console.log(dog);
可知, static 方式只能在 Animal 上定义方法, 暂不能定义属性
一等公民 class function
- 可以当做参数
- 可以被返回
- 可以立即执行
- 可以赋值给其他变量
当参数 ``` function create (fn) { return new fn(); }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
let obj = create(class{
constructor (){
this.name = 'mike'
}
});
console.log(obj); ``` > 立即执行 ```
let obj = new class {
constructor (name ){
this.name = name;
}
}('mike');
console.log(obj); ``` > 被返回
1
2
3
4
5
6
7
8
9
10
11
12
13
14
function returnClass () {
let count = 0;
return class{
constructor (name) {
this.name = name;
this.count = count;
}
}
}
let obj = new (returnClass())('mike')/ 正常
/这里可以看出 默认会先 执行 new returnClass, 再对返回函数进行()执行
let obj = new returnClass()('mike')/ 报错
console.log(obj);
class 生成器方法 ``` class iteratorArray { constructor (arr = []) { this.arr = arr; }
1
2
3
4
5
6
7
8
9
10
*[Symbol.iterator](){
yield *this.arr[Symbol.iterator]()
}
}
let arr = new iteratorArray([1,2,3]);
for(let item of arr) {
console.log(item);
} ```  > 上面的代码到底干了什么? > 一个类返回的对象可以通过 设置 *[Symbol.iterator](){yield} , 进行迭代 > yield *this.arr[Symbol.iterator]() 的意思是把arr的指针添加进实例对象的指针组之中.
测试 可以 yield * this.arr, 因为默认会调用arr的迭代器[Symbol.iterator] ``` class iteratorArray { constructor (arr = []) { this.arr = arr; }
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
*[Symbol.iterator](){
yield *this.arr
}
}
let arr = new iteratorArray([1,2,3]);
for(let item of arr) {
console.log(item);
} ```  > 测试: 我们可以任意的添加各种指针 ```
class iteratorArray {
constructor (arr = [],arr1 = []) {
this.arr = arr;
this.arr1 = arr1;
}
*[Symbol.iterator](){
yield *this.arr;
yield *this.arr1;
yield *[7,8,9];
yield 10
}
}
let arr = new iteratorArray([1,2,3],[4,5,6]);
for(let item of arr) {
console.log(item);
} ```  > 测试是否可以用next 
继承, 增加代码复用 类,本身的概念里就包好,要把相似共同的部分抽象出来
es5继承
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
function Father (name,age) {
this.name = name;
this.age = age;
}
Father.prototype.showName = function () {
console.log(this.name);
}
function Son () {
Father.call(this);
}
严格来讲, 实际上是有几种继承方式的
这几种方式,都会继承但不会让父级实例化,
或者说, 这几种算是 无new继承
Son.prototype = Object.create(Father.prototype);
Son.prototype.__proto__ = Father.prototype;
Object.setPrototypeOf(Son.prototype,Father.prototype);
当然最经典的继承 应该是 new 实例化
圣杯继承
function temp () {}
temp.prototype = Father.prototype;
Son.prototype = new temp();
es6继承
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
class Animal {
constructor (name = 'mike', age) {
console.log(name);
this.name = name;
this.age = age;
}
showName(){
console.log(this.name);
}
}
子类,派生类
class Person extends Animal {
constructor(name){
super(name)
/相当于 Animal.call(this,name)
/ 或者应该这么理解?
/this = new Animal() / 返回一个this?
}
show () {
console.log(super.showName = Animal.prototype.showName);/true
console.log(super == Animal.prototype);/ 报错,
}
}
let p = new Person();
注意, 子类使用extends 继承父类时, constructor里一定要有super字段 否则报错. 不许把super() 放在 this.赋值语句的前面,否则报错. super 作为对象的时候, 指向的是父类的原型 Father.prototype, 但this自动指向实例 super 必须执行,或者调用属性, 否则报错?
好奇,babel怎么翻译的 ``` ‘use strict’;
| var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable | false; descriptor.configurable = true; if (“value” in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); |
| function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError(“this hasn’t been initialised - super() hasn’t been called”); } return call && (typeof call === “object” | typeof call === “function”) ? call : self; } |
function _inherits(subClass, superClass) { if (typeof superClass !== “function” && superClass !== null) { throw new TypeError(“Super expression must either be null or a function, not “ + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.proto = superClass; }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(“Cannot call a class as a function”); } }
var Animal = function () { function Animal() { var name = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ‘mike’; var age = arguments[1];
1
2
3
4
5
_classCallCheck(this, Animal);
console.log(name);
this.name = name;
this.age = age; }
_createClass(Animal, [{ key: ‘showName’, value: function showName() { console.log(this.name); } }]);
return Animal; }();
var Person = function (_Animal) { _inherits(Person, _Animal);
function Person(name) { _classCallCheck(this, Person);
1
return _possibleConstructorReturn(this, (Person.__proto__ || Object.getPrototypeOf(Person)).call(this, name)); }
return Person; }(Animal);
var p = new Person(); ```
好奇害死猫, 陌生字段有点多, 回头再看吧…