还是有必要知道一些早期用JS模拟类的故事

JavaScript缓冲区与内存安全:从ArrayBuffer原理到实战防御 缓冲区是计算机科学中用于高效处理二进制数据的基础概念,它提供了一块连续的内存区域,允许程序直接操作字节序列。其核心原理在于通过视图(如TypedArray)对底层内存进行类型化解释,实现高性能的数据读写。在JavaScript中,随着Node.js、WebAssembly等技术的发展,对二进制数据的处理需求日益增长,理解缓冲区机制的技术价值愈发凸显。它不仅是处理图像、音视频、网络协议等场景的关键,更关系到应用的内存安全与稳定性。本文聚焦于JavaScript中的缓冲区操作,深入探讨ArrayBuffer、T 阅读详情

早期的 JavaScript 程序员一般都有过使用 JavaScript“模拟面向对象”的经历。

在上一篇文章我们已经讲到,JavaScript 本身就是面向对象的,它并不需要模拟,只是它实现面向对象的方式和主流的流派不太一样,所以才让很多人产生了误会。

那么,随着我们理解的思路继续深入,这些“模拟面向对象”,实际上做的事情就是“模拟基于类的面向对象”。
尽管我认为,“类”并非面向对象的全部,但我们不应该责备社区出现这样的方案,事实上,因为一些公司的政治原因,JavaScript 推出之时,管理层就要求它去模仿 Java。

所以,JavaScript 创始人 Brendan Eich 在“原型运行时”的基础上引入了 new、this 等语言特性,使之“看起来语法更像 Java”,而 Java 正是基于类的面向对象的代表语言之一。

但是 JavaScript 这样的半吊子模拟,缺少了继承等关键特性,导致大家试图对它进行修补,进而产生了种种互不相容的解决方案。

庆幸的是,从 ES6 开始,JavaScript 提供了 class 关键字来定义类,尽管,这样的方案仍然是基于原型运行时系统的模拟,但是它修正了之前的一些常见的“坑”,统一了社区的方案,这对语言的发展有着非常大的好处。

实际上,我认为“基于类”并非面向对象的唯一形态,如果我们把视线从“类”移开,Brendan 当年选择的原型系统,就是一个非常优秀的抽象对象的形式。

我们从头讲起。

什么是原型?

原型是顺应人类自然思维的产物。中文中有个成语叫做“照猫画虎”,这里的猫看起来就是虎的原型,所以,由此我们可以看出,用原型来描述对象的方法可以说是古已有之。

我们在上一节讲解面向对象的时候提到了:在不同的编程语言中,设计者也利用各种不同的语言特性来抽象描述对象。

最为成功的流派是使用“类”的方式来描述对象,这诞生了诸如 C++、Java 等流行的编程语言。这个流派叫做基于类的编程语言。

还有一种就是基于原型的编程语言,它们利用原型来描述对象。我们的 JavaScript 就是其中代表。
“基于类”的编程提倡使用一个关注分类和类之间关系开发模型。在这类语言中,总是先有类,再从类去实例化一个对象。类与类之间又可能会形成继承、组合等关系。类又往往与语言的类型系统整合,形成一定编译时的能力。

与此相对,“基于原型”的编程看起来更为提倡程序员去关注一系列对象实例的行为,而后才去关心如何将这些对象,划分到最近的使用方式相似的原型对象,而不是将它们分成类。

基于原型的面向对象系统通过“复制”的方式来创建新对象。一些语言的实现中,还允许复制一个空对象。这实际上就是创建一个全新的对象。

基于原型和基于类都能够满足基本的复用和抽象需求,但是适用的场景不太相同。

这就像专业人士可能喜欢在看到老虎的时候,喜欢用猫科豹属豹亚种来描述它,但是对一些不那么正式的场合,“大猫”可能更为接近直观的感受一些(插播一个冷知识:比起老虎来,美洲狮在历史上相当长时间都被划分为猫科猫属,所以性格也跟猫更相似,比较亲人)。

我们的 JavaScript 并非第一个使用原型的语言,在它之前,self、kevo 等语言已经开始使用原型来描述对象了。

