前端经典面试题:js数据类型

1,418 阅读14分钟

JavaScript数据类型

万丈高楼平地起,万变不离其宗,扎实的基本功对于一个研发人员来说相当重要,此文从常见面试题着手,以文字思维导图的形式回顾总结JavaScript的数据类型,偶尔阅读此文,能够查漏补缺、加深印象。

面试题引入

js有哪几种数据类型?其中基本数据类型是哪些?

5s回想

回答前的旁白:

从结构上看,所有的数据(data)最终都可以分解成三种类型:
	标量(scalar),也就是一个单独的字符串(string)或数字(number),比如"北京"这个单独的词。
	序列(sequence),也就是若干个相关的数据按照一定顺序并列在一起,又叫做数组(array)或列表(List),比如"北京,上海"。
	映射(mapping),也就是一个名/值对(Name/value),即数据有一个名称,还有一个与之相对应的值,这又称作散列(hash)或字典(dictionary),比如"首都:北京"。
json:
	Douglas Crockford声称的永远不必升级的规则:
		1) 并列的数据之间用逗号(",")分隔
		2) 映射用冒号(":")表示
		3) 并列数据的集合(数组)用方括号("[]")表示
		4) 映射的集合(对象)用大括号("{}")表示
	例子:"北京市的面积为16800平方公里,常住人口1600万人。上海市的面积为6400平方公里,常住人口1800万。"
		=>	[
				{"城市":"北京","面积":16800,"人口":1600},
				{"城市":"上海","面积":6400,"人口":1800}
			]

分类:

