您的位置:首页 > Web前端 > JavaScript

js中的对象创建与继承

2017-04-19 09:47 393 查看

对象创建

1.工厂模式

优点:解决了创建多个相似对象的问题

缺点:没有解决对象识别问题;每一个对象都有一套自己的函数,浪费资源

function createPerson(name, age, job) {
var o = new Object();
o.name = name;
o.age = age;
o.job = job;
o.sayName = function () {
alert(this.name);
};
return o;
}

//////////////////////////////////////////////////////////////
var person1 = createPerson("Nicholas", 29, "Software Engineer");
var person2 = createPerson("Greg", 27, "Doctor");

person1.sayName(); //"Nicholas"
person2.sayName(); //"Greg"

2.构造函数模式

优点:可以用来创建特定类型的对象

缺点:每个方法都要在每个实例上重新创建一遍

function Person(name, age, job){
this.name = name;
this.age = age;
this.job = job;
this.sayName = function(){
alert(this.name);
};
}

/////////////////////////////////////////////////////////////
var person1 = new Person("Nicholas", 29, "Software Engineer");
var person2 = new Person("Greg", 27, "Doctor");

3.原型模式

优点:所有对象实例可以共享它所包含的属性和方法

缺点:共享性,所有的均共享,对龚鸥的固然很好,但不能私有各自属性了

// 写法1:
function Person() {}
Person.prototype = {
constructor: Person,
name: "Nicholas",
age: 29,
job: "Software Engineer",
sayName: function() {
alert(this.name);
}
}

// 写法2:
function Person(){}
Person.prototype.name = "Nicholas";
Person.prototype.age = 29;
Person.prototype.job = "Software Engineer";
Person.prototype.sayName = function(){
alert(this.name);
};

//////////////////////////////////////////////
var person1 = new Person();
person1.sayName(); //"Nicholas"
var person2 = new Person();
person2.sayName(); //"Nicholas"
alert(person1.sayName == person2.sayName); //true

4.构造函数模式和原型模式

思路:构造函数模式用于定义实例属性,而原型模式用于定义方法和共享的属性

优点:每个实例都会有自己的一份实例属性副本,但同时又共享着对方法的引用,最大限度的节省了内存

缺点

关于constructor的补充知识点:

只要创建了一个新函数,就会根据一组特定的规则为这个函数创建一个prototype属性,这个属性指向函数的原型对象。

在默认情况下,所有原型对象都会自动获得一个constructor构造函数属性,这个属性会包含一个指向protoype属性所在函数的指针。