事实上,Brendan 更是曾透露过,他最初的构想是一个拥有基于原型的面向对象能力的 scheme 语言(但是函数式的部分是另外的故事,这篇文章里,我暂时不做详细讲述)。

在 JavaScript 之前,原型系统就更多与高动态性语言配合,并且多数基于原型的语言提倡运行时的原型修改,我想,这应该是 Brendan 选择原型系统很重要的理由。

原型系统的“复制操作”有两种实现思路:

  • 一个是并不真的去复制一个原型对象,而是使得新对象持有一个原型的引用;

  • 另一个是切实地复制对象,从此两个对象再无关联。

历史上的基于原型语言因此产生了两个流派,显然,JavaScript 显然选择了前一种方式。

JavaScript 的原型

如果我们抛开 JavaScript 用于模拟 Java 类的复杂语法设施(如 new、Function Object、函数的 prototype 属性等),原型系统可以说相当简单,我可以用两条概括:

  • 如果所有对象都有私有字段prototype,就是对象的原型;

  • 读一个属性,如果对象本身没有,则会继续访问对象的原型,直到原型为空或者找到为止。

这个模型在 ES 的各个历史版本中并没有很大改变,但从 ES6 以来,JavaScript 提供了一系列内置函数,以便更为直接地访问操纵原型。三个方法分别为:

  • Object.create 根据指定的原型创建新对象,原型可以是 null;

  • Object.getPrototypeOf 获得一个对象的原型;

  • Object.setPrototypeOf 设置一个对象的原型。

利用这三个方法,我们可以完全抛开类的思维,利用原型来实现抽象和复用。我用下面的代码展示了用原型来抽象猫和虎的例子。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

var cat = {

    say(){

        console.log("meow~");

    },

    jump(){

        console.log("jump");

    }

}

var tiger = Object.create(cat,  {

    say:{

        writable:true,

        configurable:true,

        enumerable:true,

        value:function(){

            console.log("roar!");

        }

    }

})

var anotherCat = Object.create(cat);

anotherCat.say();

var anotherTiger = Object.create(tiger);

anotherTiger.say();

这段代码创建了一个“猫”对象,又根据猫做了一些修改创建了虎,之后我们完全可以用 Object.create 来创建另外的猫和虎对象,我们可以通过“原始猫对象”和“原始虎对象”来控制所有猫和虎的行为。

但是,在更早的版本中,程序员只能通过 Java 风格的类接口来操纵原型运行时,可以说非常别扭。

考虑到 new 和 prototype 属性等基础设施今天仍然有效,而且被很多代码使用,学习这些知识也有助于我们理解运行时的原型工作原理,下面我们试着回到过去,追溯一下早年的 JavaScript 中的原型和类。

早期版本中的类与原型

在早期版本的 JavaScript 中,“类”的定义是一个私有属性 class,语言标准为内置类型诸如 Number、String、Date 等指定了class属性,以表示它们的类。语言使用者唯一可以访问class属性的方式是 Object.prototype.toString。

以下代码展示了所有具有内置 class 属性的对象:

var o = new Object;
var n = new Number;
var s = new String;
var b = new Boolean;
var d = new Date;
var arg = function(){ return arguments }();
var r = new RegExp;
var f = new Function;
var arr = new Array;
var e = new Error;
console.log([o, n, s, b, d, arg, r, f, arr, e].map(v => Object.prototype.toString.call(v)));

因此,在 ES3 和之前的版本,JS 中类的概念是相当弱的,它仅仅是运行时的一个字符串属性。

在 ES5 开始,class 私有属性被 Symbol.toStringTag 代替,Object.prototype.toString 的意义从命名上不再跟 class 相关。我们甚至可以自定义 Object.prototype.toString 的行为,以下代码展示了使用 Symbol.toStringTag 来自定义 Object.prototype.toString 的行为:

var o = { [Symbol.toStringTag]: "MyObject" }
console.log(o + "");

这里创建了一个新对象,并且给它唯一的一个属性 Symbol.toStringTag,我们用字符串加法触发了 Object.prototype.toString 的调用,发现这个属性最终对 Object.prototype.toString 的结果产生了影响。

