1.javascript类型中你不知道的细节

2023-05-16

1. 数据类型

基本数据类型:

  1. Undefined;
  2. Null;
  3. Boolean;
  4. String;
  5. Number;
  6. Symbol;
  7. Object。

1.1 undefined 和 null

1.1.1 undefined

为什么有的编程规范要求用void 0代替undefined

Undefined类型表示未定义,它的类型只有一个值,就是undefined。任何变量在赋值前是 Undefined
型、值为undefined,一般我们可以用全局变量undefined(就是名为undefined的这个变量)来表达这个
值,或者void运算来把任一一个表达式变成undefined值。
首先我们来看一下什么是void

void 运算符 对给定的表达式进行求值,然后返回 undefined。

 function asd() {
      console.log('asdasd');
 }
 console.log(void (asd()));

结果为: asdasdundefined

void 0代替undefined的好处是:

  1. void 0代替undefined省3个字节
 "undefined".length     //9
  "void 0".length    //6
  1. 避免undefined被重写的可能
    在ES5之前,window下的undefined是可以被重写的,于是导致了某些极端情况下使用undefined会出现一定的差错。所以,用void 0是为了防止undefined被重写而出现判断不准确的情况。
    注: ES5之后的标准中,规定了全局变量下的undefined值为只读,不可改写的,但是局部变量中依然可以对之进行改写。

1.1.2 null

Undefinednull有一定的表意差别,null表示的是:“定义了但是为空”。所以,在实际编程时,我们一般不会把变量赋值为undefined,这样可以保证所有值为undefined的变量,都是从未赋值的自然状态。

Null 类型也只有一个值,就是 null,它的语义表示空值,与 undefined 不同,nullJavaScript 关键字,所以在任何代码中,你都可以放心用 null 关键字来获取 null 值。

1.2 Boolean

Boolean 类型有两个值, truefalse,它用于表示逻辑意义上的真和假,同样有关键字 truefalse 来表示两个值。

1.3 String

先问一个问题,字符串有最大长度吗?

答案是有的!

String 用于表示文本数据。String 有最大长度是 2^53 - 1,这在一般开发中都是够用的,但是有趣的是,这个所谓最大长度,并不完全是你理解中的字符数。

因为String 的意义并非“字符串”,而是字符串的 UTF16 编码,我们字符串的操作 charAtcharCodeAt
length 等方法针对的都是 UTF16 编码。所以,字符串的最大长度,实际上是受字符串的编码长度影响的。

现行的字符集国际标准,字符是以 Unicode 的方式表示的,每一个 Unicode 的码点表示一个字符,理论上,Unicode 的范围是无限的。UTFUnicode的编码方式,规定了码点在计算机中的表示方法,常见的有 UTF16UTF8Unicode 的码点通常用 U+??? 来表示,其中 ??? 是十六进制的码点值。 0-65536(U+0000 - U+FFFF)的码点被称为基本字符区域

JavaScript 中的字符串是永远无法变更的,一旦字符串构造出来,无法用任何方式改变字符串的内容,所以字符串具有值类型的特征。

JavaScript 字符串把每个 UTF16 单元当作一个字符来处理,所以处理非BMP(超出 U+0000 - U+FFFF 范围)的字符时,你应该格外小心

JavaScript 这个设计继承自 Java,最新标准中是这样解释的,这样设计是为了“性能和尽可能实现起来简
单”。因为现实中很少用到 BMP 之外的字符。

1.4 Number

请问0.1 + 0.2 等于0.3么?
答案是:在javascript中不等于

Number类型表示我们通常意义上的“数字”。这个数字大致对应数学中的有理数,当然,在计算机中,我们有一定的精度限制。

JavaScript中的Number类型有 18437736874454810627(即2^64-2^53+3) 个值。

