微信公众号

扫码关注官方订阅号

讲师中心
首页
文章
后端开发 web前端 数据库 开发工具 php框架 常见问题 科技 Java 系统教程 电脑教程 硬件教程 手机教程 软件教程 游戏教程 自媒体 新闻
专题
后端开发 web前端 数据库 开发工具 php框架 科技 Java 系统教程 电脑教程 硬件教程 手机教程 软件教程 游戏教程 新闻
AI工具
AI 聊天问答 Agent智能体 AI 文本写作 AI 绘画作图 AI 设计工具 AI 视频创作 AI 音频制作 AI 办公学习 AI 编程开发 Prompt指令
学习
大前端 后端开发 数据库 移动端 运维开发 计算机基础
编程手册
大前端 后端开发 数据库 移动端 运维开发 计算机基础
下载
js特效 网站源码 工具下载 类库下载 网站素材 学习资源 插件扩展 手机/移动开发 手机游戏
搜索
登录/注册
后端开发 web前端 数据库 开发工具 php框架 常见问题 科技 Java 系统教程 电脑教程 硬件教程 手机教程 软件教程 游戏教程
自媒体 新闻
首页 > web前端 > js教程 > 正文

关于js设计模式的超详细介绍

零到壹度
发布: 2018-04-13 17:42:06
原创
1402人浏览过


本篇文章给大家分享的内容是关于js设计模式的超详细介绍,有着一定的参考价值,有需要的朋友可以参考一下

js设计模式

Jan 14, 2017 | 学习笔记 | 3387 Hits


目录

  • 前言

  • 单体模式

  • 工厂模式

  • 迭代器模式

  • 装饰者模式

  • 策略模式

  • 外观模式

  • 代理模式

  • 中介者模式

  • 观察者模式

前言

本文参考于《javascript模式》,因此会大量内容会和书中相同,手上有这本书的朋友可以直接看书。因为我的记忆习惯是抄书,所以我会先抄写下来再发到博客上。

单体模式

单体模式思想在于保证一个特定类仅有一个实例,意味着当你第二次使用同一个类创建信对象时,应得到和第一次创建对象完全相同。

方法一

@@######@@ @@######@@


缺点

instance 属性暴露。

方法二

使用闭包

@@######@@ @@######@@


缺点

因为重写了构造函数,constructor 还是指向了老的构造函数,且实例化后在添加原型属性也是不一样的。如下

@@######@@ @@######@@


方法三

解决方法二问题。

@@######@@


@@######@@


方法四

自运行函数。

@@######@@ @@######@@


工厂模式

工厂模式是为了创建对象。

例子

  • 公共构造函数 CarMaker

  • 名为factory的CarMaker静态方法来创建car对象

@@######@@ @@######@@


实现

@@######@@


@@######@@@@######@@


内置工厂对象

Object() 构造函数即为内置工厂对象。

迭代器模式

有一个包含某种数据集合的对象,该数据可能存储在一个复杂数据结构内部,而要提供一个简单方法讷讷感访问到数据结构中没一个元素。

  • next() 下一个

    创客贴设计
    创客贴设计

    创客贴设计,一款智能在线设计工具,设计不求人,AI助你零基础完成专业设计!

    创客贴设计 51
    查看详情 创客贴设计
  • hasNext() 是否有下一个

  • reWind() 重置指针

  • current() 返回当前

@@######@@


@@######@@


装饰者模式

可以在运行时候添加附加功能到对象中,他的一个方便特征在于其预期行为的可定制和可配置特性。

例子 假设在开发一个销售商品的Web应用,每一笔信销售都是一个人新的 sale 对象。该对象“知道”有关项目的价格,并可以通过 getPrice() 方法返回加个。
根据不同情况,可以用额外的功能装饰此对象。
假设客户在魁北克省,买房需要支付联邦税和魁北克省税,则此时需要调用联邦税装饰者和魁北克省税装饰者。

@@######@@ @@######@@


