成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

JavaScript系列--類型判斷的4種基本方法,研究jquery的type方法,空對象的檢測方法

lavor / 2559人閱讀

摘要:用對象字面量創(chuàng)建的對象會報錯,使用構(gòu)造函數(shù)創(chuàng)建的對象屬于。發(fā)現(xiàn),構(gòu)造函數(shù)創(chuàng)建的,,,,。從原型鏈角度講,構(gòu)造函數(shù)就是新對象的的類型。

一、前言

類型判斷有時候真的頭疼,但是一旦熟練使用就會覺得不過如此。初級的,會判斷數(shù)字和字符串。中級的,會判斷數(shù)組和對象。進(jìn)階的,會判斷日期,正則,錯誤類型。高級的,會判斷plainObject,空對象,window對象等等。

基本類型:String、Number、Boolean、Symbol、Undefined、Null 

引用類型:Object

基本類型也稱為簡單類型,由于其占據(jù)空間固定,是簡單的數(shù)據(jù)段,為了便于提升變量查詢速度,將其存儲在棧中,即按值訪問。

引用類型也稱為復(fù)雜類型,由于其值的大小會改變,所以不能將其存放在棧中,否則會降低變量查詢速度,因此,其值存儲在堆(heap)中,而存儲在變量處的值,是一個指針,指向存儲對象的內(nèi)存處,即按址訪問。引用類型除 Object 外,還包括 Function 、Array、RegExp、Date 等等。

鑒于 ECMAScript 是松散類型的,因此需要有一種手段來檢測給定變量的數(shù)據(jù)類型。對于這個問題,JavaScript 也提供了多種方法,但遺憾的是,不同的方法得到的結(jié)果參差不齊。

二、typeof

typeof是最經(jīng)常用到的判斷類型的。

typeof("saucxs")    //"string"
typeof "saucxs"   //"string"
typeof function(){console.log("saucxs")}   //"function"
typeof ["saucxs","songEagle",1,2,"a"]    //"object"
typeof {name: "saucxs"}    //"object"
typeof 1   //"number"
typeof undefined     //"undefined"
typeof null    //"object"
typeof /^d/   //"object"
typeof Symbol   // "function"

其實(shí),typeof是一個運(yùn)算符,和加減乘除類似,這就是為啥可以這樣寫 typeof "saucxs"。

在《JavaScript權(quán)威指南》中對typeof的介紹:typeof是一元操作符,放在單個操作數(shù)的前面,操作數(shù)可以是任意類型。返回值表示操作數(shù)的類型的一個字符串。

JavaScript中一共有6中基本數(shù)據(jù)類型:string,number,boolean,null,undefined,symbol,一種對象類型:object。

分別對應(yīng)的typeof的值,結(jié)果不是一一對應(yīng)的,分別:string,number,boolean,object,undefined,function,對象類型:object。

注意:typeof 可以檢測函數(shù)類型

但是在object下還有很多細(xì)分內(nèi)部屬性:Array,F(xiàn)unction,Date,RegExp,Error等。

var date = new Date();
var error = new Error();
console.log(typeof date); // object
console.log(typeof error); // object

所以還需要更好的區(qū)分。

三、instanceof

使用instanceof的前提條件:object instanceof constructor。object--要檢測的對象。constructor--某個構(gòu)造函數(shù)。說明使用這個instanceof必須是用來檢測對象的的類型,不能檢測其他類型。

A instanceof B用來判斷A是否為B的實(shí)例。如果A是B的實(shí)例,則返回true,否則false。

原理:instanceof是檢測原型。

instanceof (a,B) = {
    var l = a.__proto__;
    var R = B.prototype;
    if(l === R) {
        // a的內(nèi)部屬性 __proto__ 指向 B 的原型對象
        return true;
    }
    return false;
}

分析:a的_proto_指向B的prototype時,a就是B的實(shí)例。

[] instanceof Array    //true
[] instanceof Object    //true
new Array([1,43,6]) instanceof Array    // true
new Array([1,43,6]) instanceof Object   // true

{} instanceof Object   // 原型上沒有定義  Uncaught SyntaxError: Unexpected token instanceof
({})  instanceof Object;   //true
Object.create({"name": "saucxs"}) instanceof  Object   //true
Object.create(null) instanceof  Object    //false  一種創(chuàng)建對象的方法,這種方法創(chuàng)建的對象不是Object的一個實(shí)例

