值得学习的JS编程

251 阅读5分钟


1.构造函数模式

在经典的面向对象编程语言中,构造函数是一种特殊的中介,用于在为内存分配内存时初始化新创建的对象。
在JavaScript中,几乎所有东西都是对象,我们最常对对象构造函数感兴趣。
由于对象构造函数用于创建特定类型的对象,例如准备要使用的对象和接受参数,构造函数可以在首次创建对象时使用它来设置成员属性和方法的值。

正如我们所看到的,JavaScript不支持类的概念,因此在构造函数中,关键字this引用正在创建的新对象,重新访问对象创建,基本构造函数可能如下所示:

function Car(model, year, miles) {
  this.model = model;
  this.year = year;
  this.miles = miles;
}

// Usage:
var bmw = new Car('M4', '2019', '1000');

2.模块模式

模块是任何强大的应用程序结构中不可或缺的部分,通常有助于保持项目代码单元的清晰分离和组织。

有几种实现模块的选项。
这些包括:

  • 对象文字符号
  • 模块模式
  • AMD模块
  • CommonJS模块
  • ECMAScript Harmony模块

对象文字:

var newObject = {
  variableKey: variableValue,
  functionKey: function() {
    //…
  }
};

模块模式:

让我们通过创建一个自包含的模块来开始查看Module模式的实现。

var testModule = (function() {
  var counter = 0;
  return {
    incrementCounter: function() {
      return ++counter;
    },
    resetCounter: function() {
      counter = 0;
    }
  };
})();

// Usage:
testModule.incrementCounter();
testModule.resetCounter();

3.揭示模块模式

揭示模块可以做的一件事是当我们想要从另一个公共方法调用一个公共方法或访问公共变量时,避免重复主要项目的名称。

var myRevealingModule = (function() {
  var privateVariable = 'not okay',
    publicVariable = 'okay';
  function privateFun() {
    return privateVariable;
  }

  function publicSetName(strName) {
    privateVariable = strName;
  }

  function publicGetName() {
    privateFun();
  }

  return {
    setName: publicSetName,
    message: publicVariable,
    getName: publicGetName
  };
})();

//Usage:

myRevealingModule.setName('Marvin King');

4.单元素模式

因此,Singleton模式是已知的,因为它将类的实例化实例化为单个对象。
单例与静态类不同,因为我们可以延迟它们的初始化。
通常是因为它们需要一些在初始化期间可能无法获得的信息。
对于不知道先前对它们的引用的代码,它们不提供易于检索的方法。
让我们来看看单身人士的结构:

var singletonPattern = (function() {
  var instance;
  function init() {
    // Singleton
    function privateMethod() {
      console.log('privateMethod');
    }
    var privateVariable = 'this is private variable';
    var privateRandomNumber = Math.random();
    return {
      publicMethod: function() {
        console.log('publicMethod');
      },
      publicProperty: 'this is public property',
      getRandomNumber: function() {
        return privateRandomNumber;
      }
    };
  }

  return {
    // Get the singleton instance if one exists
    // or create if it doesn't
    getInstance: function() {
      if (!instance) {
        instance = init();
      }
      return instance;
    }
  };
})();

// Usage:
var single = singletonPattern.getInstance();

5.观察者模式

观察者是一种设计模式,其中对象根据观察者维护对象列表,自动通知他们状态的任何变化。

  • 学科
    • 维护一个观察者列表,设施添加或删除观察者
  • 观察
    • 为对象提供更新接口,需要通知对象的状态更改
  • ConcreteSubject
    • 向Observers广播关于状态变化的通知,存储ConcreteObservers的状态
  • ConcreteObserver
    • 存储对ConcreteSubject的引用,为观察者实现更新接口,以确保状态与主题一致
function ObserverList() {
  this.observerList = [];
}

ObserverList.prototype.Add = function(obj) {
  return this.observerList.push(obj);
};

ObserverList.prototype.Empty = function() {
  this.obsererList = [];
};

ObserverList.prototype.Count = function() {
  return this.observerList.length;
};

ObserverList.prototype.Get = function(index) {
  if (index > -1 && index < this.observerList.length) {
    return this.observerList[index];
  }
};

