Round 1 数据类型相关
数据类型
JavaScript 的数据类型共有六种(ES6 又新增了第七种 Symbol 类型的值):
数值(number)、字符串(string)、布尔值(boolean)、undefined、null、对象(object)。
对象又可以分为三个子类:狭义的对象(object)、数组(array)、函数(function)。
其中数值、字符串、布尔值、undefined 和 null,合称为基本数据类型;而对象称为引用数据类型。
什么是基本数据类型?什么是引用数据类型?
在理解“什么是什么是基本数据类型,什么是引用数据类型”之前,我们先要知道什么是堆内存和栈内存。
栈内存
栈内存主要用于简单存储,一般存储一些大小已知或者有上限的变量。栈内存一般为有序存储,容量小,系统分配效率高。
堆内存
堆内存主要用于存储一些大小未知变量。堆内存存储时不仅要在堆内存中分配存储区域,还要把引用地址存到栈内存中,效率相对较低。
基本数据类型
基本数据是存在栈内存中的简单数据段,可以直接按值访问。
举个栗子:
var a = 1;
var b = a;
b = 2;
console.log(a); //1
- 声明一个变量
a = 1;此时a被存的栈内存中; - 声明一个变量
b = a;此时b获得了a值的拷贝,这个时候虽然两个变量的值相等,但是实际上两个变量是保存了两个不同的基本数据类型; - 改变变量
b = 2;此时b变量发生改变但是不会影响变量a;

引用数据类型
引用数据是存在堆内存中的对象,需要通过指向储存对象的内存地址的指针进行访问。
举个栗子:
var obj1 = new Object();
var obj2 = obj1;
obj2.attr= "添加属性";
console.log(obj1.attr); // 添加属性
- 声明一个对象
obj1 = new Object();此时obj1被存的栈内存中,而obj1所对应的值是存在堆内存中的对象的一个引用地址(指针); - 声明一个对象
obj2 = obj1;此时obj2获得了obj1值的拷贝,此时obj2就获得了存在堆内存中的对象的引用地址(指针),这样他们共同指向了同一个堆内存中的对象; - 给对象添加属性
obj2.attr= "添加属性";此时obj2实际上是为堆内存中的对象添加属性,所以obj1同样受到影响;

