《JavaScript设计模式》笔记(二)

面向对象编程,就是将需求抽象成一个对象,然后针对这个对象分析其特征(属性)与动作(方法)。这个对象,我们称之为类。

创建一个类

在JavaScript中,类其实就是包含属性和方法的对象。

所以创建一个类,就简化成创建一个对象,并添加属性和方法。

按照编程习惯,一般将这个代表类的变量名的首字母大写。

var Book = {
  id: 1,
  bookname: "哈利波特",
  price: 70
}

我们知道,一般类是抽象的,它代表着一些具有共同特征的东西。而上方的这个例子中,书的id、名称、价格都是具体的,它更像是一个对象实例,显然这不是创建类的好方式。

在JavaScript中,函数也是对象。所以可以使用函数来创建类。

var Book = function (id, bookname, price) {
  this.id = id;
  this.bookname = bookname;
  this.price = price;
}

函数的参数可以用来为新对象创建不同的属性。

添加属性或方法的两种方式

  • 实例属性或方法
    在函数内部通过对this变量添加属性或者方法来实现对类添加属性或者方法。

通过this定义的属性或者方法是实例对象自身拥有的,所以我们每次通过类创建一个新对象时,this指向的属性和方法都会创建。

  • 原型属性或方法
    在类的原型上添加属性和方法,原型上的属性和方法是共享的,在创建新对象时,不会再次创建。

继承关系图:

《JavaScript设计模式》笔记(二)_第1张图片
image.png

属性与方法封装

面向对象的一个特点就是,对一些属性和方法的隐藏于暴露,比如私有属性、私有方法、公有属性、公有方法、特权方法等。

  • 私有变量/方法
    由于JavaScript的函数作用域,声明在函数内部的变量以及方法在外界是访问不到的,通过此特性即可创建类的私有变量以及私有方法。

  • 公有变量/方法
    在函数内部通过this创建的属性和方法,在类创建对象时,每个对象自身都拥有一份并且可以在外部访问到。

  • 特权方法
    通过this创建的方法,不但可以访问这些对象的公有属性和方法,而且还能访问到类创建的私有属性和方法,由于这些方法权利比较大,所以可以当做特权方法。

  • 构造器
    在对象创建时通过使用特权方法,可以初始化实例对象的一些属性,因此这些在创建对象时调用的特权方法还可以看作是类的构造器。

  • 类静态公有属性/方法
    通过new关键字创建新对象时,由于类外面通过点语法添加的属性和方法没有执行到,所以新创建的对象中无法获取他们,但是可以通过类来使用。

  • 对象共有属性/方法
    类通过prototype创建的属性或者方法,在类实例的对象中是可以访问到的,而通过类无法访问。

var Book = function (id, name, price) {
  // 私有属性
  var num = 1;
  // 私有方法
  function checkId () {}
  // 公有属性
  this.id = id;
  this.bookname = name;
  this.price = price;
  // 公有方法
  this.copy = function () {};
  // 特权方法
  this.getName = function () {};
  this.getPrice = function () {};
  this.setName = function () {};
  this.setPrice = function () {};
  // 构造器
  this.setName();
  this.setPrice();
}
// 类静态公有属性
Book.isChinese = true;
// 类静态公有方法
Book.restTime = function () {
  console.log("new Time")
};

Book.prototype = {
  // 对象共有属性
  isJSBook: false,
  // 对象共有方法
  display: function () {}
}

闭包实现类的静态私有变量和方法

在类外面通过点语法定义的属性以及方法,是类的静态公有属性和方法。

而通过闭包,可以实现添加类的静态私有变量和方法。

var Book = (function () {
  // 静态私有变量
  var bookNum = 0;
  // 静态私有方法
  function checkBook(name) {}
  // 创建类
  function _book(newId, newName, newPrice) {
    // 私有变量
    var name, price = 0;
    // 私有方法
    function checkId (id) {};
    // 公有属性
    this.id = newId;
    // 公有方法
    this.showNum = function () {
      console.log("静态私有变量:", ++bookNum);
    };
    this.showPrice = function () {
      console.log("私有变量:", ++price);
    };
    // 特权方法
    this.getName = function () {};
    this.getPrice = function () {};
    this.setName = function () {};
    this.setPrice = function () {};
    // 构造器
    this.setName(name);
    this.setPrice(price);
  }
  // 构建原型
  _book.prototype = {
    // 对象共有属性
    isJSBook: false,
    // 对象共有方法
    display: function () {}
  }
  // 返回类
  return _book;
})();

测试用例

  var book_1 = new Book();
  // 间接访问类的静态私有变量
  book_1.showNum();
  // 间接访问私有变量
  book_1.showPrice();
  var book_2 = new Book();
  // 间接访问类的静态私有变量
  book_2.showNum();
  // 间接访问私有变量
  book_2.showPrice(); 

结果:
每创建一个对象实例,静态私有变量bookNum加1。

image.png

私有变量和静态私有变量的区别:

  • 每个对象实例都有一份私有变量;
  • 所有对象实例共有一份静态私有变量

创建对象的安全模式

为避免在创建对象时忘记使用new关键字,应该使用安全模式创建对象。

即对this进行检测,判断this当前指向的对象是否是类的实例。

instanceof 运算符用来测试一个对象在其原型链中是否存在构造函数(类)的prototype。

 var Book = function (id,name, price) {
    // 判断执行过程中this是否是当前这个对象
    if (this instanceof Book) {
      // 构造函数的具体内容
    } else {
      return new Book(id, name, price);
    }
  }

你可能感兴趣的:(《JavaScript设计模式》笔记(二))