//...

当主体需要通知观察者有趣的事情时,它会向观察者广播通知(包括与通知主题相关的specofoc数据)

当我们不再希望特定的观察者通知其注册的主题的变化时,主体可以将其从观察者列表中删除。
将来,我将更多地讨论观察者如何在JavaScript中广泛使用的特性。

6.媒介模式

如果系统看起来系统之间有太多直接关系。
可能是时候有一个中心控制点,组件通过相反的方式进行通信。
中介模式通过确保代替组件明确地相互引用来促进松散耦合。

var mediator = (function() {
  var topics = {};
  var subscribe = function(topic, fn) {
    if (!topics[topic]) {
      topics[topic] = [];
    }
    topics[topic].push({ context: this, callback: fn });
    return this;
  };

  // publish/broadcast an event to the rest of the application
  var publicsh = function(topic) {
    var args;
    if (!topics[topic]) {
      return false;
    }
    args = Array.prototype.slice.call(arguments, 1);
    for (var i = 0, l = topics[topic].length; i < l; i++) {
      var subscription = topics[topic][i];
      subscription.callback.apply(subscription.content, args);
    }
    return this;
  };
  return {
    publish: publish,
    subscribe: subscribe,
    installTo: function(obj) {
      obj.subscribe = subscribe;
      obj.publish = publish;
    }
  };
})();

7.原型模式

使用Prototype模式的好处之一是我们已经使用了JavaScript本身提供的prototypa优势,而不是试图模仿其他语言的功能。
让我们看看模式示例。

var myCar = {
  name: 'bmw',
  drive: function() {
    console.log('I am driving!');
  },
  panic: function() {
    console.log('wait, how do you stop this thing?');
  }
};

//Usages:

var youcar = Object.create(Car);

console.log(yourcar.name); //'bmw'

8.工厂模式

Facotry ccan提供了用于创建对象的通用接口,我们可以在其中指定我们希望创建的工厂对象的类型。
见下图。

function Car(options) {
    this.doors=options.doors || 4;
    this.state=options.state || "brand new";
    this.color=options.color || "silver";
}

9. 混合模式

Mixins是提供功能的类,这些功能可以由子类或子类组轻松继承,以便重用函数。

var Person = function(firstName, lastName) {
  this.firstName = firstName;
  this.lastName = lastName;
  this.gender = 'male';
};

var clark = new Person('Clark', 'kent');

var Superhero = function(firstName, lastName, powers) {
  Person.call(this.firstName, this.lastName);
  this.powers = powers;
};

SuperHero.prototyp = Oject.create(Person.prototype);
var superman = new Superhero('Clark', 'Kent', ['flight', 'heat-vision']);

console.log(superman); //output personal attributes as well as power

在这种情况下,超级英雄能够使用特定于其对象的值来覆盖任何继承的值。

10.装饰者模式

装饰器是一种旨在促进代码重用的结构设计模式。
与Mixins类似,它们可以被认为是对象子类化的另一种可行替代方案。
传统上,装饰器提供了动态地将actviro添加到系统中现有类的能力。
这个想法是装饰自己并不是这个类的基本功能所必需的。
让我们来看看装饰器在JavaScript中是如何工作的

function MacBook() {
    this.cost=function() { return 997; }
    this.screenSize = function() { reutnr 11.6; }
}

// Decorator 1

function Memory( macbook ) {
    var v = macbook.cost();
    macbook.cost = function() {
      return v + 75;
    };
}

// Decorator 2

function Engraving( macbook ) {
    var v = macbook.cost();
    macbook.cost = function() {
        return v + 200;
    };
}

// Decorator 3

function Insturance( macbook ) {
    var v = macbook.cost();
    macbook.cost = function() {
        return v + 250;
    };
}

var mb = new MacBook();

Memory(mb);
Engraving(mb);
Insturance(mb);

mb.cost(); // 1522

所有模式都可能不会用于一个项目,一些项目可能会受益于Observer模式提供的解耦优势。
也就是说,一旦我们牢牢掌握了设计模式和最适合的具体问题。
因此,集成到我们的应用程序架构中变得更加容易。