new Date() instanceof Date   //true
new Date() instanceof Object   //true

"saucxs" instanceof Object   //false
"saucxs" instanceof String  //false
new String("saucxs") instanceof Object  //true
new String("saucxs") instanceof String  //true

1 instanceof Object   //false
1 instanceof Number   //false
new Number(1) instanceof Object  //true
new Number(1) instanceof Number  //true

true instanceof Object   //false
true instanceof Boolean   //false
new Boolean(true) instanceof Object  //true
new Boolean(true) instanceof Boolean   //true

null instanceof Object    //false
undefined instanceof Object  //false
Symbol() instanceof Symbol   //false

注意:1、new Date對象既屬于Object,又屬于Date。(他們是由Object類派生出來的)。

2、用字面量創(chuàng)建的數(shù)組或者構(gòu)造函數(shù)創(chuàng)建的數(shù)組,既屬于Object,又屬于Array。

3、用對象字面量創(chuàng)建的對象object 會報錯, {} instanceof Object;使用構(gòu)造函數(shù)創(chuàng)建的對象屬于Object。

4、用字面量的創(chuàng)建的字符串,數(shù)字,布爾,既不屬于Object,也不屬于各自類型;只有使用構(gòu)造函數(shù)創(chuàng)建的字符串,數(shù)字,布爾,既屬于Object,又屬于各自的類型。

發(fā)現(xiàn)[],構(gòu)造函數(shù)創(chuàng)建的Date,Object,String,Number,Boolean。既屬于自身,又屬于Object。

舉個例子,[], Array, Object的關(guān)系:

從 instanceof 能夠判斷出 [ ].__proto__ 指向 Array.prototype,而 Array.prototype.__proto__ 又指向了Object.prototype,最終 Object.prototype.__proto__ 指向了null,標(biāo)志著原型鏈的結(jié)束。因此,[]、Array、Object 就在內(nèi)部形成了一條原型鏈:

從原型鏈可以看出,[] 的 proto 直接指向Array.prototype,間接指向 Object.prototype,所以按照 instanceof 的判斷規(guī)則,[] 就是Object的實(shí)例。依次類推,類似的 new Date()、new Person() 也會形成一條對應(yīng)的原型鏈 。因此,instanceof 只能判斷兩個對象是否屬于實(shí)例關(guān)系, 而不能判斷一個對象實(shí)例具體屬于哪種類型。

存在的問題:

它假定只有一個全局執(zhí)行環(huán)境。如果網(wǎng)頁中包含多個框架,那實(shí)際上就存在兩個以上不同的全局執(zhí)行環(huán)境,從而存在兩個以上不同版本的構(gòu)造函數(shù)。如果你從一個框架向另一個框架傳入一個數(shù)組,那么傳入的數(shù)組與在第二個框架中原生創(chuàng)建的數(shù)組分別具有各自不同的構(gòu)造函數(shù)。

var iframe = document.createElement("iframe");
document.body.appendChild(iframe);
xArray = window.frames[0].Array;
var arr = new xArray(1,2,3); // [1,2,3]
arr instanceof Array; // false

針對數(shù)組問題,ES5 提供了 Array.isArray() 方法 。該方法用以確認(rèn)某個對象本身是否為 Array 類型。

if (Array.isArray(value)){
   //對數(shù)組執(zhí)行某些操作
}

Array.isArray() 本質(zhì)上檢測的是對象的 [[Class]] 值,[[Class]] 是對象的一個內(nèi)部屬性,里面包含了對象的類型信息,其格式為 [object Xxx] ,Xxx 就是對應(yīng)的具體類型 。對于數(shù)組而言,[[Class]] 的值就是 [object Array] 。

四、constructor

定義一個構(gòu)造函數(shù)Func(),JS引擎會給Func添加prototype原型,然后再給prototype上添加一個constructor屬性,并且指向Func的引用。

實(shí)例化一個函數(shù)func,var func = new Func()。此時Func原型上的constructor傳遞到func上,因此func.constructor === Func。

