可檢測基本數據類型和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]) }
沒法檢測基本數據類型,可檢測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
提示:雖可檢測,但 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) }
通常類型都能檢測,建議使用。函數
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)。this
類型轉換髮生在靜態類型語言的編譯階段,而強制類型轉換則發生在動態類型語言的運行時(runtime)。spa
強制類型轉換又分如下兩種:prototype
「抽象操做」(即「僅供內部使用的操做」),是js的內置函數。code
處理非字符串到字符串的強制類型轉換。對基本類型有效,對引用類型(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 字符串化和 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 ); // undefined JSON.stringify( function(){} ); // undefined JSON.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}"
處理非數字值到數字的強制類型轉換, 處理失敗時返回NaN。
Number("33"); // 33 Number(null); // 0 Number(undefined); // NaN Number(true); // 1 Number(false); // 0 Number({a: '12'}); // NaN Number(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 |
八進制和十六進制
// 八進制的377 -> 十進制255 Number(0377); // 255 // 十六進制 -> 十進制的255 Number(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 ); // 42 Number( b ); // 42 Number( c ); // 42 Number( "" ); // 0 Number( [] ); // 0 Number( [ "abc" ] ); // NaN Number(['1']); // 1 Number(['1', '2']); // NaN
除了假值和假值對象,其餘的均可以看作是真值。
// 假值 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([]); // true Boolean({}); // true Boolean(function(){}); // true Boolean(1) // true ...
toString() 是顯式的,不過其中涉及隱式轉換。由於toString() 對 number 這樣的基本類型值不適用,因此 JavaScript 引擎會自動爲 number 類型建立一個封裝對象,而後對該對象調用 toString()。這裏顯式轉換中含有隱式轉換。
var a = 42; a.toString(); // "42"
+
和 -
一元運算 + 被廣泛認爲是顯式強制類型轉換
var c = "3.14"; var d = +c; var e = -c; // 會反轉符號位 var f = - -c; // 中間要有空格 d; // 3.14 e; // -3.14 f; // 3.14 // 日期顯式轉換爲數字 var d = new Date; +d; // 時間戳 1595836134918 // 更好的辦法(建議使用) var timestamp = Date.now()
~
運算符(非)~
運算符(位非)用於對一個二進制操做數逐位進行取反操做。
~12; // -13
~
和 indexOf() 結合使用
var a = "Hello World"; if (~a.indexOf( "lo" )) { // -4 -> 真值 -> true // 找到匹配! } if (!~a.indexOf( "ol" )) { // -4 -> 真值 -> true // 沒有找到匹配! }
var a = "42"; var b = "42px"; Number( a ); // 42 parseInt( a ); // 42 Number( b ); // NaN parseInt( b ); // 42 var c = '12.3333' parseInt( c ); // 12 parseFloat( c ); // 12.3333
!!
一元運算符 ! 顯式地將值強制類型轉換爲布爾值,它同時還將真值反轉爲假值(或假值反轉爲真值)。
顯式強制類型轉換爲布爾值最經常使用的方強制類型轉換方法是 !!
,由於第二個 ! 會將結果反轉回原值。
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({} == !{})