美文网首页
《JavaScript设计模式》笔记(二)

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

作者: 回调的幸福时光 | 来源:发表于2017-09-12 19:28 被阅读11次

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

    创建一个类

    在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指向的属性和方法都会创建。

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

    继承关系图:

    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设计模式》笔记(二)

          本文链接:https://www.haomeiwen.com/subject/fcucsxtx.html