2. 创建对象的几种方式
2.1 工厂模式
function createPeople(name, age, job) {
var o = new Object();
o.name = name;
o.age = age;
o.job = job;
o.sayName = function(){
console.log(this.name);
}
return o;
}
var p1 = createPeople("landy", "20", "fe");
2.2 构造函数模式
function Person(name, age, job) {
this.name = name;
this.age = age;
this.job = job;
this.sayName = function(){
console.log(this.name);
};
}
var p1 = new Person("landy", "20", "fe");
注意: 与工厂模式不同的地方主要有:
1. 没有显示创建对象。
2. 直接将属性和方法赋给this对象
3. 没有return语句
构造函数的缺点:方法无法复用。例如以上例子中的sayName函数。 我们可以将方法移到外部来实现复用。
function Person(name, age, job) {
this.name = name;
this.age = age;
this.job = job;
this.sayName = sayName;
}
function sayName(){
console.log(this.name);
};
var p1 = new Person("landy", "20", "fe");
但是如果很多方法的话,就需要定义很多全局函数,而且这些函数只能被某个对象调用。这种情况下,已经破坏了该引用类型的封装性。
2.3 原型模式
function Person() {
}
Person.prototype.name = "landy";
Person.prototype.age = "20";
Person.prototype.job = "fe";
Person.prototype.sayName = function(){
console.log(this.name);
};
var p1 = new Person();
var p2 = new Person();
p1.sayName(); // landy
console.log(p1.sayName == p2.sayName) // true
方法 | 说明 |
---|---|
isPrototypeOf() | 确定对象是否存在原型关系 |
hasOwnProperty() | 确定是实例拥有某一属性还是原型拥有该属性 |
in | 判断是否对象拥有某一属性。但不能准确判断出是实例属性还是原型的属性 |
function Person() {
}
var p = new Person();
Person.prototype.sayHi = function() {
console.log("hi");
}
p.sayHi(); // no error
function Person() {
}
var p = new Person();
Person.prototype = {
constructor: Person;
sayHi: function() {
console.log("hi");
}
}
p.sayHi(); // error
// 第二种情况对原型进行了重写,p的原型是之前的person.prototype.而不是重写后的。所以会报错。
注意:原型模式的问题: 数据共享。
2.4 组合使用构造函数模式和原型模式
集合两者之长,构造函数定义实例属性,原型定义方法和constructor属性。
function Person(name, age, job){
this.name = name;
this,age = age;
this.job = job;
}
Person.prototype = {
constructor: Person,
sayName: function() {
console.log(this.name);
}
}
注意:目前使用最广泛,认同度最高的方式。
2.5 动态原型模式
将所有信息封装在构造函数中,通过构造函数初始化原型
function Person(name, age, job) {
// 属性
this.name = name;
this.age = age;
this.job = job;
if(typeof this.sayName !== "function") {
Person.prototype.sayName = function() {
console.log(this.name);
}
}
// 在动态原型模式中,不能进行原型重写,否则会切断现有实例与新原型之间的联系
}
2.6 寄生构造函数模式
// 注意比较代码和工厂模式以及构造函数模式的区别
function Person(name, age, job) {
var o = new Obect();
o.name = name;
o.age = age;
o.job = job;
o.sayName = function(){
console.log(this.name);
}
return o;
}
var p1 = new Person('landy', '20', 'fe');
// 构造函数在无返回值的时候,会默认返回新对象实例。可以使用return重写构造函数返回的值。
注意:该种情况下,p1和构造函数Person以及Person的原型属性没有任何关系。所以不能使用instanceof来确定对象类型。
2.7 稳妥构造函数模式
稳妥对象是指没有公共属性,而且方法也不引用this对象。适合在安全环境中引用(这些环境会禁止使用 this 和 new)
funtion Person(name, age, job) {
var o = new Object();
// 在这里定义私有变量,eg name = name;
// 有点类似C++类中的 private name = ?;
o.sayName = function(){
console.log(name);
}
return o;
}
// 以上处理通过sayName,没有其他办法访问内部成员。稳妥构造函数提供了较高的安全性。