并且装饰是可选的,例如不再魁北克省有可能没有省税。

方法一

@@######@@ @@######@@


方法二

此方法使用列表实现,而且相对来说比较好理解一点。本质就是把装饰者名称保存到一个列表中并且一次调用此列表中的方法。

@@######@@


@@######@@


策略模式

策略模式支持在运行时候选择算法。例如用在表单验证问题上,可以创建一个具有 validate() 方法的验证器对象,无论表单具体类型是什么,该方法都会被调用,
并且返回结果或者错误信息。

@@######@@


@@######@@


策略模式定义及例子实现参考与《javascript模式》及 汤姆大叔的博客

外观模式

外观模式即让多个方法一起被调用

例如。 stopPropagation() 和 preventDefault() 兼容性一起调用。

@@######@@


@@######@@


代理模式

在代理模式中,一个对象充当另外一个对象的接口,和外观模式区别是:外观模式是合并调用多个方法。
代理模式是介于对象的客户端和对象本身之间,并且对该对象的访问进行保护。

包裹例子

现在有个包裹,卖家要把这个包裹寄给gary,则需要通过快递公司寄过来,此时快递公司就是一个 proxy

@@######@@


@@######@@


论坛权限管理例子

本例子参考与 大熊君

  • 权限列表

    • 发帖 1

    • 帖子审核 2

    • 删帖 3

    • 留言、回复 4

用户 代码 权限
注册用户 001 1 4
论坛管理员 002 2 3 4
系统管理员 003 1 2 3 4
游客 000 null

用户类

@@######@@


@@######@@


论坛类

@@######@@


@@######@@


运行

@@######@@


@@######@@


中介者模式

中介者模式可以让多个对象之间松耦合,并降低维护成本

例如:游戏程序,两名玩家分别给与半分钟时间来竞争决出胜负(谁按键的次数多胜出,这里玩家1按1,玩家2按0)

  • 计分板(scoreboard)

  • 中介者 (mediator)

中介者知道所有其他对象的信息。他与输入设备(此时是键盘)进行通信并处理键盘上的按键时间,之后还将消息通知玩家。玩家玩游戏同时(每一分都更新自己分数)还要
通知中介者他所做的事情。中介者将更新后的分数传达给计分板。

除了中介者莫有对象知道其他对象。

图示

图示

@@######@@


@@######@@


观察者模式

观察者模式在 javascript 中使用非常广泛。所有的浏览器时间就是该模式的实现,node.js中的events也是此模式实现。
此模式另一个名称是 订阅/发布模式 。
设计这种模式原因是促进形成松散耦合,在这种模式中,并不是一个对象调用另一个对象的方法,而是一个对象订阅另一个对象的
特定活动并在状态改编后获得通知。订阅者因此也成为观察者,而被观察的对象成为发布者或者主题。当发生了一个重要事件时候
发布者会通知(调用)所有订阅者并且可能经常已事件对象的形式传递消息。

小结

1.单体模式

针对一个类仅创建一个对象。

2.工厂模式

根据字符串制定类型在运行时创建对象的方法。

3.迭代器模式

提供一个API来遍历或者操作复杂的自定义数据结构。

4.装饰者模式

通过从预定义装饰者对象中添加功能,从而在运行时侯调整对象

5.策略模式

在悬在最佳策略以处理特定任务的时候仍然保持相同的接口。

6.外观模式

通过把常用方法包装到一个新方法中,从来提供一个更为便利的API。

7.代理模式

通过包装一个对象从而控制对它的访问,其中主要方法是将方位聚集为租或者
仅当真正必要时侯才执行访问,从未避免高昂的操作开销。

8.终结者模式

通过是你的对象之间相互不直接“通话”,而是通过一个中介者对子昂进行通信,
从而形成松散耦合。

9.观察者模式

通过创建“可观察”的对象,当发生一个感兴趣的事件时可将改时间通告给所有观察者
从而形成松散耦合。