JavaScript 中的 Number 类型基本符合 IEEE 754-2008 规定的双精度浮点数规则,但是JavaScript为了表达几个额外的语言场景(比如不让除以0出错,而引入了无穷大的概念),规定了几个例外情况:

  • NaN,占用了 9007199254740990,这原本是符合IEEE规则的数字;
  • Infinity,无穷大;
  • -Infinity,负无穷大。

另外,值得注意的是,JavaScript中有 +0-0,在加法类运算中它们没有区别,但是除法的场合则需要特
别留意区分,“忘记检测除以-0,而得到负无穷大”的情况经常会导致错误,而区分 +0-0 的方式,正是检测 1/xInfinity还是-Infinity

根据双精度浮点数的定义,Number类型中有效的整数范围是-0x1fffffffffffff0x1fffffffffffff,所以Number
无法精确表示此范围外的整数。

同样根据浮点数的定义 ,非整数的Number类型无法用 ==(===也不行)来比较 ,一段著名的代码,这也正是为什么在JavaScript中,0.1+0.2不能=0.3:

console.log(	0.1	+	0.2	==	0.3);     //false

这里输出的结果是false,说明两边不相等的,这是浮点运算的特点,也是很多同学疑惑的来源,浮点数运
算的精度问题导致等式左右的结果并不是严格相等,而是相差了个微小的值。

所以实际上,这里错误的不是结论,而是比较的方法,正确的比较方法是使用JavaScript提供的最小精度
值:

console.log(	Math.abs(0.1	+	0.2	-	0.3)	<=	Number.EPSILON);    //true

检查等式左右两边差的绝对值是否小于最小精度,才是正确的比较浮点数的方法。这段代码结果就是true
了。

1.5 Symbol

ES6新加入的Symbol是个什么东西?

SymbolES6中引入的新类型,它是一切非字符串的对象key的集合,在ES6规范中,整个对象系统被用 Symbol重塑

Symbol可以具有字符串类型的描述,但是即使描述相同,Symbol也不相等。

我们创建Symbol的方式是使用全局的Symbol函数。例如:

var mySymbol = Symbol("my symbol");

一些标准中提到的Symbol,可以在全局的 Symbol 函数的属性中找到。例如,我们可以使用Symbol.iterator 来自定义 for…of 在对象上的行为:

var o = new Object
o[Symbol.iterator] = function() {
	var v = 0
	return {
		next: function() {
			return { value: v++, done: v > 10 }
		}
	}
};
for(var v of o)
console.log(v); // 0 1 2 3 ... 9

代码中我们定义了iterator之后,用for(var v of o)就可以调用这个函数,然后我们可以根据函数的行为,产
生一个for…of的行为。

这里我们给对象o添加了 Symbol.iterator 属性,并且按照迭代器的要求定义了一个010的迭代器,之后我
们就可以在for of中愉快地使用这个o对象啦。

这些标准中被称为“众所周知”的 Symbol,也构成了语言的一类接口形式。它们允许编写与语言结合更紧
密的 API。

1.6. Object

为什么给对象添加的方法能用在基本类型上?

ObjectJavaScript 中最复杂的类型,也是 JavaScript 的核心机制之一。Object表示对象的意思,它是一切有形和无形物体的总称。

JavaScript 中,对象的定义是“属性的集合”。属性分为数据属性和访问器属性,二者都是key-value
构,key可以是字符串或者 Symbol类型。

提到对象,我们必须要提到一个概念:类。

因为 C++ 和 Java 的成功,在这两门语言中,每个类都是一个类型,二者几乎等同,以至于很多人常常会把
JavaScript的 “类” 与 类型 混淆

事实上,JavaScript 中的“类”仅仅是运行时对象的一个私有属性,而JavaScript中是无法自定义类型的。

JavaScript中的几个基本类型,都在对象类型中有一个“亲戚”。它们是:

  • Number
  • String
  • Boolean
  • Symbol

所以,我们必须认识到3new Number(3) 是完全不同的值,它们一个是 Number类型,一个是对象类型。

