我们都知道,js有面向对象编程的,这里讲解下js创建对象的九种方式:
Object构造函数、对象字面量、工厂模式、构造函数、原型模式、组合使用构造函数模式和原型模式 、动态原型模式、寄生构造函数模式、稳妥构造函数模式
下面逐个举例子
1、Object构造函数
var p1 = new Object();
p1.name="p1";
p1.age=18;
p1.sayHello = function(){ alert("Hello,"+this.name+",your age is "+this.age)};
alert(p1.name);
alert(p1.age);
p1.sayHello();
2、对象字面量
var p2 ={
name:"p2",
age:18,
sayHello:function(){ alert("Hello,"+this.name+",your age is "+this.age)}
};
alert(p2.name);
alert(p2.age);
p2.sayHello();
3、工厂模式
function createPerson(name,age){
var o={
name:name,
age:age,
sayHello:function(){
alert("Hello,"+name+",your age is "+age);
}
}
return o;
}
var p3 = createPerson("p3",18,"IT");
var p4 = createPerson("p4",19,"EAT");
alert(p3.name);
alert(p3.age);
p3.sayHello();
alert(p4.name);
alert(p4.age);
p4.sayHello();
4、构造函数(Object和Array是原生构造函数,会在运行的时候自动加入执行环境)
步骤:
(1) 创建一个新对象;
(2) 将构造函数的作用域赋给新对象(this 就指向了这个新对象);
这个意思是,如果有new,那么就指向新对象,没有new,this就指向window,也可以用户call方法,指定对象作用域。
(3) 执行构造函数中的代码(为这个新对象添加属性);
(4) 返回新对象。
function Person(name,age){
this.name=name,
this.age=age,
this.sayHello=function(){
alert("Hello,"+this.name+",your age is "+this.age);
};
}
var p5= new Person("p5",18);
var p6 = new Person("p6",18);
alert(p5.name);
alert(p5.age);
p5.sayHello();
alert(p6.name);
alert(p6.age);
p6.sayHello();
alert(p5.constructor == Person); //true
alert(p6.constructor == Person); //true
alert(p5 instanceof Object); //true
alert(p5 instanceof Person); //true
alert(p6 instanceof Object); //true
alert(p6 instanceof Person); //true
任何函数,只要通过new 操作符来调用,那它就可以作为构造函数;而任何函数,如果不通过new 操作符来调用,那它跟普通函数也不会有什么两样
a、当作构造函数使用
var p7 = new Person("Nicholas", 29);
p7.sayHello(); //"Nicholas"
b、作为普通函数调用
Person("Person", 27); // 添加到window
window.sayHello(); //"Greg"
c、在另一个对象的作用域中调用
var o = new Object();
Person.call(o, "Person", 25);
o.sayHello(); //"Kristen"
5、原型模式
我们创建的每个函数都有一个prototype(原型)属性,这个属性是一个指针,指向一个对象,而这个对象的用途是包含可以由特定类型的所有实例共享的属性和方法如果按照字面意思来理解,那么prototype 就是通过调用构造函数而创建的那个对象实例的原型对象。使用原型对象的好处是可以让所有对象实例共享它所包含的属性和方法。换句话说,不必在构造函数中定义对象实例的信息,而是可以将这些信息直接添加到原型对象中。
function Dog(){};
Dog.prototype.name="Dog";
Dog.prototype.age=18;
Dog.prototype.sayHello=function(){alert(this.name)};
var dog1 =new Dog();
var dog2 =new Dog();
alert(dog1.name);
alert(dog2.name);
alert(dog1.sayHello==dog2.sayHello);
上面的结果应该是Dog,Dog,true.因为属性name,age和方法sayHello都是在原型对象上的。
下面为String类型的对象在原型上添加方法
String.prototype.sayHello=function(){alert("Hello")};
var msg="";
msg.sayHello();
6组合使用构造函数模式和原型模式:定义引用类型的一种默认模式
这样子该构造函数不仅仅有私有属性,还有共有属性
function Cat(name,age){
this.name=name;
this.age=age;
this.friends = ["Shelby", "Court"];
this.sayHello=function(){alert("Hello")};
}
Cat.prototype={
constructor:Cat,
sayName:function(){
alert(this.name);
}
}
var cat1 = new Cat("cat1",18);
var cat2 = new Cat("cat2",18);
cat1.friends.push("Hhh");
alert(cat1.friends);
alert(cat2.friends);
alert(cat1.friends === cat2.friends); //false
alert(cat1.sayName === cat2.sayName); //true
7、动态原型模式
function Chick(name){
this.name=name;
if(typeof this.sayName!="function"){
Chick.prototype.sayName=function(){
alert(this.name);
};
}
}
var chick = new Chick("Chick");
chick.sayName();
8、寄生构造函数模式
除了使用new 操作符并把使用的包装函数叫做构造函数之外,这个模式跟工厂模式其实是一模一样的,工厂里面用的是对象字面量。里面引用了this
function Pig(name){
var o = new Object();
o.name=name;
o.sayName=function(){alert(this.name)};
return o;
}
var pig1 = Pig("bbb");
pig1.sayName();
9、稳妥构造函数模式
稳妥构造函数遵循与寄生构造函数类似的模式,但有两点不同:一是新创建对象的实例方法不引用this;二是不使用new操作符调用构造函数。里面没有用this
function Pig2(name){
var o = new Object();
//可以在这里定义是由变量和函数
o.sayName=function(){alert(name)};
return o;
}
var pig2 = Pig2("aaa");
pig2.sayName();
结语
虽然js提供了如此多的构造函数,但是我们用的其实比较少,我经常使用的就是对象字面量的方法即可。