<br/>
登录后复制
function Universe(){
if(typeof Universe.instance==="object"){
return Universe.instance; //防止被篡改
}
this.xx="xx";
Universe.instance=this;
return this;
}
var uni=new Universe();
var uni2=new Universe();
uni===uni2; //true
登录后复制
<br/>
登录后复制
function Universe(){
var instance=this; //缓存this
this.xx="xx";
Universe=function(){ //重写此构造函数
return instance;
}
}
var uni=new Universe();
var uni2=new Universe();
uni===uni2; //true
登录后复制
<br/>
登录后复制
var uni = new Universe();
Universe.prototype.a = 1
var uni2 = new Universe();
console.log(uni === uni2) //true
console.log(uni.a) //undefinded
console.log(uni2.a) //undefinded
console.log(uni.constructor === Universe); //false
登录后复制
<br/>
登录后复制
function Universe(){
var instance;
Universe=function Universe(){
return instance ;
}
Universe.prototype=this; //保存原型属性
instance=new Universe();
instance.constructor=Universe;
instance.xx="xx";
}
登录后复制
<br/>
登录后复制
var Universe;
(function(){
var instance;
Universe=function Universe(){
if(instance){
return instance;
}
instance=this;
this.xx="xx";
}
})();
var uni = new Universe();
Universe.prototype.a = 1
var uni2 = new Universe();
console.log(uni === uni2) //true
console.log(uni.a)   //1
console.log(uni2.a)  //1
console.log(uni.constructor === Universe);  //true
登录后复制
<br/>
登录后复制
var corolla=CarMaker.factory('compact');
var solstice=CarMaker.factory('convertible');
var cherokee=CarMaker.factory('suv');
corolla.drive() //I have 4 doors
solstice.drive() //I have 2 doors
cherokee.drive() //I have 6 doors
登录后复制
<br/>
登录后复制
<br/>
登录后复制
function CarMaker() {}
CarMaker.prototype.drive = function() {
return "I have " + this.doors + " doors";
}
CarMaker.compact = function() {
this.doors = 4;
}
CarMaker.convertible = function() {
this.doors = 2
}
CarMaker.suv = function() {
this.doors = 6;
}
CarMaker.factory = function(type) {
if (typeof CarMaker[type] !== "function") {
throw "Error"
}
if (typeof CarMaker[type].prototype.drive !== "function") {
CarMaker[type].prototype = new CarMaker();
}
var newCar = new CarMaker[type]();
return newCar;
}
var corolla = CarMaker.factory('compact');
console.log(corolla.drive()); //I have 4 doors
登录后复制
<br/>
登录后复制
var agg = (function() {
var index = 0;
var data = [1, 2, 3, 4, 5, 6];
var length = data.length;
return {
next: function() { //这里是从第一个数据开始输出 本例中为 1
if (!this.hasNext()) {
return null;
}
var element = data[index];
index++;
return element;
},
hasNext: function() {
return index < length;
},
reWind: function() {
index = 0;
},
current: function() {
return data[index];
}
}
})();
while (agg.hasNext()) {
console.log(agg.next()); //1,2,3,4,5,6
}
agg.reWind();  //此时重置指针到0
登录后复制
<br/>
登录后复制
var sale=new Sale(100);
sale=sale.decorate("fedtax"); //联邦税
sale=sale.decorate("quebec"); //魁北克省税
sale=sale.decorate("miney"); //转为美元格式
sale.getPrice(); //返回价格
登录后复制
<br/>
登录后复制
function Sale(price) {
this.price = price;
}
Sale.prototype.getPrice = function() {
return this.price;
};
Sale.decorators = {}; //储存装饰者的对象
//装饰者
Sale.decorators.fedtax = {
getPrice: function() {
var price = this.uber.getPrice();
return price * 0.8; //对price进行处理
},
}
Sale.decorators.quebec = {
getPrice: function() {
var price = this.uber.getPrice();
return price * 0.7; //对price进行处理
},
}
Sale.decorators.money = {
getPrice: function() {
var price = this.uber.getPrice();
return "$" + price * 0.9; //对price进行处理
},
}
/*decorate() 方法
调用装饰者方法 sale.=sale.decorate("fedtax");
fedtax字符串对应 Sale.decorators中的对象属性。新装饰对象 newobj 将继承目前我们所拥有的对象,这就是ixiangthis
为了完成继承部分代码,此时需要一个临时构造函数,先设置 newobj 的 uber 属性,以便于自对象可以访问到父对象。之后从装饰者中
将所有的额外属性复制到新装饰的对象 newobj 中,最后返回 newobj。
*/
Sale.prototype.decorate = function(decorate) {
var F = function() {};
var overrides = this.constructor.decorators[decorate]; //获取装饰者对象
F.prototype = this;
var newobj = new F();
newobj.uber = F.prototype;
for (var key in overrides) {
if (overrides.hasOwnProperty) { //判断对象是不是自身的
newobj[key] = overrides[key];
}
}
return newobj;
};
var sale = new Sale(100);
sale = sale.decorate("fedtax"); //联邦税
sale = sale.decorate("quebec"); //魁北克省税
sale = sale.decorate("money"); //转为美元格式
console.log(sale.getPrice()); //$50.4
登录后复制
<br/>
登录后复制
function Sale(price) {
this.price = price;
this.decorateList = [];
}
Sale.decorators = {};
Sale.decorators.fedtax = {
getPrice: function(price) {
var price = this.uber.getPrice();
return price * 0.8; //对price进行处理
},
}
Sale.decorators.quebec = {
getPrice: function(price) {
var price = this.uber.getPrice();
return price * 0.7; //对price进行处理
},
}
Sale.decorators.money = {
getPrice: function(price) {
var price = this.uber.getPrice();
return "$" + price * 0.9; //对price进行处理
},
}
Sale.prototype.decorate = function(decorator) {
this.decorateList.push(decorator);
};
Sale.prototype.getPrice = function() {
var price = this.price;
this.decorateList.forEach(function(name) {
price = Sale.decorators[name].getPrice(price);
});
return price;
};
var sale = new Sale(100);
sale = sale.decorate("fedtax"); //联邦税
sale = sale.decorate("quebec"); //魁北克省税
sale = sale.decorate("money"); //转为美元格式
console.log(sale.getPrice()); //$50.4
登录后复制
<br/>
登录后复制
var validator = {
// 所有可以的验证规则处理类存放的地方,后面会单独定义
types: {},
// 验证类型所对应的错误消息
messages: [],
// 当然需要使用的验证类型
config: {},
// 暴露的公开验证方法
// 传入的参数是 key => value对
validate: function (data) {
var i, msg, type, checker, result_ok;
// 清空所有的错误信息
this.messages = [];
for (i in data) {
if (data.hasOwnProperty(i)) {
type = this.config[i];  // 根据key查询是否有存在的验证规则
checker = this.types[type]; // 获取验证规则的验证类
if (!type) {
continue; // 如果验证规则不存在,则不处理
}
if (!checker) { // 如果验证规则类不存在,抛出异常
throw {
name: "ValidationError",
message: "No handler to validate type " + type
};
}
result_ok = checker.validate(data[i]); // 使用查到到的单个验证类进行验证
if (!result_ok) {
msg = "Invalid value for *" + i + "*, " + checker.instructions;
this.messages.push(msg);
}
}
}
return this.hasErrors();
},
// helper
hasErrors: function () {
return this.messages.length !== 0;
}
};
//然后剩下的工作,就是定义types里存放的各种验证类了
// 验证给定的值是否不为空
validator.types.isNonEmpty = {
validate: function (value) {
return value !== "";
},
instructions: "传入的值不能为空"
};
// 验证给定的值是否是数字
validator.types.isNumber = {
validate: function (value) {
return !isNaN(value);
},
instructions: "传入的值只能是合法的数字,例如:1, 3.14 or 2010"
};
// 验证给定的值是否只是字母或数字
validator.types.isAlphaNum = {
validate: function (value) {
return !/[^a-z0-9]/i.test(value);
},
instructions: "传入的值只能保护字母和数字,不能包含特殊字符"
};
//使用的时候,我们首先要定义需要验证的数据集合,然后还需要定义每种数据需要验证的规则类型,代码如下:
var data = {
first_name: "Tom",
last_name: "Xu",
age: "unknown",
username: "TomXu"
};
validator.config = {
first_name: 'isNonEmpty',
age: 'isNumber',
username: 'isAlphaNum'
};
//最后获取验证结果 
validator.validate(data);
if (validator.hasErrors()) {
console.log(validator.messages.join("\n"));
}
登录后复制
<br/>
登录后复制
var myEvent = {
stop: function(e) {
if (typeof e.preventDefault() === "function") {
e.preventDefault();
}
if (typeof e.stopPropagation() === "function") {
e.stopPropagation();
}
//for IE
if (typeof e.returnValue === "boolean") {
e.returnValue = false;
}
if (typeof e.cancelBubble === "boolean") {
e.cancelBubble = true;
}
}
}
登录后复制
<br/>
登录后复制
var package = function(receiver) {
this.receiver = receiver;
}
var seller = function(package) {
this.package = package;
this.send = function(gift) {
return package.receiver + "你的包裹:" + gift;
}
}
var express = function(package) {
this.package = package;
this.send = function(packageName) {
return new seller(package).send(packageName);
}
}
//调用
var ems = new express(new package("gary"));
console.log(ems.send("键盘")); //gary你的包裹:键盘
登录后复制
<br/>
登录后复制
function User(name, code) {
this.name = name;
this.code = code;
}
User.prototype.getName = function() {
return this.name;
};
User.prototype.getCode = function() {
return this.code;
};
User.prototype.post = function() {
//发帖功能
};
User.prototype.remove = function() {
// 删帖功能
};
User.prototype.check = function() {
//审核
};
User.prototype.comment = function() {
//留言回复
};
登录后复制
<br/>
登录后复制
function Forum(user) {
this.user=user;
}
Forum.prototype.getUser = function () {
return this.user;
};
Forum.prototype.post = function () {
var code=this.user.getCode();
if(code=="001"||code=="003"){
return this.user.post();
}else{
return false;
}
};
Forum.prototype.remove = function () {
var code=this.user.getCode();
if(code=="002"||code=="003"){
return this.user.remove();
}else{
return false;
}
};
Forum.prototype.check = function () {
var code=this.user.getCode();
if(code=="002"||code=="003"){
return this.user.check();
}else{
return false;
}
};
Forum.prototype.comment = function () {
var code=this.user.getCode();
if(code=="001"||code=="002"||code=="003"){
return this.user.comment();
}else{
return false;
}
};
登录后复制
<br/>
登录后复制
new Forum(new User("administartor","003"));
登录后复制
<br/>
登录后复制
function Player(name) {
this.points = 0;
this.name = name;
}
Player.prototype.play = function() {
this.points += 1;
mediator.played();
};
var scoreboard = {
element: "这里是获取的element用于展示分数",
update: function(score) { //更新分数
var msg;
for (var key in score) {
if (score.hasOwnProperty(key)) {
msg += score[key];
}
}
this.element.innerText = msg;
},
}
var mediator = {
players: {}, //玩家对象
setup: function() {
var players = this.players;
players.home = new Player("home");
players.guest = new Player('guest');
},
played: function() {
var players = this.players;
var score = {
home: players.home.points,
guest: players.guest.points
}
},
keypress: function(e) {
e = e || window.event;
if (e.which === 49) { //or keycode   对应按键 1
mediator.players.home.play();
return;
}
if (e.which === 48) { // 对应按键 0
mediator.player.guest.play();
return;
}
},
}
//运行
mediator.setup();
window.onkeypress = mediator.keypress;
setTimeout(function() { //设置30秒游戏时间
window.onkeypress = null;
alert("game end");
}, 30000);
登录后复制