但是,考虑到 JavaScript 语法中跟 Java 相似的部分,我们对类的讨论不能用“new 运算是针对构造器对象,而不是类”来试图回避。

所以,我们仍然要把 new 理解成 JavaScript 面向对象的一部分,下面我就来讲一下 new 操作具体做了哪些事情。

new 运算接受一个构造器和一组调用参数,实际上做了几件事:

  • 以构造器的 prototype 属性(注意与私有字段prototype的区分)为原型,创建新对象;

  • 将 this 和调用参数传给构造器,执行;

  • 如果构造器返回的是对象,则返回,否则返回第一步创建的对象。

new 这样的行为,试图让函数对象在语法上跟类变得相似,但是,它客观上提供了两种方式,一是在构造器中添加属性,二是在构造器的 prototype 属性上添加属性。

下面代码展示了用构造器模拟类的两种方法:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

function c1(){

    this.p1 = 1;

    this.p2 = function(){

        console.log(this.p1);

    }

}

var o1 = new c1;

o1.p2();

function c2(){

}

c2.prototype.p1 = 1;

c2.prototype.p2 = function(){

    console.log(this.p1);

}

var o2 = new c2;

o2.p2();

第一种方法是直接在构造器中修改 this,给 this 添加属性。

第二种方法是修改构造器的 prototype 属性指向的对象,它是从这个构造器构造出来的所有对象的原型。
没有 Object.create、Object.setPrototypeOf 的早期版本中,new 运算是唯一一个可以指定prototype的方法(当时的 mozilla 提供了私有属性 proto,但是多数环境并不支持),所以,当时已经有人试图用它来代替后来的 Object.create,我们甚至可以用它来实现一个 Object.create 的不完整的 polyfill,见以下代码:

Object.create = function(prototype){
    var cls = function(){}
    cls.prototype = prototype;
    return new cls;
}

这段代码创建了一个空函数作为类,并把传入的原型挂在了它的 prototype,最后创建了一个它的实例,根据 new 的行为,这将产生一个以传入的第一个参数为原型的对象。

这个函数无法做到与原生的 Object.create 一致,一个是不支持第二个参数,另一个是不支持 null 作为原型,所以放到今天意义已经不大了。

ES6 中的类

请参考以下链接内容:还是有必要知道一些早期用JS模拟类的故事

前端开发者入门LangChain JS:从零构建AI应用开发环境与实战项目 大语言模型(LLM)作为当前人工智能领域的核心技术,通过API接口为应用程序提供了强大的自然语言理解和生成能力。其工作原理基于海量文本数据训练,能够根据输入的提示词(Prompt)生成连贯、相关的文本响应。这项技术的核心价值在于将复杂的AI能力封装为标准化服务,极大地降低了开发者集成智能功能的门槛。在实际工程实践中,开发者需要解决模型调用、上下文管理、提示词工程等一系列通用问题,这正是LangChain这类框架的设计初衷。LangChain JS作为专为JavaScript/TypeScript生态打造的框 阅读详情

相关推荐

JavaScript模块化演进史:CommonJS到ES Modules全解析

本文旨在梳理JavaScript模块化技术的演进路线,重点解析CommonJS与ES Modules的实现原理及适用场景,覆盖从Node.js服务端到浏览器端的完整生态。(图示说明:脚本标签 -> IIFE -> CommonJS -> AMD/CMD -> ES Modules)模块化:将程序分解为独立可复用代码单元的开发方式依赖管理:处理模块间引用关系的机制静态分析:在不执行代码的情况下解析模块结构的能力CommonJS是同步战士,擅长服务端战场ES Modules是智能管家。

小白菜的博客 512

Rowhammer.js:浏览器JavaScript如何利用DRAM物理缺陷发起硬件攻击

