在面向对象编程中,类(class)是对象(object)的模板,定义了同一组对象(又称"实例”)共有的属性和方法。
Javascript语言不支持"类”,但是可以用一些变通的方法,模拟出"类”。
1、构造函数法
第一种是经典方法,它用构造函数模拟"类”,在其内部用this关键字指代实例对象。
1
2
3
|
function Dog() {
this.name = "旺财";
}
|
生成实例的时候,使用new关键字。
1
2
|
var dog = new Dog();
console.log(dog.name); // 旺财
|
类的属性和方法,还可以定义在构造函数的prototype对象之上。
1
2
3
|
Dog.prototype.wow = function(){
console.log("汪~汪~汪!");
}
|
关于这种方法的详细介绍,请看《Javascript 面向对象编程》,这里就不多说了。
它的主要缺点是,比较复杂,用到了this和prototype,编写和阅读都很费力。
2、Object.create()法
在ECM5中,加入一个新的方法 Object.create()
,用这个方法,“类"就是一个对象,不是函数。
1
2
3
4
5
6
|
var Dog = {
this.name = "旺财";
wow: function() {
console.log("汪~汪~汪!");
}
}
|
然后,直接用Object.create()生成实例,不需要用到new。
1
2
3
|
var dog = Object.create(Dog);
console.log(dog.name); // 旺财
dog.wow(); // 汪~汪~汪!
|
这种方法不能实现私有属性和私有方法,实例对象之间也不能共享数据。
3、BlackScript 法
荷兰程序员Gabor de Mooij提出了一种比Object.create()更好的新方法。
事实上就是用一个对象模拟类,在这个类里,定义一个构造函数 createNew() 用来生成实例。
1
2
3
4
5
|
var Dog = {
createNew: function(){
//some code
}
}
|
然后,在 createNew() 里面,定义一个实例对象,把这个实例对象作为返回值
1
2
3
4
5
6
7
8
9
10
|
var Dog = {
createNew: function(){
var dog = {};
dog.name = "旺财";
dog.wow = function() {
console.log("汪~汪~汪!");
}
return dog;
}
}
|
使用方法
1
2
|
var dog1 = Dog.createNew();
dog1.wow(); // 汪~汪~汪!
|
这种方法简单易学,可以实现OOP的特性,继承、私有属性和方法、数据共享。
继承
比如让 Dog 继承 Animal,只要在 Dog的 createNew()方法中,调用后者的createNew()方法即可。
1
2
3
4
5
6
7
8
9
|
var Animal = {
createNew: function(){
var animal = {};
animal.sleep = function(){
console.log("睡懒觉");
};
return animal;
}
};
|
然后,在 Dog 的 createNew() 方法中,调用 Animal 的 createNew() 方法。
1
2
3
4
5
6
7
8
9
10
|
var Dog = {
createNew: function(){
var dog = Animal.createNew();
dog.name = "旺财";
dog.wow = function() {
console.log("汪~汪~汪!");
}
return dog;
}
}
|
这样得到的 Dog 实例,就会同时继承 Dog 类和Animal类。
1
2
3
4
|
var dog1 = Dog.createNew();
dog1.sleep() // 睡懒觉
dog1.wow() // 汪~汪~汪!
|
私有属性和方法
在 createNew() 方法中,只要不是定义在 dog 对象上的方法和属性,都是私有的。
1
2
3
4
5
6
7
8
9
10
11
|
var Dog = {
createNew: function(){
var dog = {};
var sound = "汪汪汪";
dog.name = "旺财";
dog.wow = function() {
console.log(sound);
}
return dog;
}
}
|
上例的内部变量 sound,外部无法读取,只有通过 dog 的公有方法 wow() 来读取。
1
2
3
4
|
var dog1 = Dog.createNew();
dog1.name // 旺财
dog1.sound // undefined
dog1.wow() // 汪汪汪
|
数据共享
有时候,我们需要所有实例对象,能够读写同一项内部数据。
这个时候,只要把这个内部数据,封装在类对象的里面、createNew()方法的外面即可。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
var Dog = {
sound: "汪汪汪",
createNew: function(){
var dog = {};
dog.name = "旺财";
dog.sound = function() {
console.log(Dog.sound);
}
dog.changSound = function(para){
Dog.sound = para
}
return dog;
}
};
|
生成两个实例
1
2
3
4
|
var dog1 = Dog.createNew();
var dog2 = Dog.createNew();
dog1.sound(); // 汪汪汪
dog2.sound(); // 汪汪汪
|
这时,如果有一个实例对象,修改了共享的数据,另一个实例对象也会受到影响。
1
2
3
|
dog2.changSound("呱呱呱");
dog1.sound(); // 呱呱呱
|
本文转载引用自 Javascript定义类(class)的三种方法