基本数据类型(值类型、原始类型):
	包括:
		undefined
			定义:表示“无”的原始值、未定义,转为数值时为NaN
			场景:
				变量声明,但没有赋值
				调用函数时,应该提供的参数没有提供,该参数等于undefined
				对象没有赋值的属性
				函数没有返回值时,默认返回undefined
		null
			定义:表示“无”的对象、空值,转为数值时为0
			场景:调用函数时,不需要传入某个参数,这时就可以传入null
			注意:typeof(null)返回'object'
		boolean
			定义:表示“真”(true)和“假”(false)两个状态
			场景:
				两元逻辑运算符: && ,||
				前置逻辑运算符: !
				相等运算符:===,!==,==,!=
				比较运算符:>,>=,<,<=
			自动转换:
				false:undefined, null, false, 0, NaN, ""或''
				true:除了转为false的外都转为true,特别的[], {}
			应用:用于程序流程的控制
		number
			概述
				整数和浮点数
					所有数字都是以64位浮点数形式储存,1与1.0是相同的,是同一个数1 === 1.0  =>  true
					注意:
						某些运算只有整数才能完成,此时JavaScript会自动把64位浮点数,转成32位整数
						浮点数不是精确的值 0.1 + 0.2 === 0.3, (0.3 - 0.2) === (0.2 - 0.1) =>  false
				数值精度
					国际标准IEEE 754:
						第1位:符号位,0表示正数,1表示负数
						第2位到第12位:储存指数部分(11个二进制)
						第13位到第64位:储存小数部分(即有效数字)
					精度:-(2e53-1)到2e53-1,超过无法保持精度
				数值范围
					指数范围:最大2e11-1 => 2047
					数值范围:2e1024到2e-1023,超过不能表示
					正向溢出:指数部分等于或超过最大正值1024 => Infinity
					负向溢出:指数部分等于或超过最小负值-1023 => 0
					最大值:Number.MAX_VALUE  =>  1.7976931348623157e+308
					最小值:Number.MIN_VALUE  =>  5e-324
			表示法
				字面量
					35(十进制)和0xFF(十六进制)
				科学计数法
					123e3  =>  123000,123e-3  =>  0.123
				自动转科学计数法
					小数点前的数字多于21位
					小数点后的零多于5个
			进制
				十进制:没有前导0的数值
				八进制:有前缀0o或0O的数值,或者有前导0、且只用到0-7的七个阿拉伯数字的数值
				十六进制:有前缀0x或0X的数值
				二进制:有前缀0b或0B的数值
			特殊数值
				正零和负零
					区别:+0或-0当作分母,返回的值是不相等
						1 / +0 => +Infinity
						1 / -0 => -Infinity
				NaN
					定义:“非数字”(Not a Number)
					场景:
						将字符串解析成数字出错 5 - 'x'  =>  NaN
						数学函数的运算结果
							Math.acos(2) => NaN
							Math.log(-1) => NaN
							Math.sqrt(-1) => NaN
						0 / 0 => NaN
					运算规则:
						NaN === NaN => false
						[NaN].indexOf(NaN) => -1
						Boolean(NaN) => false
						NaN + 32 => NaN
					判断方法:
						isNaN(NaN) => true
						注意:只对数值有效,其他值要先转换成数值
					注意:
						NaN不是一种独立的数据类型
						是一种特殊数值,typeof NaN => 'number'
				Infinity
					定义:
						正的数值太大,或一个负的数值太小,无法表示
						非0数值除以0,得到Infinity
						有正负之分
					运算规则:略
					isFinite:返回一个布尔值,检查某个值是不是正常数值,而不是Infinity
						isFinite(Infinity) => false,isFinite(NaN) => false,isFinite(-1) => true
			全局方法
				parseInt()
					将字符串转为整数
					进制转换
				parseFloat()
					将一个字符串转为浮点数
			Number对象实例方法
				toString	把数字转换为字符串,使用指定的基数。
				toLocaleString	把数字转换为字符串,使用本地数字格式顺序。
				toFixed	把数字转换为字符串,结果的小数点后有指定位数的数字。
				toExponential	把对象的值转换为指数计数法。
				toPrecision	把数字格式化为指定的长度。
				valueOf	返回一个 Number 对象的基本数字值。
		string
			概述
				定义
				转义:反斜杠(\)转义符,表示特殊字符
					特殊:
						三个八进制数:'\251' => "©"
						两个十六进制数:'\xA9' => "©"
						四个十六进制数:'\u00A9' => "©"
				字符串与数组
					相同取值方式,不可赋值
					使用数据方法:Array.prototype.join.call(s, ' ')
				长度
					length不可改
			字符集
				Unicode
			Base64转码
				处理特殊字符,方便打印
				btoa():字符串或二进制值转为Base64编码
				atob():Base64编码转为原来的编码
				非ASCII码字符(汉字)转为Base64编码:
					btoa(encodeURIComponent(str))
			String对象方法:
				anchor()	创建 HTML 锚。
				big()	用大号字体显示字符串。
				blink()	显示闪动字符串。
				bold()	使用粗体显示字符串。
				charAt()	返回在指定位置的字符。
				charCodeAt()	返回在指定的位置的字符的 Unicode 编码。
				concat()	连接字符串。
				fixed()	以打字机文本显示字符串。
				fontcolor()	使用指定的颜色来显示字符串。
				fontsize()	使用指定的尺寸来显示字符串。
				fromCharCode()	从字符编码创建一个字符串。
				indexOf()	检索字符串。
				italics()	使用斜体显示字符串。
				lastIndexOf()	从后向前搜索字符串。
				link()	将字符串显示为链接。
				localeCompare()	用本地特定的顺序来比较两个字符串。
				match()	找到一个或多个正则表达式的匹配。
				replace()	替换与正则表达式匹配的子串。
				search()	检索与正则表达式相匹配的值。
				slice()	提取字符串的片断,并在新的字符串中返回被提取的部分。
				small()	使用小字号来显示字符串。
				split()	把字符串分割为字符串数组。
				strike()	使用删除线来显示字符串。
				sub()	把字符串显示为下标。
				substr()	从起始索引号提取字符串中指定数目的字符。
				substring()	提取字符串中两个指定的索引号之间的字符。
				sup()	把字符串显示为上标。
				toLocaleLowerCase()	把字符串转换为小写。
				toLocaleUpperCase()	把字符串转换为大写。
				toLowerCase()	把字符串转换为小写。
				toUpperCase()	把字符串转换为大写。
				toSource()	代表对象的源代码。
				toString()	返回字符串。
				valueOf()	返回某个字符串对象的原始值。
	特点:
		1) 占用空间固定,保存在栈中
		2) 保存与复制的是值本身
		3) 使用typeof检测数据类型
