数据类型
- 为什么需要数据类型?在计算机中,不同的数据所占用的存储空间是不同的,为了便于把数据分成所需内存大小不同的数据,充分利用存储空间,于是定义了不同的数据类型。
- 变量的数据类型:JS是一种弱类型或者说解释型语言,意味着不用提前声明变量的类型,在程序运行过程中类型会被自动确定。
- 数据的存储单位:bit < byte < kb < mb < gb < tb < ...
| 存储单位 | 换算 |
|---|---|
| bit(位) | 最小单位,存储1或0 |
| b(字节) | 1b = 8bit |
| kb(千字节) | 1kb = 1024b |
| mb(兆字节) | 1mb = 1024kb |
| gb(G字节) | 1gb = 1024mb |
| ... | ... |
JS数据类型
- 简单数据类型:Number、String、Boolean、Null、Undefined(Symbol、BigInt为ES6新增)。
- 复杂数据类型: Object(array、Object、function、date…)。
- 简单数据类型又叫做原始值,存在栈(stack)内存中,也叫做不可改变的原始值。
- 理解原始值的存放方式:
var a = 10; // 在栈中申请一个内存空间 a,值为10
var b = a; // 再申请一个内存空间 b,将 a 的值拷贝一份放到 b 中,相当于副本。互相不影响
a = 30; // a不再指向之前的内存空间,而是在栈中重新申请一个空间 a,值为30。之前的内存空间失去了指向(无法访问),但数据依然存在,等待着接下来其他变量申请空间被覆盖。
- 复杂数据类型也叫做引用值,存在堆(heap)内存中,包括Array、Object、Function、Date、RegExp……
- 理解引用值的存放方式:
var arr = [1, 2]; // 将数组的值存放到堆中,同时栈也申请内存空间 arr,存放指向堆里的值的地址
var arr1 = arr; // 申请一个栈内存空间 arr1, 将 arr 栈中存放的地址拷贝一份放到 arr1 中(拷贝的是地址),两者栈中的值相同,都指向堆中的同一个数据
arr.push(3); // 根据 arr 栈中的地址找到堆数据,修改为[1, 2, 3] 此时修改 arr 就相当于修改了 arr1 ,因为二者都指向同一个堆中的数据
// arr = [3, 4]; 在堆中又重新申请了新的空间存放[3, 4],然后 arr 在栈中重新申请空间存放指向这个新空间的地址。 此时 arr1 还是[1, 2], 因为 arr 重新指向了一个新的地址,而 arr1 的指向却没变
null 和 undefined
- 都表示“没有”,区别是在JS中一般使用
null表示一个空对象;使用undefined表示一个未定义的原始值。
boolean
- 只有
true和false,表示真和假。 - 以下运算符会返回布尔值:
!、===、==、!==、!=、>、<、>=、<=。 - 除了
""、NaN、0、null、undefined、false以外任何值转为boolean都为true。
number
- JS内部所有的数字都是以64位浮点数形式储存,也就是说JS底层根本没有整数,所有数字都是64位浮点数的小数。
console.log(1 === 1.0); // true
- 由于浮点数不是精确的值,所以尽量避免涉及到小数的比较和运算。
console.log(0.1 + 0.2 === 0.3); // false
cosnole.log(0.3 / 0.1); // 2.9999999999999996
特殊数值
+0和-0:几乎相等,除了当作除数时。
console.log(-0 === +0); // true
console.log(0 === -0); // true
console.log(0 === +0); // true
console.log((1 / +0) === (1 / -0)); // false 因为 1 / +0 等于 Infinity; 1 / -0 等于 -Infinity
```
* `NaN`:表示非数,依然是`number`类型。
```javascript
console.log(5 - 'a'); // NaN
console.log(0 / 0); // NaN
console.log(typeof(NaN)); // 'number'
NaN与任何数运算得到的都是NaN;NaN不等于任何值,包括它自己。
Infinity和-Infinity:表示正负无穷。
console.log(1 / 0); // Infinity
console.log(1 / -0); // -Infinity
Infinity大于一切数值(除了NaN),-Infinity小于一切数值(除了NaN)。
全局方法
parseInt(string, radix)
- 用于将字符串转换成整数(小数位直接去掉),数字类型的值也可用。只能转换以数字开头的数值或字符串,其余一律 NaN。
radix表示以radix进制数为基底,将string转化为10进制的数,取值范围 2~36之间。省略则表示10进制。
console.log(parseInt("123")); // 123
console.log(parseInt("123.43")); // 123
console.log(parseInt("123px")); // 123
console.log(parseInt("1a23")); // 1
console.log(parseInt(' 1')); // 1 空格会被自动去除
// parseInt只能转换以数字开头的数值或字符串,其余一律 NaN
//(前提radix不是16进制,因为十六进制允许以a~f开头)
console.log(parseInt("a123")); // NaN
console.log(parseInt('')); // NaN
console.log(parseInt(true)); // NaN
console.log(parseInt(false)); // NaN
console.log(parseInt(null)); // NaN
console.log(parseInt(undefined)); // NaN
console.log(parseInt("a1", 16)); // 161 以十六进制基底,将 a1 转化为10进制的数
console.log(parseInt("0x1")); // 1 虽未填写 radix,但以"0x"开头则同样表示以十六进制为基底,将 "0x1"转化为10进制的数
parseFloat(string)
- 用于将字符串转换成浮点数(保留小数位),数字类型的值也可用。
console.log(parseFloat(100.2)); // 100.2
console.log(parseFloat(100)); // 100
// 如果非纯数字的字符串,则只保留至非数字位(不包括 .)前的数字。要是以非数字(不包括 .)开头则返回 NaN
console.log(parseFloat("100.2")); // 100.2
console.log(parseFloat("100")); // 100
console.log(parseFloat("100.2a")); // 100.2
console.log(parseFloat("12.a0")); // 12
console.log(parseFloat(".3")); // 0.3
console.log(parseFloat(' 1.56')); // 1.56
console.log(parseFloat('12a23ads')); // 12
console.log(parseFloat('12e23ads')); // 1.2e+24 数字后面跟着的字母 e是特殊值
转为
NaN的规则同parseInt。
isNaN(obj)
- 用来判断一个值是否为
NaN。只对数值有效,如果传入其他值,会被先转成数值。
console.log(isNaN(123)); // false
console.log(isNaN("123")); // false Number("123") ==> 123
console.log(isNaN(true)); // false Number(true) ==> 1
console.log(isNaN(null)); // false Number(null) ==> 0
console.log(isNaN(NaN)); // true
console.log(isNaN(undefined)); // true Number(undefined) ==> NaN
console.log(isNaN("abc")); // true Number("abc") ==> NaN
console.log(isNaN({})); // true Number({}) ==> NaN
// 数组比较特殊
console.log(isNaN([])); // false Number([]) == > 0
console.log(isNaN([1])); // false Number([1]) == > 1
console.log(isNaN([1,2])); // true Number([1,2]) == > NaN
console.log(isNaN(['aaa'])); // true Number(['aaa']) == > NaN
内部实现相当于调用 Number(obj)。
isFinite(obj)
- 返回一个布尔值,表示某个值是否为正常的数值。
console.log(isFinite(Infinity)); // false
console.log(isFinite(-Infinity)); // false
console.log(isFinite(NaN)); // false
console.log(isFinite(undefined)); // false
console.log(isFinite(null)); // true
console.log(isFinite(true)); // true
console.log(isFinite(0)); // true
console.log(isFinite("123")) // true
内部实现相当于调用 Number(obj)。
string
-
Unicode字符集: 也叫统一码、万国码,字符集表示多个字符的集合。它将世界各种语言里的每一个字符都定义了一个唯一的编码,这意味着世界上所有的语言都可以使用它,而不会出现冲突。 -
Unicode字符集的编码范围是
0x0000 - 0x10FFFF,可以容纳一百多万个字符,每个字符都有独一无二的编码,即每个字符都有一个二进制数值对应,也叫码点。 -
字符编码:字符集的一种实现方式,把字符集中的字符映射为特定的字节或字节序列,它是一种规则。UTF-8、UTF-16、UTF-32都是字符编码规则。 -
UTF-16有两种长度,对于码点在U+0000到U+FFFF之间的字符,长度为16位,也就是2个字节;对于码点在U+10000到U+10FFFF之间的字符,长度为32位,也就是4个字节。所以UTF-16的编码长度可以是2个字节或4个字节,这取决于每个字符的码点值。 -
JS内所有字符都是使用Unicode字符集表示,每个字符在JS中都是以16位(2个字节)的UTF-16格式存储,即使码点值是4个字节。这也就导致了字符串的length属性识别4个字节的字符会当成2个字符。
// 𝌆 对应码点为 U+1D306,在U+10000 到 U+10FFFF码点区间内,所以是4个字节
console.log('𝌆'.length); // 2 被当成了2个字符
- 字符串可以被视为字符数组,可以使用数组的方括号获取对应下标的值,但无法根据下标修改其中的单个字符。
var s = 'hello';
console.log(s[0]); // 'h'
s[0] = 'a';
console.log(s); // 'hello'
length属性
- 字符串的
length属性返回字符串的长度,该属性只能查询,无法修改。
var s = 'hello';
console.log(s.length); // 5
s.length = 4;
console.log(s.length); // 5
Base64
- base64是一种编码方法,可以将任意值转为
0~9、a-z、A-Z、+、/这64个字符组成的可打印字符。主要目的不是为了加密,而是为了不出现特殊字符。 btoa():任意值转为Base64编码。atob():Base64编码转为原来的值。
var str = 'Hello World!';
console.log(btoa(str)); // 'SGVsbG8gV29ybGQh'
console.log(atob('SGVsbG8gV29ybGQh')); // 'Hello World!'
console.log(btoa('你好')); // 报错
// 以上2个方法不适合非ASCII码的字符,会报错。如需要处理非ASCII码中间需插入一个转码环节
/**
* base64编码
*/
function b64Encode(str) {
return btoa(encodeURIComponent(str));
}
/**
* base64解码
*/
function b64Decode(str) {
return decodeURIComponent(atob(str));
}
console.log(b64Encode('你好')); // 'JUU0JUJEJUEwJUU1JUE1JUJE'
console.log(b64Decode('JUU0JUJEJUEwJUU1JUE1JUJE')); // '你好'
typeof 运算符
- 用来获取检测变量的数据类型,返回字符串类型的值:
- js共有3种方法用于检测一个变量到底是什么类型:
typeofinstanceofObject.prototype.toString()
console.log(typeof 123); // "number"
console.log(typeof "123"); // "string"
console.log(typeof true); // "boolean"
console.log(typeof {}); // "object"
console.log(typeof []); // "object"
console.log(typeof null); // "object"
console.log(typeof(new Number(1))); // "object" 包装类对象也会返回 object
function Person(name) {
this.name = name;
}
var stu = new Person();
console.log(typeof stu); // "object"
console.log(typeof Person); // "function"
var a;
var arr = [1, 2];
var obj = {};
console.log(typeof a); // "undefined" 只声明未赋值
console.log(typeof aaa); // "undefined" 未声明的变量,只有在 typeof中才不会报错,否则在其他任何地方都会报错
console.log(typeof arr[2]); // "undefined" 数组中没有第 3个元素或第 3个元素未赋值
console.log(typeof obj.uname); // "undefined" 对象中没有 uname属性
typeof 返回的 6种数据类型为:number、string、boolean、undefined、object、function