内存安全是计算机系统安全的基石,而DRAM(动态随机存取存储器)作为核心存储部件,其物理特性直接决定了数据的可靠性。Rowhammer攻击揭示了现代高密度DRAM存在的设计缺陷:当特定内存行被高频访问时,产生的电信号干扰可能导致相邻行存储单元发生比特翻转(Bit Flip)。这一硬件层面的漏洞,传统上被认为需要本地高权限才能利用,但通过结合缓存侧信道和缓存逐出技术,攻击者成功在沙盒化的JavaScript环境中实现了远程利用。Rowhammer.js项目正是这一突破的实践体现,它通过精心设计的JavaScr

defkaug153461的博客 442

c语言播放背景音乐

相信很多童鞋都在为大学课设而伤透头脑,而背景音乐的使用无疑会成为其中的一个亮点(总比没有好吧(╯▽╰)),故接下来我将介绍一下如何用C播放音乐。我用的编译器是CodeBlocks16.01接下来新建一个C文件建立完后是这样滴然后添加其中mciSendString()函数是由<mmsystem.h>库提供的供播放音乐(MP3)的函数第一个参数是歌曲所在的绝对路径 打开音乐所在位置 复制这...

qq_41443987的博客 3万+

1024程序员节图片背后的故事:你不知道的行业文化真相

auto-generated

CompiLume的博客 1089

SoapUI 5.0 模拟WebService接口实战:从WSDL文件到Mock服务端完整流程

本文详细介绍了如何使用SoapUI 5.0模拟WebService接口,从解析WSDL文件到搭建完整的Mock服务端流程。通过实战案例和效率技巧,帮助开发者快速掌握接口模拟技术,提升开发与测试效率。

weixin_26833139的博客 405

kaggle项目:纽约出租车行程时间NYC Taxi Trip Duration

纽约出租车形成时间预测(NYC Taxi Trip Duration)是Kaggle中的一个Playground竞赛。比赛数据集基于2016年纽约市黄色出租车行程记录数据,需要建立一个模型,根据单个行程属性,预测测试集中每次行程的持续时间。Kaggle项目模型XGBoost,评价指标RMSLE。

weixin_42113929的博客 2788

一个关于抽象的故事:寻求更好的 CKB 开发工具

三年前,我们踏上了一段充满传奇和冒险的旅程,我们开始打造一个全新的区块链平台,一个作为开发者的我们,自身就非常喜欢并且希望可以长久依赖的区块链平台。在这个基础上,我们开始精心打造 Nervos CKB 的根基: 安全性: 让 CKB 来守护人们的资产时,人们能放心吗? 稳定性: 在未来几十年里,人们是否还能稳定的使用 CKB? 性能: 在满足前面两个目标的前提下,人们能否相信 CKB 可以提供最佳的性能? 我们非常努力地解决所有这些问题,我们坚信 Nervos CKB 已经为这些问题提供了充分的答案。然而,

NervosNetwork的博客 468

一步步指导:在Chrome中安装Vue插件vue-devtools

Vue.js是现代Web开发中最流行的前端框架之一,它以其轻量级、高性能和易于理解的设计理念受到开发者的喜爱。为了更高效地开发和调试Vue应用,Vue.js官方提供了一个强大的开发工具——vue-devtools。

小透明的博客 5618

Nashorn引擎:JVM上JavaScript性能优化的实战与启示

在Java虚拟机(JVM)生态中,运行动态语言如JavaScript一直面临核心挑战。JVM作为静态类型语言的运行时环境,其JIT编译、方法内联和逃逸分析等优化机制,主要针对类型稳定的场景设计。而JavaScript的动态类型特性,如变量类型可变、对象属性可动态增删,导致传统优化策略难以直接应用,性能优化成为技术难点。其技术价值在于,通过探索类型推断、调用点缓存等适配方案,为高并发服务端渲染、多语言运行时等场景提供了实践参考。Nashorn引擎作为JVM上运行JavaScript的经典案例,深入剖析了其在字

weixin_30443075的博客 321

【重启后nvidia-smi 命令出现错误】

NVIDIA-SMI has failed because it couldn't communicate with the NVIDIA driver. Make sure that the latest NVIDIA driver is installed and running.

qq_44769377的博客 5210

Unity坦克物理系统:履带驱动与力场建模实战指南

