寫javascript程式碼的時候常常要判斷變量,字面量的型別,可以用typeof,instanceof,Array.isArray(),等方法,究竟哪一種最方便,最實用,最省心呢?本文探討這個問題。
1. typeof
1.1 語法
typeof傳回字串,表示未經計算的操作數的類型。
語法:typeof(operand) | typeof operand
參數:一個表示物件或原始值的表達式,其類型將被傳回
描述:typeof可能傳回的值如下:
【相關課程推薦:JavaScript影片教學】
類型 結果
Undefined“undefined” Null“object” Boolean“boolean” Number“number” Bigint“bigint” String“string” Symbol“symbol”
宿主物件(由JS環境提供) 取決於具體實作
Function物件 「function」
其他任何物件 「object」
從定義和描述來看,這個語法可以判斷出很多的資料類型,但是仔細觀察,typeof null居然返回的是“object”,讓人摸不著頭腦,下面會具體介紹,先看看這個效果:
// 数值 console.log(typeof 37) // number console.log(typeof 3.14) // number console.log(typeof(42)) // number console.log(typeof Math.LN2) // number console.log(typeof Infinity) // number console.log(typeof NaN) // number 尽管它是Not-A-Number的缩写,实际NaN是数字计算得到的结果,或者将其他类型变量转化成数字失败的结果 console.log(Number(1)) //number Number(1)构造函数会把参数解析成字面量 console.log(typeof 42n) //bigint // 字符串 console.log(typeof '') //string console.log(typeof 'boo') // string console.log(typeof `template literal`) // string console.log(typeof '1') //string 内容为数字的字符串仍然是字符串 console.log(typeof(typeof 1)) //string,typeof总是返回一个字符串 console.log(typeof String(1)) //string String将任意值转换成字符串 // 布尔值 console.log(typeof true) // boolean console.log(typeof false) // boolean console.log(typeof Boolean(1)) // boolean Boolean会基于参数是真值还是虚值进行转换 console.log(typeof !!(1)) // boolean 两次调用!!操作想短语Boolean() // Undefined console.log(typeof undefined) // undefined console.log(typeof declaredButUndefinedVariabl) // 未赋值的变量返回undefined console.log(typeof undeclaredVariable ) // 未定义的变量返回undefined // 对象 console.log(typeof {a: 1}) //object console.log(typeof new Date()) //object console.log(typeof /s/) // 正则表达式返回object // 下面的例子令人迷惑,非常危险,没有用处,应避免使用,new操作符返回的实例都是对象 console.log(typeof new Boolean(true)) // object console.log(typeof new Number(1)) // object console.log(typeof new String('abc')) // object // 函数 console.log(typeof function () {}) // function console.log(typeof class C { }) // function console.log(typeof Math.sin) // function
1.2 迷之null
#javascript誕生以來,typeof null都是回傳'object'的,這個是因為javascript中的值由兩個部分組成,一部分是表示類型的標籤,另一部分是表示實際的值。物件類型的值類型標籤是0,不巧的是null表示空指針,它的型別標籤也被設計成0,於是就有這個typeof null === ‘object’這個‘惡魔之子’。
曾經有ECMAScript提案讓typeof null返回‘null’,但是該提案被拒絕了。
1.3 使用new運算子
除Function之外所有建構子的型別都是'object',如下:
var str = new String('String'); var num = new Number(100) console.log(typeof str) // object console.log(typeof num) // object var func = new Function() console.log(typeof func) // function
# 1.4 語法中的括號
typeof運算的優先權要高於「 」運算,但是低於圓括號
var iData = 99 console.log(typeof iData + ' Wisen') // number Wisen console.log(typeof (iData + 'Wisen')) // string
1.5 判斷正規表示式的相容性問題
typeof /s/ === 'function'; // Chrome 1-12 , 不符合 ECMAScript 5.1 typeof /s/ === 'object'; // Firefox 5+ , 符合 ECMAScript 5.1
1.6 錯誤
ECMAScript 2015之前,typeof總是能保證對任何所給予的運算元都傳回字串,即使是沒有聲明,沒有賦值的標示符,typeof也能回傳undefined,也就是說使用typeof永遠不會報錯。
但是ES6中加入了區塊級作用域以及let,const指令之後,在變數宣告之前使用由let,const宣告的變數都會拋出一個ReferenceError錯誤,區塊級作用域變數在區塊的頭部到宣告變數之間是“暫時性死區”,在這段期間存取變數會拋出錯誤。如下:
console.log(typeof undeclaredVariable) // 'undefined' console.log(typeof newLetVariable) // ReferenceError console.log(typeof newConstVariable) // ReferenceError console.log(typeof newClass) // ReferenceError let newLetVariable const newConstVariable = 'hello' class newClass{}
1.7 例外
目前所有瀏覽器都暴露一個類型為undefined的非標準宿主物件document.all。 typeof document.all === 'undefined'。景觀規範允許為非標準的外來物件自訂類型標籤,單一要求這些類型標籤與現有的不同,document.all的類型標籤為undefined的例子在web領域被歸類為對原ECMA javascript標準的「故意侵犯”,可能就是瀏覽器的惡作劇。
總結:typeof傳回變數或值的型別標籤,雖然對大部分型別都能傳回正確結果,但是對null,建構函式實例,正規表示式這三種不太理想。
2. instanceof
2.1 語法
instanceof運算子用於偵測實例物件(參數)的原型鏈上是否出現建構函數的prototype。
語法:object instanceof constructor
#參數:object 某個實例物件
constructor 某個建構子
說明說明:instance運算子用來偵測.property是否存在於參數object的原型鏈上。
// 定义构造函数 function C() { } function D() { } var o = new C() console.log(o instanceof C) //true,因为Object.getPrototypeOf(0) === C.prototype console.log(o instanceof D) //false,D.prototype不在o的原型链上 console.log(o instanceof Object) //true 同上 C.prototype = {} var o2 = new C() console.log(o2 instanceof C) // true console.log(o instanceof C) // false C.prototype指向了一个空对象,这个空对象不在o的原型链上 D.prototype = new C() // 继承 var o3 = new D() console.log(o3 instanceof D) // true console.log(o3 instanceof C) // true C.prototype现在在o3的原型链上
要注意的是,如果表達式obj instanceof Foo傳回true,則不表示該表達式會永遠傳回true,應為Foo.prototype屬性的值可能被修改,修改之後的值可能不在obj的原型鏈上,這時表達式的值就是false了。另外一種情況,改變obj的原型鏈的情況,雖然在當前ES規範中,只能讀取物件的原型而不能修改它,但是藉助非標準的__proto__偽屬性,是可以修改的,例如執行obj.__proto__ = {}後,obj instanceof Foo就回傳false了。另外ES6中Object.setPrototypeOf(),Reflect.setPrototypeOf()都可以修改物件的原型。
instanceof和多全域物件(多個iframe或多個window之間的互動)
#瀏覽器中,javascript腳本可能需要在多個視窗之間互動。多個視窗意味著多個全域環境,不同全域環境擁有不同的全域對象,從而擁有不同的內建建構函數。這可能會引發一些問題。例如表達式[] instanceof window.frames[0].Array會回傳false,因為
Array.prototype !== window.frames[0].Array.prototype。
起初,这样可能没有意义,但是当在脚本中处理多个frame或多个window以及通过函数将对象从一个窗口传递到另一个窗口时,这就是一个非常有意义的话题。实际上,可以通过Array.isArray(myObj)或者Object.prototype.toString.call(myObj) = "[object Array]"来安全的检测传过来的对象是否是一个数组。
2.2 示例
String对象和Date对象都属于Object类型(它们都由Object派生出来)。
但是,使用对象文字符号创建的对象在这里是一个例外,虽然原型未定义,但是instanceof of Object返回true。
var simpleStr = "This is a simple string"; var myString = new String(); var newStr = new String("String created with constructor"); var myDate = new Date(); var myObj = {}; var myNonObj = Object.create(null); console.log(simpleStr instanceof String); // 返回 false,虽然String.prototype在simpleStr的原型链上,但是后者是字面量,不是对象 console.log(myString instanceof String); // 返回 true console.log(newStr instanceof String); // 返回 true console.log(myString instanceof Object); // 返回 true console.log(myObj instanceof Object); // 返回 true, 尽管原型没有定义 console.log(({}) instanceof Object); // 返回 true, 同上 console.log(myNonObj instanceof Object); // 返回 false, 一种创建非 Object 实例的对象的方法 console.log(myString instanceof Date); //返回 false console.log( myDate instanceof Date); // 返回 true console.log(myDate instanceof Object); // 返回 true console.log(myDate instanceof String); // 返回 false
注意:instanceof运算符的左边必须是一个对象,像"string" instanceof String,true instanceof Boolean这样的字面量都会返回false。
下面代码创建了一个类型Car,以及该类型的对象实例mycar,instanceof运算符表明了这个myca对象既属于Car类型,又属于Object类型。
function Car(make, model, year) { this.make = make; this.model = model; this.year = year; } var mycar = new Car("Honda", "Accord", 1998); var a = mycar instanceof Car; // 返回 true var b = mycar instanceof Object; // 返回 true
不是...的实例
要检测对象不是某个构造函数的实例时,可以使用!运算符,例如if(!(mycar instanceof Car))
instanceof虽然能够判断出对象的类型,但是必须要求这个参数是一个对象,简单类型的变量,字面量就不行了,很显然,这在实际编码中也是不够实用。
总结:obj instanceof constructor虽然能判断出对象的原型链上是否有构造函数的原型,但是只能判断出对象类型变量,字面量是判断不出的。
3. Object.prototype.toString()
3.1. 语法
toString()方法返回一个表示该对象的字符串。
语法:obj.toString()
返回值:一个表示该对象的字符串
描述:每个对象都有一个toString()方法,该对象被表示为一个文本字符串时,或一个对象以预期的字符串方式引用时自动调用。默认情况下,toString()方法被每个Object对象继承,如果此方法在自定义对象中未被覆盖,toString()返回“[object type]”,其中type是对象的类型,看下面代码:
var o = new Object(); console.log(o.toString()); // returns [object Object]
注意:如ECMAScript 5和随后的Errata中所定义,从javascript1.8.5开始,toString()调用null返回[object, Null],undefined返回[object Undefined]
3.2. 示例
覆盖默认的toString()方法
可以自定义一个方法,来覆盖默认的toString()方法,该toString()方法不能传入参数,并且必须返回一个字符串,自定义的toString()方法可以是任何我们需要的值,但如果带有相关的信息,将变得非常有用。
下面代码中定义Dog对象类型,并在构造函数原型上覆盖toString()方法,返回一个有实际意义的字符串,描述当前dog的姓名,颜色,性别,饲养员等信息。
function Dog(name,breed,color,sex) { this.name = name; this.breed = breed; this.color = color; this.sex = sex; } Dog.prototype.toString = function dogToString() { return "Dog " + this.name + " is a " + this.sex + " " + this.color + " " + this.breed } var theDog = new Dog("Gabby", "Lab", "chocolate", "female"); console.log(theDog.toString()) //Dog Gabby is a female chocolate Lab
4. 使用toString()检测数据类型
目前来看toString()方法能够基本满足javascript数据类型的检测需求,可以通过toString()来检测每个对象的类型。为了每个对象都能通过Object.prototype.toString()来检测,需要以Function.prototype.call()或者Function.prototype.apply()的形式来检测,传入要检测的对象或变量作为第一个参数,返回一个字符串"[object type]"。
// null undefined console.log(Object.prototype.toString.call(null)) //[object Null] 很给力 console.log(Object.prototype.toString.call(undefined)) //[object Undefined] 很给力 // Number console.log(Object.prototype.toString.call(Infinity)) //[object Number] console.log(Object.prototype.toString.call(Number.MAX_SAFE_INTEGER)) //[object Number] console.log(Object.prototype.toString.call(NaN)) //[object Number],NaN一般是数字运算得到的结果,返回Number还算可以接受 console.log(Object.prototype.toString.call(1)) //[object Number] var n = 100 console.log(Object.prototype.toString.call(n)) //[object Number] console.log(Object.prototype.toString.call(0)) // [object Number] console.log(Object.prototype.toString.call(Number(1))) //[object Number] 很给力 console.log(Object.prototype.toString.call(new Number(1))) //[object Number] 很给力 console.log(Object.prototype.toString.call('1')) //[object String] console.log(Object.prototype.toString.call(new String('2'))) // [object String] // Boolean console.log(Object.prototype.toString.call(true)) // [object Boolean] console.log(Object.prototype.toString.call(new Boolean(1))) //[object Boolean] // Array console.log(Object.prototype.toString.call(new Array(1))) // [object Array] console.log(Object.prototype.toString.call([])) // [object Array] // Object console.log(Object.prototype.toString.call(new Object())) // [object Object] function foo() {} let a = new foo() console.log(Object.prototype.toString.call(a)) // [object Object] // Function console.log(Object.prototype.toString.call(Math.floor)) //[object Function] console.log(Object.prototype.toString.call(foo)) //[object Function] // Symbol console.log(Object.prototype.toString.call(Symbol('222'))) //[object Symbol] // RegExp console.log(Object.prototype.toString.call(/sss/)) //[object RegExp]
上面的结果,除了NaN返回Number稍微有点差池之外其他的都返回了意料之中的结果,都能满足实际开发的需求,于是我们可以写一个通用的函数来检测变量,字面量的类型。如下:
let Type = (function () { let type = {}; let typeArr = ['String', 'Object', 'Number', 'Array', 'Undefined', 'Function', 'Null', 'Symbol', 'Boolean', 'RegExp', 'BigInt']; for (let i = 0; i < typeArr.length; i++) { (function (name) { type['is' + name] = function (obj) { return Object.prototype.toString.call(obj) === '[object ' + name + ']' } })(typeArr[i]) } return type })() let s = true console.log(Type.isBoolean(s)) // true console.log(Type.isRegExp(/22/)) // true
除了能检测ECMAScript规定的八种数据类型(七种原始类型,Boolean,Null,Undefined,Number,BigInt,String,Symbol,一种复合类型Object)之外,还能检测出正则表达式RegExp,Function这两种类型,基本上能满足开发中的判断数据类型需求。
5. 判断相等
既然说道这里,不妨说一说另一个开发中常见的问题,判断一个变量是否等于一个值。ES5中比较两个值是否相等,可以使用相等运算符(==),严格相等运算符(===),但它们都有缺点,== 会将‘4’转换成4,后者NaN不等于自身,以及+0 !=== -0。ES6中提出”Same-value equality“(同值相等)算法,用来解决这个问题。Object.is就是部署这个算法的新方法,它用来比较两个值是否严格相等,与严格比较运算(===)行为基本一致。
console.log(5 == '5') // true console.log(NaN == NaN) // false console.log(+0 == -0) // true console.log({} == {}) // false console.log(5 === '5') // false console.log(NaN === NaN) // false console.log(+0 === -0) // true console.log({} === {}) // false
Object.js()不同之处有两处,一是+0不等于-0,而是NaN等于自身,如下:
let a = {} let b = {} let c = b console.log(a === b) // false console.log(b === c) // true console.log(Object.is(b, c)) // true
注意两个空对象不能判断相等,除非是将一个对象赋值给另外一个变量,对象类型的变量是一个指针,比较的也是这个指针,而不是对象内部属性,对象原型等。
本文来自 js教程 栏目,欢迎学习!
以上是javascript中判斷資料類型的幾種方式的詳細內容。更多資訊請關注PHP中文網其他相關文章!