合成数据类型(引用类型):
	包括:
		object:
			理解:
				(1)“对象”是单个实物的抽象。
				一本书、一辆汽车、一个人,一个数据库、一张网页、一个与远程服务器的连接也可以是“对象”。当实物被抽象成“对象”,实物之间的关系就变成了“对象”之间的关系,从而就可以模拟现实情况,针对“对象”进行编程。
				(2)“对象”是一个容器,封装了“属性”(property)和“方法”(method)。
				所谓“属性”,就是对象的状态;所谓“方法”,就是对象的行为(完成某种任务)。比如,我们可以把动物抽象为animal对象,“属性”记录具体是那一种动物,“方法”表示动物的某种行为(奔跑、捕猎、休息等等)。
			分类:
				狭义的对象(object)
					概述
						生成方法
							var o1 = {};
							var o2 = new Object();
							var o3 = Object.create(null);
					键名
						都是字符串
						键名是数值,会被自动转为字符串
						不符合标识名的条件,必须加引号
					属性
						任何数据类型
					对象的引用
						指向同一个内存地址,修改其中一个变量,会影响到其他所有变量。
					属性操作
						读取:. []
						赋值:. []
						所有:Object.keys(o);
						删除:delete可以删除的
						检查:in
						遍历:for...in
							所有可遍历(enumerable)的属性,跳过不可遍历的属性
							对象自身的属性 + 继承的属性
					with语句
						一般模板引擎的原理
					Object静态方法
						(0)Object.keys(),Object.getOwnPropertyNames()
						(1)对象属性模型的相关方法

						Object.getOwnPropertyDescriptor():获取某个属性的attributes对象。
						Object.defineProperty():通过attributes对象,定义某个属性。
						Object.defineProperties():通过attributes对象,定义多个属性。
						Object.getOwnPropertyNames():返回直接定义在某个对象上面的全部属性的名称。
						(2)控制对象状态的方法

						Object.preventExtensions():防止对象扩展。
						Object.isExtensible():判断对象是否可扩展。
						Object.seal():禁止对象配置。
						Object.isSealed():判断一个对象是否可配置。
						Object.freeze():冻结一个对象。
						Object.isFrozen():判断一个对象是否被冻结。
						(3)原型链相关方法

						Object.create():生成一个新对象,并该对象的原型。
						Object.getPrototypeOf():获取对象的Prototype对象。
					Object实例方法
						valueOf():返回当前对象对应的值。
						toString():返回当前对象对应的字符串形式。
						toLocaleString():返回当前对象对应的本地字符串形式。
						hasOwnProperty():判断某个属性是否为当前对象自身的属性,还是继承自原型对象的属性。
						isPrototypeOf():判断当前对象是否为另一个对象的原型。
						propertyIsEnumerable():判断某个属性是否可枚举。
				数组(array)
					定义:有序集合,特殊的对象
					length
						32位整数,保存数组的元素个数,最大值2e32 - 1
						成员删除:length比实际小
						数组清空:length=0
					类数组对象
						arguments,需要call方法来使用数组方法
					in
						适用于数组
					空位
						某个位置是空元素
						空位不影响length
						最后一个逗号不产生空位
						delete可产生
						遍历跳过
							forEach方法、for...in结构、以及Object.keys
					静态方法
						Array.isArray(a)
					实例方法
						concat()	连接两个或更多的数组,并返回结果。
						join()	把数组的所有元素放入一个字符串。元素通过指定的分隔符进行分隔。
						pop()	删除并返回数组的最后一个元素
						push()	向数组的末尾添加一个或更多元素,并返回新的长度。
						reverse()	颠倒数组中元素的顺序。
						shift()	删除并返回数组的第一个元素
						slice()	从某个已有的数组返回选定的元素
						sort()	对数组的元素进行排序
						splice()	删除元素,并向数组添加新元素。
						toSource()	返回该对象的源代码。
						toString()	把数组转换为字符串,并返回结果。
						toLocaleString()	把数组转换为本地数组,并返回结果。
						unshift()	向数组的开头添加一个或更多元素,并返回新的长度。
						valueOf()	返回数组对象的原始值
				函数(function)
	特点:
		1) 占用空间不固定,保存在堆中
		2) 保存与复制的是对象的一个指针(需要对象拷贝的原因)
		3) 使用instanceof检测数据类型