Func利用原型對象上的constructor引用自身,當(dāng)Func作為構(gòu)造函數(shù)來創(chuàng)建實(shí)例化對象時,原型上的constructor就會遺傳到新創(chuàng)建的對象上。從原型鏈角度講,構(gòu)造函數(shù)Func就是新對象的func的類型。這樣存在的意義就是新對象產(chǎn)生之后,可以追蹤數(shù)據(jù)類型。

JavaScript 中的內(nèi)置對象在內(nèi)部構(gòu)建時也是這樣做的:

"saucxs".constructor === String    //true
new String("saucxs").constructor === String   //true
[].constructor === Array     //true
new Array([12,56]).constructor === Array     //true

new Number(12).constructor === Number    //true
new Function(console.log("saucxs")).constructor === Function     //true
new Date().constructor === Date     //true
new Error().constructor === Error     //true

window.constructor === Window   //true
document.constructor === HTMLDocument  //true

注意:

(1) null 和 undefined 是無效的對象,因此是不會有 constructor 存在的,這兩種類型的數(shù)據(jù)需要通過其他方式來判斷。

(2)函數(shù)的 constructor 是不穩(wěn)定的,這個主要體現(xiàn)在自定義對象上,當(dāng)開發(fā)者重寫 prototype 后,原有的 constructor 引用會丟失,constructor 會默認(rèn)為 Object

為什么變成了 Object?

因?yàn)?prototype 被重新賦值的是一個 { }, { } 是 new Object() 的字面量,因此 new Object() 會將 Object 原型上的 constructor 傳遞給 { },也就是 Object 本身。

因此,為了規(guī)范開發(fā),在重寫對象原型時一般都需要重新給 constructor 賦值,以保證對象實(shí)例的類型不被篡改。

五、Object.prototype.toString

toString() 是 Object 的原型方法,調(diào)用該方法,默認(rèn)返回當(dāng)前對象的 [[Class]] 。這是一個內(nèi)部屬性,其格式為字符串 [object xxx] ,其中 xxx 就是對象的類型。

這個方法到底是個啥?可以 先看ES5 規(guī)范地址:https://es5.github.io/#x15.2.4.2

toString方法被調(diào)用的時候,會按照這個步驟執(zhí)行:

(1)如果this的值是undefined,就返回[object Undefined];

(2)如果this的值是null,就返回[object Null];

(3)讓O成為ToObject(this)的結(jié)果;

(4)讓class成為O的內(nèi)部屬性[[class]]的值;

(5)最后返回由"[object" 和 class 和 "]"三個部分組成的字符串。

一句話就是:調(diào)用Object.prototype.toString 會返回一個"[object" 和 class 和 "]"組成的字符串,而class要判斷對象的內(nèi)部屬性。

console.log(Object.prototype.toString.call(undefined)) // "[object Undefined]"
console.log(Object.prototype.toString.call(null)) // "[object Null]"
console.log(Object.prototype.toString.call(Window))  // "[object Function]"

var date = new Date();
console.log(Object.prototype.toString.call(date)) // "[object Date]"
console.log(Object.prototype.toString.call(Symbol)) // "[object Function]"

注意:通過call改變this的指向。

所以這個class的值是識別對象類型的關(guān)鍵,所以使用Object.prototype.toString方法識別出更多的類型,可以識別出至少11種類型

var number = 1;          // [object Number]
var string = "123";      // [object String]
var boolean = true;      // [object Boolean]
var und = undefined;     // [object Undefined]
var nul = null;          // [object Null]
var obj = {a: 1}         // [object Object]
var array = [1, 2, 3];   // [object Array]
var date = new Date();   // [object Date]
var error = new Error(); // [object Error]
var reg = /a/g;          // [object RegExp]
var func = function a(){}; // [object Function]
Math    //[object Math]
JSON  //[object JSON]

注意:

1、其實(shí)Math對象和JSON對象,并不會去判斷;

2、Math對象并不像Date和String那樣對象的類,沒有構(gòu)造函數(shù)Math(), Math.sin()這樣的只是函數(shù),不是某一個對象的方法。

六、研究jquery的type API

使用Object.prototype.toString這個方法,判斷各種類型就比較輕松了,參考了jquery的源碼的type部分:

function type(obj) {
    // 一箭雙雕
    if (obj == null) {
        return obj + "";
    }
    return typeof obj === "object" || typeof obj === "function" ?
        class2type[Object.prototype.toString.call(obj)] || "object" :
        typeof obj;
}