数据类型确定方法
使用 typeof 确定数据类型(typeof xxx)
数值 —— number
字符串 —— string
布尔值 —— boolean
函数 —— function
undefined —— undefined
[], {}, [...], {...}, null —— object
使用 instanceof 确定数据类型(object instanceof constructor)
使用 Object.prototype.toString 确定数据类型
null 和 undefined
null:空值
undefined:未定义
undefined == null —— true
Number(null) —— 0
Number(undefined) —— NaN
数值
JavaScript 内部,所有数字都是以64位浮点数形式储存(1 === 1.0 —— true)。
0.1 + 0.2 —— 0.30000000000000004
0.1 + 0.2 === 0.3 —— false
国际标准 IEEE 754,JavaScript 浮点数的 64 个二进制位
- 符号位(第1位):决定正负(0 —— 正数,1 —— 负数)
- 指数部分(第2位到第12位):决定大小 ——
64位浮点数的指数部分的长度是11个二进制位,意味着指数部分的最大值是2047(2的11次方减1)。也就是说,64位浮点数的指数部分的值最大为2047,分出一半表示负数,则 JavaScript 能够表示的数值范围为21024到2-1023,超出这个范围的数无法表示(正向溢出:返回Infinity;负向溢出:返回0)。
Number.MAX_VALUE // 1.7976931348623157e+308
Number.MIN_VALUE // 5e-324
- 小数部分(第13位到第64位):决定精度 —— 精度最多只能到53个二进制位,所以,绝对值小于2的53次方的整数,即
-253到253可以精确表示。
数值表示
- 自动将数值转为科学计数法的几种情况:
- 小数点前的数字多于21位;
- 小数点后的零多于5个
- 进制表示:
- 十进制:没有前缀;
- 二进制:前缀
0b或0B; - 八进制:前缀
0o或0O(或者有前导0、且只用到0-7的数值); - 十六进制:前缀
0x或0X。
特殊数值
-
+0 / -0:除了(1 / +0) === (1 / -0) // false,正零和负零是等价的; -
NaN:NaN不等于任何值,包括它本身; -
Infinity:Infinity与NaN比较,总是返回false;
数值相关操作
-
parseInt(): 将字符串转为整数
-
parseFloat(): 将一个字符串转为浮点数
-
isNaN(): 用来判断一个值是否为NaN
-
isFinite(): 判断某个值是否为正常的数值
字符串
- 长字符串分成多行,可在每行尾部使用反斜杠;
- 反斜杠(
\)表示字符(应该字符的 Unicode 码点)的三种用法:-
\后面紧跟三个八进制数 -
\x后面紧跟两个十六进制数 -
\u后面紧跟四个十六进制数
-
-
btoa():任意值转为 Base64 编码
atob():Base64 编码转为原来的值
对象
对象相关操作
-
Object.keys:查看一个对象本身的所有属性 -
delete:删除对象的属性,删除成功后返回true,存在且不得删除返回false
-
in('属性名' in 对象):检查对象是否包含某个属性,包含就返回true,否则返回false
-
hasOwnProperty(对象.hasOwnProperty('属性名')):判断是否为对象自身的属性 -
for...in:遍历一个对象的全部属性
-
with:方便操作同一个对象的多个属性
var obj = {
a: 1,
};
with (obj) {
a = 2;
b = 3;
}
obj.a // 2;
obj.b // undefined
b // 3;
函数
作用域
举个栗子:
var a = 1;
var x = function () {
console.log(a);
};
function f() {
var a = 2;
x();
}
f() // 1
函数 x 在声明的时候是处于最外层作用域,即使在函数 f 内部被调用,也不会取 f 内部的变量 a 的值,所以会返回 1 而不是 2。
参数
- 有同名的参数,则取最后出现的那个值;
-
arguments:函数运行时的所有参数,只有在函数体内部,才可以使用
-
arguments转为真正的数组的两种方法:
var args = Array.prototype.slice.call(arguments);
-
var args = [];
for (var i = 0; i < arguments.length; i++) {
args.push(arguments[i]);
}
-
callee:返回它所对应的原函数(可以通过arguments.callee调用函数自身)
闭包
闭包的两个最大用处:
- 可以读取函数内部的变量,这些变量始终保持在内存中,即闭包的诞生环境一直存在;
举个栗子:记住上一次调用时的运算结果
function fun(n) {
return function () {
return n++;
};
}
var f = fun(1);
f() // 1
f() // 2
f() // 3
- 封装对象的私有属性和私有方法
eval
只要不是直接调用,都属于别名调用,别名调用的作用域是全局作用域。
数组
-
length最大值是 4294967295; - 数组本质上是对象,所以可以为数组添加属性(但是不影响
length属性);
函数相关操作
name:返回函数的名字
var myFunc = function () {
console.log(11111);
}
function test(f) {
return f.name;
}
eval(test(myFunc))(); //11111
new Function('return ' + test(myFunc))()(); //11111
length:返回函数预期传入的参数个数,即函数定义之中的参数个数
toString:返回函数的源码字符串(原生的函数返回原生代码提示 function (){[native code]})
类型转换
强制转换
-
Number()—— 数字
转换规则
a. 原始类型值
Number(123) —— 123
Number('123') —— 123
Number('123abc') —— NaN
Number('') —— 0
Number(true) —— 1
Number(false) —— 0
Number(undefined) —— NaN
Number(null) —— 0
b. 对象
Number({a: 1}) —— NaN
Number([1, 2, 3]) —— NaN
Number([1]) —— 1
-
String()—— 字符串
转换规则同Number()只是调换了valueOf()和toString()的顺序。
a. 原始类型值
String(123)——"123"
String('abc')——"abc"
String(true)——"true"
String(undefined)——"undefined"
String(null)——"null"
b. 对象
String({a: 1})——"[object Object]"
String([1, 2, 3])——"1,2,3" -
Boolean()—— 布尔值
undefined、null、false、0、NaN、" "、' ' 为false,其他都为true。
空数组([])和空对象({}),都是true
隐式转换:
- 不同类型的数据互相运算(
+-*/)-
+:有可能转为字符串
注:
'1' + {}——"1[object Object]"
'1' + function (){}——"1function (){}"
'1' + undefined——"1undefined"
'1' + null——"1null" -
-或*或/:转成数值
-
- 对非布尔值类型的数据求布尔值
-
!():同Boolean()
-
- 对非数值类型的值使用一元运算符(
+/-)- 转成数值
注:
+{}——NaN
+{a: 1}——NaN
+[]——0
+[1, 2]——NaN
- 转成数值
- 比较判断(
===、!==、==、!=、>、>=、<、<=)- 转成布尔值
