代码要写成别人看不懂的样子(二十四)

【C++】I/O流文件字符串读写 文章目录一、operator bool二、C++中的文件读写1. fstream头文件1. ofstream如何写?2. ifstream如果是读取,同理3. 文本读写4. 读取自定义类型三、C++中的字符串读写1. sstream头文件2. ostringstream3. istringstream 一、operator bool while()里面可以是指针,也可以是整型 这里面用了一个operator bool的类型 #include <iostream> using namespace 阅读详情

本篇文章参考书籍《JavaScript设计模式》–张容铭

前言

  上一节的同步模块应用范围多在服务端,那对于客户端的架构模式,我们通常选择异部模块模式,因为浏览器环境不同于服务器环境,在浏览器中对文件的加载时异步的。因此要使用未加载文件中某些模块方法时必然经历文件加载过程。

  对未加载文件中的模块引用,同步模块模式是无能为力的,为了解决这个问题,我们一起研究下今天的课题。

异步模块模式

  模块化:将复杂的系统分解成高内聚、低耦合的模块,使系统开发变得可控,可维护,可扩展,提高模块的复用率。

  异步模块模式—AMD:请求发出后,继续其他业务逻辑,直到模块加载完成,再执行后续的逻辑,实现模块开发中对模块加载完成后的引用。

  大家一开始可能有个问题,我们上一节写的同步模块,如果使用到了还没加载的模块,那就加载一下不行嘛?比如下面:

//加载脚本文件
var loadScript = function(src) {
	var _script = document.createElement('script');  //创建脚本元素
	_script.type = 'text/JavaScript';                //设置类型
	_script.src = src;                               //设置加载路径
	document.getElementByTagName('head')[0].appendChild(_script);
	//将元素插入到页面中
}
//加载 localstorage 文件
loadScript('localstorage.js');
//使用 localstorage 模块
F.module('localstorage', function(ls) {
	// do something
});

  上面代码即使加载了文件也获取不到,问题出在了 localstorage 上面。应为浏览器的文件是异步加载的,虽然一开始加载 localstorage.js 文件,不过在文件没有加载完之前,还是可以继续做其他事情的,并且上面代码对于文件什么时候加载完成无法获取,而同步模块模式会立即调用该模块,此时文件尚未加载完成,才最终导致加载不到。

  所以我们需要一种新的模式,异步模块模式。

  一部模块模式的创建和调用都通过一个方法,如创建 Event 模块,但要涉及 DOM ,使用的时候可以如下:

F.module('lib/event', ['lib/dom'], function(dom) {})

  需要注意的是,第一个参数( lib/event )是模块 id ,一定要对应文件路径,这样实现起来会成本更小。

  具体实现需要闭包环境,如下:

//向闭包中传入模块管理器对象 F (~屏蔽压缩文件时,前面漏写;报错)
~(fucntion(F) {
	//模块缓存器。储存已创建模块
	
}) ((function() {
	//创建模块管理器 F ,并保存在全局作用域中
	return window.F = {};
}) ());

  有了安全的闭包环境,下面要做的就是为模块管理器对象提供一个 module 方法。这个 module 方法集模块创建方法于一身,在这个方法中要遍历所有依赖模块,并判断所有模块都存在才可执行回调函数,否则加载相应文件,直到文件加载完成才执行回调。

