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

【DM】达梦数据库与MySQL适配 通用性、高性能、高可用、跨平台、高可扩展。 阅读详情

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

前言

  熟悉 react 的同学,给绑定事件传递额外参数,这种操作是不是信手拈来,这是得益于 jsx 语法,所有代码都是 js 当然可以为所欲为了,但是当不使用框架的时候,我们又应该怎么实现这种功能呢?

  本节就来学一个参与者模式,帮我们解决传参问题。

参与者模式

  在特定的作用域中执行给定的函数,并将参数原封不动地传递。

  之前我们封装过可以兼容各个浏览器的事件框架,如下:

//事件绑定方法
A.event.on = function(dom, type, fn) {
	//w3c标准事件绑定
	if(dom.addEventListener) {
		dom.addEventListener(type, fn, false);
	//ie事件绑定
	} else if(dom.attachEvent) {
		dom.attachEvent('on' + type, fn)
	//dom 0级事件绑定
	} else {
		dom['on' + type] = fn;
	}
}

  我们知道 addEventListener 方法不能传递自定义参数,那么我们想要传递额外的数据的话,就得在回调函数中做文章。

A.event.on = function(dom, type, fn, data) {
	//w3c标准事件绑定
	if(dom.addEventListener) {
		dom.addEventListener(type, function(e) {
			//在dom环境中调用fn, 并传入事件对象与 data 数据参数
			fn.call(dom, e, data);
		}, false);
	}
	//ie绑定事件...
}

   JavaScript 中的 call 和 apply 方法很神奇,它可以使我们在特定的作用域中执行某个函数并传入参数,所以,在回调函数中,我们借助 call 函数实现了需求。

  不过上面代码有一个问题,添加的事件回调函数不能移除。因为此时事件回调函数是匿名函数,这就需要借用参与者模式来帮我们解决这一问题了。让更多的对象执行参与执行时的函数。

  大家知道函数的绑定方法不? 如果熟悉框架的话,那一定接触过 bind ,这东西的实现思想很简单,就是让一个函数在一个作用域中执行,根据这一条原理我们实现它就简单多了,只需要一个闭包就行。

//函数绑定 bind
function bind(fn, context) {
	//闭包返回新函数
	return function() {
		//对 fn 装饰并返回
		return fn.apply(context, arguments);
	}
}

  我们可以测试一下,新建一个对象 demoObj 和一个函数 demoFn ,然后让 demoObj 对象参与 demoFn 的执行,并保存在 bindFn 变量中,我们来观察一下 demoFn 和 bindFn 执行的结果。

//测试对象
var demoObj = {
	title: '这是一个例子'
}
//测试方法
function demoFn() {
	console.log(this.title);
}
//让 demoObj 参与 demoFn 的执行
var bindFn = bind(demoFn, demoObj);
demoFn();  //undefined
bindFn();  //这是一个例子

   bindFn 函数返回了结果,这说明 demoObj 参与进来并提供了作用域,不过注意 bindFn 是让 demoObj 寄生其中,并在执行时才让 demoObj 加入的,所以说 bindFn 和 demoFn 是两个不同的函数。应用于事件如下:

var btn = document.getElementsByTagName('button')[0];
var p = document.getElementsByTagName('p')[0];
//对 demoFn 改进,在控制台输出参数与 this 对象
function demoFn() {
	console.log(arguments, this);
}
//未设置提供参与对象
var bindFn = bind(demoFn);
//绑定事件
btn.addEventListener('click', bindFn);
//chrome 输出:[MouseEvent] Window

//提供 btn 元素参与对象
var bidnFn = bind(demoFn, btn);
//chrome 输出:[MouseEvent] <button>按钮</button>

//提供 p 元素参与对象
var bidnFn = bind(demoFn, btn);
//chrome 输出:[MouseEvent] <p>hello</p>

