JavaScript 设计模式之原型模式
原型模式
一般模式
所谓原型,一般就类似将数据放置到原型上,通过原型继承模式来实现一个基类,然后用子类继承方式来实现
// 汽车基类
const Car = function (car,sale) {
this.car = car;
this.sale = sale;
this.getName = function () {
}
this.getPrice = function () {
console.log(`this car ${this.car} has price ${this. Sale}`)
}
}
// 奔驰汽车
const BenChiCar = function (car, sale) {
Car.call(this, car, sale);
this.getName = function () {
console.log(`my car name is benChi-${this. Car}`)
}
}
// 宝马汽车
const BaoMaCar = function (car, sale) {
Car.call(this, car, sale);
this.getName = function () {
console.log(`my car name is baoMa-${this. Car}`)
}
}
const m1 = new BaoMaCar('x1', '22w')
m1.getName() // my car name is baoMa-x1
m1.getPrice() // this car x1 has price 22w
Car 将一些公用的属性或方法抽离出来,用 call 的方式进行调用
更优模式
上面的 Car 我们在使用每次使用的时候,其公用方法都会实例化一次,我们将一些耗资源的一些方法应该放置到 Car 的原型上
const Car = function (car,sale) {
this.car = car;
this.sale = sale;
}
car.prototype.getName = function () {
// todo:
}
Car.prototype.getPrice = function () {
console.log(`this car ${this.car} has price ${this.sale}`)
}
const BenChiCar = function (car, sale) {
Car.call(this, car, sale);
this.getName = function () {
console.log(`my car name is benChi-${this.car}`)
}
}
BenChiCar.prototype = new Car
const BaoMaCar = function (car, sale) {
Car.call(this, car, sale);
this.getName = function () {
console.log(`my car name is baoMa-${this.car}`)
}
}
BaoMaCar.prototype = new Car
const m1 = new BaoMaCar('x1', '22w')
m1.getName() // my car name is baoMa-x1
m1.getPrice() // this car x1 has price 22w
不过这也是有缺点的
缺点
这里我们是用的基类原型,那就是说我们在用到的基类原型对于其子类都是共享的数据,比如
const Car = function (car,sale) {
this.car = car;
this.sale = sale;
}
Car.prototype.getName = function () {
// todo:
console.log(`my car name is benChi-${this.car}`)
}
Car.prototype.getPrice = function () {
console.log(`this car ${this.car} has price ${this.sale}`)
}
const BenChiCar = function (car, sale) {
Car.call(this, car, sale);
}
const BaoMaCar = function (car, sale) {
Car.call(this, car, sale);
}
BaoMaCar.prototype = new Car
BenChiCar.prototype = new Car
const m1 = new BaoMaCar('x1', '22w')
const m2 = new BenChiCar('x5', '43w')
m1.getName() // my car name is baoMa-x1
m2.getName() // my car name is benChi-x5
Car.prototype.getColor = function () {
console.log("my color is white")
}
m1.getColor() // my color is white
m2.getColor() // my color is white
m1.getPrice() // this car x1 has price 22w
比如我们修改了基类 Car 的原型,所有的子类都会受到影响,所以在使用这种方式的时候是需要注意到这点
原型继承
我们可以写一个原型继承类来实现原型继承
const prototypeExtend = function () {
let F = function () { },
args = arguments,
i = 0,
len = args.length
for (; i < len; i++){
for (let j in args[i]) {
F.prototype[j] = args[i][j];
}
}
return new F
}
let demo = prototypeExtend({
name: '梅剑',
getAge() {
return 22
}
}, {
getName() {
return '李师师'
}
}, {
sayHi() {
return 'Hello 狄镖头'
}
})
console.log(demo.name) // 梅剑
console.log(demo.getName()) // 李师师
console.log(demo.sayHi()) // Hello 狄镖头
这种我们就可以避免使用 new 关键字来实现原型继承了