在js中创建对象可以有多种方式,比如字面量和构造函数的方式,但是这两种方式有缺点:产生大量重复的代码。
1.工厂模式: 不能确定对象的类型。(即instanceof无法判断。p1 instanceof ob-->false
)
function ob(name,sex){
var o=new Object();
o.name=name;
o.sex=sex,
o.sayName=function(){
alert(this.name);
}
return o;
}
var p1=ob("xs",1)
var p2=ob("ys",2)
console.log(p1.name)
2.构造函数模式:缺点时相同的方法都要在每个实例上创建一遍,创建的两个方法是不同的,因此,实例其实并没有共享这个方法,而是,各自创建了一个函数。如果将方法定义为全局函数,内部方法通过指针指向这个全局函数会让这个自定义对象缺失封装性。
function ob(name,age){
this.name=name;
this.age=age;
this.say=function(){
alert(this.name)
}
}
var p1=new ob("xjf",12);
console.log(p1);
console.log(p1 instanceof ob)//--true;
3.原型模式:将属性和方法全部添加到这个对象的原型对象prototype中,每个对象都包含一个prototype属性,它指向这个函数的原型对象,这个原型对象包含了所有对象实例共享的属性和方法。
function ob(){
}
ob.prototype.name="xxj";
ob.prototype.sex="nan";
ob.prototype.say=function(){
return this.name
}
var p1=new ob()
console.log(p1.name);
console.log(p1 instanceof ob);
console.log(p1.say())
所有原型对象都会获得一个constructor属性,这个属性指向原型对象所在函数。当为对象实例添加一个同名属性时,这个属性会覆盖原型的属性。
hasOwnProperty()
方法可以检测一个属性是否存在于对象实例而非对象原型中。(若存在于对象实例中则返回“true”,若存在于原型中则返回“false”)。
"in"
方法则无论是存在于对象实例中还是原型对象中都会返回true.
for-in
循环,返回的是所有能通过对象访问的,可枚举的属性,无论是对象实例的属性,还是对象原型上的属性。
Object.keys(object)
方法取得对象上所有可枚举的属性,返回一个包含所有可枚举属性的字符串数组。
更简单的原型语法
function ob(){}
ob.prototype={
name:"xx",
sex:"nan",
say:function(){
console.log(this.name)}
这样写的好处是省去了很多的object.prototype代码。但是,每创建一个函数的同时就创建了他的prototype对象并且自动添加了coonstructor属性。但是简单的写法意味着:我们重写了整个ob的原型对象,因此,此时的constructor也不再指向创建这个原型对象的函数ob了,而是指向了object构造函数。
可以在prototype对象中添加“constructor:ob
”重新设置。
function ob (){}
ob.prototype.name="xx";
ob.prototype.say=function(){
console.log();
}//第一种写法只是在prototype对象中添加了name,say属性而已,此时prototyp的constructor指向ob.
function ob (){}
ob.prototype={
name:"xx",
age:"12",
say:function(){
console.log()
}
}
//第二种写法本质上重写了prototype对象。此时的constructor已经不再指向ob.
原型对象存在的问题,所有实例默认情况下都会取得相同的属性值,更重要的是对于包含引用类型值的属性来说,不同的对象实例对属性的操作对在这些对象实例中共享。
function ob(){}
ob.prototype={
constructor:ob,
num:[1,2,3]
}
var p1=new ob();
p1.num.push('4');
var p2=new ob();
console.log(p4.num)--->1,2,3,4
4.组合使用构造函数模式和原型模式
function ob(name,sex,num){
this.name=name;
this.sex=sex;
this.num=num
}
ob.prototype={
constructor:ob,
sayname:function(){
console.log();
}
}