//移除事件
btn.removeEventListener('click', bindFn);

  当未提供参与对象时,执行的结果是返回 this 对象指向全局对象 Window , 说明此时是在全局作用域中执行的,当提供 btn 元素参与对象时,返回的 this 对象时元素自身,说明此时是在 btn 元素作用域中执行的,当提供 p 元素参与对象时,返回的是 p 元素,说明此时是在 p 元素作用域中执行的。并且我们发现函数的参数中还为我们传递了事件对象。并且这种方式添加的事件还可以通过 removeEventListener 来移除。

  有个好消息是,在一些标准浏览器如高版本的 FireFox, chrome, Safari 等中还是为我们提供了原生 bind 方法,所以你还可以像下面这种方式使用原生 bind 方法。

//提供 p 元素参与对象
var bindFn = demoFn.bind(p);

  这只是实现需求的第一步,将添加的事件成功移除。下面我们要完成第二部,为运行的函数添加额外的自定义数据参数。这就需要借助函数柯里化了。

函数柯里化

   bind 函数的本质,其实就是柯里化,函数柯里化思想是对函数的参数分割,根据参数的不同,让一个函数存在多种状态,只不过函数柯里化处理的是函数,因此要以函数为基础,借助柯里化器伪造其他函数,这些伪造的函数在执行时调用这个计函数完成不同的功能。

  怎对柯里化举个例子大家就明白了。

function add(x, y) {
    return x + y
}

// 柯里化后
function curryingAdd(x) {
    return function (y) {
        return x + y
    }
}

add(1, 2)           // 3
curryingAdd(1)(2)   // 3

  大家有没有觉得上面代码很熟悉,没错,上一节我们学习惰性模式的时候,就i是通过这种返回函数来实现的。下面创建一个函数柯里化器

//函数柯里化
function curry(fn) {
	//缓存数组 slice 方法 Array.prototype.slice
	var Slice = [].slice;
	//从第二个参数开始截取参数
	var args = Slice.call(arguments, 1);
	//闭包返回新函数
	return function() {
		//将参数(类数组)转化为数组
		var addArgs = Slice.call(arguments),
			//拼接参数
			allArgs = args.concat(addArgs);
		//返回新函数
		return fn.apply(null, allArgs);
	}
}

  接下来测试下这个柯里化器,老规矩,拿加法器进行拓展。

//加法器
function add(num1, num2) {
	return num1 + num2;
}
//加 5 加法器
function add5(num) {
	return add(5, num);
}

//测试 add 加法器
console.log(add(1, 2));   //3
//测试加 5 加法器
console.log(add5(6));   //11
//函数柯里化创建加5加法器
var add_5 = curry(add, 5);
console.log(add_5(7))  //12
//7 + 8
var add7add8 = curry(add, 7, 8);
console.log(add7add8())    //15

  通过柯里化器对 add 方法实现的多态拓展且不需要像以前那样明确声明函数了,因为函数的声明过程已经在柯里化器中完成了。

  接下来回归到一开始的需求,我们需求的第二部是传递额外的自定义数据参数,所以我们需要用函数柯里化思想来拓展函数执行的参数就可以了。我们重写一下 bind 函数。

//重写 bind
function bind (fn, context) {
	//缓存数组 slice 方法
	var Slice = Array.prototype.slice,
		//从第三个参数开始截取参数(包括第三个参数)
		args = Slice.call(arguments, 2);
	//返回新方法
	return function() {
		//将参数转化为数组
		var addArgs = Slice.call(arguments),
			//拼接参数
			allArgs = addArgs.concat(args);
		//对 fn 装饰并返回
		return fn.apply(context, allArgs);
	}
}

  现在我们创建两个数据对象, demoData1 和 demoData2 ,然后传入事件的回调函数中,我们在控制台看看输出结果。

var demoData1 = {
	text: '这是第一组数据'
},
	demoData2 = {
		text: '这是第二组数据'
	};
//提供 btn 元素、demoData1 参与对象
var bindFn = bind(demoFn, btn, demoData1);
//chrome 输出:[MouseEvent, Object] <button>按钮</button>
//提供 btn 元素、demoData1 demoData2 参与对象
var bindFn = bind(demoFn, btn, demoData1, demoData2);
//chrome 输出:[MouseEvent, Object, Object] <button>按钮</button>
//提供 p 元素、demoData1 参与对象
var bindFn = bind(demoFn, p, demoData1);
//chrome 输出:[MouseEvent, Object] <p>hello</p>

  在回调函数中果然可以访问到传入的自定义数据对象,浏览器内置的 bind 方法也可以这样用。