```

function Person(name, age, job){

this.name = name;

this.age = age;

this.job = job;

this.friends = ["Shelby", "Court"];

}

Person.prototype = {

constructor : Person,

sayName : function(){

alert(this.name);

}

}

/////////////////////////////////////////////////////////

var person1 = new Person("Nicholas", 29, "Software Engineer");

var person2 = new Person("Greg", 27, "Doctor");

person1.friends.push("Van");

alert(person1.friends); //"Shelby,Count,Van"

alert(person2.friends); //"Shelby,Count"

alert(person1.friends === person2.friends); //false

alert(person1.sayName === person2.sayName); //true

#### 5.动态原型模式
思路:和4相比只是多了一个函数存在的检测

function Person(ame,age,job){

//属性

this.name = name;

this.age = age;

this.job = job;

//方法

if (typeof this.sayName != "function"){

Person.prototype.sayaName = function(){

alert(this.name);

}

}

}

/////////////////////////////////////////////////////////

var friend = new Person("Nicholas",29,"Software Engineer");

friend.sayName(); // Nicholas

#### 6.寄生构造函数模式
从表面上看是和工厂模式一样,只是最后实例化了一次,而工厂模式是没有再实例化

function Person(name,age,job){

var o = new Object();

o.name = name;

o.age = age;

o.job = job;

o.sayName = function(){

alert(this.name);

}

}

/////////////////////////////////////////////////////////

var friend = new Person("Nicholas",29,"Software Engineer");

friend.sayName(); // Nicholas

#### 7.稳妥构造函数模式
所谓稳妥对象,指的是没有公共属性,而且其方法也不引用this的对象。稳妥构造函数遵循与寄生构造函数类似的模式,有两点不同:
1.新创建对象的实例方法不引用this
2.不使用new操作符调用构造函数

function Person(name,age,job){

//创建要返回的对象

var o = new Object();

// 可以在这里定义私有变量和函数

//添加方法

o.sayName = function(){

alert(name);

}

return o;

}

/////////////////////////////////////////////////////////

var friend = Person("Nicholas",29,"Software Engineer");

friend.sayName(); // Nicholas

### 继承
#### 1.原型链继承
**思路**:用父类实例来充当子类实例对象
**缺点**:
1.共享(包含引用类型值的原型属性会被所有实例共享)
2.不能传参(没有办法在不影响对象实例的情况下给超类型的构造函数传递参数)

function SuperType() { // 定义父函数

this.property = true;

};

SuperType.prototype.getSuperValue = function() { // 给父函数添加方法

return this.property;

};

function SubType() { // 定义子函数

this.subproperty = false;

};

SubType.prototype.getSubValue = function() { // 给子函数添加方法

return this.subproperty;

};

/////////////////////////////////////

SubType.prototype = new SuperType(); // (关键)

var instance = new SubType(); // 实例化instance

alert(instance.getSuperValue()); //true

#### 2.借用构造函数
**思路**:借父类的构造函数来增强子类实例(等于把父类的实例属性复制了一份给子类实例装上了)
**优点**:可传参(可以在子类型的构造函数向超类型的构造函数传递参数)
**缺点**:不能复用(超类型原型链中定义的方法对子类是不可见的)

function SuperType() { // 定义父函数

this.colors = ["red", "blue", "green"];

}

function SubType() { // 定义子函数

SuperType.call(this); // (关键)

}

/////////////////////////////////////////////////

var instance1 = new SubType();

instance1.colors.push("black");

alert(instance1.colors); // "red,blue,green,black"

var instance2 = new SubType();

alert(instance2.colors); // "red,blue,green"

#### 3.组合继承
**思路**:把实例函数放在原型对象上,以实现函数复用
**优点**:无共享问题,可传参,可复用
**缺点**:父类构造函数会被调用两次,生成两份,而子类实例上的那一份屏蔽了子类原型上的,内存浪费。

function SuperType(name) { // 定义父函数

this.name = name;

this.colors = ["red", "blue", "green"];

}

SuperType.prototype.sayName = function() { // 给父函数添加方法

alert(this.name);

};

function SubType(name, age) { // 定义子函数

//继承属性

SuperType.call(this, name); // (关键:继承私有属性)

this.age = age;

}

//继承方法

SubType.prototype = new SuperType(); // (关键:继承公有方法)

SubType.prototype.constructor = SubType;

SubType.prototype.sayAge = function() {

alert(this.age);

};

///////////////////////////////////////////////////

var instance1 = new SubType("Nicholas", 29);

instance1.colors.push("black");

alert(instance1.colors); // "red,blue,green,black"

instance1.sayName(); // "Nicholas";

instance1.sayAge(); // 29

var instance2 = new SubType("Greg", 27);

alert(instance2.colors); // "red,blue,green"

instance2.sayName(); // "Greg";

instance2.sayAge(); // 27

#### 4.原型式继承
**思路**:用Object函数得到一个空的新对象,再逐步增强填充实例属性
**优点**:从已有的对象上衍生新对象,不需要创建自定义类型
**缺点**:共享问题

Object.create() :ES5中规范了原型式继承
参数1:用作新对象原型的对象
参数2:为新对象定义额外属性的对象

function object(o){

function F(){}

F.prototype = o;

return new F();

}

var person = { // 父函数

name: "Nicholas",

friends: ["Shelby", "Court", "Van"]

};

var anotherPerson = object(person); // (关键)子1继承父

anotherPerson.name = "Greg";

anotherPerson.friends.push("Rob");

var yetAnotherPerson = object(person); // (关键)子2继承父

yetAnotherPerson.name = "Linda";

yetAnotherPerson.friends.push("Barbie");

alert(person.friends); //"Shelby,Court,Van,Rob,Barbie"

#### 5.寄生式继承
**思路**:创建一个用于封装继承过程的函数,该函数在内部以某种方式来增强对象,最后返回
**优点**:不需要创建自定义类型
**缺点**:不能复用

function createAnother(original) {

var clone = object(original); //通过调用函数创建一个新对象

clone.sayHi = function(){ //以某种方式来增强这个对象

alert("hi");

};

return clone; //返回这个对象

}

var person = { // 父函数

name: "Nicholas",

friends: ["Shelby", "Court", "Van"]

};

var anotherPerson = createAnother(person); // (关键)子函数继承父函数

anotherPerson.sayHi(); //"hi"

#### 6.寄生组合式
**思路**:切掉了原型对象上多余的那份父类实例属性

function inheritPrototype(subType, superType) {

var prototype = object(superType.prototype); //创建对象

prototype.constructor = subType; //增强对象

subType.prototype = prototype; //指定对象

}

function SuperType(name) {

this.name = name;

this.colors = ["red", "blue", "green"];

}

SuperType.prototype.sayName = function() {

alert(this.name);

};

function SubType(name, age) {

SuperType.call(this, name); // (关键)

this.age = age;

}

inheritPrototype(SubType, SuperType); // (关键)

SubType.prototype.sayAge = function() {

alert(this.age);

};

```
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: