您的位置:首页 > Web前端 > JavaScript

js创建对象之设计模式

2015-11-30 12:12 489 查看

1. 工厂模式

function createPerson(name, age){

var obj = new Object();

obj.name = name;
obj.age = age;

obj.sayName = function(){
console.log(this.name); // | console.log(obj.name)
};

return obj;
}

var p1 = createPerson("ys", 12);
var p2 = createPerson("ys", 12);
console.log(p1);         // { name: 'ys', age: 12, sayName: [Function] }
console.log(p2);         // { name: 'ys', age: 12, sayName: [Function] }
console.log(p1 == p2);   //false


特点:

内部创建对象,外部返回,相当于调用函数,

对象无类型(比如其他oo语言,new一个对象,那个这个对象的构造函数就是对象类型)

2.构造函数模式

function Person(name, age){
this.name = name;
this.age = age;

this.sayName = function(){
console.log(this.name);
};
}

var p1 = new Person("ys", 12);
var p2 = new Person("ys", 12);
console.log(p1);                        // { name: 'ys', age: 12, sayName: [Function] }
console.log(p2);                        // { name: 'ys', age: 12, sayName: [Function] }
console.log(p1 == p2);                  //false
console.log(p1 instanceof Person);      //true
console.log(p2 instanceof Person);      //true
console.log(p1 instanceof Object);      //true
console.log(p2 instanceof Object);      //true

console.log(p1.constructor == Person);  //true  /*constructor属性为构造函数属性,指向构造函数Person*/
console.log(p2.constructor == Person);  //true


特点:

通过该模式创建的对象有自定义类型Person, 每个对象都是构造函数的实例

构造函数已经不再是意义上的调用函数,而是使用了new,构造过程包括四个步骤:

①创建一个新对象

②将构造函数的作用域赋给新对象(因此this指向了这个新对象)

③执行构造函数中的代码(为这个新对象添加属性)

④返回新对象

对于这样的构造函数模式,会发现有一点瑕疵,那就是sayName函数的功能是一样的,但是每个对象的实例都有该函数,这样却显得有点冗余,在此基础上,进行了一些改良:

function Person(name, age){
this.name = name;
this.age = age;

this.sayName = sayName;
}

function sayName(){
console.log(this.name);
}


将公共的函数部分,提取出来,作为全局函数,使得每个构造函数去调用他,达到了所有实例对象复用的效果。

2015-12-12 补充…

通过不断的的学习,对构造函数模式有了新的理解,补充:

上面我写的构造函数是用函数声明的方式定义的,另一种方法,我们也可以用对象直接量方法声明

var Person = function(name, age){
this.name = name;
this.age = age;

this.sayName = function(){
console.log(this.name);
};
}

var p1 = new Person("ys", 12);
var p2 = new Person("ys", 12);
console.log(p1);                        // { name: 'ys', age: 12, sayName: [Function] }
console.log(p2);                        // { name: 'ys', age: 12, sayName: [Function] }


这样同样我得到了效果….但是最近看书学习,发现了一个问题,上面我这种方法(包括两种方法 )安全吗?

就连我之前都没有质疑过安全性,看看下面的代码

构造函数我就不写了.函数,对象直接量都是一个意思…

var p1 = Person("ys", 12);
var p2 = Person("ys", 12);
console.log(p1);                        // undefined
console.log(p2);                        // undefined


我们会发现竟然是undefined,怎么会,快找找原因….原因是他少了new这个关键字…

为什么会出现这样的原因呢,我们正确的结果,或许一看你就会了解。

var p1 = Person("ys", 12);
var p2 = Person("ys", 12);
console.log(p1);                        // undefined
console.log(p2);                        // undefined

console.log(window.name); //ys
console.log(window.age); //12


原因就是没了new这个关键字,对于js的new关键字,大家可以这样理解:

new就是将函数内部的this的值,赋值给当前对象的this,如:this.name(实例对象) = this.name(构造函数)

当没有new的时候,this就变为了window,也就解释了。

那么问题又来了,有时候我们就是会忘记new,那这样的构造函数就显得不安全,这里有一个安全的构造函数模式,可以帮到你

/*安全的构造函数模式*/
var Person = function(name, age){

if(this instanceof Person){
this.name = name;
this.age = age;

this.sayName = function(){
console.log(this.name);
};
}else{
return new Person(name, age);
}

}

var p1 = Person("ys", 12);
var p2 = Person("ys", 12);
console.log(p1);                        // { name: 'ys', age: 12, sayName: [Function] }
console.log(p2);                        // { name: 'ys', age: 12, sayName: [Function] }

console.log(window.name);               // undefined
console.log(window.age);                // undefined


3.原型对象模式

然后我们也觉得一个问题出现了,对于上面改良后的构造函数模式,所创建的全局函数sayName似乎成了Person构造函数的私人司机,只对于他一个人用,这样也就失去了全局函数的价值,而且当存在诸多构造函数时候,诸多的“sayName”也是一个问题,这个时候,原型模式完美的解决了这个问题

//需要变动部分
function Person(name){
this.name = name;
}
//永久不变部分
Person.prototype.age = 12;
Person.prototype.sayName = function(){
console.log(this.name);
}

var p1 = new Person("ys");
var p2 = new Person("ab");
console.log(p1.sayName());              //ys
console.log(p1.age);                    //12

console.log(p2.sayName());              //ab
console.log(p2.age);                    //12

console.log(p1.sayName == p2.sayName);  //true


当创建一个函数时候,该函数存在一个prototype属性,该属性是一个指针,指向一个对象,这个对象是一个方法和属性的集合,存储公共的属性和方法,达到所有实例共享的目的。

有全局对象的特性,区别于全局,Person构造函数的私人全局,只对它(Person)一个人生效。

当存在于对象实例时候,他们共享prototype里面的东西。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息