以上就是关于js设计模式的超详细介绍的详细内容,更多请关注php中文网其它相关文章!

相关标签:
javascript

大家都在看:

优化数组循环:PHP/JavaScript中for循环的最佳实践 JavaScript函数中循环累加的陷阱:理解return语句的作用 解决JavaScript函数中循环过早返回的问题 掌握JavaScript函数中循环与return语句的正确用法 PHP与JavaScript数组循环中的性能与可读性优化实践
最佳 Windows 性能的顶级免费优化软件
最佳 Windows 性能的顶级免费优化软件

每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。

下载
来源:php中文网
收藏 点赞
上一篇:JS怎么判断客户端类型 下一篇:一些关于js的实用小算法
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
作者最新文章
  • 跟我学PS第八天02:光效素材的抠图方法
    2018-08-28 15:02:42
  • 跟我学PS第八天01:如何抠取文件中的印章
    2018-08-25 10:55:46
  • 跟我学PS第七天02:如何抠出复杂树林
    2018-08-20 16:25:41
  • 跟我学PS第七天01:如何将彩图抠出线稿效果
    2018-08-18 11:26:54
  • 跟我学PS第六天02:模糊工具
    2018-08-14 16:35:58
  • 跟我学PS第六天01:修复画笔工具
    2018-07-28 15:36:43
  • 跟我学PS第五天02:移动工具的使用方法和应用
    2018-07-27 16:59:00
  • 跟我学PS第五天01:使用裁剪工具
    2018-07-27 15:22:47
  • 跟我学PS第四天02:练习Photoshop中的套索工具
    2018-07-23 17:56:00
  • 跟我学PS第四天01:如何给照片加边框效果
    2018-07-23 16:21:38