NumberStringBoolean,三个构造器是两用的,当跟 new 搭配时,它们产生对象,当直接调用时,它们表示强制类型转换。

Symbol函数比较特殊,直接用new调用它会抛出错误,但它仍然是Symbol对象的构造器。

JavaScript 语言设计上试图模糊对象和基本类型之间的关系,我们日常代码可以把对象的方法在基本类型上使用,比如:

console.log('asd'.charAt(0)); //a

甚至我们在原型上添加方法,都可以应用于基本类型,比如以下代码,在 Symbol原型上添加了hello方法,在任何 Symbol类型变量都可以调用。

Symbol.prototype.hello	=	()	=>	console.log("hello");

var	a	=	Symbol("a");
console.log(typeof	a);	//symbol, a并⾮对象
a.hello();	//hello,有效

我们来回答开头提到的问题: 运算符提供了装箱操作,它会根据基础类型构造一个临时对象,使得
我们能在基础类型上调用对应对象的方法。

2.类型转换

讲完了基本类型,我们来介绍一个现象:类型转换。

因为JS是弱类型语言,所以类型转换发生非常频繁,大部分我们熟悉的运算都会先进行类型转换。大部分类型转换符合人类的直觉,但是如果我们不去理解类型转换的严格定义,很容易造成一些代码中的判断失误。

其中最为臭名昭著的是JS中的“ == ”运算,因为试图实现跨类型的比较,它的规则复杂到几乎没人可以记
住。

这里我们当然也不打算讲解==的规则,它属于设计失误,并非语言中有价值的部分,很多实践中推荐禁止
使用“ ==”,而要求程序员进行显式地类型转换后,用 === 比较。

其它运算,如加减乘除大于小于,也都会涉及类型转换。幸好的是,实际上大部分类型转换规则是非常简单
的,如下表所示:
在这里插入图片描述
在这个里面,较为复杂的部分是Number和String之间的转换,以及对象跟基本类型之间的转换。我们分别
来看一看这几种转换的规则。

2.1 String to Number

字符串到数字的类型转换,存在一个语法结构,类型转换支持十进制、二进制、八进制和十六进制,比如

  • 30;
  • 0b111;
  • 0o13;
  • 0xFF。

此外,JavaScript支持的字符串语法还包括正负号科学计数法,可以使用大写或者小写的e来表示

  • 1e3;
  • -1e-2。

需要注意的是,parseIntparseFloat 并不使用这个转换,所以支持的语法跟这里不尽相同。

在不传入第二个参数的情况下,parseInt只支持16进制前缀“0x”,而且会忽略非数字字符,也不支持科学
计数法。

在一些古老的浏览器环境中,parseInt还支持0开头的数字作为8进制前缀,这是很多错误的来源。所以在任何环境下,都建议传入parseInt的第二个参数,而parseFloat则直接把原字符串作为十进制来解析,它不会引入任何的其他进制。

多数情况下,Number 是比 parseIntparseFloat 更好的选择。

2.2 Number to String

在较小的范围内,数字到字符串的转换是完全符合你直觉的十进制表示。当Number绝对值较大或者较小
时,字符串表示则是使用科学计数法表示的。这个算法细节繁多,我们从感性的角度认识,它其实就是保证
了产生的字符串不会过长。

具体的算法,你可以去参考JavaScript的语言标准。由于这个部分内容,我觉得在日常开发中很少用到,所
以这里我就不去详细地讲解了。

2.3 装箱转换

每一种基本类型NumberStringBooleanSymbol在对象中都有对应的类,所谓装箱转换,正是把基本
类型转换为对应的对象,它是类型转换中一种相当重要的种类。

前文提到,全局的Symbol函数无法使用new来调用,但我们仍可以利用装箱机制来得到一个Symbol对象,我们可以利用一个函数的call方法来强迫产生装箱。

我们定义一个函数,函数里面只有return this,然后我们调用函数的call方法到一个Symbol类型的值上,这
样就会产生一个symbolObject

