ECMAScript有两种开发模式:1.函数式(过程化),2.面向对象(OOP)。面向对象(Object - Oriented,OO)的语言有一个标志,那就是类的概念,而通过类可以创建任意多个具有相同属性和方法的对象。但是,ECMAScript没有类的概念,因此它的对象也与基于类的语言中的对象有所不同。
一、创建对象
创建一个对象最简单的方式就是创建一个object的实例,然后再为他添加属性和方法。
var person = new Object();
person.name = "Nich";
person.age = 27;
person.job = "Software Engineer";
person.sayName = function(){
alert(this.name);
}
上面创建了一个对象,并且创建属性和方法,在 sayName() 方法里的this,就是代表 person 对象本身。
1.属性类型
ECMAScript 中有两种属性 :数据属性和访问器属性。
数据属性包含一个数据值的位置。在这个位置可以读取和写入值。
var person = {
name : "Nich"
};
创建一个名为name的属性,为它指定的值是“Nich”。
2.访问器属性
访问器属性不包含数据值;它们包含一对 getter 和 setter 函数。在读取访问器属性时,会调用getter函数,这个函数负责返回有效的值;在写入访问器属性时候,会调用 setter 函数并传入新值;
访问器属性不能直接定义,必须使用 Object.defuneProperty()来定义。
var book = { _year : 2013, edition : 1 }; Object.defineProperty(book,"year",{ get : function(){ return this._year; }, set : function(newValue){ if(newValue > 2013){ this._year = newValue; this.edition += newValue - 2013; } } });
这里创建了一个book对象,并给它定义两个默认的属性。
3.读取属性
读取属性要用到 Object.getOwnPropertyDescriptor() 方法;
var book = {}; Object.defineProperties(book,{ _year : { value : 2013 }, edition : { value : 1 }, year : { get : function(){ return this._year; }, set : function(newValue){ if(newValue > 2013){ this._year = newValue; this.edition += newValue -2013; } } } }); var descriptor = Object.getOwnPropertyDescriptor(book,"_year"); alert(descriptor.value); //2013 alert(descriptor.confi gurable); //false
二、工厂模式
工厂模式是软件工程领域一种设计模式,这种模式抽象了创建具体对象的过程,考虑到ECMAScript无法创建类,开发人员就发明了一种函数,用函数来封装以特定接口创建对象的细节。
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("Nice", 27 ,"Software Engineer"); var person2 = createPerson("Greg", 29, "Doctor");
工厂模式解决了重复实例化的问题,但还有一个问题,那就是识别问题,因为根本无法搞清楚他们到底是哪个对象的实例。
ECMAScript中可以采用构造函数(构造方法)可用来创建特定的对象。类型于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("Nice", 27 ,"Software Engineer"); var person2 = new Person("Greg", 29, "Doctor");
两个函数不同之处:
1.没有显示的创建对象;
2.直接将属性和方法赋给了this对象;
3.没有return语句。
构造函数的方法有一些规范:
1.函数名和实例化构造名相同且大写,这么写有助于区分构造函数和普通函数;
2.通过构造函数创建对象,必须使用new运算符。
要创建Person的新实例,必须使用 new 操作符。这种方式调用构造函数经历了4个步骤:
1.创建一个新对象;
2.将构造函数的作用域赋给新对象;
3.执行构造函数中的代码;
4.返回新对象。
关于this的使用,this其实就是代表当前作用域对象的引用。如果在全局范围this就代表window对象,如果在构造函数体内,就代表当前的构造函数所声明的对象。
构造函数和普通函数的唯一区别,就是他们调用的方式不同。只不过,构造函数也是函数,必须用new运算符来调用,否则就是普通函数。
构造函数问题
构造函数每次使用使用都需要实例重新创建一次,以上面一个例子:
alert(person1.sayName == person2.sayName); //false
创建两个完全同样任务的Function实例是没有不要的;况且有 this 对象在,根本不用在执行代码前就把函数绑定到特定对象上面。
function Person(name, age, job){ this.name = name; this.age = age; this.job = job; this.sayName = sayName; } var sayName=function() { alert(this.name); } var person1 = new Person("Nice", 27 ,"Software Engineer"); var person2 = new Person("Greg", 29, "Doctor");
alert(person1.sayName == person2.sayName); //true