var bindFn = demoFn.bind(p, demoData1);
//chrome 输出: [Object, MouseEvent] <p>hello</p>

  跟我们自己封装的函数不同的是,内置的 bind 把事件对象放在了后面。

  接下来我们写个兼容版本,对未提供 bind 方法的浏览器的原生 Function 对象添加 bind 方法,这样在各个浏览器中就可以兼容了。

//兼容各个浏览器
if(Function.prototype.bind === undefined) {
	Function.prototype.bind === function(context) {
		//缓存数组 slice 方法
		var Slice = Array.prototype.slice,
			//从第二个参数截取参数
			args = Slice.call(arguments, 1);
			//保存当前函数引用
			that = this;
		//返回新函数
		return fucntion() {
			//将参数数组化
			var addArgs = Slice.call(arguments),
				//拼接参数,注意:传入的参数放在了后面
				allArgs = args.concat(addArgs);
			//对当前函数装饰并返回
			return that.apply(context, allArgs);
		}
	}
}

  参与者模式其实是两种技术的结晶,函数绑定和函数柯里化,早期浏览器未能提供 bind 方法,因此工程师们为了使添加的事件能够移除,事件回调函数中能够访问到事件源,并可以向事件回调函数中传入自定义数据,才发明了函数绑定与函数柯里化技术。

  对于函数绑定,他将函数以函数指针的形式传递,是函数在被绑定的对象作用域中执行,因此函数的执行中可以顺利的访问到对象内部数据,由于函数绑定构造复杂,执行时需要消耗更多的内存,因此执行速度上稍慢一些,不过相对于解决的问题来说,这种程度的消耗还是可以接受的。

  对于函数柯里化即是将接受多个参数的函数转化为接收一部分参数的新函数,余下的参数保存下来,当函数调用时,但会传入的参数与保存的参数共同执行的结果。通常保存下来的参数保存于闭包中,所以函数柯里化需要消耗一定的资源。

  柯里化有点类似类的重载,不同点是类的重载是同一个对象,函数柯里化是两个不同的函数。随着柯里化的发展,现在又衍生出一种反柯里化函数,目的是方便我们对方法的调用。

//反柯里化
Function.prototype.uncurry = function() {
	//保存当前对象
	var that = this;
	return function() {
		return Function.prototype.call.apply(that, arguments);
	}
}

  当用 Object.prototype.toString 校验对象类型时:

//获取校验方法
var toString = Object.prototype.toString.uncurry();
//测试对象数据类型
console.log(toString(function() {})) //chrome: [object Function]
console.log(toString([]));           //chrome: [object Array]

  用数组的 push 方法给对象添加成员

//保存数组 push 方法
var push = [].push.uncurry();
//创建一个对象
var demoArr = {};
//通过 push 方法为对象添加数据成员
push(demoArr, '第一个成员', '第二个成员');
console.log(demoArr);  //chrome: Object { 0: '第一个成员', 1: '第二个成员', length: 2}




达梦数据库自增主键与UUID主键测试 本文主要描述达梦数据库的自增主键和UUID主键,通过测试比对两种主键方式在执行效率,并发支持,空间占用方面的差异。 阅读详情

相关推荐

自动生成32位UUID的函数

直接通过 dbo.[FunGetUUID32](NEWID())即可获取到32位UUID,非常简单方便。

达梦数据库利用SQL语句生成UUID

【代码】达梦数据库利用SQL语句生成UUID。

今天怎么又下雨的博客 9365

别再只会regress了!用Stata的csdid命令搞定多期DID的完整实操指南

本文详细介绍了如何在Stata中使用csdid命令进行多期DID分析,解决传统DID方法在交错处理场景下的局限性。通过完整的实操指南,包括环境搭建、核心语法、结果解读和高阶应用,帮助研究者更准确地评估政策效果,适用于计量经济学和实证研究领域。