/**
* 创建或调用模块方法
* @param    url       模块 url
* @param    deps      依赖模块
* @param    callback  模块主函数
*/
F.module = function(url, modDeps, modCallback) {
		//将参数转化为数组
	var args = [].splice.call(arguments),
		//获取模块构造函数(参数数组中最后一个参数成员)
		callback = args.pop(),
		//获取依赖模块(紧邻回调函数参数,且数据类型为数组)
		dep = (args.length && args[args.length - 1] instanceof Array) ? args.pop() : [],
		//该模块 url (模块ID)
		url = args.length ? args.pop() : null,
		//依赖模块序列
		params = [],
		//未加载的依赖模块数量
		depsCount = 0,
		//依赖模块序列中索引值
		i = 0,
		//依赖模块序列长度
		len;
	//获取依赖模块长度
	if(len = deps.length) {
		//遍历依赖模块
		while(i < len) {
			//闭包保存i
			(function(i) {
				//增加未加载依赖模块数量统计
				depsCount++;
				//异步加载依赖模块
				loadModule(deps[i], function(mod) {
					//依赖模块序列中添加依赖模块接口引用
					params[i] = mod;
					//依赖模块加载完成,依赖模块数量统计减一
					depsCount--;
					//如果依赖模块全部加载
					if(depsCount === 0) {
						//在模块缓存器中矫正该模块,并执行构造函数
						setModule(url, params, callback);
					}
				});
			})(i);
			//遍历下一依赖模块
			i++
		}
	//无依赖模块
	} else {
		//在模块缓存器中矫正该模块,并执行构造函数
		setModule(url, [], callback);
	}
}

  在 module 方法中有两个方法我们还没定义, loadModule 方法与 setModule 方法。接下来先实现 loadModule 方法, loadModule 方法目的是加载依赖模块对应的文件并执行回调函数。

  我们需要分为三种情况:

  ①如果文件已经被要求加载过,需要区分已经加载完成还是正在加载,如果是加载完成,异步执行该模块的加载完成回调函数(详见 F.module 方法中对 loadModule 方法调用部分)。

  ②如果文件未加载完成,我们需要将加载完成回调函数缓存入模块加载完成回调函数容器中(该模块的 onload 数组容器)。

  ③如果依赖模块对应的文件未被要求加载过,那么我们要加载该文件,并将该依赖模块的初始化信息写入模块缓存器中。

var moduleCache = {},
	setModule = function(moduleName, params, callback) {},
	/**
	* 异步加载依赖模块所在文件
	* @param    moduleName     模块路径(id)
	* @param    callback       模块加载完成回调函数
	*/
	loadModule = function(moduleName, callback) {
		//依赖模块
		var _module;
		//如果依赖模块被要求加载过
		if(moduleCache[moduleName]) {
			//获取该模块信息
			_module = moduleCache[moduleName];
			//如果模块加载完成
			if(_moudle.status === 'loaded') {
				//执行模块加载完成回调函数
				setTimeout(callback(_module.exports), 0);
			} else {
				//缓存该模块所处文件加载完成回调函数
				_module.onload.push(callback);
			}
		//模块第一次被依赖引用
		} else {
			//缓存该模块初始化信息
			moduleCache[moduleName] = {
				moduleName: moduleName,  //模块ID
				status: 'loading',       //模块对应文件加载状态(默认加载中)
				exports: null,           //模块接口
				onload: [callback]       //模块对应文件加载完成回调函数缓冲器
			};
			//加载模块对应文件
			loadScript(getUrl(moduleName));
		}
	},
	getUrl = function() {},
	loadScrript = function() {};

  上面的思路是执行模块对应文件加载完成回调函数是为了使 module 修改内部的依赖模块统计变量 depsCount ,直到所有依赖模块全部加载后顺利执行 setModule 。加载模块对应的文件时需要引用 loadScript 加载脚本方法与 getUrl 获取文件路径方法,接下来是实现这两个方法。

//获取文件路径
getUrl = function(src) {
	//拼接完整的文件路径字符串,如'lib/ajax' => 'lib/ajax.js'
	return String(moduleName).replace(/\.js$/g, '') + '.js';
},
//加载脚本文件
loadScript = function(src) {
	//创建 script 元素
	var _script = document.createElement('script');
	_script.type = 'text/JavaScript'; //文件类型
	_script.charset = 'UTF-8';        //确认编码
	_script.async = true;             //异步加载
	_script.src = src;                //文件路径
	document.getElementsByTagName('head')[0].appendChild(_script); //插入页面中
};

  之前说将模块 id 和 文件的路径对应,这样的对应关系可以让我们加载该模块对应的文件更简单。有时同页面一起加载的模块不会被其他模块引用,对于这些匿名模块我们有时候也不用添加模块 id 。

  接下来,实现最后一个核心方法, setModule 方法。这个方法实现很简单,却很巧妙。表面上看,该方法是执行模块回调函数,但实质上,它做了三件事:

  ①对创建模块来说,当我的所有依赖模块加载完成时,需要使用该方法。

  ②对于被依赖的模块来说,其所在的文件加载后要执行该依赖模块(即创建该模块过程)又间接的使用该方法。

  ③对于一个匿名模块来说( F.module 方法中无 url 参数数据),执行过程中也会使用该方法。

