数据类型
数据类型检测
typeof
可检测根本数据类型和function,无奈检测援用数据类型
var arr = [ null, // object undefined, // undefined true, // boolean 12, // number 'haha', // string Symbol(), // symbol 20n, // bigint function(){}, // function {}, // object [], // object]for (let i = 0; i < arr.length; i++) { console.log(typeof arr[i])}
instanceof
无奈检测根本数据类型,可检测function 、援用类型和继承关系
var arr = [ // { 'value': null, 'type': null}, ----> error // { 'value': undefined, 'type': undefined}, ----> error { 'value': true, 'type': Boolean}, // false { 'value': 12, 'type': Number}, // false { 'value': 'haha', 'type': String}, // false { 'value': Symbol(), 'type': Symbol}, // false { 'value': 20n, 'type': BigInt}, // false { 'value': function(){}, 'type': Function}, // true { 'value': {}, 'type': Object}, // true { 'value': [], 'type': Array}, // true]for (let i = 0; i < arr.length; i++) { console.log(arr[i].value instanceof arr[i].type)}
instanceof 除了能够检测类型外,还能够在继承关系的检测中应用
function Aoo(){} function Foo(){} Foo.prototype = new Aoo(); // JavaScript 原型继承 var foo = new Foo(); console.log(foo instanceof Foo) // true console.log(foo instanceof Aoo) // true
constructor
提醒:虽可检测,但 prototype 可被改写,constructor 会扭转,不倡议应用该办法判断。
var arr = [ // { 'value': null, 'type': Null}, ----> error // { 'value': undefined, 'type': Undefined}, ----> error { 'value': true, 'type': Boolean}, // true { 'value': 12, 'type': Number}, // true { 'value': 'haha', 'type': String}, // true { 'value': Symbol(), 'type': Symbol}, // true { 'value': 20n, 'type': BigInt}, // true { 'value': function(){}, 'type': Function}, // true { 'value': {}, 'type': Object}, // true { 'value': [], 'type': Array}, // true]for (let i = 0; i < arr.length; i++) { console.log(arr[i].value.constructor == arr[i].type)}
Object.prototype.toString.call()
个别类型都能检测,倡议应用。
var arr = [ null, // [object Null] undefined, // [object Undefined] true, // [object Boolean] 12, // [object Number] 'haha', // [object String] Symbol(), // [object Symbol] 20n, // [object BigInt] function(){},// [object Function] {}, // [object Object] [], // [object Array] new Date(), // [object Date] new RegExp(),// [object RegExp] new Error(), // [object Error]]for (let i = 0; i < arr.length; i++) { console.log(Object.prototype.toString.call(arr[i]))}
数据类型转换
将值从一种类型转换为另一种类型通常称为类型转换(type casting),这是显式的状况;隐式的状况称为强制类型转换(coercion)。
类型转换产生在动态类型语言的编译阶段,而强制类型转换则产生在动静类型语言的运行时(runtime)。
强制类型转换又分以下两种:
- 显式强制类型转换(explicit coercion)
- 隐式强制类型转换(implicit coercion)
形象操作
“形象操作”(即“仅供外部应用的操作”),是js的内置函数。
String()
解决非字符串到字符串的强制类型转换。对根本类型无效,对援用类型(object)有效。
String(12); // "12"String("haha"); // "haha"String(null); // "null"String(undefined); // "undefined"String(true); // "true"String({a: '12'}); // [object Object]
value值 | 原始类型 | 转换后 |
---|---|---|
12 | number | "12" |
haha | string | "haha" |
null | null | "null" |
undefined | undefined | "undefined" |
true | boolean | "true" |
{a: '12'} | object | [object Object] |
JSON.stringify(..)
JSON 字符串化和 toString() 的成果基本相同,只不过序列化的后果总是字符串。
1. 平安的 JSON 值转换
JSON.stringify(12); // "12"JSON.stringify("str"); // ""str""JSON.stringify(null); // "null"JSON.stringify(true); // "true"JSON.stringify({a: '12'}); // "{"a":"12"}"
value值 | 原始类型 | 转换后 |
---|---|---|
12 | number | "number" |
haha | string | ""haha"" (含有双引号的字符串) |
null | null | "null" |
true | boolean | "true" |
{a: '12'} | object | "{"a":"12"}" |
2. 不平安的 JSON 值转换
JSON.stringify(..) 在对象中遇到 undefined
、function
和 symbol
时会主动将其疏忽,在
数组中则会返回 null
(以保障单元地位不变)。
JSON.stringify( undefined ); // undefinedJSON.stringify( function(){} ); // undefinedJSON.stringify( [ 1, undefined, function(){}, 4]); // "[1, null, null, 4]"JSON.stringify( { a:2, b:function(){} }); // "{"a":2}
对蕴含循环援用的对象执行 JSON.stringify(..) 会出错
var o = { };var a = { b: 42, c: o, // 循环援用 d: function(){}};// 在a中创立一个循环援用o.e = a;// 循环援用在这里会产生谬误// JSON.stringify( a );// JSON.stringify( o );
3. 自定义 JSON 序列化
var a = { b: 42, c: 'haha', d: function(){}};// 自定义的JSON序列化a.toJSON = function() { // 序列化仅蕴含b return { b: this.b };};JSON.stringify( a ); // "{"b":42}"
Number()
解决非数字值到数字的强制类型转换, 解决失败时返回NaN。
Number("33"); // 33Number(null); // 0Number(undefined); // NaNNumber(true); // 1Number(false); // 0Number({a: '12'}); // NaNNumber(function(){}); // NaN
value值 | 原始类型 | 转换后value值 |
---|---|---|
"33" | string | 33 |
<span class="red">null</span> | null | <span class="red">0</span> |
undefined | undefined | NaN |
true | boolean | 1 |
false | boolean | 0 |
{a: '12'} | object | NaN |
八进制和十六进制
- 如果前缀为 0,则 JavaScript 会把数值常量解释为八进制数
- 如果前缀为 0 和 "x",则解释为十六进制数
// 八进制的377 -> 十进制255Number(0377); // 255// 十六进制 -> 十进制的255Number(0xFF); // 255
对象和数组
对象(包含数组)会首先被转换为相应的根本类型值,如果返回的是非数字的根本类型值,则再遵循以上规定将其强制转换为数字。
为了将值转换为相应的根本类型值,形象操作会查看该值是否有 valueOf()
办法。如果有并且返回根本类型值,就应用该值进行强制类型转换。如果没有就应用 toString()
的返回值(如果存在)来进行强制类型转换。如果 valueOf() 和 toString() 均不返回根本类型值,会产生 TypeError 谬误。
从 ES5 开始,应用 Object.create(null) 创立的对象 [[Prototype]] 属性为 null,并且没有 valueOf() 和 toString() 办法,因而无奈进行强制类型转换。
var a = { valueOf: function(){ return "42"; }};var b = { toString: function(){ return "42"; }};var c = [4,2];c.toString = function(){ return this.join( "" ); // "42"};Number( a ); // 42Number( b ); // 42Number( c ); // 42Number( "" ); // 0Number( [] ); // 0Number( [ "abc" ] ); // NaNNumber(['1']); // 1Number(['1', '2']); // NaN
Boolean()
除了假值和假值对象,其余的都能够看做是真值。
// 假值Boolean(""); // false Boolean(undefined); // false Boolean(null); // false Boolean(false); // false Boolean(+0); // false Boolean(-0); // false Boolean(0); // false Boolean(NaN); // false // 假值对象(浏览器本人创立的对象)Boolean(document.all) // false...// 真值Boolean([]); // trueBoolean({}); // trueBoolean(function(){}); // trueBoolean(1) // true...
显式强制类型转换
字符串与数字
1. String() 和 Number()
2. toString()
toString() 是显式的,不过其中波及隐式转换。因为toString() 对 number 这样的根本类型值不实用,所以 JavaScript 引擎会主动为 number 类型创立一个封装对象,而后对该对象调用 toString()。这里显式转换中含有隐式转换。
var a = 42;a.toString(); // "42"
3. 一元运算 +
和 -
一元运算 + 被普遍认为是显式强制类型转换
var c = "3.14";var d = +c;var e = -c; // 会反转符号位var f = - -c; // 两头要有空格d; // 3.14e; // -3.14f; // 3.14// 日期显式转换为数字var d = new Date;+d; // 工夫戳 1595836134918// 更好的方法(倡议应用)var timestamp = Date.now()
4. ~
运算符(非)
~
运算符(位非)用于对一个二进制操作数逐位进行取反操作。
- 第 1 步:把运算数转换为 32 位的二进制整数。
- 第 2 步:逐位进行取反操作。
- 第 3 步:把二进制反码转换为十进制浮点数。
~12; // -13
~
和 indexOf() 联合应用
var a = "Hello World";if (~a.indexOf( "lo" )) { // -4 -> 真值 -> true // 找到匹配!}if (!~a.indexOf( "ol" )) { // -4 -> 真值 -> true // 没有找到匹配!}
显式解析数字字符串
- Number():将非数字值转换为数字,解决失败时返回NaN
- parseInt(): 仅针对字符串值,其余类型有效,返回一个整数
- parseFloat():作用和parseInt() 统一,但可返回浮点数
var a = "42";var b = "42px";Number( a ); // 42parseInt( a ); // 42Number( b ); // NaNparseInt( b ); // 42var c = '12.3333'parseInt( c ); // 12parseFloat( c ); // 12.3333
显式转换为布尔值
1. Boolean()
2. !!
一元运算符 ! 显式地将值强制类型转换为布尔值,它同时还将真值反转为假值(或假值反转为真值)。
显式强制类型转换为布尔值最罕用的方强制类型转换办法是 !!
,因为第二个 ! 会将后果反转回原值。
var a = "0";var b = [];var c = {};var d = "";var e = 0;var f = null;var g; // undefined!!a; // true!!b; // true!!c; // true!!d; // false!!e; // false!!f; // false!!g; // false
value值 | Boolean()转换 | !!转换 |
---|---|---|
"" | false | false |
0 | false | false |
null | false | false |
undefined | false | false |
<span class="red">"0"</span> | <span class="red">true</span> | <span class="red">true</span> |
[] | true | true |
{} | true | true |
在 if(..).. 这样的布尔值上下文中,如果没有应用 Boolean(..) 和 !!,就会主动隐式地进行 ToBoolean 转换。
隐式强制类型转换
主动转换类型
当 JavaScript 尝试操作一个 "谬误" 的数据类型时,会主动转换为 "正确" 的数据类型。
5 + null // 返回 5 null 转换为 0"5" + null // 返回"5null" null 转换为 "null""5" + 1 // 返回 "51" 1 转换为 "1" "5" - 1 // 返回 4 "5" 转换为 5"5" * true // 返回 5 "true" 转换为 1
主动转换为字符串
当你尝试输入一个对象或一个变量时 JavaScript 会主动调用变量的 toString() 办法:
document.getElementById("demo").innerHTML = myVar;myVar = {name:"Fjohn"} // toString 转换为 "[object Object]"myVar = [1,2,3,4] // toString 转换为 "1,2,3,4"myVar = new Date() // toString 转换为 "Fri Jul 18 2014 09:08:55 GMT+0200"
数字和布尔值也常常互相转换:
myVar = 123 // toString 转换为 "123"myVar = true // toString 转换为 "true"myVar = false // toString 转换为 "false"
类型转换小结
下表展现了应用不同的数值转换为数字(Number), 字符串(String), 布尔值(Boolean):
原始值 | 转换为数字 | 转换为字符串 | 转换为布尔值 |
---|---|---|---|
false | 0 | ""false"" | false |
true | 1 | "true" | true |
0 | 0 | "0" | false |
1 | 1 | "1" | true |
"0" | 0 | "0" | true |
"000" | 0 | "000" | true |
"1" | 1 | "1" | true |
NaN | NaN | "NaN" | false |
"" | 0 | "" | false |
[ ] | 0 | "" | true |
function(){} | NaN | "function(){}" | true |
{ } | NaN | "[object Object]" | true |
null | 0 | "null" | false |
undefined | NaN | "undefined" | false |
Infinity | Infinity | "Infinity" | true |
-Infinity | -Infinity | "-Infinity" | true |
经典面试题
1 + '1' true + 0{}+[]4 + {} 4 + [1] 'a' + + 'b'console.log ( [] == 0 )console.log ( ! [] == 0 )console.log ( [] == ! [] )console.log ( [] == [] )console.log({} == !{})