其中class2type部分

var class2type = {};

// 生成class2type映射
"Boolean Number String Function Array Date RegExp Object Error".split(" ").map(function(item, index) {
    class2type["[object " + item + "]"] = item.toLowerCase();
})

使用:

type(1);   //"number"
type("123456");  //"string"
type(true);      //boolean
type(undefined);    //undefined
type(null);     //"null"
type({name: "saucxs"});   //"object"
type([1,2,"saucxs",3,4]);   //"array"
type(new Date());    // "date"
type(new Error());   //"error"
type(/^d/);    //"regexp"
type(function(){console.log("saucxs")});   //"function"
type(Symbol);   //"function"

這就非常完美的實(shí)現(xiàn)了,對我們?nèi)粘P枰愋偷呐袛唷?/p>

實(shí)現(xiàn)了判斷日期,正則,錯誤類型等。

如果還需要判斷比較復(fù)雜的,比如:空對象,window對象,類數(shù)組對象等等。

七、空對象EmptyObject

jQuery提供了 isEmptyObject 方法來判斷是否是空對象

function isEmptyObject( obj ) {
        var name;
        for ( name in obj ) {
            return false;
        }
        return true;
}

思路:判斷空對象就是判斷是是否有屬性值,for循環(huán)一旦執(zhí)行,就說明有屬性,有屬性返回false。

console.log(isEmptyObject({})); // true
console.log(isEmptyObject([])); // true
console.log(isEmptyObject(null)); // true
console.log(isEmptyObject(undefined)); // true
console.log(isEmptyObject(123)); // true
console.log(isEmptyObject("")); // true
console.log(isEmptyObject(true)); // true

這個判斷主要用來區(qū)別 {} 和 {name: "saucxs"} 就行。

注意點(diǎn):(1)for in 是ES6的屬性,這個會遍歷原型上的屬性。(2)使用Object.keys(obj)是ES5的屬性,不會遍歷原型上的屬性

八、window對象

window對象是客戶端js的全局對象,他有一個window屬性指向自身。根據(jù)這個特性判斷是否為window對象。

function isWindow(obj){
   return obj != null && obj ===obj.window;
}

注意:一個普通對象擁有 window 屬性,并且指向自身。比如這個:

function isWindow( obj ) {
    return obj != null && obj === obj.window;
}
let fakeWindow = {}
fakeWindow.window = fakeWindow
isWindow(fakeWindow) // true

是不是可以這么修改呢?

function isWindow(obj) {
    return !!(window && obj === window)
}
九、類數(shù)組對象

如果對類數(shù)組沒有概念,舉個例子:

1、數(shù)組和類數(shù)組

var arr = [,,3];

對應(yīng)的類數(shù)組是

var arrLike = {
     2: 3,
     length: 3
}

看jquery的源碼

function isArrayLike(obj) {

    // obj 必須有 length屬性
    var length = !!obj && "length" in obj && obj.length;
    var typeRes = type(obj);

    // 排除掉函數(shù)和 Window 對象
    if (typeRes === "function" || isWindow(obj)) {
        return false;
    }

    return typeRes === "array" || length === 0 ||
        typeof length === "number" && length > 0 && (length - 1) in obj;
}

所以如果 isArrayLike 返回true,至少要滿足三個條件之一:

(1)是數(shù)組

(2)長度為 0

(3)lengths 屬性是大于 0 的數(shù)字類型,并且obj[length - 1]必須存在

第三個條件:數(shù)組中用逗號直接跳過的時候,我們認(rèn)為該元素是不存在的,類數(shù)組對象中也就不用寫這個元素,但是最后一個元素是一定要寫的,要不然 length 的長度就不會是最后一個元素的 key 值加 1。比如數(shù)組可以這樣寫

var arr = [1,,];
console.log(arr.length) // 2

改寫成類數(shù)組

var arrLike = {
    0: 1,
    length: 1
}

所以符合條件的類數(shù)組對象是一定存在最后一個元素的!

十、判斷是不是dom元素

isElement 判斷是不是 DOM 元素。

isElement = function(obj) {
    return !!(obj && obj.nodeType === 1);
};
十一、總結(jié)

判斷類型主要時四個方法:(1)typeof;(2)instanceof;(3)constructor;(4)Object.prototype.toString()。

