JS基础知识梳理(一)

最近花了点小钱买了本《前端面试之道》小册,目前刚看完JS基础知识部分,感觉挺不错的,收获挺多。由于是作者收集+个人积累所总结的知识,读后确实很有收获,但是毕竟是他人经验,时间一久,总是容易忘记。所以打算记录下来,毕竟好记性不如烂键盘,😄。

基本数据类型(英文为Primitive)

boolean

truefalse, 这里注意new BooleanBoolean的区别。

如果使用new Boolean()会返回一个Boolean对象,而使用Boolean()则返回一个基础boolean类型。

等于false的值: false, '', undefined, null, 0, NaN
判断代码:

1
2
3
if ([false, '', undefined, null, 0, NaN].every(item => !Boolean(item))) {
console.log('全部等于false');
}

使用例子

  1. 清除数组中的false项: arr.filter(Boolean)
  2. 待补充

null

null并不是对象, 这个算是JS的bug。因为在JS的最初版本中使用的是32位系统,出于性能考虑使用低位存储变量的类型信息,000开头代表是对象,然而null为全零表示,所以错误的判断为对象。
from 小册

undefined

表示变量只声明但是未赋值

number

浮点类型,会有精度缺失问题。坑点预警。

string

单纯的字符串。

symbol

ES6新引入的类型,为了唯一性.

复合数据类型(对象)

对象变量存储的是对象的指针地址。

如何判断数据类型

typeof

对于typeof null会返回object,上面解释了这是一个bug。其他的数据基本ok,

1
2
3
4
5
typeof 1 // number
typeof 'zyt' // string
typeof undefined // undefined
typeof true // boolean
typeof {} // object

instanceof

从名字上来看,表示是否是其的实例对象。适用于复合类型数据的判断.

1
2
const arr = new Array();
arr instanceof Array; // true

类型转换

类型转换规则

转成布尔值

使用Boolean。如:

1
2
3
4
5
6
7
8
9
10
11
12
// 1. number -> boolean
Boolean(1); // true
Boolean(0); // false
Boolean(NaN); // false
// 2. string -> boolean
Boolean(''); // false
Boolean('zyt'); // true
// 3. undefined/null -> boolean
Boolean(null); // false
Boolean(undefined); // false
// 4. 对象 -> Boolean
Boolean([]); // true

转成字符串

使用String。如:

1
2
3
4
5
6
7
8
9
10
11
12
13
// 1. number -> string
String(1); // '1'
String(NaN); // 'NaN'
// 2. boolean -> string
String(false); // 'false'
// 3. 函数 -> string. 并不是上图说的为'true',而是为函数体
String(function() {}); // 'function() {}'
// 4. 数组 -> string. 机制等同于 arr.join(',')
String([]); // '';
String([1,2,3]); // '1,2,3'
// 5. 对象 -> string
String({}); // "[object Object]"
// 6. null/undefined => 'null'/'undefined'

转成数字

使用Number。如:

1
2
3
4
5
6
7
// 1. string -> number, 如果含有非数字字符,则返回NaN,表示不是一个数字
Number('1'); // 1
// 2. 数组 -> number
Number([]); // 0
Number([1]); // NaN
// 3. null/undefined => 0/NaN, 这里因为null是用全零表示,所以会转成0
// 4. 对象 -> number => NaN

以上StringNumberBoolean方法转换都不能加new,否则则会转成相应的对象。

隐式类型转换(类型自动转换)

当我们执行下面的表达式时,类型将会进行自动转换。

  1. == 判断
  2. 加减乘除运算

先来点题目

1
2
3
4
5
6
7
8
9
const obj1 = {};
const obj2 = {
valueOf() {
return 1;
}
};

obj1 == 1; // ?
obj2 == 1; // ?

答案是: false, true

当一方为对象,而另一方为基础类型时,对象将会进行如下规则转换:

  1. 调用valueOf方法,如果返回的是基础类型则返回转换的值,否则则进入下一步(数组调用valueOf,便是返回本身,如: [1,2,3].valueOf() => [1,2,3]
  2. 调用toString方法,如果返回的是基础类型则返回转换的值,否则会报错,让我们来看看报错的例子。
1
2
3
4
5
6
7
8
9
10
const obj = {
valueOf() {
return {}; // 返回对象,非基础类型
},
toString() {
return {}; // 返回对象,非基础类型
}
};

obj == 1; // Uncaught TypeError: Cannot convert object to primitive value

1
2
'zyt' + 123; // ?
4 + [1,2,3]; // ?

答案是: zyt123, 41,2,3

规则如下:

  1. 有一方为字符串,那么就会把另一方也转成字符串。
  2. 如果既不是字符串也不是数字的前提下,如果原值是基础类型(boolean等)等价于调用Number, 如果为对象, 则调用上面复合类型的规则。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
undefined + 1; // 符合规则2, 等价于 Number(undefined) + 1; => NaN + 1 => NaN
null + 1; // 符合规则2,等价于Number(null) + 1; => 0 + 1 => 1
[] + 1; // 符合复合类型规则, 因为数组的valueOf返回本事,所以,等价于[].toString() + 1 => '' + 1; 这里符合规则1 => '1'
({}) + 1; // 符合复合类型, 和数组类型,所以等价于 ({}).toString() + 1 => '[object Object]' + 1; 这里符合规则1 => '[object Object]1'

// 自定义对象方法
const obj1 = {
valueOf() {
return 100;
}
}
obj1 + 1; // 等价于 obj1.valueOf() + 1 => 100 + 1 => 101;

const obj2 = {
valueOf() {
return {}
},
toString() {
return '100';
}
};
obj2 + 1; // 等价于 obj2.toString() + 1 => '100' + 1 => '1001'

const obj3 = {
valueOf() {
return {}
},
toString() {
return {};
}
}
obj3 + 1; // 报错 VM2821:9 Uncaught TypeError: Cannot convert object to primitive value

问题修复

  1. 关于复合类型转成原始类型的规则,有一个特例Date对象,这个转换目前还没找到规则,如你知道还请告知。
1
2
3
const date = new Date();
+date; // 1547730531065
date + 1; // 'Thu Jan 17 2019 21:08:51 GMT+0800 (中国标准时间)1'

希望对你有帮助, 不足之处还请指出

推荐文章