本文详解JavaScript中模拟类与实例的三种方法:利用构造函数结合prototype实现继承、使用Object.create进行对象创建,以及Gabor de Mooij提出的极简主义模式。文章通过具体代码示例对比了各方案在私有属性、数据共享及实现复杂度上的差异,帮助开发者根据实际需求选择合适的设计模式。
本文通过具体实例解析JavaScript中类与实例的构建机制,旨在为读者提供实用的参考方案。
JavaScript模拟类与实例的核心机制
JavaScript语言本身并不具备传统面向对象语言中的父类、子类、class或instance概念,其继承机制完全依赖于prototype chain。当访问对象属性时,引擎会沿prototype chain向上查找直至找到目标。尽管原生支持有限,仍可通过多种技巧模拟出class和instance的行为。
构造函数与原型链方案
第一种方案是利用构造函数直接创建对象,并在函数内部通过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中定义的方法。
Object.create()对象创建法
第二种方案是使用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的模拟尚不完整。
极简主义模式(Minimalist Approach)
第三种方案源自荷兰程序员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 私有属性只能通过对象自身的方法来读取.
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的概念及具体用法。
希望本文所述内容对大家的javascript程序设计有所帮助。