最新问题
js脚本如何制作元素点击放大效果_js点击放大动画脚本编写方法 答案是通过JavaScript监听点击事件并切换CSS类实现元素放大。首先创建HTML元素,使用CSS设置基础样式及transform过渡动画,再通过JavaScript为元素添加click事件监听,点击时通过classList.toggle切换应用scale放大的zoomed类,从而实现平滑放大效果,结合transition确保动画流畅,同时可扩展点击外部关闭、遮罩层等功能,保持行为与样式的分离以提升维护性。
2025-11-10 02:31:29
672
React应用中外部环境变量的配置与使用指南 本文详细阐述了如何在React应用中配置和使用环境变量,特别是针对create-react-app项目的标准实践。我们将探讨环境变量的命名约定、在.env文件中定义变量的方法、以及如何在React组件中通过process.env访问它们。此外,文章还将针对.env文件位于项目外部(如config文件夹)的特殊场景,提供实用的解决方案和注意事项,确保开发者能够灵活高效地管理应用配置。
2025-11-09 23:41:18
478
GrapesJS中自定义Ctrl+S保存命令:阻止浏览器默认保存对话框弹出 本文旨在解决GrapesJS开发中,当用户通过Ctrl+S(或Cmd+S)触发自定义保存命令时,浏览器默认“页面另存为”对话框意外弹出的问题。我们将深入探讨为何常见的event.preventDefault()在此场景下失效,并提供两种有效的解决方案:一种是深入事件对象访问原始浏览器事件以实现精细控制,另一种是利用GrapesJS按键映射的prevent选项进行简洁配置,确保您的自定义保存逻辑能无干扰地执行。
2025-11-09 23:40:01
410
用js写一个四舍五入的函数 使用Math.round()结合乘除法可实现指定小数位的四舍五入,如round(3.14159,2)返回3.14;注意浮点数精度问题但常规场景可靠。
2025-11-09 23:31:02
967
JS字符串处理怎么操作_JS字符串常用方法与处理技巧教程 JavaScript字符串处理常用方法包括:length获取长度,charAt、indexOf、includes进行字符和子串查询,slice、split实现截取与分割,replace、replaceAll完成替换操作,配合正则可全局替换,toLowerCase、toUpperCase转换大小写,trim去除空白,模板字符串方便拼接。熟练组合这些方法可高效应对数据清洗、格式化等任务,注意replace默认仅替换一次,需加g标志实现全局替换。
2025-11-09 23:29:02
728
如何阻止GrapesJS中保存命令触发浏览器默认保存对话框 本文旨在解决在GrapesJS等Web编辑器中,使用Ctrl+S等快捷键执行自定义保存命令时,浏览器默认保存对话框意外弹出的问题。我们将探讨两种有效的解决方案:一种是通过深入访问事件对象来调用preventDefault(),提供精细控制;另一种是利用GrapesJSKeymaps的prevent选项进行更简洁的配置,帮助开发者实现无缝的用户体验。
2025-11-09 23:28:01
352
GrapesJS中自定义保存命令如何禁用浏览器默认保存行为 本文详细介绍了在GrapesJS编辑器中,当用户使用Ctrl+S等快捷键触发自定义保存命令时,如何有效阻止浏览器默认的页面保存对话框弹出。我们将探讨两种主要方法:一是通过深入访问事件对象来调用preventDefault(),以实现更精细的控制;二是利用GrapesJSkeymaps.add方法提供的prevent选项,实现简洁高效的默认行为禁用。掌握这些技巧,能够确保您的GrapesJS应用提供无缝的用户体验,避免不必要的浏览器干扰。
2025-11-09 23:21:01
281
JavaScript 闭包:理解闭包原理与内存泄漏问题 闭包是函数访问其外部作用域变量的能力,即使外部函数已执行完毕。如inner函数引用outer中的count,形成闭包,使变量持久存在。闭包本身无害,但可能因延长变量生命周期导致内存泄漏,例如事件监听器引用大对象时。若未及时清理DOM事件或定时器,闭包会阻止垃圾回收,造成内存占用过高。解决方法包括:避免闭包中长期持有大对象、移除事件监听器、清除定时器、不将闭包暴露到全局。通过显式调用removeEventListener并置引用为null,可确保对象被正确回收。掌握闭包原理有助于编写高效安全的代码
2025-11-09 23:21:02
336
如何使用Webpack 5生成压缩与未压缩的静态资源 本教程详细介绍了如何使用Webpack5配置项目,以同时生成JavaScript和CSS的压缩(.min)和未压缩版本。文章将重点讲解如何利用TerserPlugin和CssMinimizerPlugin进行选择性优化,并通过MiniCssExtractPlugin正确处理CSS文件的提取与命名冲突,并提供完整的配置示例及常见问题解决方案。
2025-11-09 23:16:01
729
防止 GrapesJS 自定义快捷键触发浏览器默认保存弹窗 本文旨在解决GrapesJS中自定义Ctrl+S快捷键时,浏览器默认保存弹窗依然弹出的问题。文章详细介绍了两种解决方案:一是通过访问GrapesJS封装的事件对象中的原始DOM事件来调用preventDefault(),实现更精细的控制;二是在keymaps.add方法中直接设置prevent:true选项,以更简洁的方式阻止默认行为。
2025-11-09 23:07:01
194
相关专题
更多>
  • python除法运算符
  • python 平方
  • python 怎么安装库
  • python中不等于怎么写
  • python输入根号教程
  • 学python所需软件推荐
  • python 一个列表 相关教程大全
  • python内置函数大全
