对象的创建
工厂模式
使用普通字面量创建多个对象时,会产生大量的重复代码,为了解决该问题,引入了工厂模式。
工厂模式:通过将创建对象的方法封装起来,避免重复代码产生
function newPerson(name,age,gender){
var p =new Object();
p.name = name;
p.age = age;
p.gender = gender;
p.sayName = function(){
console.log(this.name);
}
return p;
}
var p1=newPerson("小阵",1,"女");
var p2 =newPerson('李四',18,'男');
console.log(p1);//{ name: '小阵', age: 1, gender: '女', sayName: [Function] }
console.log(p2);
p1.sayName();//小阵
p2.sayName();
缺点:创建出来的所有的对象类型都是object,没有办法去识别对象(对象到底是person还是dog)
function newPerson(name,age,gender){
var p =new Object();
p.name = name;
p.age = age;
p.gender = gender;
p.sayName = function(){
console.log(this.name);
}
return p;
}
function newDog(name,age,gender){
var d = new Object();
d.name = name;
d.age = age;
d.gender = gender;
d.sayName=function(){
console.log("汪汪的名字是:"+this.name);
}
return d;
}
console.log(typeof p1);//object
console.log(typeof d1);//object
构造函数模式
//function sayName(){
//虽然可以将方法提取出来,提取到全局范围内,然后将引用传递给对象中的函数属性中,但是全局函数太多体现不了类的封装性
// console.log(this.name);
//}
function Person(name,age,gender){
this.name=name;
this.age=age;
this.gender=gender;
//this.sayName=sayName;
this.sayName=function(){
//每个方法都要在每个实例上重新创建一遍,没有这个必要
console.log(this.name);
}
}
//创建对象时要用new关键字
var p1=new Person("小阵",1,"女");
p1.sayName();//小阵
console.log(p1);//Person { name: '小阵', age: 1, gender: '女', sayName: [Function] }
//构造函数可以区分每个类
原型模式
function Person(){}
Person.prototype.name="小阵";
Person.prototype.age=1;
Person.prototype.gender="男";
Person.prototype.sayName=function(){
console.log(this.name);
}
var p1=new Person();
var p2=new Person();
p1.sayName();//小阵
p2.sayName();//小阵
// 原型内的属性和方法是共享的
//对于共享属性,共享函数使用该方式创建是非常合适的,但是包含一些不共享的属性就很不友好
var p1=new Person();
p1.name="李四";//可以重新赋值
var p2=new Person();
p2.name="王五";
p1.sayName();//李四
p2.sayName();//王五
var p1=new Person();
p1.likes.push('画画');
console.log(p1.likes);//[ '读书', '摄影', '画画' ]
var p2=new Person();
console.log(p2.likes);//[ '读书', '摄影', '画画' ]
//对于引用类型的数据就不太好
组合模式:构造函数模式+原型模式
function Person(name,age,gender){
//构造函数用于定义实例属性
this.name=name;
this.age=age;
this.gender=gender;
this.likes=[];
}
Person.prototype={
//原型模式用于定义方法和共享属性
constructor:Person,
sayName:function(){
console.log(this.name);
}
}
var p1=new Person("小阵",1,"男");
var p2=new Person("李四",2,"男");
p1.likes.push("读书");
p2.likes.push("踢足球");
console.log(p1);//Person { name: '小阵', age: 1, gender: '男', likes: [ '读书' ] }
console.log(p2);//Person { name: '李四', age: 2, gender: '男', likes: [ '踢足球' ] }
p1.sayName();//小阵
对象的继承
详细学习: 链接
原型链继承
调用对象的某一个方法或属性
//定义父类类型
function Animal(){
this.name="animal";
}
Animal.prototype.sayName = function(){
console.log(this.name);
}
//定义子类类型
function Dog(){
this.color="黄色";
}
// 继承:将子类对象的原型指向父类对象的实例
Dog.prototype = new Animal();
//重点:让新实例的原型等于父类的实例
Dog.prototype.sayColor=function(){
console.log(this.color);
}
var dog=new Dog();
console.log(dog);//Animal { color: '黄色' }
dog.sayName();//animal
dog.sayColor();//黄色
经典继承(借用构造函数、伪造对象)
function Animal(name,age){
this.name=name;
this.age=age;
this.sayName=function(){
console.log(this.name);
}
}
Animal.prototype.sayAge=function(){
console.log(this.age);
}
function Dog(name,age,color,type){
//借用构造函数
// 找到父类
Animal.call(this,name,age);
// 用.call()和.apply()将父类构造函数引入子类函数(在子类函数中做了父类函数的自执行)
this.color=color;
this.type=type;
}
var dog= new Dog('芳芳',1,'yellow','金毛');
console.log(dog);
// dog.sayAge();//报错,因为是父类原型中的方法
dog.sayName();
组合继承
使用原型链实现对原型属性和方法的继承,而通过借用构造函数实现对实例属性的继承。
function Animal(name,age){
this.name=name;
this.age=age;
this.Age=function(){
console.log(this.age);
}
}
Animal.prototype={
constructor:Animal,
sayName:function(){
console.log("hello,my name is"+this.name);
}
}
function Dog(name,age,type){
//经典继承 属性
Animal.call(this,name,age);
this.type=type;
}
//原型链继承
Dog.prototype = new Animal();
Dog.prototype.constructor=Animal;
Dog.prototype.sayType=function(){
console.log(this.type);
}
var dog= new Dog("花花",1,"二哈");
console.log(dog);//Animal { name: '花花', age: 1, Age: [Function], type: '二哈' }
dog.sayName();//hello,my name is花花
dog.sayType();//二哈