JavaScript创建对象
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
JavaScript创建对象⼯工⼚厂模式:
//⼯工⼚厂模式
function createPerson(name, age, job) {
var o = new Object();
= name;
o.age = age;
o.job = job;
o.sayName = function() {
alert();
};
return o;
}
var person1 = createPerson("Nick" ,21 ,"DH");
var person2 = createPerson("Tom" ,23 ,"MK");
函数createPerson( )能够根据接受的参数来构建⼀一个包含所有必要信息的Person 对象。
可以解决创建多个相似对象的问题,但是没有解决对象识别的问题(即怎样知道⼀一个对象的类型)。
构造函数模式:
//构造函数模式1
function Person(name, age, job) {
= name;
this.age = age;
this.job = job;
this.sayName = function() {
alert();
};
}
var person1 = new Person("Nick", 21, "DH");
var person2 = new Person("Tom", 23, "MK");
person1和person2分别保存着Person的⼀一个不不同的实例例。
这两个对象都有⼀一个constructor(构造函数)属性,该属性指向Person。
使⽤用构造函数创建新实例例,必须要使⽤用new操作符。
以这种⽅方式调⽤用构造函数实际上会经历以下4个步骤:-创建⼀一个新对象;
-将构造函数的作⽤用域赋给新对象(因此this就指向了了这个新对象);
-执⾏行行构造函数中的代码(为这个新对象添加属性);
-返回新对象。
构造函数与其他函数的唯⼀一区别就是在于调⽤用它们的⽅方式不不同。
任何韩式,只要通过new操作符来调⽤用,都可以作为构造函数;⽽而任何函数,如果不不通过new操作符来调,那它跟普通函数也没区别。
/51
构造函数的主要问题,就是每个⽅方法都要在每个实例例上重新插 u 你更更加爱你⼀一遍。
在上述person1和person2都有⼀一个名为sayName( )的⽅方法。
所以⽤用这种⽅方式创建函数会导致不不同的作⽤用域链和标识符解析,但是创建Function新实例例的机制仍然相同。
因此,不不同实例例上的同名函数是不不相等的。
所以,可以通过把函数定义转移到构造函数外部来解决这个问题:
//构造函数模式2
function Person(name, age, job) {
= name;
this.age = age;
this.job = job;
}
function sayName() {
alert();
}
var person1 = new Person("Nick", 21, "DH");
var person2 = new Person("Tom", 23, "MK");
这样做也有缺点:
在全局作⽤用域中定义的函数实际上只能被某个对象调⽤用,⽽而且如果对象需要定义很多⽅方法,那么久要定义很多全局变量量,那这个⾃自定义的引⽤用类型久没有了了封装⾏行行可⾔言。
(这个问题可以通过使⽤用原型模式解决)
原型模式:
我们创建的每个函数都会⼜又⼀一个prototype(原型)属性,这个属性是⼀一个指针,指向⼀一个对象,⽽而这个⽤用途是包含可以有特定类型的所有实例例共享的属性和⽅方法。
使⽤用原型对象的好处是可以让所有对象实例例共享他所包含的属性和⽅方法。
即,不不必在构造⽅方法中定义对象实例例的信息,⽽而是将这些信息直接添加到原型对象中。
//原型模式
function Person() {
}
= "Nick";
Person.prototype.age = 21;
Person.prototype.job = "DH";
Person.prototype.sayName = function() {
alert();
};
/*
Person.prototype = {
name : “Nick”,
age : 21,
job : “DH”,
sayName : function( ) { alert();}
}
*/
var person1 = new Person();
person1.sayName();//"Nick"
var person2 = new Person();
person2.sayName();//"Nick"
alert(person1.sayName == person2.sayName);//true
/52
如代码所示,将sayName( )⽅方法和所有属性直接添加到了了Person的prototype 属性中,构造函数就变成了了⼀一个空函数。
即使如此,也仍然可以通过调⽤用构造函数来创建新对象,⽽而且新对象还会具有相同的属性和⽅方法,与构造函数模式不不同的是,新对象的这些属性和⽅方法是有所有实例例共享的,即person1和person2访问的都是同⼀一组属性和同⼀一个sayName( )函数。
原型对象的问题
⾸首先,它省略略了了为构造函数传递初始化参数这⼀一个环节,结果所有的实例例在默认情况下⾖豆浆去的相同的属性值。
原型中所有属性是被很多实例例共享的,这种共享对于函数⾮非常合适,对于那些包含基本址的属性也说得过去,(通过在实例例上添加⼀一个同名属性,可以隐藏原型中对应的属性)然⽽而对于包含了了引⽤用类型值的属性来说问题⽐比较突出:
function Person() {
}
Person.prototype = {
constructor : Person,
name : "Nick",
age : 21,
job : "DH",
friends : ["Shelby","Count"],
sayName : function() {
alert();
}
};
var person1 = new Person();
var person2 = new Person();
person11.friends.push("Van");
alert(person1.friends); //"Shelby,Count,Van"
alert(person2.friends); //"Shelby,Count,Van"
alert(person1.friends === person2.friends);//true
在此,Person.prototype对象⼜又⼀一个名为friends的属性,该属性包含⼀一个字符串串数组。
然后创建了了两个Person实例例。
接着修改了了Person.prototype 引⽤用的数组,由于friends数组存在于Preson.prototype⽽而⾮非person1中,所以这时候person2中的数组也被修改了了。
组合使⽤用构造函数模式和原型模式:
创建⾃自定义类型最常⻅见的⽅方式,就是组合使⽤用构造函数模式和原型模式。
构造函数模式泳⾐衣定义实例例属性,原型模式⽤用于定义⽅方法和共享的属性。
结果每个实例例都会有⾃自⼰己的⼀一份实例例属性的副本,但同时⼜又共享着对⽅方法的饮⽤用,最⼤大限度的节省了了内存。
另外这种混合模式还⽀支持⾹香构造函数传递参数。
function Person(name, age, job) {
= name;
this.age = age;
this.job = job;
this.friends = [“Shelby","court"];
}
/53
Person.prototype = {
constructor:Person,
sayName:function() {
alert();
}
}
var person1 = new Person("Nick", 21, "DH");
var person2 = new Person("Tom", 27, "MK");
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
动态原型模式:
这种模式把所有的信息都封装在了了构造函数中,⽽而通过在构造函数中初始化原型(尽在必要的情况下),有保持了了同事使⽤用构造函数和原型的优点。
即,可以通过检查某个应该存在的⽅方法是否有效,来决定是否需要初始化原型:
function Person(name, age, job) {
//属性
= name;
this.age = age;
this.job = job;
//⽅方法
if(typeOf this.sayName != "function") {
Person.prototype.sayName = function() {
alert();
};
}
}
var friend = new Person("Nick", 21, "DH");
friend.sayName();
加粗部分,只有在sayName( )⽅方法不不存⼦子啊的情况下,才会将它添加到原型中,这⼀一段代码只有在初次调⽤用构造函数的时候才会执⾏行行。
此后原型已经完成初始化,不不需要做什什么修改。
需要注意的是,这⾥里里对原型所做的修改,能够⽴立即在所有实例例中得到反映。
寄⽣生构造函数模式:function Person(name, age, job) {
var o = new Object();
= name;
o.age = age;
o.job = job;
o.sayName = function() {
alert();
}
return o;
}
var friend = . new Person("Nick", 21, "DH");
friend.sayName();//"Nick"
/54
通常在前述的⼏几种模式都不不适合的情况下,可以使⽤用这种模式。
这种模式的基本思想是创建⼀一个函数,该函数的作⽤用仅仅是封装创建对象的代码,然后再返回新创建的对象。
这个模式在特殊的情况下⽤用来为对象创建构造函数。
例例如:
function SpecialArray() {
//创建数组
var values = new Array();
//添加值
values.push.apply(values,arguments);
//添加⽅方法
values.toPipedString = function() {
return this.job("|");
};
//返回数组
return values;
}
var colors = . new SpecialArray("red", "blue", "green");
alert(colors.toPipedString());//"red|blue|green"
关于寄⽣生构造函数模式,有⼀一点需要说明:⾸首先返回的对象与构造函数或者与构造函数的原型属性之间没有关系;也就是说,构造函数返回的对象与在构造函数外部创建的对象没有什什么不不同。
为此,不不能依赖instanceof操作符来确定对象类型
稳妥构造函数模式:
与寄⽣生构造函数类似,但是有两点不不同:意识新创建对象的实例例⽅方法不不引⽤用this;⼆二是不不使⽤用new操作符调⽤用构造⽅方法。
function Person(name, age, job) {
//创建要返回的对象
var o = new Object();
//可以在这⾥里里定义私有变量量和函数
//添加⽅方法
o.sayName = function() {
alert(name);
}
//返回对象
return o;
}
这种模式创建的对象,除了了使⽤用sayName( )⽅方法外,没有其他办法访问到name的值。
var friend = Person(“Nick”, 21, “DH”);
Friend.sayName( );//“Nick”
这样,变量量person中保存的是⼀一个稳妥对象,⽽而除了了调⽤用sayName( )⽅方法外,没有别的⽅方式可以访问其数据成员。
即使有其他代码会给这个对象添加⽅方法货数据成员,但也不不可能有别的⽅方法访问传⼊入到构造函数中的原始数据。
这种安全性,使它⾮非常适合在某些安全执⾏行行环境,例例如ADsafe和Caja提供的环境下使⽤用。
与寄⽣生构造函数模式类似,使⽤用稳妥构造环视模式创建的对象与构造函数之间也没有什什么关系。
/55。