JavaScript 中的"类"与"实例"

JavaScript 中没有父类, 子类的概念, 也没有class 和 instance 的概念, 全靠 prototype chain来实现继承. 当查找一个对象的属性时, JavaScript 会向上遍历 prototype chain, 直到找到对应的属性为止. 有几种方法, 可以使得 JavaScript 模拟出 class 和 instance 的概念.

1, 直接使用构造函数来创建对象, 在构造函数内部使用 this指代对象实例.

> function Animal() {
... this.name = "animal";
... }
> Animal.prototype.makeSound = function() {
... console.log("animal sound");
... }
[Function]
> var animal1 = new Animal();
> animal1.name;
'animal'
> animal1.makeSound();
animal sound
再看另外一个例子:

> function Point(x, y) {
... this.x = x;
... this.y = y;
... }
> Point.prototype = {
... method1: function() { console.log("method1"); },
... method2: function() { console.log("method2"); },
... }
{ method1: [Function], method2: [Function] }
> var point1 = new Point(10, 20);
> point1.method1();
method1
> point1.method2();
method2

以上, 先指定好一个构造函数对象的 prototype 属性. 然后 new 一个该对象实例, 即可调用 prototype 中指定的方法.

2, 使用 Object.create()方法来创建对象

> var Animal = {
... name: "animal",
... makeSound: function() { console.log("animal sound"); },
... }
> var animal2 = Object.create(Animal);
> animal2.name;
'animal'
> console.log(animal2.name);
animal
> animal2.makeSound();
animal sound
该方法, 比构造函数的方法更简便, 但不能实现私有属性和私有方法, 且实例对象之间不能共享数据, 对 class 的模拟仍不够全面.
3, 荷兰程序员 Gabor de Mooij 提出的极简主义法(minimalist approach). 推荐用法.

> var Animal = {
... init: function() {
..... var animal = {};
..... animal.name = "animal";
..... animal.makeSound = function() { console.log("animal sound"); };
..... return animal;
..... }
... };
> var animal3 = Animal.init();
> animal3.name;
'animal'
> animal3.makeSound();
animal sound
不使用 prototype 和 this, 仅需要自定义一个构造函数init. 继承的实现也很简单.
> var Cat = {
... init: function() {
..... var cat = Animal.init();
..... cat.name2 = "cat";
..... cat.makeSound = function() { console.log("cat sound"); };
..... cat.sleep = function() { console.log("cat sleep"); };
..... return cat;
... }
... }
> var cat = Cat.init();
> cat.name; // 'animal'
> cat.name2; // 'cat'
> cat.makeSound(); // 类似于方法的重载
cat sound
> cat.sleep();
cat sleep

私有属性和私有方法的使用:

> var Animal = {
... init: function() {
..... var animal = {};
..... var sound = "private animal sound"; // 私有属性
..... animal.makeSound = function() { console.log(sound); };
..... return animal;
..... }
... };
> var animal4 = Animal.init();
> animal.sound; // 私有属性只能通过对象自身的方法来读取.
undefined
> animal4.makeSound();
private animal sound
只要不是定义在animal对象上的属性和方法都是私有的, 外界不能访问.
类与实例之间, 可以做到数据共享.

> var Animal = {
... sound: "common animal sound",
... init: function() {
..... var animal = {};
..... animal.commonSound = function() { console.log(Animal.sound); };
..... animal.changeSound = function() { Animal.sound = "common animal sound changed"; };
..... return animal;
..... }
... }
> var animal5 = Animal.init();
> var animal6 = Animal.init();
> Animal.sound;
'common animal sound'
> animal5.sound;
undefined
> animal6.sound;
undefined
> animal5.commonSound();
common animal sound
> animal6.commonSound();
common animal sound
> animal5.changeSound();
undefined
> Animal.sound;
'common animal sound'
> animal5.commonSound();
common animal sound
> animal6.commonSound();
common animal sound
如 Animal.sound 就是类与实例的共有属性, 可以视为类属性和类方法. 

若一个实例修改了该共有属性, 则该类和其他实例的共有属性也对应修改了.
综上, 就是 JavaScript 中模拟的 class 和 instance 的概念和用法.



郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。