创建对象 --- 构造函数模式

ECMAScript中的构造函数可以用来创造特定类型的对象,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("wsc",25,"software Engineer");
var person2 = new Person("yl",26,"Doctor");

注意:按照惯例,构造函数始终都应该以一个大写字母开头,而非构造函数则应该以一个小写字母开头,目的是区别ECMAScript中的其他函数,因为构造函数也是函数,只是配用来创建对象;

(1).创建Person新实例,必须使用new操纵符。这种方式调用构造函数实际上经历一下4个步骤:
  1.创建一个新对象;

  2.将构造函数的作用域赋给新对象;

  3.执行构造函数中的代码;

  4.返回新对象;

(2).构造函数都有一个构造函数属性constructor,该属性指向该对象所属的实例,以前面的例子为准:

  alert(person1.constructor == Person);//true

  1.对象的constructor属性主要目的是用来标识对象类型;

  2.检测对象类型主要是用instanceof,示例如下:
    alert(person1 instanceof Object);//true   注意:所有的对象均继承Object
    alert(person1 instanceof Person);//true

  3.创建自定义构造函数意味着将来可以将它的实力标识为一种特定的类型,这是构造模式胜过工厂模式的地方,

  注意:以这种方式的构造函数是定义在Global对象中的;

(3).构造函数与其他函数的唯一区别是调用方式的不同:任何函数只要通过new操作符来调用,那么它就作为构造函数;任何函数如果不通过new操作符来调用,那么它就作为普通函数;

// 当作构造函数
var person = new Person("wsc",26,"Software Engineer");
person.sayName();//"wsc";

//普通函数
Person("wsc",26,"Software Engineer");//添加到window
window.sayName()//"wsc"

//在另一个对象的作用域中调用
var o = new Object();
Person.call(o,"wsc",26,"Software Engineer");
o.sayName();//"wsc"

 (4).构造函数的问题

  构造函数的主要问题是:每个方法都要在每个实例上重新创建一遍。

  以上面的例子为例:从逻辑上,此时的构造函数还可以如下定义。

  

function Person(name,age,job){
      this.name = name;
      this.age = age;
      this.job = job;
      this.sayName = new Function("alert(this.name)");//与声明函数在逻辑上是等价的        
}

//在这里ECMAscript中的函数也是对象;

此种方式创建函数,会导致不同的作用域链和标识符解析,但在创建Function新实例的机制仍然是相同的。因此不同实例上同名的函数是不等的。

 

解决此问题的方式如下:

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("wsc",29,"software engineer");
var person2 = new Person("wife",26,"techer");
alert(person1.sayName === person2.sayName);//?

但此种方式,又会产生新的问题:全局函数只能被某个对象调用,如果对象需要定义很多方法,这就需要定义多个全局函数。如何解决呢?看原型

posted @ 2016-09-19 10:55  山水如九画  阅读(3662)  评论(0编辑  收藏  举报