es6新类型:
	symbol符号对象
		定义:允许你创建唯一标识符
		使用:obj = Symbol(desc)
		检测:typeof(Symbol) => symbol
		理解:
			Symbol,表示独一无二的值。对象的属性名现在可以有两种类型,一种是原来就有的字符串,另一种就是新增的Symbol类型。凡是属性名属于Symbol类型,就都是独一无二的,可以保证不会与其他属性名产生冲突。

			Symbol 不可以使用new关键字,Symbol函数可以接受字符串参数使其返回值容易被区分,只是作为描述,即使参数相同Symbol函数返回值也不等。

			Symbol值作为对象属性名时,不能用点运算符。同理,在对象的内部,使用Symbol值定义属性时,Symbol值必须放在方括号之中。

			Symbol作为属性名,该属性不会出现在for…in、for…of循环中,也不会被Object.keys()、Object.getOwnPropertyNames()返回。但是,它也不是私有属性,有一个Object.getOwnPropertySymbols方法,可以获取指定对象的所有Symbol属性名。

			Symbol.for方法接受一个字符串作为参数,然后搜索有没有以该参数作为名称的Symbol值。如果有,就返回这个Symbol值,否则就新建并返回一个以该字符串为名称的Symbol值。注意,Symbol函数是总是返回新的值。
		例子:
			var a = Symbol('foo');
			var b = Symbol('foo');
			var s1 = Symbol.for('foo');
			var s2 = Symbol.for('foo');
			s1 === s2 => true
			a === b => false

			a === s2 => false
			Symbol.keyFor(s1) => "foo"
			Symbol.keyFor(a) => undefined
		其他:
			Symbol.hasInstance
			此方法可确定构造函数对象是否会将对象识别为构造函数实例之一。 它由 instanceof 运算符在内部使用。
			Symbol.isConcatSpreadable
			此属性返回一个布尔值,该值指示是否应通过 Array.concat 将对象平展至其数组元素。
			Symbol.iterator
			此方法返回对象的默认迭代器。 它由 for…of 语句在内部使用。
			Symbol.toPrimitive
			此方法将对象转换为相应的基元值。 它由 ToPrimitive 抽象运算符在内部使用。
			Symbol.toStringTag
			此属性返回一个字符串值,用于帮助创建对象的默认字符串说明。 它由内置方法 Object.toString 方法在内部使用。
			Symbol.unscopables
			此属性返回一个对象,该对象的属性从关联对象的 with 环境绑定中排除。

数据类型转换:

强制转换
	Number()
		原始类型:有不能转为数字的,就是NaN
			Number(false) => 0
			Number(true) => 1
			Number(undefined) => NaN
			Number(null) => 0
			Number("1.2") => 1.2
			Number("12") => 12
			Number("1.2.3") => NaN
			Number(new object()) => NaN
			Number(50) => 50
		Number({}) => NaN
	String()
		原始类型值的转换规则
			数值:转为相应的字符串。
			字符串:转换后还是原来的值。
			布尔值:true转为"true",false转为"false"。
			undefined:转为"undefined"。
			null:转为"null"。
		String({a: 1}) => "[object Object]"
		String([1, 2, 3]) => "1,2,3"
	Boolean()
		false
			undefined
			null
			-0
			0或+0
			NaN
			false
			''
		true
			所有对象,包括{}、布尔对象new Boolean(false)
自动转换
	场景:
		不同类型的数据互相运算
			123 + 'abc' => "123abc"
		对非布尔值类型的数据求布尔值
			if ('abc')
		对非数值类型的数据使用一元运算符(即“+”和“-”)
			+ {foo: 'bar'} => NaN
	本质:
		以强制类型为基础,转为需要的number、string、boolean

数据类型检测:

	typeof运算符
		数值、字符串、布尔值、undefined、函数,返分别返回number、string、boolean、undefined、function
		除此以外,其他情况都返回object
			typeof window  =>  "object"
			typeof {}  =>  "object"
			typeof []  =>  "object"
			typeof null  =>  "object"
	instanceof运算符
		定义:返回一个布尔值,表示指定对象是否为某个构造函数的实例
		实质:是检查右边构建函数的原型对象,是否在左边对象的原型链上
			v instanceof Vehicle 等价于 Vehicle.prototype.isPrototypeOf(v)
		instanceof对整个原型链上的对象都有效,因此同一个实例对象,可能会对多个构造函数都返回true
		特例:Object.create(null) instanceof Object  =>  false,除了这个其他对象的数据类型都可以这么判断
		注意:instanceof运算符只能用于对象,不适用原始类型的值
	Object.prototype.toString(value)方法
		相对准确的检测方法
			Object.prototype.toString.call(value);
		返回值
			数值:返回[object Number]。
			字符串:返回[object String]。
			布尔值:返回[object Boolean]。
			undefined:返回[object Undefined]。
			null:返回[object Null]。
			数组:返回[object Array]。
			arguments对象:返回[object Arguments]。
			函数:返回[object Function]。
			Error对象:返回[object Error]。
			Date对象:返回[object Date]。
			RegExp对象:返回[object RegExp]。
			其他对象:返回[object " + 构造函数的名称 + "]