热门推荐
  • 在Rails应用中高效安全地将数据库数据传递给JavaScript
  • JavaScript碰撞检测算法
  • 全栈项目怎么优化加载速度_全栈JavaScript项目性能优化与加载提速方法
  • JavaScript中HTML内容字符精确统计:兼顾换行符的实现策略
  • 前端埋点与数据上报的JavaScript实现_js数据分析
开源免费商场系统广告
热门教程
更多>
相关推荐
热门推荐
最新课程
  • JavaScript
    JavaScript
    78205次学习
    收藏
  • JavaScript教程
    JavaScript教程
    119437次学习
    收藏
  • JavaScript 参考手册
    JavaScript 参考手册
    290492次学习
    收藏
  • JavaScript ES5基础线上课程教学
    JavaScript ES5基础线上课程教学
    64937次学习
    收藏
  • 最新ThinkPHP 5.1全球首发视频教程(60天成就PHP大牛线上培训班课)
    最新ThinkPHP 5.1全球首发视频教程(60天成就PHP大牛线上培训班课)
    1484960次学习
    收藏
  • phpStudy极速入门视频教程
    phpStudy极速入门视频教程
    529754次学习
    收藏
  • 独孤九贱(4)_PHP视频教程
    独孤九贱(4)_PHP视频教程
    1249519次学习
    收藏
  • PHP实战天龙八部之仿爱奇艺电影网站
    PHP实战天龙八部之仿爱奇艺电影网站
    769630次学习
    收藏
  • 最新Python教程 从入门到精通
    最新Python教程 从入门到精通
    2726次学习
    收藏
  • JavaScript ES5基础线上课程教学
    JavaScript ES5基础线上课程教学
    64937次学习
    收藏
  • PHP新手语法线上课程教学
    PHP新手语法线上课程教学
    6428次学习
    收藏
  • 支付宝沙箱支付(个人也能用的支付)
    支付宝沙箱支付(个人也能用的支付)
    4508次学习
    收藏
  • 麻省理工大佬Python课程
    麻省理工大佬Python课程
    41271次学习
    收藏
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
  • [表单按钮] jQuery企业留言表单联系代码
  • [播放器特效] HTML5 MP3音乐盒播放特效
  • [菜单导航] HTML5炫酷粒子动画导航菜单特效
  • [表单按钮] jQuery可视化表单拖拽编辑代码
  • [播放器特效] VUE.JS仿酷狗音乐播放器代码
  • [html5特效] 经典html5推箱子小游戏
  • [图片特效] jQuery滚动添加或减少图片特效
  • [相册特效] CSS3个人相册封面悬停放大特效
  • [电商源码] MLM营销系统
  • [企业站源码] 六七企业网站管理系统(67CMS)2.0
  • [电商源码] 若冰企业商务平台.net
  • [企业站源码] 08cms企业建站系统 1.0 正式版
  • [电商源码] 带有QQ、MSN、贸易通功能的网站浮动
  • [企业站源码] 缤纷企业管理系统
  • [电商源码] ShopNC网上商店单用户版
  • [企业站源码] 新秀企业网站系统PHP版1.1 beta6
  • [网站素材] 手绘咖啡器具插图矢量素材
  • [网站素材] 绿色农场主题宣传海报源文件设计下载
  • [网站素材] 彩色海洋珊瑚礁合集矢量素材
  • [网站素材] 极简风格宠物店商务名片设计下载
  • [网站素材] 太空科幻主题童书插画矢量素材
  • [网站素材] 绿色弥散风格黑色星期五促销INS模板下载
  • [网站素材] 清新简约学习主题矢量素材
  • [网站素材] 创意写作比赛宣传卡片设计下载
  • [前端模板] 驾照考试驾校HTML5网站模板
  • [前端模板] 驾照培训服务机构宣传网站模板
  • [前端模板] HTML5房地产公司宣传网站模板
  • [前端模板] 新鲜有机肉类宣传网站模板
  • [前端模板] 响应式天气预报宣传网站模板
  • [前端模板] 房屋建筑维修公司网站CSS模板
  • [前端模板] 响应式志愿者服务网站模板
  • [前端模板] 创意T恤打印店网站HTML5模板
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新 English
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号

微信扫码
关注PHP中文网服务号

技术交流群

QQ扫码
加入技术交流群

PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号

  • PHP学习

  • 技术支持

  • 返回顶部