每个开发人员都喜欢的十大 JavaScript 模式

2025-05-26

每个开发人员都喜欢的十大 JavaScript 模式

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');
Enter fullscreen mode Exit fullscreen mode

2. 模块模式

模块是任何健壮应用程序架构中不可或缺的一部分,通常有助于保持项目代码单元的清晰分离和组织。
实现模块有多种选项。这些包括:

  • 对象字面量表示法
  • 模块模式
  • AMD 模块
  • CommonJS 模块
  • ECMAScript Harmony 模块

对象文字:

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

模块模式:

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

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

// Usage:
testModule.incrementCounter();
testModule.resetCounter();
Enter fullscreen mode Exit fullscreen mode

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');
Enter fullscreen mode Exit fullscreen mode

4.单例模式

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

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();
Enter fullscreen mode Exit fullscreen mode

5.观察者模式

观察者是一种设计模式,其中一个对象维护依赖于它的观察者的对象列表,并自动通知它们状态的任何变化。

  • 主题
    • 维护观察员列表,设施添加或删除观察员
  • 观察者
    • 为需要通知主体状态变化的对象提供更新接口
  • 具体主题
    • 当状态发生变化时向观察者广播通知,并存储具体观察者的状态
  • 具体观察者
    • 存储对 ConcreteSubject 的引用,为观察者实现更新接口,以确保状态与主体一致
function ObserverList() {
  this.observerList = [];
}

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

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

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

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

//...
Enter fullscreen mode Exit fullscreen mode

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

当我们不再希望某个观察者收到其注册主体的变更通知时,主体可以将其从观察者列表中移除。未来,我将进一步探讨观察者这一特性如何在 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 publish = 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;
    }
  };
})();
Enter fullscreen mode Exit fullscreen mode

7.原型模式

使用原型模式的好处之一是,我们可以利用 JavaScript 原生提供的原型优势,而不是试图模仿其他语言的特性。让我们看一下模式示例。

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

//Usages:

var yourCar = Object.create(myCar);

console.log(yourCar.name); //'bmw'
Enter fullscreen mode Exit fullscreen mode

8.工厂模式

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

function Car(options) {
  this.doors = options.doors || 4;
  this.state = options.state || 'brand new';
  this.color = options.color || 'silver';
}
Enter fullscreen mode Exit fullscreen mode

9. Mixin 模式

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.prototype = Object.create(Person.prototype);
var superman = new Superhero('Clark', 'Kent', ['flight', 'heat-vision']);

console.log(superman); //output personal attributes as well as power
Enter fullscreen mode Exit fullscreen mode

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

10.装饰器模式

装饰器是一种结构化设计模式,旨在促进代码复用。与 Mixins 类似,它们可以被视为对象子类化的另一种可行替代方案。传统上,装饰器提供了动态地向系统中现有类添加行为的能力。其理念是,装饰器本身对于类的基本功能并非必不可少。让我们来看看装饰器在 JavaScript 中的工作原理。

function MacBook() {
  this.cost = function() {
    return 997;
  };
  this.screenSize = function() {
    return 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 Insurance(macbook) {
  var v = macbook.cost();
  macbook.cost = function() {
    return v + 250;
  };
}

var mb = new MacBook();

Memory(mb);
Engraving(mb);
Insurance(mb);

mb.cost(); // 1522
Enter fullscreen mode Exit fullscreen mode

所有模式不一定适用于一个项目,有些项目可能会受益于观察者模式提供的解耦优势。也就是说,一旦我们牢牢掌握了设计模式以及它们最适合解决的具体问题,那么将其集成到我们的应用程序架构中就会变得容易得多。

文章来源:https://dev.to/shijiezhou/top-10-javascript-patterns-every-developers-like-168p
PREV
Design Patterns in Web Development - #1 Command Introduction Command Pattern Code examples design-patterns
NEXT
每个开发者都喜欢的 10 大 Chrome 扩展程序 1.Octotree 2. Dark Reader 3. SourceGraph 4. Web Developer 5. ColorPick Eyedropper 6. Ghostery 7. Session Manager 8. JSONView 9. Page Ruler 10. Wappalyzer Refined GitHub