摘要:使用的構(gòu)造函數(shù)是,它只為新對象定義了默認的屬性和方法。如果網(wǎng)頁中包含多個框架,那實際上就存在多個不同的全局執(zhí)行環(huán)境,從而存在多個不同版本的構(gòu)造函數(shù)。每個類在內(nèi)部都有一個屬性,這個屬性中就指定了上述字符串中的構(gòu)造函數(shù)。
js中常見的用于類型判斷的操作符或?qū)傩杂校簍ypeof、instanceof、prototype。下面我們就來看看他們是如何判斷數(shù)據(jù)類型的。
一.js數(shù)據(jù)類型ECMAscript中有5種簡單數(shù)據(jù)類型(基本數(shù)據(jù)類型):Undefined、Null、Boolean、Number和String。除了這五種基本數(shù)據(jù)類型之外,還有一種復(fù)雜類型值(引用類型)。引用類型又分為:原生引用類型和自定義引用類型。在ECMAscript中,引用類型是一種數(shù)據(jù)結(jié)構(gòu),用于將數(shù)據(jù)和功能無序地組織在一起,以key/value的形式在對象中存放。ECMAscript不支持任何創(chuàng)建自定義類型的機制,而所有值最終都將是上述6種數(shù)據(jù)類型之一。另外,對象是某個特定引用類型的實例,例如:
var person = new Object()
這行代碼創(chuàng)建了Object引用類型的一個新實例,然后把該實例保存在了person中。使用的構(gòu)造函數(shù)是Object,它只為新對象定義了默認的屬性和方法。Object只是ECMAscript提供的原生引用類型的一種。諸如Array、Date、RegExp、Function、Boolean、Number、String也都是內(nèi)置的原生引用類型。
二.typeof基本類型的檢驗,經(jīng)常使用typeof操作符。對一個值使用typeof操作符可能返回下列某個字符串:
"undefined"———如果這個值未定義 "boolean"———如果這個值是布爾值 "string"———如果這個值是字符串 "number"———如果這個值是數(shù)值 "object"———如果這個值是對象或null "function"———如果這個值是函數(shù)
調(diào)用typeof null會返回"object",因為特殊值null被認為是一個空的對象的引用。
Safari及之前版本、Chrome7及之前版本在對正則表達式調(diào)用typeof操作符時會返回"function",而其它瀏覽器在這種情況下會返回"object"。
從技術(shù)角度講,函數(shù)在ECMAscript中是對象,不是一種數(shù)據(jù)類型。然而,函數(shù)也確實有一些特殊的屬性,因此通過typeof操作符來區(qū)分函數(shù)和其它對象是有必要的。
三.instanceof在 JavaScript 中,判斷一個變量的類型嘗嘗會用 typeof 運算符,在使用 typeof 運算符時采用引用類型存儲值會出現(xiàn)一個問題,無論引用的是什么類型的對象,它都返回 "object"。ECMAScript 引入了另一個 Java 運算符 instanceof 來解決這個問題。instanceof 運算符與 typeof 運算符相似,用于識別正在處理的對象的類型。通常來講,使用 instanceof 就是判斷一個實例是否屬于某種類型。例如:
// 判斷 boy是否是 People類的實例 function People(){} var boy= new People(); console.log(boy instanceof People)//true
與 typeof 方法不同的是,instanceof 方法要求開發(fā)者明確地確認對象為某特定類型。例如:
var arr = [1,2,3] if(arr instanceof Array){ console.log(“arr是一個數(shù)組”) } //輸出:arr是一個數(shù)組
這段代碼問的是“變量 arr是否為 Array對象的實例?”arr的確是 Array對象的實例,因此結(jié)果是"true"。盡管不像 typeof 方法那樣靈活,但是在 typeof 方法返回 "object" 的情況下,instanceof 方法還是很有用的。
但是,instanceof操作符并不是安全的檢測方式。instanceof操作符的問題在于,它假定只有一個全局執(zhí)行環(huán)境。如果網(wǎng)頁中包含多個框架frame,那實際上就存在多個不同的全局執(zhí)行環(huán)境,從而存在多個不同版本的Array構(gòu)造函數(shù)。如果你從一個框架向另一個框架傳入一個數(shù)組,那么傳入的數(shù)組與在第二個框架中原生創(chuàng)建的數(shù)組分別具有各自不同的構(gòu)造函數(shù)。為了解決這個問題,ES5中新增了Array.isArray()方法。這個方法的目的是最終確定某個值到底是不是數(shù)組,而不管它是在哪個全局執(zhí)行環(huán)境中創(chuàng)建的。這個方法是用如下:
if(Array.isArray(arr)){ //do sometion }
目前,支持Array.isArray()方法的瀏覽器有IE9+、Firefox 4+、Safari 5+、Opera 10.5+、Chrome。要在尚未實現(xiàn)這個方法的瀏覽器中準確檢測數(shù)組,請參考“四.安全的類型檢測”。
instanceof究竟是運算什么的?
我曾經(jīng)簡單理解instanceof只是檢測一個對象是否是另個對象new出來的實例(例如var a = new Object(),a instanceof Object返回true),但實際instanceof的運算規(guī)則上比這個更復(fù)雜。
//假設(shè)instanceof運算符左邊是L,右邊是R L instanceof R //instanceof運算時,通過判斷L的原型鏈上是否存在R.prototype L.__proto__.__proto__ ..... === R.prototype ? //如果存在返回true 否則返回false
注意:instanceof運算時會遞歸查找L的原型鏈,即L.__proto__.__proto__.__proto__.__proto__...直到找到了或者找到頂層為止。
所以一句話理解instanceof的運算規(guī)則為:
instanceof檢測左側(cè)的__proto__原型鏈上,是否存在右側(cè)的prototype原型。
知道了這個也就知道為什么以下這些奇怪的表達式為什么會得到相應(yīng)的值了
Function instanceof Object // true Object instanceof Function // true Function instanceof Function //true Object instanceof Object // true Number instanceof Number //false
那么知道了原理之后,如何自己手寫一個instanceof,如下所示:
function instance_of(L, R) {//L 表示左表達式,R 表示右表達式 var O = R.prototype;// 取 R 的顯示原型 L = L.__proto__;// 取 L 的隱式原型 while (true) { if (L === null) { return false; } if (O === L) {// 這里重點:當 O 嚴格等于 L 時,返回 true return true; } L = L.__proto__; } } instance_of(Function,Function)//true instance_of(String,String)//true
JavaScript instanceof 運算符深入剖析https://www.ibm.com/developer...
四.安全的類型檢測在檢測某個對象到底是原生對象還是開發(fā)人員自定義的對象的時候,也會有問題。出現(xiàn)這個問題的原因是瀏覽器開始原生支持JSON對象了。因為很多人一直在使用Douglas的JSON庫,而該庫定義了一個全局的JSON對象。于是開發(fā)人員很難確定頁面中的JSON對象到底是不是原生的。
解決typeof、instanceof和判斷是否是原生JSON對象的方法都一樣。大家都知道,在任何值上調(diào)用Object原生的toString()方法,都會返回一個[object NativeConstructorName]格式的字符串。每個類在內(nèi)部都有一個[[Class]]屬性,這個屬性中就指定了上述字符串中的構(gòu)造函數(shù)。舉個栗子:
var o = []; alert(Object.prototype.toString.call(o));//"[object Array]"
由于原生數(shù)組的構(gòu)造函數(shù)名與全局作用域無關(guān),因此使用toString()就能保證返回一致的值。利用這一點,可以創(chuàng)建如下函數(shù):
function isArray(value){ return Object.prototype.toString.call(value) == "[object Array]" }
同樣,也可以基于這一思路來測試某個值是不是原生函數(shù)或正則表達式:
function isFunction(value){ return Object.prototype.toString.call(value) == "[object Function]" } function isRegExp(value){ return Object.prototype.toString.call(value) == "[object RegExp]" }
Object的toString()方法不能檢測非原生構(gòu)造函數(shù)的構(gòu)造函數(shù)名,因此,開發(fā)人員定義的任何構(gòu)造函數(shù)都將返回"[object Object]"。這也就是為什么在上圖中的序號③處調(diào)用test(p)會返回"[object Object]"的原因了。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/94213.html
摘要:數(shù)據(jù)類型七種內(nèi)置類型空值未定義布爾值數(shù)字字符串對象符號除對象之外,其他統(tǒng)稱為基本類型類型檢測運算符后面跟操作數(shù),或者,返回一個類型的字符串值。運算符用于測試構(gòu)造函數(shù)的屬性是否出現(xiàn)在對象的原型鏈中的任何位置。 數(shù)據(jù)類型 JavaScript七種內(nèi)置類型: 空值(null) 未定義(undefined) 布爾值(boolean) 數(shù)字(number) 字符串(string) 對象(obj...
摘要:變量的特點變量是松散類型的,所謂松散類型就是可以用來保存任何類型的數(shù)據(jù)。 變量的特點 js變量是松散類型的,所謂松散類型就是可以用來保存任何類型的數(shù)據(jù)。換句話說, 每個變量僅僅是一個用于保存值的占位符而已 js變量可以用來保存任何值,未經(jīng)過初始化的變量,會保存一個特殊的值—undefined,如:var msg; js變量的初始化并不會為它標記類型;初始化的過程就是給變量賦一個值那...
摘要:是一個數(shù)值可以被轉(zhuǎn)換成數(shù)值不能轉(zhuǎn)換成數(shù)值可以被轉(zhuǎn)換成數(shù)值十六進制數(shù)八進制數(shù)十進制數(shù)十六進制數(shù)可以避免,無法使用方法轉(zhuǎn)換成字符串的情況 1.JavaScript由三個部分組成:ECMAScript(提供核心語言功能)、DOM(文檔對象模型,提供訪問和操作網(wǎng)頁內(nèi)容的方法和接口)、BOM(瀏覽器對象模型,提供與瀏覽器交互的方法和接口) 2.JavaScript概念:是一種專為與網(wǎng)頁交互而設(shè)計...
摘要:分析及預(yù)防,又稱跨站腳本,的重點不在于跨站點,而是在于腳本的執(zhí)行。在這里需要強調(diào)一點的是,默認會禁止代碼塊的執(zhí)行禁止內(nèi)聯(lián)事件處理函數(shù)禁止內(nèi)聯(lián)樣式禁止和。 XSS分析及預(yù)防 XSS(Cross Site Scripting),又稱跨站腳本,XSS的重點不在于跨站點,而是在于腳本的執(zhí)行。在WEB前端應(yīng)用日益發(fā)展的今天,XSS漏洞尤其容易被開發(fā)人員忽視,最終可能造成對個人信息的泄漏。如今,...
摘要:舉個例子在上面的例子可以看到,我們聲明是一個數(shù)字,但是我們在之后將的值又改成了字符串和布爾值后面會講這些類型。基本類型字符串表示一個字符串,如。因此,我們可以寫一個函數(shù),用來精確檢測類型。 showImg(https://segmentfault.com/img/remote/1460000017309509?w=850&h=572); 定義 1. 什么是數(shù)據(jù)類型? 數(shù)據(jù)類型,就是將...
閱讀 2106·2021-11-05 09:42
閱讀 2851·2021-09-23 11:21
閱讀 2841·2019-08-30 14:00
閱讀 3314·2019-08-30 13:15
閱讀 465·2019-08-29 17:18
閱讀 3547·2019-08-29 16:29
閱讀 2749·2019-08-29 14:06
閱讀 2794·2019-08-23 14:41