第十五章 面向对象与原型

  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

  

原文地址:https://www.cnblogs.com/xchit/p/JavaScript_15.html