/**
* 设置模块并执行模块构造函数
* @param    moduleName     模块 id 名称
* @param    params         依赖模块
* @param    callback       模块构造函数
*/
setModule = function(moduleName, params, callback) {
	//模块容器,模块文件加载完成回调函数
	var _module, fn;
	//如果模块被调用过
	if(moduleCache[moduleName]) {
		//获取模块
		_module = moduleCache[moduleName];
		//设置模块已经加载完成
		_module.status = 'loaded';
		//矫正模块接口
		_module.exports = callback ? callback.apply(_module, params) : null;
		//执行模块文件加载完成回调函数
		while(fn = module.onload.shift()) {
			fn(_module.exports);
		}
	} else {
		//模块不存在(匿名模块),则直接执行构造函数
		callback && callback.apply(null, params);
	}
}

  喘口气哈~

  到这里我们一部模块管理器就完成了,接下来体验一下一部模块开发的乐趣吧。

  首先我们在 lib/dom.js 中定义 dom 模块。对于 dom 模块来说,它不依赖任何模块。

F.module('lib/dom', function() {
	return {
		//获取元素方法
		g: function() {
			return document.getElementById(id);
		},
		//获取或者设置元素内容方法
		html: fucntion(id, html) {
			if(html) {
				this.g(id).innerHTML = html;
			} else {
				return this.g(id).innerHTML;
			}
		}
	}
});

  接下来我们定义一个 event 模块,保存在 lib/event.js 文件中,不过由于为元素绑定事件要通过 id 获取元素,因此要引用 dom 模块。

F.module('lib/event', ['lib/dom'], function(dom) {
	var events = {
		//绑定事件
		on: function(id, type, fn) {
			dom.g(id)['on' + type] = fn;
		}
	}
	return events;
});

  最后我们在页面中引用 dom 模块与 event 模块,为页面中的 button 绑定事件,添加交互。

//index.html 页面中
F,module(['lib/event', 'lib/dom'], function(events, dom) {
	events.on('demo', 'click', function() {
		dom.html('demo', 'success');
	})
});

总个小结

  模块开发不仅解决了系统的复杂性问题,而且减少了多人开发中变量、方法名被覆盖的问题。通过其强大的命名空间管理,使模块的结构更合理。

  通过对模块的引用,提高了模块代码复用率。异部模块在此基础上增加了模块依赖,使开发者不必担心某些方法尚未加载或未加载完全造成的无法使用问题。异步加载部分功能也可将更多首屏不必要的功能剥离出去,减少首屏加载成本。




第二十四节 连接到OneNET 连接到OneNET 阅读详情

相关推荐

PCL代码:PCD点云文件读取(测试环境配置成功)

