使用Oject构造函数或者对象的字面量创建单个对象的时候会有大量的重复代码。
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");
createPerson()
的时候,每调用一次就返回来一个Object类型的对象,这个对象的属性值就是调用函数的时候传递的参数值。
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");
var person = new Person("Nicholas", 29, "Software Engineer"); person.sayName(); //"Nicholas"
Person("Greg", 27, "Doctor"); // 加 window window.sayName(); //"Greg"
var o = new Object();
// 在o的作用域中调用Person函数
Person.call(o, "Kristen", 25, "Nurse"); o.sayName(); //"Kristen"
new Object()
new Person
,经历的过程为 alert(person1.constructor == Person); //true
alert(person2.constructor == Person); //true
instanceOf()
。person1和person2既是Object的实例,也是Person的实例。 alert(person1 instanceof Object); //true
alert(person1 instanceof Person); //true
alert(person2 instanceof Object); //true
alert(person2 instanceof Person); //true
alert(person1.sayName == person2.sayName); //false
function Person(name, age, job){
this.name = name;
this.age = age;
this.job = job;
this.sayName = sayName;
}
function sayName(){
alert(this.name);
}
var person1 = new Person("Nicholas", 29, "Software Engineer");
var person2 = new Person("Greg", 27, "Doctor");
将sayName()
定义到了构造函数外面,虽然实现了person1和person2共享了全局函数sayName()
, 解决了两个函数做同一件任务的情况。但是 其实全局作用域中定义的函数只能被某个对象调用,而且如果在构造函数中需要定义多个函数,如果都拿到外面,则失去了构造函数的封装性。
function Person(){
} // 构造了一个Person,将属性加到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
function Person(){
}
Person.prototype = {
constructor : Person,
alert(this.name);
}
};
var friend = new Person();
alert(friend instanceof Object); //true
alert(friend instanceof Person); //true
alert(friend.constructor == Person); //false
alert(friend.constructor == Object); //true
function Person(){
}
var friend = new Person();
Person.prototype = {
constructor: Person,// 手动设置构造器指向Person
name : "Nicholas",
age : 29,
job : "Software Engineer",
sayName : function () {
alert(this.name);
}
};
friend.sayName(); //error
function Person(){
}
Person.prototype = {
constructor: Person,
name : "Nicholas",
age : 29,
job : "Software Engineer",
friends : ["Shelby", "Court"],
sayName : function () {
alert(this.name);
} };
var person1 = new Person();
var person2 = new Person();
person1.friends.push("Van");
alert(person1.friends); //"Shelby,Court,Van"
alert(person2.friends); //"Shelby,Court,Van"
alert(person1.friends === person2.friends); //true
当一个实例修改了原型中的应用型值的时候,另一个实例访问的时候访问到的是修改之后的值。所以我们一般不会单独使用原型模式。
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);
}
}
ar person1 = new Person("Nicholas", 29, "Software Engineer");
ar person2 = new Person("Greg", 27, "Doctor");
erson1.friends.push("Van");
lert(person1.friends); //"Shelby,Count,Van"
lert(person2.friends); //"Shelby,Count"
lert(person1.friends === person2.friends);
lert(person1.sayName === person2.sayName);
//false/true
修改person1中的friends对person2中的friends没有影响,因为这根本就是两份内存中数据。
function Person(name, age, job){
// 属性
this.name = name; this.age = age; this.job = job;
}
var friend = new Person("Nicholas", 29, "Software Engineer");
friend.sayName();
// 方法
if (typeof this.sayName != "function"){
Person.prototype.sayName = function(){
alert(this.name);
}; }
在初次调用构造函数的时候,判断如果sayName()
方法不存在的情况下,才会在构造函数的原型中添加这个方法。
function Person(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 friend = new Person("Nicholas", 29, "Software Engineer");
friend.sayName(); //"Nicholas"
就是使用了new操作符包装的的函数,其余的和工厂模式一样。构造函数在不返回值的情况下,默认会返回新的对象实例。但是如果在构造函数的末尾添加return语句,这样可以重写调用构造函数是返回的值。一般用来为对象创建构造函数。
创建一个具有额外方法的特殊数组,但是不能直接修改Array的构造函数
function SpecialArray(){
var values = new Array(); // 创建数组
values.push.apply(values, arguments); // 用构造函数接收到的值初始化values数组
values.toPipedString = function(){ // 添加方法
return this.join("|");
};
return values; // 返回数组,这个数组具有toPipedString方法
}
var colors = new SpecialArray("red", "blue", "green");
alert(colors.toPipedString()); //"red|blue|green"
寄生的意思是一般用于对已有的对象在添加某些东西,就像计生在原有的对象之上。注意:和工厂模式类似,不能使用instance()
来确定对象的类型,因为返回的对象和构造函数或者与构造函数的原型之间没有关系。其实使用寄生构造函数与在外部创建对象没有什么不同。
这个方法感觉和工厂一个样,有问题
- 没有公共属性,方法不应用this对象。
- 可以防止数据被其他应用程序改动。
function Person(name, age, job){
var o = new Object();
o.sayName = function(){
alert(name);
};
return o;
}
除了使用sayName()
方法以为没有办法访问name的值。