前言
大家好,我是龙哈哈。一个 Java
,JavaScript
两栖动物。
本篇是FuckingJavaScript
系列的第一篇,我们来一起回顾一下数据类型
的相关知识。
var foo = 42; // foo is a Number now
foo = "bar"; // foo is a String now
foo = true; // foo is a Boolean now
数据类型
最新的 ECMAScript
标准定义了 9 种数据类型,包括了原始数据类型
,复杂数据类型
。
原始数据类型
String
Boolean
Number
Undefined
Symbol
Bigint
String
字符串类型,用于表示文本数据。 JavaScript 字符串是不可更改的。这意味着字符串一旦被创建,就不能被修改。但是,可以基于对原始字符串的操作来创建新的字符串。
- 字符串截取
String.substr()
- 字符串拼接
String.concat()
Boolean
布尔类型,只有两个值 true
和 false
,用于表示逻辑真与假。
Number
数字类型,有最大值(Number.MAX_VALUE
)和最小值(Number.MIN_VALUE
)限制,超出后会自动转换为特殊值 Infinity
和NaN(非数值,Not-a-Number)
。
Undefined
只有一个值 undefined
,JavaScript中,一个没有被赋值的变量会有个默认值 undefined
。
Symbol
符号类型,是ES6
中新定义的原始数据类型,符号类型是唯一
的并且不可修改
,不可枚举
。
- 作为
Object
的属性key
可以保证永远不会出现同名属性,防止属性污染 - 模拟
class
的私有属性
,控制变量读写
const garen = Symbol(); // 盖伦标记
const jarvanIV = Symbol(); // 嘉文四世标记
// 德玛西亚类
class demacia {
constructor(){
this[garen] = 'Garen';
this[jarvanIV] = 'JarvanIV';
}
getGaren(){
return this[garen];
}
setGaren(value){
this[garen] = value;
}
getJarvanIV(){
return this[jarvanIV];
}
setJarvanIV(value){
this[jarvanIV] = value;
}
}
Bigint
字如其意,ES11
新增加的数据类型类型,可以通过在整数末尾附加 n
创建,BigInt
可以安全地存储和操作大整数,甚至可以超过数字的安全整数限制。
复杂数据类型
Null
Object
Function
Null
Null类型只有一个值 null
,typeof null
值为 object
。
Object
对象类型,几乎所有可以通过 new Keyword
创建的,类型都是 Object
,例如 new Array()
、new Date()
、new Map()
、new Set()
、new WeekMap()
, new WeekSet()
等。
Function
Function
是一个特殊的 Obejct
,Function
的原型对象 prototype
的原型 __proto__
指向 Object
(有点绕口,关于原型对象和原型,在后续说到原型编程
时会讲)
Array
数组类型,常用于表示列表数据
数组的方法可总结为三类
- 会改变调用它们的对象自身的值,
pop
、push
、reverse
、splice
等 - 不会改变调用它们的对象的值,只会返回一个新的数组,
concat
,slice
,join
等 - 遍历方法,遍历过程中,不要对原数组进行任何操作,否则遍历结果可能会受影响,
foEach
,entries
,every
,some
,filter
,find
等
不同方法的具体用法这里就不一一说明了。
参考资料【MDN】数组Array
Date
日期类型,基于 Unix Time
,即自 1970年1月1日(UTC)
起经过的 毫秒数
。
Set,WeakSet,Map,WeakMap
- Map:键值对,并且能够记住键的原始插入顺序。任何值都可以作为一个键或一个值
- WeakMap:键必须是对象,而值可以是任意的,不可枚举,键名所指向的对象,都是弱引用,不计入垃圾回收机制
- Set:任意值的集合,你可以按照插入的顺序迭代它的元素。 Set中的元素只会出现一次,即 Set 中的元素是唯一的。
- WeakSet:对象值的集合,不可枚举,对象都是弱引用,不计入垃圾回收机制
不同数据类型的储存
JavaScript的 堆栈
和 Java 有些许差别
- 栈:原始类型的局部变量,对象的引用
- 堆:原始类型的全局变量,闭包场景中的变量, 对象类型数据
解释:下图中 闭包函数
的 原始类型
的 变量b
还存在于[[Scopes]]
对象中
var a = 1;
var f1 = function() {
var b = 2;
return function(){ console.log(b) }
}
console.dir(f1())
类型判断
typeof
检测一个变量的类型
typeof '1' // string
typeof 1 // number
typeof 1n // bigint
typeof false // boolean
typeof undefined // undefined
typeof null // object
typeof [] // object
typeof new Date() // object
typeof function(){} // function
typeof Date // function
typeof Array // function
typeof null
的值为 object
不同的对象在底层都表示为二进制,在JavacSript
中二进制前三位
都为0
的话会被判断为是Object
,null
的二进制表示全为0
,自然前三位也是0
,所以执行 typeof
时会返回 object
判断 null
类型,建议用 xxx=== null
对于复杂类型的数据来说,函数的类型为 function
,对象的类型为 object
instanceof
返回true/false,用于检测构造函数的 prototype 是否出现在实例对象的 原型链 上,从而判断对象类型。
如何手动实现 instanceof
instanceof
可以正确的判断对象的类型,原理是通过判断对象的原型链中能不能找到对应的类型。
function instanceof(left, right) {
// 原型
let proto = left.__proto__;
// 一层一层找对应的原型对象
while(proto) {
if (proto === right.prototype) {
return true;
}
proto = proto.__proto__
}
return false;
}
Object.prototype.toString
个人比较推荐的判断类型的方法是Object.prototype.toString
,可以完整的判断数据的类型,需要搭配 call
或者 apply
使用
Object.prototype.toString.call('1') // [object String]
Object.prototype.toString.call(1) // [object Number]
Object.prototype.toString.call(1n) // [object BigInt]
Object.prototype.toString.call(false) // [object Boolean]
Object.prototype.toString.call(undefined) // [object Undefined]
Object.prototype.toString.call(null) // [object Null]
Object.prototype.toString.call({}) // [object Object]
Object.prototype.toString.call([]) // [object Array]
Object.prototype.toString.call(new Date()) // [object Date]
返回值[object {type}]
中的 type
就是变量的类型
类型转换
- 强制转换
- 隐式转换
强制转换
通过 String(),Number(),Boolean()等函数做类型转换
隐式转换
类型转换中,编译器自动转换的方式,通常发生在通过运算符运算时
- 算术运算符
+
,-
,*
,÷
,%
等 ==
,!=
- 条件运算
if( )
,else if( )
等
算术运算符
- 字符串
+
数字,数字会转成字符串 - 数字
-
字符串,字符串会转成数字。如果字符串不是纯数字
就会转成NaN
。字符串-数字也一样。字符串-字符串也要先转成数字 +
,*
,÷
,%
,>
,<
和-
的转换也是一样
==,!=
先自动做类型转换
,再比较
- 字符串和数字比时,会将字符串转为数字,再比较
- 字符串和布尔比时,都转为数字,再比较
- 数字和布尔比时,会将布尔转为数字,再比较
条件运算
将条件内数据或表达式
转换为 Boolean
转换例子
转Number
true
为 1,false
为 0null
为 0,undefined
为NaN
,symbol
报错- 字符串看内容,如果是数字或者进制值就正常转,否则就
NaN
Number(true) // 1
Number(false) // 0
Number(null) // 0
Number(undefined) // NaN
Number(Symbol('1')) // Uncaught TypeError: Cannot convert a Symbol value to a number at Number
Number('1') // 1
Number('1a') // NaN
parseInt('1') // 1
parseInt('1.23 abc') // 1
parseFloat('1.1') // 1.2
parseFloat('1.1 abc') // 1.1
+'1' // 1
转String
String(1) // '1'
1.toString() // '1'
1.234.toFixed('2') // '1.23'
转Boolean
undefined
、null
、false
、0
、-0
、NaN
、空字符串
转为false
- 其他所有值都转为
true
Boolean(undefined) // false
Boolean(null) // false
Boolean(0) // false
Boolean('') // false
Boolean('0') // true
Boolean(NaN) // false
Boolean({ a: null }) // `true`
相等性判断
- 非严格相等比较 (
==
) - 严格相等比较 (
===
) Object.is(args1,args2)
区别
==
将执行类型转换后,比较值===
直接进行相同的比较,而不进行类型转换 (如果类型不同, 总会返回 false )Object.is
与===
处理类似,但是对NaN
、0
、-0
进行特殊处理,Object.is(NaN,NaN)
结果为true
,Object.is(0. -0)
结果为false
参考资料
- 【MDN】JavaScript 数据类型和数据结构
- 【MDN】JavaScript相等性判断
最后
文中如有错误,欢迎在评论区指正。
如果这篇文章对你有所帮助,欢迎点赞、评论和关注。
系列文章
- 【FuckingJavaScript系列】数据类型,你真的掌握了吗?
- 【FuckingJavaScript系列】原型编程,你真的理解了吗?
- 【FuckingJavaScript系列】函数编程,你真的熟练了吗?
- 【FuckingJavaScript系列】异步编程,你真的学会了吗?
- 【FuckingJavaScript系列】事件循环,你真的明白了吗?
- 【FuckingJavaScript系列】垃圾回收,你真的清楚了吗?
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!