從基本的六種類型判斷,可以使用typeof,如果涉及到對象的內(nèi)部類型時候;還可以使用instanceof,檢測對象原型的;還可以使用constructor屬性是不是指向他們構(gòu)造函數(shù);需要使用Object.prototype.toString(),如果需要判斷空對象,可以使用ES6 的 for in 來判斷,用window屬性指向自身來判斷是不是window對象。以及類數(shù)組對象的判斷,以及判斷是不是dom元素的判斷。

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/109555.html

相關(guān)文章

  • JavaScript系列類型判斷4基本方法,研究jquerytype方法,對象檢測方法

    摘要:用對象字面量創(chuàng)建的對象會報錯,使用構(gòu)造函數(shù)創(chuàng)建的對象屬于。發(fā)現(xiàn),構(gòu)造函數(shù)創(chuàng)建的,,,,。從原型鏈角度講,構(gòu)造函數(shù)就是新對象的的類型。 一、前言 類型判斷有時候真的頭疼,但是一旦熟練使用就會覺得不過如此。初級的,會判斷數(shù)字和字符串。中級的,會判斷數(shù)組和對象。進(jìn)階的,會判斷日期,正則,錯誤類型。高級的,會判斷plainObject,空對象,window對象等等。 基本類型:String、N...

    xiongzenghui 評論0 收藏0
  • JavaScript專題之類型判斷(上)

    摘要:專題系列第四篇,講解類型判斷的各種方法,并且跟著寫一個函數(shù)。返回值為表示操作數(shù)類型的一個字符串??紤]到實(shí)際情況下并不會檢測和,所以去掉這兩個類型的檢測。 JavaScript專題系列第四篇,講解類型判斷的各種方法,并且跟著 jQuery 寫一個 type 函數(shù)。 前言 類型判斷在 web 開發(fā)中有非常廣泛的應(yīng)用,簡單的有判斷數(shù)字還是字符串,進(jìn)階一點(diǎn)的有判斷數(shù)組還是對象,再進(jìn)階一點(diǎn)的有判...

    lk20150415 評論0 收藏0
  • JavaScript專題系列文章

    摘要:專題系列共計篇,主要研究日常開發(fā)中一些功能點(diǎn)的實(shí)現(xiàn),比如防抖節(jié)流去重類型判斷拷貝最值扁平柯里遞歸亂序排序等,特點(diǎn)是研究專題之函數(shù)組合專題系列第十六篇,講解函數(shù)組合,并且使用柯里化和函數(shù)組合實(shí)現(xiàn)模式需求我們需要寫一個函數(shù),輸入,返回。 JavaScript 專題之從零實(shí)現(xiàn) jQuery 的 extend JavaScritp 專題系列第七篇,講解如何從零實(shí)現(xiàn)一個 jQuery 的 ext...

    Maxiye 評論0 收藏0
  • JavaScript專題之類型判斷(下)

    摘要:專題系列預(yù)計寫二十篇左右,主要研究日常開發(fā)中一些功能點(diǎn)的實(shí)現(xiàn),比如防抖節(jié)流去重類型判斷拷貝最值扁平柯里遞歸亂序排序等,特點(diǎn)是研究和的實(shí)現(xiàn)方式。 JavaScript專題系列第五篇,講解更加復(fù)雜的類型判斷,比如 plainObject、空對象、類數(shù)組對象、Window對象、DOM 元素等 前言 在上篇《JavaScript專題之類型判斷(上)》中,我們抄襲 jQuery 寫了一個 typ...

    QLQ 評論0 收藏0
  • 前端面試之手寫代碼

    摘要:雖然構(gòu)造函數(shù)或者對象字面量的方法都可以用來創(chuàng)建對象,但是這些方法使用同一個接口創(chuàng)建很多對象,會產(chǎn)生大量的重復(fù)代碼。參考資料冴羽的專題系列中高級前端面試手寫代碼無敵秘籍前端筆試之手寫代碼一本系列會從面試的角度出發(fā)圍繞JavaScript,Node.js(npm包)以及框架三個方面來對常見的模擬實(shí)現(xiàn)進(jìn)行總結(jié),具體源代碼放在github項(xiàng)目上,長期更新和維護(hù) showImg(https://use...

    niceforbear 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<