用es5来模拟es6中的class

1) new的原理

es5中没有类 用构造函数来模拟类

1
2
3
4
function Animal(){

}
// es5中的类可以当做函数来调用 ,es6中不行

首先来判断是否是通过new来调用的

1
2
3
4
5
6
7
function Animal(){
if( !(this instanceof Animal)){
throw new Error('NOT NEW');
}
}
// Animal(); // Error: NOT NEW
new Animal();

2) 在类中有2种属性 一种是实例上的属性 一种是公共属性

1
2
3
4
5
6
7
8
9
10
11
function Animal(){
if( !(this instanceof Animal)){
throw new Error('NOT NEW');
}
this.name = {name: '加菲'};
this.age = 18;
}
let a1 = new Animal();
let a2 = new Animal();
console.log(a1, a2); // Animal { name: { name: '加菲' }, age: 18 } Animal { name: { name: '加菲' }, age: 18 }
console.log(a1.name === a2.name); // false

所以 name、age这些属性都是实例上的属性,每个实例都独自的有这些属性

公共属性:一般会加到这个类(Animal)的原型上

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
function Animal(){
if( !(this instanceof Animal)){
throw new Error('NOT NEW');
}
this.name = {name: '加菲'};
this.age = 18;
}
Animal.prototype.say = function(){
console.log('说话');
}
let a1 = new Animal();
let a2 = new Animal();
console.log(a1.say === a2.say); // true
console.log(a1.__proto__ === Animal.prototype); // true
console.log(a1.__proto__.constructor === Animal); // true
console.log(a1.__proto__.__proto__ === Object.prototype); // true
console.log(Object.prototype.__proto__); // null
// 一般情况下 最要不要操作__proto__ 有些浏览器不兼容IE
// 这里增加原型链知识点 可以参考《原型链 & 继承》这篇

3) 类的继承: 继承实例上的属性、公共属性

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
function Animal(){
this.type = '哺乳动物';
}
Animal.prototype.say = function(){
console.log('我是动物');
}
function Tiger(name){
this.name = name;
Animal.call(this); // 调用父类的构造函数 并且让this指向子类即可
}
let tiger = new Tiger("老虎");
//Tiger.prototype.__proto__ = Animal.prototype; // 功能与下面这行等同
Object.setPrototypeOf(Tiger.prototype, Animal.prototype); // es6语法就是指定了链的指向
console.log(tiger.type); // 哺乳动物

// Object.create
function Animal(){
this.type = '哺乳动物';
}
Animal.prototype.say = function(){
console.log('我是动物');
}
function Tiger(name){
this.name = name;
Animal.call(this);
}
let tiger = new Tiger("老虎");
Tiger.prototype = Object.create(Animal.prototype, {constructor:{value: Tiger}});
console.log(tiger.type); // 哺乳动物