JavaScript 之 Symbol 数据类型
一、简介
symbol
类型是ES6新引入的一种基本数据类型,该类型具有静态属性和静态方法。其中静态属性暴露了几个内建的成员对象,静态方法暴露了全局的symbol
注册。
symbol
类型具有以下特点:① 唯一性:每个symbol
值都是唯一的;② 不可变性:symbol
值是不可被修改的;③ 属性标识符:symbol
类型的值可以作为对象属性的标识符key
;④Symbol可以与其他数据类型进行运算,但不能被强制转换为其他数据类型。利用前两个特性,可以避免属性名的冲突和保证属性不会被意外覆盖。
symbol
类型在许多库和框架中被广泛应用,常见的应用场景有创建私有属性、定义常量、定义事件名称以及实现各种标识符相关的功能。
二、创建
1、Symbol([description])
通过Symbol([description])
函数创建symbol
类型的值,但并不会被添加到全局symbol表中,可选参数description
,是字符串类型的数据,表示对当前symbol
的描述,该参数只用来作为标识,并不会影响symbol
的唯一性。
但该函数并不是一个构造函数,因为该函数不支持new Symbol()
的语法,如果使用该语法将会抛出TypeError
错误。每个通过Symbol()
函数获取的symbol
类型的值都是唯一的、独一无二的,即使两个symbol
拥有相同的description
,它们也属于两个不同的值。
// 创建symbol数据
let s = Symbol();
console.log(s); // Symbol()
console.log(typeof s); // symbol
// 创建symbol数据并添加描述
let s1 = Symbol('one');
console.log(s1); // Symbol(one)
console.log(typeof s1); // symbol
// 创建symbol数据并添加相同的描述
let s2 = Symbol('one');
console.log(s2); // Symbol(one)
console.log(typeof s2); // symbol
// 判断symbol数据是否相等
console.log(s1 === s2); // false
console.log(s1 == s2); // false
// 使用new关键字创建symbol数据
let s3 = new Symbol(); // Uncaught TypeError: Symbol is not a constructor
2、Symbol.for(key)
第四部分,常用方法章节中讲解。
三、常用属性
1、description(只读)
该属性是一个只读属性,用于获取当前symbol
值的描述字符串。
案例代码:
// 创建symbol数据 不添加描述
let s = Symbol();
// 创建symbol数据并添加描述
let s1 = Symbol('one');// 使用description输出symbol数据的描述
console.log(s.description); // undefined
console.log(s1.description); // one
2、hasInstance
该属性是 Symbol
类型的一个内置静态属性,属性值是一个 Symbol 值,它是不可变的,用于定义对象的 @@hasInstance
方法的键,@@hasInstance
方法用于判断一个对象是否为某个构造函数的实例,我们可以利用该属性自定义instanceof
操作符在某个类上的行为。
当一个对象被使用 instanceof
运算符检查其原型链时,会调用该对象的 @@hasInstance
方法。换句话说,obj instanceof Constructor
实际上是调用了 Constructor[Symbol.hasInstance](obj)
。因此我们可以通过自定义的 @@hasInstance
方法,来自定义判断对象是否为某个构造函数的实例。
案例代码:
class MyArray {static [Symbol.hasInstance](instance) {return Array.isArray(instance);}
}
console.log([] instanceof MyArray); // true
console.log({} instanceof MyArray); // fales
3、isConcatSpreadable
该属性是 Symbol
类型的一个内置静态属性,属性值是一个 Symbol 值,它是不可变的,用于定义对象的 @@isConcatSpreadable
的键。@@isConcatSpreadable
方法是一个内部Symbol,用于确定对象在调用数组的 concat()
方法时是否展开其元素。
如果@@isConcatSpreadable
返回true
(默认值),则对象元素被展开合并;如果方法返回false
,则将对象作为单个元素添加到数组中,构成多维数组的形式。我们可以通过设置对象的 @@isConcatSpreadable
来自定义对象在 concat()
方法中的展开行为
案例代码:
let arr1 = [1, 2, 3]
let arr2 = ['a', 'b', 'c']
// 默认为true 进行展开合并
console.log(arr1.concat(arr2)); // [1, 2, 3, 'a', 'b', 'c']
// 设置arr2 的值为false
arr2[Symbol.isConcatSpreadable] = false
// 再次合并 此时不会展开
console.log(arr1.concat(arr2)); // [1, 2, 3, ['a', 'b', 'c']]
4、iterator
Symbol.iterator
是 Symbol 类型的一个内置静态属性,属性值是一个 Symbol 值,用于定义对象的默认的迭代器@@iterator
。 @@iterator
方法是一个特殊的内部方法,用于返回一个迭代器对象。
当一个对象使用 for...of
循环或扩展运算符 (...
)进行遍历时,会调用该对象的 @@iterator
方法来获取一个迭代器对象。迭代器对象可以通过调用其 next()
方法来依次访问对象的每个元素。我们可以通过自定义 @@iterator
方法来实现自定义的迭代器行为。自定义的 @@iterator
方法应该返回一个具有 next()
方法的迭代器对象。每次调用 next()
方法时,迭代器对象应该返回一个包含 value
和 done
属性的对象,value
表示当前迭代的值,done
表示迭代是否结束。
案例代码:
let arr3 = [1, 2, 3]
// for..of..形式遍历
console.log('for..of..形式遍历');
for (const item of arr3) {console.log(item);
}
// ... 扩展运算符形式遍历
console.log('扩展运算符形式遍历');
console.log([...arr3]);
// 自定义默认迭代器
arr3[Symbol.iterator] = function () {let index = 0;return {next: function () {if (index < arr3.length) {return { value: arr3[index++] * 3, done: false };} else {return { value: undefined, done: true };}}};
};
// 输出数组本身
console.log('输出数组本身');
console.log(arr3);
// for..of..形式遍历
console.log('for..of..形式遍历');
for (const item of arr3) {console.log(item);
}
// ... 扩展运算符形式遍历
console.log('扩展运算符形式遍历');
console.log([...arr3]);
// forEach 形式遍历
console.log(' forEach 形式遍历');
arr3.forEach(item => {console.log(item);
});
// for 形式遍历
console.log('for 形式遍历');
for (let i = 0; i < arr3.length; i++) {console.log(arr3[i]);
}
执行结果:
5、toPrimitive
Symbol.toPrimitive
是 Symbol 类型的一个内置静态属性,用于定义对象的 @@toPrimitive
转换方法的键。 @@toPrimitive
转换方法是一个内部方法,用于将对象转换为一个原始值,它接受一个参数 hint
,表示预期的转换类型。hint
参数可以是以下三个值之一:
"default"
:表示该对象可以被转换为任意类型的原始值,例如:"" + x
(强制转为原始值,而不是字符串)。"number"
:表示该对象被期望转换为数字类型的原始值,例如:算术运算(+-*/
)。"string"
:表示该对象被期望转换为字符串类型的原始值,例如模板字符串(${}
)、String()
等。
参数 hint
的值根据上下文和操作的需要等诸多复杂因素来决定,如:调用对象的运算符、隐式类型转换、valueOf
和 toString
方法等等。
当一个对象被用于需要原始值的上下文中,例如进行算术运算或字符串拼接时,JavaScript 引擎会首先查找对象的 Symbol.toPrimitive
属性。如果该属性存在并且是一个函数,引擎将调用该函数,并传入相应的 hint
参数,转换获取对象的原始值,即字符串、数字或布尔值。我们可以通过自定义 @@toPrimitive
方法来自定义对象的转换行为,完全控制原始转换过程,并返回对象的原始值。
案例代码:
// 一个没有提供 Symbol.toPrimitive 属性的对象
const obj1 = {};
console.log(+obj1); // NaN
console.log(`${obj1}`); // "[object Object]"
console.log(obj1 + ""); // "[object Object]"// 接下面声明一个对象,手动赋予了 Symbol.toPrimitive 属性
const obj2 = {};
obj2[Symbol.toPrimitive] = function (hint) {// hint 参数值是 "number"if (hint === "number") {// 返回对象有多少条属性return Object.keys(obj2).length;}// hint 参数值是 "string"if (hint === "string") {// 返回对象转换成的JSON字符串return JSON.stringify(obj2);}// hint 参数值是 "default"return true;
};
console.log(+obj2); // 0
console.log(`${obj2}`); // "{}"
console.log(obj2 + ""); // "true"
6、match、replace、search、toStringTag等其他属性
请自行了解。。。
四、常用方法
1、for()
Symbol.for(key)
方法会根据参数key
,从所有声明的全局symbol数据中寻找对应的值(不包括通过Symbol()
创建的数据),如果这个值存在,则返回它;如果不存在,则新建一个以这个key
为description
的全局symbol数据,并将创建的数据返回。
如果先使用Symbol()
创建了以这个key
为description
的数据,然后再使用该方法进行查找,则也不会被查找到,因为该方法只在全局symbol
数据中进行查找,而Symbol()
创建的是非全局的数据。
// 第一次使用for()方法 由于之前不存在以foo为key的symbol 所以创建一个 symbol 并放入 symbol 注册表中,键为 "foo"
const a = Symbol.for("aaa");
// 第二次使用for()方法 由于之前注册过 所以直接从 symbol 注册表中读取键为"foo"的 symbol
const b = Symbol.for("aaa");
// 验证两者是否为同一个symbol
console.log(a === b); // true// 如果是通过Symbol()方法创建 则会创建两个key相同的symbol 但并不是同一个symbol
const c = Symbol("bbb");
const d = Symbol("bbb");
// 验证两者是否为同一个symbol
console.log(c === d); // false
2、keyFor()
Symbol.keyFor(symbol)
方法会根据参数symbol
,从所有声明的全局symbol
数据中寻找该数据,并返回该数据的key
。如果从全局symbol
数据中查找到该 symbol
,则返回该 symbol
的 key
值,返回值为字符串类型;如果不存在该symbol
或者该symbol
对应的key
为空,则返回 undefined
。
如果参数symbol
是通过Symbol()
创建的数据,则也不会被查找到,因为该方法创建symbol
数据并非全局的,返回值为undefined
。
// 创建一个全局 Symbol 且有key
const a = Symbol.for("aaa");
console.log(Symbol.keyFor(a)); // "aaa"
// 创建一个全局 Symbol 但没有key
const b = Symbol.for();
console.log(Symbol.keyFor(b)); // undefined
// 创建一个非全局 Symbol 且有key
const c = Symbol("ccc");
// 创建一个全局的 Symbol 且有相同的key
const c2 = Symbol.for("ccc");
console.log(Symbol.keyFor(c)); // undefined
console.log(Symbol.keyFor(c2)); // "ccc"
// 验证两者是否为同一个symbol
console.log(c === c2); // false
// 下面的 原生Symbol 没有保存在全局 Symbol 注册表中
console.log(Symbol.keyFor(Symbol.iterator)); // undefined
3、toString()
Symbol
对象拥有自己的toString()
方法,覆盖了原型链上的Object.prototype.toString()
方法。
symbol数据不能隐式转换为字符串,因此需要toString()
方法,将数据转换成字符串。
// 创建一个symbol
const a = Symbol("aaa");
console.log(a.toString()); // Symbol(aaa)
// 创建一个全局symbol
const b = Symbol.for("bbb");
console.log(b.toString()); // Symbol(bbb)
4、valueOf()等其他方法
请自行了解。。。
五、相关应用
1、作为对象唯一的属性键
Symbol
可以用作对象属性的键,确保属性key
的唯一性,避免属性被意外覆盖或冲突。
// 声明一个 symbol 数据
const a = Symbol('aaa');
// 声明一个全局 symbol 数据
const b = Symbol.for('bbb')
// 声明对象 利用 symbol 数据作为 key
const obj = {[a]: '11111111',a: '22222222',[b]: '33333333'
};
// 再次声明一个 symbol 数据 与 a 有相同的description
// 以该symbol作为key 修改数据 虽然声明时的 description 相同
// 但是是两个不同的 symbol 数据 所以obj[Symbol('aaa')] 与 obj[a] 是两个不同的属性
// 修改其中一个不会影响另一个
obj[Symbol('aaa')] = '44444444';
// 输出属性数据
console.log(obj[a]); // 11111111
// 此处相当于又声明了一个symbol
console.log(obj[Symbol('aaa')]); // undefined
// 再次输出对象的数据
console.log(obj);// 可通过 symbol 数据作为 key 修改数据
// obj[a] = '44444444';
执行结果:
2、声明唯一的常量
借助Symbol
数据的唯一性,我们可以声明常量,并确保常量值的唯一性,而且不会被意外修改或覆盖。
// 声明一个常量 且常量值为 symbol 数据
const a = Symbol("aaa");
// 在函数中匹配常量值
function myFunction(value) {// 判断传入的值是否与常量值相等if (value === a) {console.log("常量值被匹配");} else {console.log("常量值未匹配");}
}
// 传入定义的变量
myFunction(a); // 输出 "常量值被匹配"
// 传入一个新的 symbol 数据 且 description 与常量值相同
myFunction(Symbol("aaa")); // 输出 "常量值未匹配"
3、改写对象的内置方法
通过利用Symbol和内置属性,我们可以改写对象的内置方法,以适应特定的业务场景,并自定义对象的行为。但在改写内置方法时不能破坏原有的语言规范和其他代码的预期行为。
// 声明一个对象 并改写其内置toString方法的返回值
const myObj = {// 该Symbol的内置属性 决定了toString方法的返回值[Symbol.toStringTag]: "MyObject",
};
// 输出对象的toString方法的返回值
console.log(Object.prototype.toString.call(myObj)); // 输出 "[object MyObject]"
4、定义类的私有成员
Symbol
可以在类中作为私有成员的标识符。
// 定义一个symbol数据
const _privateMember = Symbol("private");
// 定义一个类
class MyClass {constructor() {// 定义类的私有成员 以symbol数据作为标识符this[_privateMember] = "私有成员";}// 私有成员的get方法getPrivateMember() {return this[_privateMember];}
}// new 一个实体对象
const instance = new MyClass();
// 通过get方法正常访问
console.log(instance.getPrivateMember()); // 输出 "私有成员"
// 直接访问 无法访问
console.log(instance[_privateMember]); // 输出 undefined
5、其他用法。。。
六、参考资料
Symbol
相关文章:
JavaScript 之 Symbol 数据类型
一、简介 symbol类型是ES6新引入的一种基本数据类型,该类型具有静态属性和静态方法。其中静态属性暴露了几个内建的成员对象,静态方法暴露了全局的symbol注册。 symbol类型具有以下特点:① 唯一性:每个symbol值都是唯一的…...
在Docker中运行PostgreSQL数据库
1.下载Docker 2.设置DockerHub账号 3.运行Docker并下载Image 4.启动PostgreSQL Image 5.连接到数据库运行SQL docker run --name some-postgres -p 5432:5432 -e POSTGRES_PASSWORDmysecretpassword -d postgres 开放端口从Docker容器到主操作系统,这将允许我们…...
实现Spring Boot集成MyBatis
引言 在Java开发中,Spring Boot和MyBatis是非常常用的框架。Spring Boot是一个快速开发应用程序的框架,而MyBatis是一个持久化框架,可以方便地操作数据库。本文将介绍如何使用Idea集成Spring Boot和MyBatis,并创建一个简单的示例…...
关于算法的时间复杂度(度量算法执行时间的两种方法、渐进时间复杂度、时间复杂度的几个性质、渐进估算、常见的渐进时间复杂度排序)
目录 度量算法执行时间的两种方法 事后统计法(Post Hoc Analysis): 事前统计法(Pre Hoc Analysis): 渐进时间复杂度 时间复杂度的几个性质 渐进估算 常见的渐进时间复杂度排序 度量算法执行时间的两…...
SpringBoot项目--电脑商城【显示商品详情功能】
1.持久层[Mapper] 1规划需要执行的SQL语句 根据商品id显示商品详情的SQL语句 SELECT * FROM t_product WHERE id?2 设计接口和抽象方法 在ProductMapper接口中添加抽象方法 /*** 根据商品id查询商品详情* param id 商品id* return 匹配的商品详情,如果没有匹配…...
VLAN笔记
虚拟VLAN 什么是VLAN VLAN的作用 VLAN的优缺点 VLAN的配置方法 VLAN有哪些接口模式 access与trunk接口的区别 Hybrid接口 拓扑实验enspCiscoH3C 什么是VLAN VLAN(Virtual Local Area Network)又称虚拟局域网,是指在交换局域网的基础上&a…...
分类算法系列⑤:决策树
目录 1、认识决策树 2、决策树的概念 3、决策树分类原理 基本原理 数学公式 4、信息熵的作用 5、决策树的划分依据之一:信息增益 5.1、定义与公式 5.2、⭐手动计算案例 5.3、log值逼近 6、决策树的三种算法实现 7、API 8、⭐两个代码案例 8.1、决策树…...
前端面试(基础)
一、CSS 1.说一下CSS的盒模型。 在HTML页面中的所有元素都可以看成是一个盒子 盒子的组成:内容content、内边距padding、边框border、外边距margin 盒模型的类型: 标准盒模型 margin border padding content IE盒模型 margin content(border…...
element-ui switch开关组件二次封装,添加loading效果,点击时调用接口后改变状态
先看效果: element-ui中的switch开关无loading属性(在element-plus时加入了),而且点击时开关状态就会切换,这使得在需要调用接口后再改变开关状态变得比较麻烦。 思路:switch开关外包一层div,给…...
【GAN小白入门】Semi-Supervised GAN 理论与实战
🍨 本文为🔗365天深度学习训练营 中的学习记录博客🍖 原作者:K同学啊🚀 文章来源:K同学的学习圈子论文原文:Semi-Supervised Learning with Generative Adversarial Networks.pdf在学习GAN的时候你有没有想过这样一个问题呢,如果我们生成的图像是带有标签的,例如数…...
Python自动化测试(1)-自动化测试及基本技术手段概述
生产力概述 在如今以google为首的互联网时代,软件的开发和生产模式都已经发生了变化, 在《参与感》一书提到:某位从微软出来的工程师很困惑,微软在google还有facebook这些公司发展的时候,为何为感觉没法有效还击&…...
小程序中如何查看会员的余额和变更记录
通过查看会员的余额和变更记录,可以帮助商家更好地管理会员资金,提供更好的服务和用户体验。下面将介绍小程序中如何查看会员的余额以及余额的变更记录。 1. 找到指定的会员卡。在管理员后台->会员管理处,找到需要查看余额和记录的会员…...
【项目经验】elementui--table表格自定义表头及bug
一.思路 首先我们肯定得循环表头,我们原生js封装的表格的实现原理就是这样。其次我们要把自己循环的label显示出来,对应的prop也要和表格数据相对应。用div标签循环都会出现错误(div里面套column),大家不要踩坑。第一…...
flink实现kafka、doris精准一次说明
前言说明:本文档只讨论数据源为kafka的情况实现kafka和doris的精准一次写入 flink的kafka连接器已经实现了自动提交偏移量到kafka,当flink中的数据写入成功后,flink会将这批次数据的offset提交到kafka,程序重启时,kafka中记录了当前groupId消费的offset位置,开始消费时将…...
【git】git commit、push之前自动执行脚本
可以使用 Git 的钩子(hooks)功能。Git 钩子是在特定事件发生时执行自定义脚本的方式。 下面是一个使用 pre-commit 钩子的例子,用于在执行 git commit 之前自动执行脚本: 进入你的 Git 仓库的根目录。进入 .git/hooks 目录&…...
基于springboot+vue的加盟店管理系统(前后端分离)
博主主页:猫头鹰源码 博主简介:Java领域优质创作者、CSDN博客专家、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战 主要内容:毕业设计(Javaweb项目|小程序等)、简历模板、学习资料、面试题库、技术咨询 文末联系获取 项目介绍…...
Gin中的Cookie和Session的用法
Gin中的Cookie和Session的用法 文章目录 Gin中的Cookie和Session的用法介绍Cookie代码演示 Session代码展示 介绍 cookie 和 session 是 Web 开发中常用的两种技术,主要用于跟踪用户的状态信息。 Cookie func (c *Context) Cookie(name string, value string, max…...
【算法】反悔贪心
文章目录 反悔贪心力扣题目列表630. 课程表 III871. 最低加油次数LCP 30. 魔塔游戏2813. 子序列最大优雅度 洛谷题目列表P2949 [USACO09OPEN] Work Scheduling GP1209 [USACO1.3] 修理牛棚 Barn RepairP2123 皇后游戏(🚹省选/NOI− TODO) 相关…...
Hadoop的安装和使用,Windows使用shell命令简单操作HDFS
1,Hadoop简介 Hadoop是一个能够对大量数据进行分布式处理的软件框架,并且是以一种可靠、高效、可伸缩的方式进行处理的,它具有以下几个方面的特性。 高可靠性。 高效性。 高可扩展性。 高容错性。 成本低。 运行在Linux平台上。 支持多种编程…...
ubuntu上ffmpeg使用framebuffer显示video
这个主题是想验证使用fbdev(Linux framebuffer device),将video直接显示到Linux framebuffer上,在FFmpeg中对应的FFOutputFormat 就是ff_fbdev_muxer。 const FFOutputFormat ff_fbdev_muxer {.p.name "fbdev",.p.long_…...
82 # koa-bodyparser 中间件的使用以及实现
准备工作 安装依赖 npm init -y npm i koakoa 文档:https://koajs.cn/# koa 中不能用回调的方式来实现,因为 async 函数执行的时候不会等待回调完成 app.use(async (ctx, next) > {console.log(ctx.path, ctx.method);if (ctx.path "/login…...
计算一串输出数字的累加和
计算一个文件内数字的累加和 awk {sum$1}END{print sum} 直接抽取数据以后的打印是这样的 cat step-iostat.1125.log |grep sda |cut -c "49-56" |awk {sum$1}END{print sum}...
python包导入原理解析
原文链接: https://www.cnblogs.com/hi3254014978/p/15317976.html 根据编程经验的不同,我们在运行程序时可能经常或者偶尔碰到下面这些问题,仔细观察后会发现这些问题无一例外都出现了一个相同的短语,很容易就可以发现࿰…...
MNIST手写数字辨识-cnn网路 (机器学习中的hello world,加油)
用PyTorch实现MNIST手写数字识别(非常详细) - 知乎 (zhihu.com) 参考来源(这篇文章非常适合入门来看,每个细节都讲解得很到位) 一、模块函数用法-查漏补缺: 1.关于torch.nn.functional.max_pool2d()的用法: 上述示例…...
论文笔记《3D Gaussian Splatting for Real-Time Radiance Field Rendering》
项目地址 原论文 Abstract 最近辐射场方法彻底改变了多图/视频场景捕获的新视角合成。然而取得高视觉质量仍需神经网络花费大量时间训练和渲染,同时最近较快的方法都无可避免地以质量为代价。对于无边界的完整场景(而不是孤立的对象)和 10…...
数据库管理系统,数据库,sql的基本介绍以及它们之间的关系
数据库管理系统(Database Management System,简称DBMS)是一种软件工具或系统,用于管理和维护数据库的创建、访问、更新和管理。DBMS允许用户在数据库中存储、检索和操作数据,同时提供了数据安全性、完整性和一致性的控…...
【Flowable】Springboot使用Flowable(一)
一、项目依赖 <dependency><groupId>org.flowable</groupId><artifactId>flowable-engine</artifactId><version>6.3.0</version></dependency><dependency><groupId>mysql</groupId><artifactId>my…...
戳泡泡小游戏
欢迎来到程序小院 戳泡泡 玩法: 鼠标点击上升的起泡泡,点击暴躁记录分数,不要让泡泡越过屏幕,共有三次复活生命,会有随机星星出现,点击即可暴躁全屏哦^^。开始游戏https://www.ormcc.com/play/gameStart/1…...
Redis缓存
1. Redis缓存相关问题 1.1 缓存穿透 缓存穿透是指查询一个数据库一定不存在的数据。 我们以前正常的使用Redis缓存的流程大致是: 1、数据查询首先进行缓存查询 2、如果数据存在则直接返回缓存数据 3、如果数据不存在,就对数据库进行查询࿰…...
mysql 插入更新数据
insert into insert into 语句进行插入时,如果插入的字段包含 主键或者唯一索引字段,那么, 1)主键或唯一索引 已存在,则插入失败 1062 - Duplicate entry 1 for key PRIMARY 2)只有主键或者唯一索 引不存…...
网站 微信小程序怎么做/太原seo管理
若在git中出现这个http://eslint.org/docs/rules/eol-last 他是提醒你:在文件末尾要求或禁止换行 比如代码如下: 若在git中出现这个https://eslint.org/docs/rules/semi 他是提醒你:需要或不允许使用分号代替 点进去翻译文字。 若在git中出现…...
喀什网站建设公司/一键生成原创文案
Processing入门简介 http://blog.csdn.net/mysunnytime/article/details/16104723 Processing官方教程 https://processing.org/tutorials/gettingstarted/ Processing程序中重写了两个函数:setup()和draw()。 setup()是在程序开始时调用的函数,只执…...
绵阳做网站的有哪些/大型集团网站建设公司
背景 在服务器上安装了服务,其中有使用chromedp来进行网页截屏 在云服务器使用chromedb包需要事先安装chrome ##下载源加入到系统的源列表 sudo wget http://www.linuxidc.com/files/repo/google-chrome.list -P /etc/apt/sources.list.d/##导入谷歌软件公钥 wget…...
县门户网站建设方案/自己建个网站要多少钱
this this 是自身的一个对象,代表对象本身,可以理解为:指向对象本身的一个指针。 this 的用法在 java 中大体可以分为 3 种: 普通的直接引用 这种就不用讲了,this 相当于是指向当前对象本身。 形参与成员名字重名&…...
绚丽的网站/网址导航大全
前言 今天我们来学习一下动态sql,看起来很NB的感觉。我们来看看官网是怎么来介绍动态sql的。动态 SQL 是 MyBatis 的强大特性之一。如果你使用过 JDBC 或其它类似的框架,你应该能理解根据不同条件拼接 SQL 语句有多痛苦,例如拼接时要确保不能…...
手机网站建设比较好的公司/临沂seo公司
最近在看JVM虚拟机,想要搞懂虚拟机的内部运行机制,指令码的分析是必不可少的!来看一个简单的测试小程序,看看里面的运行机制!这里就需要借助javap命令去查看了! 第一步,创建一个简单的测试程序…...