我们可以用console.log看一下这个东西的type of,它的值是object,我们使用symbolObject instanceof 可以看到,它是Symbol这个类的实例,我们找它的constructor也是等于Symbol的,所以我们无论从哪个角度看,它都是Symbol装箱过的对象:

var	symbolObject = (function(){	return	this;	}).call(Symbol("a"));
console.log(typeof	symbolObject);	//object
console.log(symbolObject	instanceof	Symbol);	//true
console.log(symbolObject.constructor	==	Symbol);	//true

装箱机制会频繁产生临时对象,在一些对性能要求较高的场景下,我们应该尽量避免对基本类型做装箱转
换。

使用内置的Object函数,我们可以在JavaScript代码中显式调用装箱能力。

var	symbolObject = Object(Symbol("a"));
console.log(typeof	symbolObject);	//object
console.log(symbolObject	instanceof	Symbol);	//true
console.log(symbolObject.constructor	==	Symbol);	//true

每一类装箱对象皆有私有的 Class属性,这些属性可以用Object.prototype.toString获取:

var	symbolObject	=	Object(Symbol("a"));
console.log(Object.prototype.toString.call(symbolObject)); //[object Symbol]

在 JavaScript 中,没有任何方法可以更改私有的 Class 属性,因此Object.prototype.toString 是可以准确识别对象对应的基本类型的方法,它比 instanceof 更加准确。

但需要注意的是,call本身会产生装箱操作,所以需要配合 typeof 来区分基本类型还是对象类型

2.4 拆箱转换

JavaScript标准中,规定了 ToPrimitive 函数,它是对象类型到基本类型的转换(即,拆箱转换)。

对象到 StringNumber 的转换都遵循“先拆箱再转换”的规则。通过拆箱转换,把对象变成基本类型,
再从基本类型转换为对应的 String 或者 Number

拆箱转换会尝试调用 valueOftoString 来获得拆箱后的基本类型。如果 valueOftoString 都不存在,或
者没有返回基本类型,则会产生类型错误 TypeError

var o = {
	valueOf : () => {console.log("valueOf"); return {}},
	toString : () => {console.log("toString"); return {}}
} 
o * 2
// valueOf
// toString
// TypeError

我们定义了一个对象oovalueOftoString两个方法,这两个方法都返回一个对象,然后我们进行o*2这个运算的时候,你会看见先执行了valueOf,接下来是toString,最后抛出了一个TypeError,这就说明了这
个拆箱转换失败了。

String 的拆箱转换会优先调用 toString。我们把刚才的运算从o*2换成 String(o),那么你会看到调用顺序
就变了。

var o = {
	valueOf : () => {console.log("valueOf"); return {}},
	toString : () => {console.log("toString"); return {}}
}
String(o)
// toString
// valueOf
// TypeError

在ES6 之后,还允许对象通过显式指定 @@toPrimitive Symbol 来覆盖原有的行为

var	o	=	{
	valueOf	:	()	=>	{console.log("valueOf");	return	{}},
	toString	:	()	=>	{console.log("toString");	return	{}}
}
o[Symbol.toPrimitive]	=	()	=>	{console.log("toPrimitive");	return	"hello"}

console.log(o	+	"")
//	toPrimitive
//	hello

参考: winter老师的重学前端-JavaScript类型:关于类型,有哪些你不知道的细节?

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

