ECMAScript中是没有类的概念的,它对于对象的定义是“无序属性的集合,其属性可以包含基本值、对象或者函数”
以下是几种js的函数模式来封装实现类以及他们的优缺点
- 工厂模式
工厂模式使用普通函数以根据参数创建一个包含需要的属性和方法的Person对象
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;
}
优点:可以无数次地调用这个函数,而每次它都会返回一个包含三个属性的一个方法对象。解决了封装和用字面量创建多个相似对象的问题
缺点:对象识别问题(即知道一个对象的类型)
- 构造函数模式
一、什么是构造函数?
构造函数可以创建特定类型的对象,即像object和array这样的原生构造函数,在运行时会自动出现在执行环境中。我们可以创建自定义的构造函数,从而定义自定义对象类型的属性和方法。
二、创建构造函数
构造函数本身也是函数,只不过可以用来创建对象而已。
要创建新实例,必须使用new操作符。它的内部执行步骤如下:
1.创建一个新对象
2.将构造函数的作用域赋给新对象(因此this就指向了这个新对象)
3.执行构造函数中的代码(为这个新对象添加属性)
4.返回新对象
function Person(name, age, job) {
this.name = name;
this.age = age;
this.job = job;
this.sayName = function(){
alert(this.name)
}
}
var person1 = new Person("Amy", "22", "Engineer");
var person2 = new Person("Mavis", "25", "accountant");
alert(person1.constructor == Person); //true
alert(person2.constructor == Person); //true
alert(person1 instanceof Object); //true
alert(person1 instanceof Person); //true
优点:这里的person1 和person2 作为Person的两个不同的实例,这两个对象都有一个constructor(构造函数)属性,该属性指向Person,或者使用instanceof操作符识别,解决了对象识别问题。
alert(person1.sayName == person2.sayName); //false
缺点:每个实例上都会重新把方法创建一遍,两个是不同的function,完成同样事的方法多次创建,占内存又没必要
- 原型模式
一、什么是原型?
我们创建的每个函数都有一个prototype(原型)属性,这个属性是一个指针,指向通过构造函数创建的那个对象实例的原型对象,使用它可以让所有对象实例共享它所包含的属性和方法。即不用在构造函数中定义对象实例的属性方法,可以将这些直接添加到原型对象去。
function Person(){};
Person.property.name = 'Amy';
Person.property.age= '22';
Person.property.job= 'Engineer';
Person.property.sayName = function(){
alert(this.name)
}
var person1 = new Person();
person1 .sayName ();//Amy
var person2 = new Person();
person2 .sayName ();//Amy
alert(person1.sayName == person2.sayName) //true
优点:解决了构造函数模式的占用内存方法不共用的问题
缺点:因为它的共享特性,例如:
......
Person.property.hobby= ["play games", "cooking"];
......
person1.hobby.push("sleep");
alert(person1.hobby); //"play games,cooking,sleep"
alert(person2.hobby); //"play games,cooking,sleep"
alert(person1.hobby === person2.hobby); //true
- 组合使用构造函数模式和原型模式
这种模式是用构造函数来定义那些实例属性(即不共用的一些属性),用原型模式用来定义方法和共享的属性
function Person(name, age, job){
this.name = name;
this.age = age;
this.job = job;
this.friends = "Mavis";
}
Person.prototype = {
constructor : Person,
sayName : function(){
alert(this.name);
}
}
后面会写实现继承的方式,深刻了解原型链。