详解JavaScript中的原型OOP
什么是原型OOP
原型OOP是指JavaScript中通过原型链实现面向对象编程的方式。它利用每个JavaScript对象都有一个指向原型的指针,通过原型链可以实现继承和复用,从而实现面向对象编程的特性。
原型链
原型链是通过每个对象都有一个指向原型的指针,从而形成的链式结构。例如:
let animal = {
eat: function() {
console.log('I\'m eating.');
}
};
let cat = {
meow: function() {
console.log('Meow.');
}
};
cat.__proto__ = animal;
在这个例子中,我们创建了一个animal
对象,并定义了一个eat
方法。然后我们创建了一个cat
对象,并定义了一个meow
方法。接着,我们将cat
的原型指向了animal
对象。这样,cat
对象就继承了animal
对象的属性和方法。
构造函数
构造函数是一种特殊的函数,用于创建一个类。构造函数通过new
关键字创建一个实例,这个实例可以访问构造函数中定义的属性和方法。例如:
function Animal(name) {
this.name = name;
this.eat = function() {
console.log(this.name + ' is eating.');
}
}
let cat = new Animal('Kitty');
cat.eat(); // 输出 "Kitty is eating."
在这个例子中,我们定义了一个Animal
构造函数,其中包含一个name
属性和一个eat
方法。然后,我们创建了一个cat
实例。我们通过new
关键字来调用构造函数,并把"Kitty"
作为参数传入。最后,我们调用cat
对象的eat
方法,输出"Kitty is eating."
。
原型继承
原型继承是通过原型链实现的继承方式,它允许子类继承父类的属性和方法。例如:
function Animal(name) {
this.name = name;
}
Animal.prototype.eat = function() {
console.log(this.name + ' is eating.');
};
function Cat(name) {
Animal.call(this, name);
}
Cat.prototype = Object.create(Animal.prototype);
Cat.prototype.constructor = Cat;
Cat.prototype.meow = function() {
console.log('Meow.');
};
let kitty = new Cat('Kitty');
kitty.eat(); // 输出 "Kitty is eating."
kitty.meow(); // 输出 "Meow."
在这个例子中,我们定义了一个Animal
构造函数,它包含一个name
属性和一个eat
方法。接着,我们定义了一个Cat
构造函数,它继承了Animal
构造函数,并添加了一个meow
方法。
我们通过Object.create
函数来创建一个对象,这个对象的原型指向了Animal.prototype
。然后我们将Cat.prototype
指向了这个新的对象,这样就建立了Cat
对象和Animal
对象之间的原型链。最后,我们把Cat.prototype.constructor
指向了Cat
构造函数。
这样,Cat
对象就成功地继承了Animal
对象的name
属性和eat
方法,并添加了meow
方法。我们创建一个kitty
实例,并调用eat
和meow
方法,输出"Kitty is eating."
和"Meow."
。
示例1:实现类的继承
下面是另一个示例,展示了如何使用原型继承实现类的继承:
function Shape(x, y) {
this.x = x;
this.y = y;
}
Shape.prototype.move = function(x, y) {
this.x += x;
this.y += y;
};
function Circle(x, y, r) {
Shape.call(this, x, y);
this.r = r;
}
Circle.prototype = Object.create(Shape.prototype);
Circle.prototype.constructor = Circle;
Circle.prototype.area = function() {
return Math.PI * this.r * this.r;
};
let c = new Circle(0, 0, 5);
c.move(10, 10);
console.log(c.area()); // 输出 "78.53981633974483"
在这个例子中,我们定义了一个Shape
构造函数,它有x
和y
属性以及一个move
方法。然后,我们定义了一个Circle
构造函数,它继承了Shape
构造函数,并添加了一个r
属性以及一个area
方法。
我们通过Object.create
函数来创建一个对象,这个对象的原型指向了Shape.prototype
。然后我们将Circle.prototype
指向了这个新的对象,这样就建立了Circle
对象和Shape
对象之间的原型链。最后,我们把Circle.prototype.constructor
指向了Circle
构造函数。
这样,Circle
对象就成功地继承了Shape
对象的x
、y
属性和move
方法,并添加了r
属性和area
方法。我们创建一个c
实例,并调用move
和area
方法,输出"78.53981633974483"
。
示例2:利用原型实现单例模式
下面是另一个示例,展示了如何利用原型实现单例模式:
let Singleton = (function() {
let instance;
function SingletonClass(name) {
if (instance) {
return instance;
}
instance = this;
this.name = name;
}
SingletonClass.prototype.getName = function() {
return this.name;
};
return SingletonClass;
})();
let a = new Singleton('A');
let b = new Singleton('B');
console.log(a.getName()); // 输出 "A"
console.log(b.getName()); // 输出 "A"
console.log(a === b); // 输出 "true"
在这个例子中,我们定义了一个SingletonClass
构造函数,并使用一个闭包保存了实例对象。当我们通过new
关键字创建一个实例的时候,我们首先检查实例对象是否存在。如果实例对象已经存在,直接返回该对象。否则,我们就创建一个新的实例对象,并保存在闭包内。这样,我们的SingletonClass
构造函数就变成了单例模式。
我们将getName
方法添加到SingletonClass
原型中,并在创建实例之后,我们可以通过getName
方法来获取实例的name
属性。这样,我们就实现了利用原型实现的单例模式。
我们创建了a
和b
两个实例,并分别调用getName
方法,输出"A"
。然后我们比较a
和b
是否相等,输出"true"
,这是因为a
和b
都指向同一个实例对象。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:详解Javascript中的原型OOP - Python技术站