JavaScriptusestwotypesofcomments:single-line(//)andmulti-line(//).1)Use//forquicknotesorsingle-lineexplanations.2)Use//forlongerexplanationsorcommentingoutblocksofcode.Commentsshouldexplainthe'why',notthe'what',andbeplacedabovetherelevantcodeforclari

Python和JavaScript的主要區別在於類型系統和應用場景。 1.Python使用動態類型,適合科學計算和數據分析。 2.JavaScript採用弱類型,廣泛用於前端和全棧開發。兩者在異步編程和性能優化上各有優勢,選擇時應根據項目需求決定。

選擇Python還是JavaScript取決於項目類型:1)數據科學和自動化任務選擇Python;2)前端和全棧開發選擇JavaScript。 Python因其在數據處理和自動化方面的強大庫而備受青睞,而JavaScript則因其在網頁交互和全棧開發中的優勢而不可或缺。

Python和JavaScript各有優勢,選擇取決於項目需求和個人偏好。 1.Python易學,語法簡潔,適用於數據科學和後端開發,但執行速度較慢。 2.JavaScript在前端開發中無處不在,異步編程能力強,Node.js使其適用於全棧開發,但語法可能複雜且易出錯。

javascriptisnotbuiltoncorc; sanInterpretedlanguagethatrunsonenginesoftenwritteninc.1)JavascriptwasdesignedAsignedAsalightWeight,drackendedlanguageforwebbrowsers.2)Enginesevolvedfromsimpleterterpretpretpretpretpreterterpretpretpretpretpretpretpretpretpretcompilerers,典型地,替代品。