weixin_30236595的博客 582

python基础包括什么-python中f是什么

python中的f是format函数的缩写,用于格式化输出。format函数常见的用法是str.format(),其基本语法是通过{}和:来代替以前的%。示例:>>>"{} {}".format("hello", "world") # 不设置指定位置,按默认顺序'hello world'>>> "{0} {1}"...

weixin_37988176的博客 8090

PyCharm与MicroPython联手:打造高效ESP32开发环境

本文详细介绍了如何使用PyCharm与MicroPython打造高效的ESP32开发环境。通过配置PyCharm插件、刷写MicroPython固件以及实战示例,帮助开发者快速上手嵌入式Python开发,显著提升物联网项目的开发效率。

weixin_29169899的博客 380

奇迹mu服务端DATA文件解析:从基础配置到高级玩法

本文深入解析奇迹MU服务端DATA文件的核心配置与高级玩法,涵盖基础设置、怪物AI系统、技能战斗机制、副本事件管理及物品商城定制。通过详细示例和实用技巧,帮助开发者掌握从经验倍率调整到动态事件触发的全方位配置方法,实现个性化的私服搭建与运营。

weixin_29254673的博客 529

代码要写成别人看不懂的样子(一)

本篇文章参考以下博文 文章目录前言 前言   最近读了一本书,张容铭老师的 《JavaScript设计模式》 ,书中提到的编码模式,编码风格,让我想起了我刚学 JS 的时候,特别向往像大神一样,全篇没什么 div 罗列,都是方法或者构造函数之类的东西,一顿操作后, body 里面只要添加一个 <div id=“demo”> ,大功告成。   逼格满满有没有,当时就想,什么时候我也能这样,别人看不懂我的代码,所有的事情不用自己手写,只要给一个容器,然后执行函数就

不见浅诗的博客 1713

从0入门LocoTrack:6倍加速的SLAM追踪新范式实战指南

传统点追踪方法(如CorrTracker、TAPIR)在处理大规模场景或实时任务时,要么精度不足,要么速度太慢。而LocoTrack通过“局部4D相关性”和“Transformer全局关联”的创新设计,实现了精度与速度的双重突破速度:比现有SOTA方法快6倍,吞吐量高达数万点/秒;精度:在Kinetics、DAVIS等数据集上,定位误差显著低于传统方法;鲁棒性:能应对低纹理、动态场景等复杂环境,这是传统方法的“噩梦场景”。

m0_71589036的博客 95

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

文章目录前言前期准备如何才能让别人看不懂1.四两拨千斤2.指桑骂槐 前言   上一期我们,浅尝辄止,稍微介绍了下代码如何写才能更高级,更有内涵,主要是需要配合继承,或是某些数据特性来说。这一节咱们放个大招,运用兵法来写代码,保证初学者看不懂,既便能看懂,也不知道为什么这样做,即便知道为什么这样做,没有系统学习过的人也做不好。   这部兵法就是–设计模式。 前期准备   各位乡绅,读这本书前,个人建议要对 继承 , 类 (虽然JS在ES6之前没有类,但是可以通过一些手段实现类), 构造函数 ,

不见浅诗的博客 623

2026 Claude Code 标准化前端UI SKILL——Frontend Design

是 Anthropic 官方开源的技能包,在 Claude 官方插件站中排名第一,超过 52k 的下载量。场景推荐方案快速体验批量安装官方 Skills深度设计策略叠加完整打磨流程集成终端跑claude一句话总结:Frontend Design 不是给 AI 加新能力,而是给 AI 加审美标准。它让 AI 从“能画”变成“会设计”——先想清楚风格,再动手写代码。

十年老程序猿,AI 疯狂研究专家,前沿硬核知识分享 3606

《SOC架构-ARM架构-文档导读》-目录

小白请看“Armv8/Armv9架构从入门到精通”专栏。以翻译为主的,深度深度深度深度/深入深入深入 学习ARM架构的文章。

baron-周贺贺-代码改变世界ctw 2083

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

