面向对象可以把程序中的关键模块都视为对象,而模块拥有属性及方法。
这样我们如果把一些属性及方法封装起来,日后使用将非常方便,也可以避免繁琐重复的工作。
1.对象直接量
创建对象最简单的方式就是在JavaScript代码中使用对象直接量。
对象直接量是一个表达式,这个表达式的每次运算都创建并初始化一个新的对象。每次计算对象直接量的时候,也都会计算它的每个属性的值。
如果在一个重复调用的函数中的循环体内使用了对象直接量,它将创建很多新对象,并且每次创建的对象的属性值也有可能不同。
示例
var book = {
"main title" : "JavaScript",
//属性名里有空格,必须用字符串表示。
'sub-title' : "The Definitive Guide",
//属性名里有连字符,必须用字符串表示。
"for" : "all audiences",
//"for"是保留字,必须用引号。
//在ES5中,保留字可以用做不带引号的属性名。
author: {
//这个属性的值是一个对象
firstname: "David",
//这里的属性名都没有引号
surname: "Flanagan"
}
};
2.使用Object构造函数创建
new运算符创建并初始化一个新对象。
关键字new后跟随一个函数调用,这里的函数称为构造函数(constructor),构造函数用以初始化一个新创建的对象。
js语言核心中的原始类型都包含内置构造函数。
示例
var Person = new Object();
Person.name = 'Mike';
Person.age = 29;
前两种方法的缺点——它们都用了同一个接口创建很多对象,会产生大量的重复代码,假如要创建100个对象,那就要写100次很多相同的代码。
有什么方法可以避免过多的重复代码呢?就是把创建对象的过程封装在函数体内,通过函数的调用直接生成对象。
3.工厂模式
在函数内创建一个对象,给对象赋予属性及方法再将对象返回。
示例
function createBlog(name, url) {
var o = new Object();
o.name = name;
o.url = url;
o.sayUrl= function() {
alert(this.url);
}
return o;
}
var blog = createBlog('zhangsiyang', 'https://blog.csdn.net/weixin_38840741');
工厂模式的实现方法解决了创建多个相似对象的问题,但是工厂模式无法识别对象的类型,因为全部都是Object,因此出现了构造函数模式。
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('Mike',29,'teacher');
var person2 = new Person('Arvin',20,'student');
对比工厂模式,我们可以发现以下区别——
- 没有显示地创建对象;
- 直接将属性和方法赋给了this对象;
- 没有return语句;
- 可以识别的对象的类型。
对于检测对象类型,我们应该使用instanceof操作符,下面是自主检测:
alert(person1 instanceof Object);//ture
alert(person1 instanceof Person);//ture
alert(person2 instanceof Object);//ture
alert(person2 instanceof Person);//ture
按照惯例,构造函数 始终要应该以一个大写字母开头,而非构造函数 则应该以一个小写字母开头。
构造函数也有缺点——
每个方法都要在每个实例上重新创建一遍,方法指的就是我们在对象里面定义的函数。如果方法的数量很多,就会占用很多不必要的内存。
于是就有了第五种创建对象的方法,原型创建对象模式。
5.原型创建对象模式
function Person(){
Person.prototype.name = 'Mike';
Person.prototype.age = 20;
Person.prototype.jbo = 'teacher';
Person.prototype.sayName = function(){
alert(this.name);
};
};
var person1 = new Person();
var person2 = new Person();
person1.name ='Greg';
alert(person1.name); //'Greg' --来自实例
alert(person2.name); //'Mike' --来自原型
当为对象实例添加一个属性时,这个属性就会覆盖原型对象中保存的同名属性。
这时候我们就可以使用构造函数模式与原型模式结合的方式,构造函数模式用于定义实例属性,而原型模式用于定义方法和共享的属性。
6.组合使用构造函数模式和原型模式
function Person(name,age,job){
this.name =name;
this.age = age;
this.job = job;
};
Person.prototype = {
constructor:Person,
sayName: function(){
alert(this.name);
};
};
var person1 = new Person('Mike',20,'teacher');
7.Object.create()
ES5定义了一个名为Object.create()的方法,它创建一个新对象,其中第一个参数是这个对象的原型。Object.create()提供第二个可选参数,用以对对象的属性进行进一步描述。
Object.create()是一个静态函数,而不是提供给某个对象调用的方法。使用它的方法很简单,只需传入所需的原型对象即可:
var o1 = Object.create({x:1, y:2});
//o1继承了属性x和y