前端那些事系列之进阶篇创建对象、继承(四)

创建对象的多种方式

1)工厂模式

function createPerson(name) {
	var _obj = new Object();
	_obj .name = name;
	_obj .getName = function () {
		console.log(this.name);
	};
	return _obj ;
}
var person1 = createPerson('anissa');

优点:简单;
缺点:对象⽆法识别,因为所有的实例都指向⼀个原型;

2)构造函数模式

function createPerson(name) {
	this.name = name;
	this.getName = function () {
		console.log(this.name);
	};
}
var person1 = createPerson('anissa');

优点:实例可以识别为⼀个特定的类型;
缺点:每次创建实例时,每个⽅法都要被创建⼀次;
优化

function Person(name) {
	this.name = name;
	this.getName = getName;
}
function getName() {
	console.log(this.name);
}
var person1 = new Person('anissa');

3)原型模式

function Person(name) {
}
Person.prototype.name = 'anissa';
Person.prototype.getName = function () {
	console.log(this.name);
};
var person1 = new Person();

优点:⽅法不会重新创建;
缺点:

  1. 所有的属性和⽅法都共享;
  2. 不能初始化参数;
    优化
function Person(name) {
}
Person.prototype = {
	name: 'anissa',
	getName: function () {
		console.log(this.name);
	}
};
var person1 = new Person();

优点:封装清晰点;
缺点:重写了原型,丢失了constructor属性;
再次优化

function Person(name) {
}
Person.prototype = {
	constructor: Person,
	name: 'anissa',
	getName: function () {
		console.log(this.name);
	}
};
var person1 = new Person();

优点:实例可以通过constructor属性找到所属构造函数;
缺点:

  1. 所有的属性和⽅法都共享;
  2. 不能初始化参数;

4)组合模式

function Person(name) {
	this.name = name;
}
Person.prototype = {
	constructor: Person,
	getName: function () {
		console.log(this.name);
	}
};
var person1 = new Person();

优点:属性共享,方法私有,使⽤最⼴泛的⽅式;
缺点:希望写在⼀个地⽅,即更好的封装性;
优化:动态原型模式

function Person(name) {
	this.name = name;
	if (typeof this.getName != "function") {
		Person.prototype.getName = function () {
			console.log(this.name);
		}
	}
}
var person1 = new Person();

继承的多种方式

1)原型链继承

function Parent () {
	this.name = 'anissa';
}
Parent.prototype.getName = function () {
	console.log(this.name);
}
function Child () {
}
Child.prototype = new Parent();
var child1 = new Child();
console.log(child1.getName()) // anissa

在这种情况下,引用类型的属性会被多个实例更改共享

2)构造函数继承

function Parent () {
	this.names = ['anissa', 'delyn'];
	this.sex=arguments[0];
	console.log(this.sex);//female
}
function Child () {
	console.log(...arguments);//female
	Parent.call(this,...arguments);
}
var child1 = new Child("female");
child1.names.push('test');
console.log(child1.names); // ["anissa", "delyn", "test"]
var child2 = new Child();
console.log(child2.names); // ["anissa", "delyn"]

优点:

  1. 避免了引⽤类型的属性被所有实例共享;
  2. 可以在 Child 中向 Parent 传参;

3)组合继承

function Parent (name) {
	this.name = name;
	this.colors = ['red', 'blue', 'green'];
}
function Child (name, age) {
	Parent.call(this, name);
	this.age = age;
}
Child.prototype = new Parent();
Child.prototype.constructor = Child;
var child1 = new Child('anissa', '18');
child1.colors.push('black');
console.log(child1.name); // anissa
console.log(child1.age); // 18
console.log(child1.colors); // ["red", "blue", "green", "black"]
var child2 = new Child('delyn', '20');
console.log(child2.name); // delyn
console.log(child2.age); // 20
console.log(child2.colors); // ["red", "blue", "green"]

优点:融合原型链继承和构造函数的优点,是 JavaScript 中最常⽤的继承模式

4)原型继承

function createObj(o) {
	function F(){}
	F.prototype = o;
	return new F();
}

缺点:
包含引⽤类型的属性值始终都会共享相应的值,这点跟原型链继承⼀样。

var person = {
	name: 'anissa',
	friends: ['delyn', 'krystal']
}
var person1 = createObj(person);
var person2 = createObj(person);
person1.name = 'person1';
console.log(person2.name); // anissa
person1.friends.push('kitty');
console.log(person2.friends); // ["delyn", "krystal", "kitty"]

5)寄生式继承

创建⼀个仅⽤于封装继承过程的函数,该函数在内部以某种形式来做增强对象,最后返回对象

function createObj (o) {
	var clone = Object.create(o);
	clone.sayName = function () {
		console.log('hi');
	}
	return clone;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值