在游戏物理仿真中,履带车辆的运动建模远超传统轮式控制器的范畴。其核心在于摒弃WheelCollider的滚动幻觉,转向基于牛顿力学的力与力矩协同求解——通过主推进力场、转向力矩场和地面反作用力场三重叠加,实现对质量、摩擦、惯性及坡度阻力的真实响应。这种建模方式不仅支撑坦克爬坡、陷泥、侧倾等复杂行为,更保障了多人同步与高帧率下的物理稳定性。Physics Tank Maker 正是这一思路的工业级落地,它将PhysX底层机制与坦克动力学深度耦合,提供可调参数、事件驱动视觉反馈及标准扩展接口,成为面向严肃模拟类

weixin_29535577的博客 562

在Windows Azure中使用Node.js,开启云计算之旅!

Node.js 是一个很好的平台,在过去的两年里它越来越受欢迎。它提供了一个服务器端的理想的构建高度可扩展性和高性能网络应用程序(不论是在非云端或者是在云端)的JavaScript编程模型。它的突出特点之一是,它将引导你使用无阻塞的IO来写代码,使得实现更大规模的应用程序称为可能。另一个特点是...

chenqunan3231的博客 64

LabVIEW波形图表时间轴设置:三种方法实现横坐标显示日期时间

在数据采集与设备监控场景中,波形图表的横坐标默认显示采样点序号而非日期时间,这给工程师分析历史数据带来不便。理解时间标识(Timestamp)的本质——一个自1904年起算的双精度秒数,是解决问题的关键。时间轴设置既是显示格式问题,更是数据层与显示层的协同设计。通过属性节点动态生成刻度标签、将时间标识数组直接作为X轴数据、或使用波形数据(Waveform)类型绑定t0与dt,分别适用于固定点数显示、非等间隔事件记录和等间隔连续采样等不同需求。合理选择方案并注意缓冲区预分配与时间连续性处理,可让波形图表准确呈

weixin_33416697的博客 252

从 3 秒到 1 秒:Wiki.js 性能优化实战手册

Wiki.js 是一个基于 Node.js 的开源知识库系统,一次"打开页面"的点击,背后要穿过浏览器、静态资源、应用进程和数据库四道关卡。这篇 Wiki.js 性能优化实战不按"前端/后端"分章节,而是带着你沿一条真实请求走完全程,逐站省时间,学完你也能把页面打开从 3 秒压到 1 秒左右、编辑卡顿明显减轻。 ## 先讲一个真实故事:Wiki.js 打开慢,差点劝退整个团队 小张把团队文档从

gitblog_00562的博客 899

【35】软考软件设计师——设计模式代码填空(C++版)满分精讲|第5/6题二选一必考

本文是《软件设计师·50讲通关|从零基础到工程师职称》专栏第35篇,聚焦下午选做题**第5/6题C++版设计模式代码填空**,与上一篇Java版形成双子配套,单题分值稳定12~15分。全文超4000字深度拆解C++独有核心考点:虚函数/纯虚函数、构造与析构函数规范、继承权限、模板类编程在设计模式中的应用;精讲单例、工厂、策略、观察者、适配器五大高频模式的C++专属代码写法,标注所有填空核心点位、语法陷阱、内存安全规范

专注于人工智能、软件开发、工控自动化、工厂数字化及智能化等领域,希望和大家共同进步! 543

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

在JavaScript中 Promise、Generator、Async/Await 的区别与应用场景?

专业回答Promise是ES6引入的异步编程解决方案,它代表一个异步操作的最终完成(或失败)及其结果值。Promise有三种状态:pending(进行中)、fulfilled(已成功)和rejected(已失败),状态一旦改变就不可逆。Promise主要解决了回调地狱的问题,通过链式调用的方式,让多个异步操作的代码变得扁平易读。同时,它也统一了异步操作的处理方式,提供了更优雅的错误处理机制。大白话回答Promise就像是外卖订单,你下单后不需要一直盯着商家,他们做好了会给你送过来。

前端大白话 960

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

用原生HTML/CSS/JS打造交互式数字情书:前端技术的情感化实践

