ECMAScript:面向对象、工厂模式、构造模式

  面向对象(Object-Oriendted,OO)的语言有一个标志,那就是它们都有类的概念,而通过类可以创建任意多个具有相同属性和方法的对象。ECMAScript中没有类的概念类是面向对象程序设计(OOP,面向对象编程)实现信息封装的基础。类是一种用户定义类型,也称类类型。每个类包含数据说明和一组操作数据或传递消息的函数。的类实例称为对象】  ,因此它的对象也与基于类的语言中的对象有所不同 

   ECMA-262把对象定义为:“ 无序属性的集合,其属性可以包含基本值,对象或者函数”严格来讲,这就相当于说对象是一组没有特定顺序的值。对象的每个属性或方法都有一个名字,而每个名字都映射到一个值,正因为这样,我们可以把ECMAScript中的对象想象为散列表:无非就是一组名值对,其中值可以是数据或函数(这或许有点难理解〜 一组是指一个对象对应属性和方法。名是指属性或函数的名。值是指属性的值或函数的内容)

  理解对象

  创建自定义对象的最简单方式就是创建一个对象的实例,然后再为它添加属性和方法,早期的JavaScript开发人员经常这样写,如下所示:

 var person = new Object();         //直接用new操作符创建一个实例化对象

person.name =“yao”;

person.age = 19;

person.job =“Student”;

person .sayName = function(){

alert(this .name);                //将被解析为person.name

};                                             //注意不要少了分号

这个例子可以用对象字面量语法这样写:

var person = {                   //(还是用new操作符创建了一个对象)  也相当于直接创建对象,只不过换了一种更好的方式。

name:“yao”,

age:19

job:“Student”,                     //注意不要写成了分号,是逗号

sayName:function(){

alert(this.name);

 }

};                            //注意不要少了分号

创建对象

工厂模式

这种模式抽象了创建具体对象的过程。考虑到在ECMAScript中无法创建类,开发人员就发明了一种函数,用函数来封装(函数封装开发人员所写的内容)以特定接口(如此,我在想,接口是不是就相当于函数调用!)创建对象的细节,(你想想,函数中包含属性,属性值和函数不就相当于java中的类吗!),工厂模式写法如下所示:

  function createPerson(name,age,job){     //所谓的用函数来封装,作为一个特定的接口,如果要用到它,就用它来创建对象

var A=new Object();        //还是用new操作符创建了一个对象A

A.name=name;        //定义A的属性和方法

A.age=age;

A.sayName=function(){

alert(this.name);                    //函数中不仅包含属性,而且还包含这个函数

};

return 0;

}

var person1=createPerson("yao",19,"Student");

var person2=createPerson("xiyao",29,"Teacher");  //这个时候就相当于调用createPerson()函数了,传递对象参数进去即可

         函数createPerson()能够根据接受的参数来构建一个包含所有必要信息的Person对象。可以无数次地调用这个函数,而每次它都会返回一个包含三个属性和一个方法的对象。工厂模式虽然解决了创建多个相似对象的问题,但却没有解决对象识别的问题(即怎么知道一个对象的类型。这就要说到对象的类型概念啦~    对象是引用类型的一个实例,引用类型的值就是对象。引用类型包含Object类型、Array类型、Date类型、RegExp类型、Function类型、(基本包装类型:Boolean类型,Number对象,String类型)、单体内置对象:Global对象,Math对象)。

      一个问题的出现,就会有解决之案,所以随着JavaScript的发展,又一个新模式出现了。

构造模式

ECNAScript中的构造函数可用来创建特定类型的对象。像Object和Array这样的原生构造函数,在运行时会自动出现在执行环境中。此外,也可以创建自定义的构造函数,从而定义自定义对象类型的属性和方法。例如,可以使用构造函数模式将前面的例子重写如下:

function Person(name,age,job){

this.name=name;

this.age=age;

this.job=job;

this.sayName=function(){

alert(this.name);

 };

}

 var person1=new Person("yao",19,"Student"); //这个时候Person()就相当于一个特定对象类型了,这个类型是我们自定义的

var person2=new Person("xiyao",29,"Teacher");//该类对象被创建时,编译系统对象分配内存空间,并自动调用该构造函数->由构造函数完成成员的初始化工作

在这个例子中,Person()函数取代了createPerson()函数。我们注意到,Person()中的代码除了与createPerson()中相同的部分外,还存在以下不同之处:

1、没有显示地创建对象;(即没有在函数中用new操作符创建对象了)

2、直接将属性和方法赋给了this对象;

3、没有return语句;(即没有返回值类型)

此外,还应该注意到函数名Person使用的是大写字母P。按照惯例,构造函数始终都应该以一个大写字母开头,而非构造函数则应该一个小写字母开头。这个做法借鉴自其他OO语言,主要是为了区别于ECMAScript中的其他函数;因为构造函数本身也是函数,只不过可以用来创建对象而已。

要创建Person的新实例,必须使用new操作符。以这种方式调用构造函数实际上会经历以下4个步骤:

1、创建一个新对象;

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

3、执行构造函数中的代码(为这个新对象添加属性和方法)

4、返回新对象

注意:1、我们在这个例子中创建的所有对象既是Object的实例(因为所有对象均继承自Object),同时也是Person的实例。

2、构造函数与其他函数的唯一区别,就在于调用它们的方式不同。任何函数,只要通过new操作符来调用,那它就可以作为构造函数,而不通过new操作符来调用,那它跟普通函数也不会有什么两样。例如,举个栗子:

//当作构造函数来创建对象

var person=new Person("yao",19,"Student");

person.sayName();

//作为普通函数调用

Person("xiyao",29,"Teacher");     //添加到window

widnow.sayName();

//在另一个对象的作用域中调用

var A=new Object();

Person.call(A,"yao",19,"Student");

A.sayName();

3、ECMAScript中的函数是对象,是Function的一个实例化对象,因此当定义了一个对象,也就是实例化了一个对象。所以在之前的构造函数中,sayName方法原来是这样写的:

this.sayName=function(){

alert(this.name);

 };

现在可以这么写:

this.sayName=new Function("alert(this.name)");  //与声明函数在逻辑上是等价的

4、其实,我们可以将原来的构造函数这么写也是正确的:

function Person(name,age,job){

this.name=name;

this.age=age;

this.job=job;

this.sayName=sayName;

}

function sayName(){

alert(this.name);

}     //无分号

 var person1=new Person("yao",19,"Student");

var person2=new Person("xiyao",29,"Teacher");

猜你喜欢

转载自blog.csdn.net/qq_39178993/article/details/81412658