JavaScript可用於前端和後端開發。前端通過DOM操作增強用戶體驗,後端通過Node.js處理服務器任務。 1.前端示例:改變網頁文本內容。 2.後端示例:創建Node.js服務器。

選擇Python還是JavaScript應基於職業發展、學習曲線和生態系統:1)職業發展:Python適合數據科學和後端開發,JavaScript適合前端和全棧開發。 2)學習曲線:Python語法簡潔,適合初學者;JavaScript語法靈活。 3)生態系統:Python有豐富的科學計算庫,JavaScript有強大的前端框架。

JavaScript框架的強大之處在於簡化開發、提升用戶體驗和應用性能。選擇框架時應考慮:1.項目規模和復雜度,2.團隊經驗,3.生態系統和社區支持。


熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

PhpStorm Mac 版本
最新(2018.2.1 )專業的PHP整合開發工具

DVWA
Damn Vulnerable Web App (DVWA) 是一個PHP/MySQL的Web應用程序,非常容易受到攻擊。它的主要目標是成為安全專業人員在合法環境中測試自己的技能和工具的輔助工具,幫助Web開發人員更好地理解保護網路應用程式的過程,並幫助教師/學生在課堂環境中教授/學習Web應用程式安全性。 DVWA的目標是透過簡單直接的介面練習一些最常見的Web漏洞,難度各不相同。請注意,該軟體中

SublimeText3漢化版
中文版,非常好用

SecLists
SecLists是最終安全測試人員的伙伴。它是一個包含各種類型清單的集合,這些清單在安全評估過程中經常使用,而且都在一個地方。 SecLists透過方便地提供安全測試人員可能需要的所有列表,幫助提高安全測試的效率和生產力。清單類型包括使用者名稱、密碼、URL、模糊測試有效載荷、敏感資料模式、Web shell等等。測試人員只需將此儲存庫拉到新的測試機上,他就可以存取所需的每種類型的清單。

Dreamweaver Mac版
視覺化網頁開發工具