在Web开发领域,HTML、CSS和JavaScript作为前端技术的基石,构成了现代网页交互体验的核心。通过DOM操作与CSS动画,开发者能够将静态内容转化为动态、可交互的界面。这种技术组合的价值在于其轻量、高效与广泛的兼容性,使其成为快速实现创意想法和个性化项目的理想选择。在实际应用场景中,例如创建个性化的数字贺卡、纪念页面或互动式礼物,原生技术栈能够绕过复杂框架的约束,直接聚焦于用户体验与情感表达。本文以打造一个“数字情书”项目为例,深入探讨了如何利用Intersection Observer API

weixin_30781775的博客 379

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

WINCC7.3破解文件

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

JavaScript测试分层策略:单元、集成与功能测试的实战指南

软件测试是保障代码质量与系统稳定性的核心工程实践,其核心原理在于通过不同层级的验证来确保软件从微观到宏观的正确性。在JavaScript生态中,测试分层策略尤其关键,它能显著提升代码的可维护性与团队协作效率。从技术价值看,清晰的测试分层如同构建一个金字塔:底层是快速、隔离的单元测试,用于验证函数与模块的逻辑正确性;中层是集成测试,关注模块间协作与接口;顶层则是功能测试,确保完整的用户业务流程畅通。这种分层体系能高效定位问题,降低维护成本,并支持持续集成与交付。在实际应用场景中,开发者常使用Jest、Cypr

weixin_34128839的博客 376

电影:从微缩模型到AI纹理

在电影制作和计算机生成图像 (CGI) 中,纹理是指将详细的表面特征应用于 3D 模型或视觉效果元素,使其看起来更逼真。纹理对于创建视觉上引人入胜且可信的电影场景至关重要,尤其是涉及 CGI、动画或特效的场景。

ygtu2018的博客 412

基于Three.js的鲸落文化线上体验馆:Web3D沉浸式数字展陈实践

Web3D技术让深度文化内容得以突破物理展馆的空间限制,在浏览器中构建可交互的虚拟场景。Three.js作为WebGL生态中成熟的渲染框架,通过自定义Shader、粒子系统、雾效与音频引擎,能够实现从海面到深海的连续沉浸体验。这种技术路径不仅服务于自然科普与数字展陈,也适用于虚拟展厅、产品展示等泛文化传播场景。当“鲸落”这一生态现象被转化为线上体验馆时,关键在于以生物事实为骨架、情绪节奏为血肉,完成从视觉吸引、知识理解到情感共鸣的完整叙事链路。本文结合项目实操,梳理了场景构建、交互设计、性能调优与内容解耦的

weixin_29885875的博客 217

滴滴前端面试复盘:从JS基础到Vue3与微前端实战

前端面试考察的不仅是知识点的记忆,更是对技术原理与工程落地能力的综合评估。JavaScript事件循环、闭包、深拷贝等基础概念是面试中的高频考点;Vue3响应式原理、Proxy替代Object.defineProperty、性能优化与微前端架构则体现了业务复杂度对前端技术的现实需求。理解这些技术的底层机制,能够帮助开发者在实际项目中做出更合理的选型与优化,例如大文件上传的切片与断点续传、组件库设计、状态管理等场景。本文以滴滴前端面试真实经历为线索,梳理了从一面技术面到HR面的完整流程与核心题目,并给出项目复

weixin_34174422的博客 422

用JS实现excel预览

这次为大家分享的是,如何用js写出excel文件的预览。 他方便了pc用户和手机端用户可以无需下载,并且直接在线预览excel文件。 因为excel转html的显示用的是第三方开源库的代码,所以实现上有所限制。具体请参见所用到开源的库这些库的说明。 支持 不支持 多sheet显示 图片显示 合并后的单元格显示 链接,文字样式等 手机画面优化 效果图 PC: 手机: 示例代码 所用到开源的库 js: jQuery:ht......

cybozu的博客 1万+
上一篇: 微信小程序+web数据库的开发实践
下一篇: JS的对象分类原来还有这些门道
cybozu开发者
博客等级 码龄9年 275粉丝 79原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值