众所周知,在 ES5 中是没有类的概念的( ES6 已支持 ),但是有模拟类的方法。”类“主要是为了实现继承。本文主要讲解 ES5 如何实现类的定义和继承。
一、ES5 中定义一个类
1、构造函数方法
这个方法就是我的上一篇博客面向对象中讲的 当我们在使用 new Object 或 new Array() 时 JS 都做了什么 ,也就是使用关键字 new 进行实例化,也就是构造函数方法。看例子:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16function Person(name,age,job){
this.name = name;
this.age = age;
this.job = job;
}
Person.prototype = {
sayName : function(){
return this.name;
}
}
var person1 = new Person('summer','12','doctor');
var person2 = new Person('sunny','22','writer');
person1.sayName(); //输出 'summer'
console.log(person2.sayName()) //输出 'sunny'
2、Object.create() 方法
Object.create()
方法创建一个新对象,使用现有的对象来提供新创建的对象的__proto__
。 具体请看代码:1
2
3
4
5
6
7
8
9
10
11
12
13const person = {
isHuman: false,
printIntroduction: function () {
console.log(`My name is ${this.name}. Am I human? ${this.isHuman}`);
}
};
const me = Object.create(person);
me.name = "Matthew";
me.isHuman = true;
me.printIntroduction();
第八行代码的意思是定义一个对象 me , me.__prototype__ = person
。在执行 me.printIntroduction() 时会先从 me 自身的属性方法上查找,如果找到则执行,如果未找到则回去找原型上是否有此方法。
3、极简方法
这种方法既不使用 prototype 也不使用 this ,代码部署起来非常简明易懂。首先,使用一个对象来模拟”类”。在这个类里面,定义一个构造函数 createFn() 用来生成实例,代码如下:1
2
3
4
5
6
7
8
9
10
11
12var Dog = {
createFn : function(){
var dog = {};
dog.name = "柯基";
dog.makeSound = function(){
alert('汪汪汪')
}
return dog;
}
}
var dog1 = Dog.createFn();
dog1.makeSound();
以上,构造函数 createFn() 内定义一个对象,并为对象定义属性 name 和方法 makeSound() ,并将此对象返回。使用时,调用 Dog.createFn()即可。
使用这种方法模拟一个类容易理解。接下来,使用这种方法尝试着实现继承:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22var Animal = {
createFn : function(){
var animal = {};
animal.name = 'animal';
animal.eat = function(){
alert('吃饭饭')
}
return animal;
}
}
var Dog = {
createFn : function(){
var dog = Animal.createFn();
dog.name = "柯基";
dog.makeSound = function(){
alert('汪汪汪')
}
return dog;
}
}
var dog1 = Dog.createFn();
dog1.eat();
以上打印输出 dog1 有属性值 name:'柯基'
,方法 makeSound() 和继承自 Animal 的方法 eat()
二、实现继承
继承最常用的两种方式为:
- 原型链继承(对象间的继承)
- 类式继承(构造函数间的继承)
1、原型链继承
原型链继承其实就是用 prototype 来继承父级。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21function Parent = function(){
this.name = 'parent';
}
function Child = function(){
this.age = 20;
}
Child.prototype = new Parent(); // Child 继承 parent ,通过原型,形成链条
let test = new Child();
console.log(test.name); // parent
console.log(test.age); // 20 得到被继承的属性
function Brother(){
this.weight = 55;
}
Brother.prototype = new Child();
var borther = new Brother();
alert(brother.name); // parent
alert(brother.age); //20
以上的例子,通过原型,行程链条, Child 继承了 Parent , Brother 继承了 Child ,最后 Brother 既有 Child 和 Parent 的属性,又有自有属性。这就是原型链的继承。
2、类式继承
类式继承一般是通过运用 call 或 apply 进行子类型构造函数的内部调用超类型的构造函数:1
2
3
4
5
6
7
8
9
10
11
12function Parent(age){
this.name = ['mike','summer','sunny'];
this.age = age;
}
function Child(age){
Parent.call(this,age);
}
let test = new Child(12);
alert(test.age);
alert(test.name);
test.name.push('Lucy');
alert(test.name)
以上是最基本的两种继承方式。接下来介绍下 ES6 实现继承的方法
3、ES6 实现继承
首先定义个 Class:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15Class Point{
constructor(x,y){
this.x = x;
this.y = y;
}
toString(){
return '('+this.x+', '+this.y+')';
}
}
var point = new Point(2,3);
point.toString() // (2, 3)
point.hasOwnProperty('x') // true
point.hasOwnProperty('y') // true
point.hasOwnProperty('toString') // false
point.__proto__.hasOwnProperty('toString') // true
class 实现继承:1
2
3
4
5
6
7
8
9class ColorPoint extends Point {
constructor(x, y, color) {
super(x, y); // 调用父类的constructor(x, y)
this.color = color;
}
toString() {
return this.color + ' ' + super.toString(); // 调用父类的toString()
}
}