本篇文章参考书籍《JavaScript设计模式》–张容铭 文章目录前言状态模式 前言   各位写代码的时候,经常会出现条件判断吧,那么条件判断里面脸最熟的当属 if 了吧,这个东西在我们开始编码的时候,真的是隔一段时间不写,就浑身难受。   但是呢,if 这个东西,哪怕是再简单的判断,也会有隐含问题,而且在代码可读性上,条件判断的效果很不友好,当存在多重判断的时候,简直就是灾难。   所以为了解决条件判断的这些弊端,状态模式应运而生。 状态模式   状态模式:当一个对象的内部状态发生改变时,会导

不见浅诗的博客 447

【Bug已解决】[Bug]: ValueError: No user query found in messages QWEN 3.5 27B VLLM 0.16.0 NIGHTLY 解决方案

用 vLLM 0.16.0 nightly 给发聊天请求时,服务端在处理消息时抛ValueError,请求失败。

博客 402

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

本篇文章参考书籍《JavaScript设计模式》–张容铭 文章目录前言惰性模式 前言   各位接触过机器学习没有,没了解过也没关系,这东西的大体思路就是,当第一次执行某种情况时,机器会去判断一些情况,到第二次执行的时候,就不需要再重复判断了,那么机器学习就会在第一次执行完成后,记录当时的计算过程,参数等数据,然后重新定义这种特定情况,当再次遇到后,不需要重复判断,直接获取上次的结果就行。   这个机器学习,就很像我们今天要说的惰性模式。真的超级像(我个人猜测,有可能当年发明机器学的人,就是惰性模式用的比较好

不见浅诗的博客 250

【OpenClaw从入门到精通】零基础入门——OpenClaw核心概念快速理解(2026入门版)

OpenClaw是一个强大的AI代理框架,旨在构建智能化的自动化任务处理系统。随着人工智能技术的快速发展,OpenClaw为开发者和企业提供了一个完整的解决方案,用于创建能够理解、学习和执行复杂任务的智能体。本文将带领零基础的读者快速理解OpenClaw的核心概念,从基础架构到实际应用,为后续深入学习奠定坚实基础。通过本文的学习,你将掌握OpenClaw的基本原理、核心组件和快速上手方法。

一键难忘的博客 325

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

代码要写成别人看不懂的样子(三)

文章目录前言 前言   书接上回,我们学习了装饰器模式,不知各位道友是否还有印象,               

不见浅诗的博客 416

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

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

代码要写成别人看不懂的样子(八)

本篇文章参考书籍《JavaScript设计模式》–张容铭 文章目录前言注意事项 前言   铁汁们,我又来了,上节的组合模式,各位乱了没?不慌哈,这一节我们一起学个更乱的,就不会觉得上一个乱了。   通过不同的组合我们可以拼出很多我们像要的东西,只有想不到的需求,没有实现不了的方案。 注意事项      组合模式刚上手有点乱,不过核心思想还是比较清晰明确的,把需求拆分成一个一个子类,让所有子类继承一个虚拟父类就可以了。之前问过一位高人,如何才能写好代码,前辈指点:“ 惟手熟尔 ”。设计模式初学的时候,一定要

不见浅诗的博客 920

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

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

本篇文章参考书籍《JavaScript设计模式》–张容铭 文章目录前言数据访问对象模式 前言   各位作为一名前端开发,大家有没有遇到过前端存储,比如用户初次进入程序,会有一个个性化引导,一般来说这块功能是交给后台同事来做的,但是有时候需要放在前端,来保存是否第一次登陆的字段。   那我们在本地存储的时候呢,可能会遇到很多问题,每添加一组数据,担心会不会覆盖别人的数据等等,本节的设计模式,就介绍怎么合理前端存储。 数据访问对象模式   抽象和封装对数据源的访问与存储, DAO通过对数据源链接的管理方便对数据

不见浅诗的博客 341

代码要写成别人看不懂的样子(六)

文章目录前言一、代理模式 前言   由于现在网络的发展,访问量,需求量越来越高,很难再使用一台服务器解决所有请求了,这就需要设置专门功能的服务器,来处理专门的业务。比如一个大型应用中,地图功能需要配置一台地图服务器,实况功能需要配置一台媒体服务器,数据上传专门来一台服务器,数据库系统再来一台,管理这些服务器还需要一台。在一些高并发的地方,一台服务器处理不过来,要把请求分散到各个服务器上进行处理。   服务器越来越多,不可避免地要考虑一个问题,跨域请求,跨域本身是一种安全策略,为了网络安全,不能直接请求非本服

不见浅诗的博客 368

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

本篇文章参考书籍《JavaScript设计模式》–张容铭 文章目录前言链模式 前言   大家一定用过 JQuery 吧,这东西的一大特性就是链式调用,获取到某个元素后,直接连续执行多个方法,贼帅,其实我们也可以做到。   本节开始,就给大家介绍一些技巧性的设计模式,平时能经常用到,类似语法糖一样,简单易懂,而且功能奇妙,不会像前面的设计模式那样长篇大论,肯定比前面容易接收,而且有趣。 链模式    通过对象方法中,将当前对象返回,实现对同一个对象多个方法的链式调用。   

不见浅诗的博客 192

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

本篇文章参考书籍《JavaScript设计模式》–张容铭 文章目录前言备忘录模式 前言   各位有没有做过分页,做分页一定会涉及到上一页,下一页,我们为了页面的流畅性,一般都是只请求当前页的数据,当点击上下页按钮的时候,才会请求对应的数据。   这个策略没错,但是用户一般都很调皮,不会老老实实,只点下一页,或者只点上一页,有时候可能会来回,上一页,下一页疯狂点击,那么这种情况就会疯狂请求数据。   页面很可能会卡死,那有没有什么方法能解决这种调皮鬼行为呢?   有时候我们可以增加点击限制,数据没返回之前,不

不见浅诗的博客 278

代码要写成别人看不懂的样子(五)

文章目录前言一、外观模式二、适配器模式 前言   通过前面几篇文章,大家估计对对象的创建有了一个新的认识,在很多大型应用里面,对象会相当复杂,但是其刚创建的时候,并不是这样,而是通过后续的组合,封装,才一步一步完善起来的,从本章节开始,我们一块来学一学,如何把这些对象组合的更合理,从而使想强大的功能。 一、外观模式   大家一定绑定过事件,而且一定像下面这样绑定过 document.onclick = fucntion(e) { e.preventDefault(); if(e.target !== d

不见浅诗的博客 455

代码要写成别人看不懂的样子(九)

本篇文章参考书籍《JavaScript设计模式》–张容铭 文章目录前言模板方法模式 前言   前几节的结构型设计模式,各位学的乱不乱,我个人刚开始接触的时候,也觉得很抽象,不太好理解,尤其是实战的时候,总是不知道在什么情况下使用。记住一点,当我们单纯的创建一个    模板方法模式       ...

不见浅诗的博客 397

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

本篇文章参考书籍《JavaScript设计模式》–张容铭 文章目录前言简单模板模式 前言   大家有没有遇到过操作大量节点的情况,比如我们在页面上想要创建一个展示区域,这块区域,需要跟不同的选项来展示不同结构的内容,那我们就需要根据选项来操作不同的节点。首先创建节点,然后创建节点内容,将节点内容插入到创建的节点中,最后将节点插入到父节点中。   这一套操作下俩,一个节点就需要 4 步,如果节点比较多,那这性能消耗就有点遭不住了。   为了解决这一个问题,我们可以使用简单模板方法。如果各位接触过模板字符串

不见浅诗的博客 353

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

本篇文章参考书籍《JavaScript设计模式》–张容铭 文章目录前言状态模式 前言    状态模式   

不见浅诗的博客 407

代码要写成别人看不懂的样子(七)

本篇文章参考书籍《JavaScript设计模式》–张容铭 文章目录前言一、组合模式 前言   来了各位,本节整个硬活, 一、组合模式    var News = function() { //子组件容器 this.children = []; //当前组件元素 this.element = null; } News.prototype = { init: function() { throw new Error('重写方法'); }, add: function() { throw n

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

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值