1.javascript类型中你不知道的细节 的相关文章

  • EventLoop execute() 怎么保证线程安全

    EventLoop 的 execute 是在 SingleThreadEventLoop 中实现的 64 Override public void execute Runnable task if task 61 61 null throw
  • 关于 find grep xargs 命令总结

    1 定义 amp 区别 xff1a 1 find命令是根据文件的属性进行查找 xff0c 如文件名 xff0c 文件大小 xff0c 所有者 xff0c 所属组 xff0c 是否为空 xff0c 访问时间 xff0c 修改时间等 2 gre
  • ubuntu如何在当前文件夹下打开终端

    1 打开终端 xff0c 执行以下命令 xff1a sudo apt get install nautilus open terminal 2 在终端中执行下列命令 xff0c 重新加载文件管理器 nautilus q 3 执行以上指令后在
  • 解决libssl.so.1.0.0: 找不到的问题

    安装了多个版本的openssl后 xff0c 导致adb或svn无法使用 xff0c 出现以下错误 xff1a libssl so 1 0 0 no version information available 记录下最后的解决方法 xff0
  • JS对象—5.文档对象(document)

    document对象 一 span class token punctuation span 元数据 span class token number 1 span characterSet span class token operator
  • Keil5及芯片包的安装以及 Keil5打开Keil4工程编译出错解决方法

    一 温馨提示 1 安装路径不能带中文 xff0c 必须是英文路径 2 安装目录不能跟 51 的 KEIL 或者 KEIL4 冲突 xff0c 三者目录必须分开 3 KEIL5 的安装比起 KEIL4 多了一个步骤 xff0c 必须添加 MC
  • 上下文切换

    上下文切换是操作系统比较重要的一部分 xff0c 提到它 xff0c 我们第一时间想到的会是使用时间片轮转方式调度的os中涉及的进程之间上下文切换 再问还有没有其他 xff0c 也许会想到中断时 xff0c 上下文似乎也要切换 这两种切换是
  • Android系统 应用图标显示未读消息数(BadgeNumber) 桌面app图标的角标显示

    http www 51itong net android badgenumber 9789 html
  • smbclient介绍

    smbclient介绍 1 Smbclient介绍1 1 SMB 协议介绍 2 Smbclient命令使用技巧2 1 Smbclient 功能说明2 2 语法2 3 参数2 4 使用举例 1 Smbclient介绍 Smbclient sa
  • 关于void指针的地址问题

    如图 void指针指向其他类型的数据时对其地址加1 它可指向几乎任何数据 xff0c 且指针加1时相当于字符指针加1 xff0c 利用这一特性可将void指针作为形参类型 xff0c 可传入任意数据且对形参操作时可类比字符指针 xff0c
  • Ubuntu apt update无论使用什么源都出现类似的错误

    下面是清华源执行后的情况 Ign 1 https mirrors tuna tsinghua edu cn ubuntu jammy InRelease Ign 2 https mirrors tuna tsinghua edu cn ub
  • 从源码分析C++中forward完美转发和move移动语义的本质区别

    完美转发可以看做一种能够按照原来类型转发到另一个地方 xff08 函数 xff09 的方法 xff08 废话 xff09 咱不如直接上源代码 xff08 move h xff09 xff1a template lt typename Tp
  • 实现对单链表的倒置

    我们知道数组的倒置比较简单 xff0c 只需要知道数组的头 xff0c 和数组的尾 xff0c 将其数据互换 xff0c 再将第二个和倒数第二个互换 xff0c 一直这样操作下去 xff0c 数组就实现倒置了 那么单链表也可以通过这样的方法
  • 立创开源|18650锂电池四路充电器

    该工程为18650四路电池充电器 xff0c 支持DC Micro USB USB typec输入 xff0c 同时四路充电 充电芯片采用价格便宜的TP4056 xff0c 电池盒采用直插电池盒 每节电池充电电流为1A xff0c 由于电流
  • 无法连接上 archive.ubuntukylin.com:10006 (120.79.211.60),连接超时

    无法连接上 archive ubuntukylin com 10006 120 79 211 60 xff0c 连接超时解决方法 问题描述 执行sudo apt get update时出现如下错误 xff1a 错误 12 http arch
  • 【C++】模板与泛型编程

    泛型编程 泛型编程最初诞生于C 43 43 中 xff0c 由Alexander Stepanov 2 和David Musser 3 创立 目的是为了实现C 43 43 的STL xff08 标准模板库 xff09 其语言支持机制就是模板
  • LXC(Linux containers)常用命令介绍

    lxc version 用于显示系统LXC的版本号 xff08 可以通过此命令判断系统是否安装了lxc xff09 用法 xff1a lxc version 例如 lxc version lxc checkconfig 用于判断linux内
  • Docker 大势已去,Podman 万岁

    前言 郑重声明 xff1a 本文不是 Podman 的入门篇 xff0c 入门请阅读这篇文章 xff1a 再见 Docker xff0c 是时候拥抱下一代容器工具了 Podman 原来是 CRI O 项目的一部分 xff0c 后来被分离成一
  • 使用node开发一个解放双手的小工具《二》- vsCode插件包装

    背景 xff1a 此篇是上篇 使用node开发一个解放双手的小工具 的后续 xff0c 前边遗留了一些问题 xff0c 最近完善了一下 因为发现实际使用起来 xff0c 有很多的不方便 xff1a 使用上 xff0c 需要配置对应的根目录
  • 使用网络调试助手时,踩坑

    在使用网络调试助手时 xff0c 踩坑很多 xff1a 1 作为tcp的客户端 xff0c 或者服务端 xff0c 没有注意发送设置以ASCII还是HEX 导致目标环境接收解析数据异常出现段错误 2 xff1a 作为UDP作为客户端 xff