/******************************************************************** 创建日期: 2020/10/09 创建时间: 20:11 文件名字: C:\Users\17806\Desktop\pcl教程\3.1\3.1\3.1.cpp -------------------------------------- 文件功能: 读取PCD格式的文件 ----------------

kangjielearning的博客 1422

C++的IO流(文件读写流,字符串流)

一、简介 C++中的IO操作被包装成类,它们的继承关系如下。 二、C++文件IO C++的文件IO依赖<fstream>库,包含三个类:ifstream(从文件中读)、ofstream(向文件中写)、fstream(对文件读写)。 我们只讲fstream的使用,另外两种相比而言知识功能受限,操作方法相同。 1.创建文件流对象,有两种方式。 a. fstream iofile(char *filename,mode=default,filetype=default);//default表示参数使用

qq_38656988的博客 2118

Arduino 入门学习笔记(二十四):SPI_SDCARD 实验

Arduino SPI_SDCARD实验,开发板:正点原子ESP32S3,SD卡,记录学习过程。

分享技术笔记,希望对大家能够有一定的帮助,同时也通过归纳总结提升自己的个人能力。 1543

python 格式文件 读取off_.off转.ply(python)

1. 读取.off为Nx3 点云和Mx3网格面def read_off(filename):points = []faces = []with open(filename, 'r') as f:first = f.readline()if (len(first) > 4): # Too handle error in .off like OFF492 312 0n, m, c = firs...

weixin_39907591的博客 1355

off 文件数据读取

用 matlab 读取off 文件数据。文件包含一个简单的off文件和m文件。运行m文件可以读取任意off文件格式,提取三维模型的点与面数据。

ATE测试的未来:自动化与智能化的技术演进

本文探讨了自动测试设备(ATE)在半导体产业中的技术演进,重点关注自动化与智能化的发展趋势。随着芯片制程的不断进步,ATE面临测试复杂度激增和成本压力等挑战。文章分析了AI技术在测试优化中的应用,如自适应测试和缺陷预测,以及模块化架构和端到端测试生态系统的创新。这些技术突破显著提升了测试效率和设备利用率,为半导体测试的未来发展指明了方向。

weixin_29232507的博客 614

python调用图片应该存到哪里_Python读取和保存图像

在图像处理中,我们经常使用cv2和PIL来处理图像,但其实python中有很多方法都可以,现在总结一些关于python处理图像的常用库,当然其读取出来图片的类型也各不相同,另外,其读取的格式也可能不同,有的是RGB,有的是BGR,要注意区分。PIL(Python Imaging Library,常配合matplotlib使用)安装方式:pip install Pillow示例代码:import n...

weixin_39754616的博客 1347

Android开发者必看:F2FS文件系统如何优化你的手机存储性能(附实测数据对比)

本文深入解析了F2FS文件系统如何针对闪存特性优化Android设备存储性能。通过对比ext4,F2FS采用追加写和冷热数据分离策略,将随机写转化为顺序写,显著提升写入速度并减少GC卡顿。实测数据显示,其在随机写入和SQLite事务等场景下性能提升显著,为开发者提供了优化应用IO性能的关键思路。

weixin_29248313的博客 325

Kotlin研发第二十四弹—— 动态类型

动态类型 动态类型 动态类型 作为静态类型的语言,kotlin仍然拥有与无类型或弱类型语言的调用,比如JavaScript。为了方便使用,Dynamic应运而生 val dyn:dynamix= dynamic类型关闭了kotlin的类型检查: 这样的类型可以分配任意变量或者在任意的地方作为参数传递 任何值都可以分配为dynamic类型,或者作为参数传递给任何接受dynamic类型参数的函...

u010785186的专栏 814

ArcGIS高效拆分shp文件:无需依赖属性表的实用技巧

本文针对ArcGIS中shp文件因属性表缺失而难以拆分的问题,详细介绍了无需依赖属性表的实用技巧。核心是使用“拆分多部件要素”工具,直接根据图形结构将多个独立但被合并的部件拆分为单个要素,并提供了ArcGIS Pro和ArcMap的操作流程、关键注意事项及拆分后的属性处理方案。

n2o3p4的博客 376

Claude Code启动失败解决方案,执行文件不兼容一键修复

Claude Code命令行工具突然报错,显示"不支持的16位应用程序"。作者排查Node版本无果后,发现是Anthropic更新导致Windows兼容性问题。解决方法很简单:卸载旧版、切换npm镜像源、重装最新版即可恢复。经验教训:遇到类似问题应先搜索社区反馈,避免无谓排查,同时注意npm源使用后及时还原。整个踩坑过程虽折腾,但最终只是简单的重装问题。

1453

OpenCV探索之路(二十四)图像拼接和图像融合技术

图像拼接在实际的应用场景很广,比如无人机航拍,遥感图像等等,图像拼接是进一步做图像理解基础步骤,拼接效果的好坏直接影响接下来的工作,所以一个好的图像拼接算法非常重要。 再举一个身边的例子吧,你用你的手机对某一场景拍照,但是你没有办法一次将所有你要拍的景物全部拍下来,所以你对该场景从左往右依次拍了好几张图,来把你要拍的所有景物记录下来。那么我们能不能把这些图像拼接成一个大图呢?我们利用opencv

lla520的博客 1万+

AWS RDS 介绍 三)创建 RDS 实例

AWS RDS 介绍 共分为 7 个部分, 其中 第 3部分重点介绍,如何创建一个RDS 实例。 三) AWS RDS 试用MySQL http://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/CHAP_GettingStarted.CreatingConnecting.MySQL.

XuYongshi02的专栏 7645

Flutter(二十四)——参数回传

本文目录前言主页面跳转界面 前言 上一篇通过静态路由以及动态路由了解了,在Flutter开发中界面的跳转,但在实际的项目中,并不仅仅只有跳转这么一种需求,还有回传参数。(下图为本文实现最终效果图) 比如在某些悬浮窗口中选择城市,然后返回地址等等,都具有回传参数的需求,那么在Flutter开发中,要怎么实现这么一种需求呢?不妨我们来做一个城市参数回传的例子。 主页面 首先,就是我们App的主页面设...

李元静 1万+

告别重打包:在Android 9上实现免Root的Frida-Gadget持久化Hook(附AOSP源码修改详解)

本文详细介绍了在Android 9上实现免Root的Frida-Gadget持久化Hook技术方案。通过修改AOSP源码,绕过传统重打包方式面临的签名校验和完整性检查,实现在非Root环境下的系统级Hook。文章包含核心代码修改、编译配置调整及调试技巧,为移动安全研究提供高效稳定的解决方案。

weixin_33726313的博客 501

仿真学习系列(四十三):Sigrity仿真之平面谐振分析

在 SIGRITY 中,平面谐振分析(Plane Resonance Analysis)是一种用于分析信号完整性(SI)问题的高级仿真方法,尤其关注于层间电磁波的传播、谐振现象和信号衰减等问题。平面谐振分析通常用于电源分配网络(PDN)、信号线和参考平面之间的相互作用。本文将详细介绍如何在 SIGRITY 中进行平面谐振分析,并提供一些实用的分析方法与步骤,帮助工程师们识别和优化可能存在的设计问题。

案例文章,高速信号 478

我们在业余时间做了一款优雅的节气小组件 App,希望它能成为你桌面上的一抹东方诗意

「二十四节气」是一款由热爱东方文化的小团队开发的iOS应用,旨在让用户感知自然的时令节奏。不同于商业化工具,这款App以克制、安静的设计风格呈现节气之美,提供当前节气展示、详细解说、桌面小组件等功能,支持离线使用和无广告打扰。设计融合Apple指南与东方美学,采用素雅配色与响应式布局。技术实现上运用SwiftUI和WidgetKit,确保轻盈流畅的体验。团队希望这款App成为数字生活中的诗意存在,后续计划拓展更多平台版本和内容。现已上架App Store,欢迎体验自然的时间韵律。

DevOpenClub 专栏 1108

Oracle数据库表空间使用情况查询

在Oracle数据库中,表空间(Tablespace)是用于存储表、索引和其他数据库对象的逻辑存储单元。了解表空间的使用情况对于数据库管理员和开发人员来说是非常重要的,因为它可以帮助他们监控数据库的空间使用情况并进行容量规划。本文将介绍如何查询Oracle数据库中的表空间使用情况。通过执行以上SQL查询语句,你可以获得Oracle数据库中表空间的使用情况、文件大小和表空间大小等信息。这些信息可以帮助你了解数据库的存储情况,并进行适当的优化和容量规划。查看表空间的数据文件和表空间大小。查看表空间的使用情况。

CsmbPascal的博客 857

二十四设计模式之原型设计模式

二十四设计模式之原型设计模式 前段时间写了有关工厂设计模式的文章,今天我们就再说一下同样是创建型设计模式的原型模式。 老样子,我们先说一下何为原型模式: 原型模式中使用了一种克隆的技术来复制实例化的对象,注意工厂模式是对类本身的一些改进写法,而原型模式主要集中在对实例的操作。这里我们就少不了用到的关键字clone了,有人会问为什么要用到原型模式,实例化时直接创建一个new实例不就得了,针

lwl13207136100的博客 332

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

TensorFlow学习笔记(二十四)自制TFRecord数据集 读取、显示及代码详解

在跑通了官网的mnist和cifar10数据之后,笔者尝试着制作自己的数据集,并保存,读入,显示。 TensorFlow可以支持cifar10的数据格式, 也提供了标准的TFRecord 格式,而关于 tensorflow 读取数据, 官网提供了3中方法 1 Feeding: 在tensorflow程序运行的每一步, 用python代码在线提供数据 2 Reader : 在一个计算图(tf.g

春华秋实 1万+

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

二十四节气-解读

二十四节气,在2011年6月入选第三批国家级非物质文化遗产名录。 分别为:(2013年) 其中,有一首节歌:               《二十四节歌》 春雨惊春清谷天,夏满芒夏暑相连。 秋处露秋寒霜降,冬雪雪冬小大寒。 每月两节不变更,最多相差一两天。 上半年来六廿一,下半年是八廿三。   立春 立春,是二十四...

weixin_33778778的博客 1279

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

【软件开发底层知识修炼】二十四 ABI之函数调用约定

上一篇文章学习了Linux环境下的函数栈帧的形成与摧毁。点击链接查看相关文章:软件开发底层知识修炼】二十三 ABI-应用程序二进制接口三之深入理解函数栈帧的形成与摧毁 本篇文章继续学习ABI接口相关的内容。函数调用约定 文章目录1 函数参数如何入栈,返回值在哪里2 函数调用约定的编程实验2.1 使用gdb调试代码证明eax存的值是函数返回值2 .2 查看程序的反汇编文件来说明调用约定的不...

厚积薄发 1999

webrtc代码走读(二十四)-QOS系列16-音频QOS-3A算法

WebRTC音频前处理3A算法摘要:AEC(回声消除)、AGC(自动增益控制)和ANS(噪声抑制)共同保障音频质量。AEC通过分析参考信号消除回声;AGC动态调整音量保持舒适听感;ANS识别并抑制环境噪声。源码实现上,AEC3模块处理回声路径估计与双讲检测,AGC通过数字增益平滑调整音量,ANS则在频域过滤噪声。这些算法通过AudioProcessing类统一调度,按帧实时处理音频数据,最终输出清晰稳定的语音信号。

qq_31065851的博客 1750

网络流二十四题之魔术球问题

P2765 魔术球问题 题目描述 «问题描述: 假设有n根柱子,现要按下述规则在这n根柱子中依次放入编号为1,2,3,...的球。 (1)每次只能在某根柱子的最上面放球。 (2)在同一根柱子中,任何2个相邻球的编号之和为完全平方数。 试设计一个算法,计算出在n根柱子上最多能放多少个球。例如,在4 根柱子上最多可放11 个球。 «编程任务: 对于给定的n,计算在n...

weixin_30872157的博客 117

SpringBoot自定义Starter(二十四)

主要内容 1. 自定义Starter 2. 自定义Starter的四个部分 3. 自定义Starter的使用 4. 条件注解的使用

两个蝴蝶飞 2299

【Linux系统编程二十四】:(信号3)--信号的捕捉处理与周边细节

【Linux系统编程二十四】:本篇知识点:sigaction如何使用,信号何时被捕捉,用户态和内核态,操作系统的本质,信号捕捉周边细节:可重入函数,volatile以及SIG_CHILD信号

Extreme_wei的博客 1121
上一篇: 代码要写成别人看不懂的样子(二十三)
下一篇: 代码要写成别人看不懂的样子(二十五)
不见浅诗~
博客等级 码龄7年 506粉丝 129原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值