随机推荐

  • Win7 32 不能安装STM32 虚拟串口驱动解决方法

    1 对于一些精简过的系统 xff0c 无法安装虚拟串口 xff0c 是由于系统缺少mdmcpq inf和usbser sys文件所造成的 只需要将文件下载下来放在相应的文件夹下面就行了 文件对应的目录如下 xff1a mdmcpq inf在
  • gitee使用教程

    目录 版本控制 1 Gitee上注册账户 2 新建一个远程代码仓 xff0c 点击右上方的加号 3 修改远程仓为开源的 编辑 4 本地下载git 5 克隆远程仓到本地 xff0c 复制地址 6 创建代码并提交到远程仓库 7 将本地代码提交到
  • Telnet 接口的使用(一):Telnet的安装与开启

    什么是 Telnet 简介 telnet 用于远程登录 xff0c Telnet的工作方式为 服务器 客户端 方式 xff0c 它提供了从一台设备 xff08 Telnet客户端 xff09 远程登录到另一台设备 xff08 Telnet服
  • Android系统四层体系架构

    Android体系架构分为四层 xff1a 应用层 应用框架层 库层 内核层 xff08 盗用一张图 xff09 一 应用层 应用层包括手机上的所有APP xff0c 无论是系统自带的还是用户开发的 他们都是基于第二层应用框架层开发的 二
  • 芯片的开发板和评估板的区别

    评估版一般都是半导体生产厂家所提供的 xff0c 用于器件性能评估用 xff0c 大公司不用他来赚钱 xff1b 开发板大多说是通过板子赚钱的 xff0c 就是很多的网友工程师做的 xff1b 目标板是在开发产品的过程中 xff0c 相对于
  • 增量式pid+位置式PID(电机位置闭环控制)

    ps xff1a 2022更新 pid详细解释 一般很少用增量式 xff0c 都是用位置式 xff0c 下文增量式可以不看 本文分为几个部分 xff1a 1 编码器 2 定时器输入捕获 xff08 把定时器初始化为编码器模式 xff09 3
  • Vmware 扩容磁盘

    Vmware 扩容磁盘 第一步 xff0c 首先添加一块磁盘 xff0c 进行分区第二步 xff0c 创建物理卷加入组第三步 xff0c 进行扩容 目录第四步 xff0c 刷新逻辑卷 第一步 xff0c 首先添加一块磁盘 xff0c 进行分
  • 思科模拟器中的交换机使用方法

    思科模拟器中的交换机使用方法 思科模拟器中有较多种交换机型号 xff0c 这里只是简单的介绍一下二层交换机2960 xff0c 以及三层交换机中的3560 1 关于交换机的原理 xff1a 交换机是通过其保存的MAC地址表来进行工作的 xf
  • 计算机发展15件重大事件(图说)

    链接 xff1a https vision xitek com famous 201001 28 36559 html 一 1946年 xff0c 第一台电子计算机 埃尼阿克 问世 二 1976年 xff0c 苹果电脑Apple I现世 三
  • vsftp登录报530 Login incorrect无法登录问题解决

    vsftp登录报530 Login incorrect无法登录问题解决 今天在搭建FTP服务器的时候遇到了530 Login incorrect这个问题 通过修改配置文件解决了 总结了一下在搭建FTP服务器的时要注意的地方大概有下面这几点
  • Linux上SMB挂载提示mount: block device //xxx.xxx.xx.xx/xx is write-protected, mounting read-only时解决办法

    当在Linux上挂载SMB服务器时候有时会提示如下错误 xff1a root 64 test mount o username 61 lisi 192 168 23 32 smb test mount block device 192 16
  • Linux下的LAMP环境搭建时访问PHP页面时变成下载页面的原因

    在搭建LAMP环境的时候遇到了配置完PHP环境后测试访问PHP页面的时候却变成下载的情况 xff0c 主要的影响有一下两个方面 1 PHP的配置问题 2 主要原因是httpd conf配置文件内容出错大致有下面几个地方 xff1a Load
  • 服务器肉鸡/入侵被恶意利用的排查和优化方案

    排查方法 xff1a 1 账户方面 xff1a Windows xff1a xff08 1 xff09 检查服务器内是否有异常的账户 xff0c 查看下服务器内是否有非系统和用户本身创建的账户 xff0c 一般黑客创建的账户账户名 后会有
  • Opensuse如何安装桌面环境

    安装必须的范式 xff1a zypper install t pattern kde kde plasma 编辑 etc sysconfig displaymanager 文件并设定 DISPLAYMANAGER 61 kdm xff0c
  • 怎么用谷歌学术检索下载外文文献

    谷歌学术是一个可以免费搜索外文学术文章的搜索引擎 xff0c 包括了世界上绝大部分出版的学术期刊 xff0c 可广泛搜索学术文献 谷歌学术可了解有关某一领域的学术文献 xff1b 了解某一作者的著述 xff0c 并提供书目信息 xff08
  • 英文文献去哪里查找,8个超强英文文献查找网站建议收藏

    英文文献去哪里查找 xff1f 找对方向用对工具可大幅提升学习和研究效率 xff01 下面详细介绍8个查找英文文献非常好用的网站 一 文献党下载器 xff08 wxdown org xff09 xff1a 该网站几乎整合汇聚了所有文献数据库
  • 基于STM32系列的模拟串口(非阻塞式)

    STM32单片机一般少则3个串口 多则5个 而我这次的项目还偏偏5个硬件串口还是不够用 至于不够用的原因 哎 是项目做到后面有定制 随便哪个串口都省不得 没得办法 只能另想法子咯 板子上有几个预留IO口 可以用来模拟串口 模拟串口一般都选9
  • 复制一个目录下的所有文件到另外一个目录(Java实现)

    首先说说我的思路 xff0c 要复制一个目录下的所有文件到另外的一个目录下 xff0c 我们不知道目录下的结构是怎么样的 xff0c 也不知道目录有多少层 xff0c 文件有多少个 xff0c 这样我们会想用循环 xff0c for 但是我
  • RT-Thread嵌入式操作系统

    一 系统架构 RT Thread xff0c 全称是 Real Time Thread xff0c 顾名思义 xff0c 它是一个嵌入式实时多线程操作系统 RT Thread 主要采用 C 语言编写 xff0c 浅显易懂 xff0c 方便移
  • 1.javascript类型中你不知道的细节

    1 数据类型 基本数据类型 xff1a Undefined xff1b Null xff1b Boolean xff1b String xff1b Number xff1b Symbol xff1b Object 1 1 undefined