<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                [TOC] >[info] ## 判斷類型 ~~~ 1.判斷類型常用方法'typeof'、'instanceof'、'Object.prototype.toString'、'constructor' ~~~ >[info] ## 使用typeof 區分數據類型 ~~~ 1.'typeof' 是一個操作符,不是方法因此使用的時候可以加括號,也可以省略 2.雖然'typeof'是用來區分數據類型的但是8個數據類型中'null'可以理解成是空 對象(object),并多了一個function 檢測 因此還是可以檢測類型依舊是8種類依次是用來區分'undefined','function','boolean','number','string','object','bigInt','symbol' 3.因此簡單的說'null' 在使用typeof 驗證的時候是'object' 4.typeof檢測未被聲明的變量,不會報錯,結果是 'undefined' 舉個例子 // 報錯 因為a變量沒有聲明 if (!a) { console.log(a) } // typeof 即使對沒聲明的變量也不會報錯 if (typeof a !== 'undefined') { console.log(a) } 針對這種特性在封裝第三方包的時候就可以使用,在node 環境中是沒有window 變量,相對的在瀏覽器環境中沒有 module和module.exports這種cjs 導出變量,為了讓我們封裝的東西可以在兩個環境運行就可以利用typeof 這種對 未聲明變量的不報錯的性質做出下面形式的寫法 // 支持瀏覽器導入 && 支持NODE端運行{CommonJS規范} (function () { let utils = { // ... }; /!* 暴露API *!/ if (typeof module === "object" && typeof module.exports === "object") module.exports = utils; if (typeof window !== "undefined") window.utils = utils; })(); 但是在es6出現后 let const在其被聲明之前對塊中的 let 和 const 變量使用 typeof 會拋出 一個 ReferenceError。塊作用域變量在塊的頭部處于“暫存死區”,直至其被初始化,在這 期間,訪問變量將會引發錯誤。 typeof undeclaredVariable === 'undefined'; typeof newLetVariable; // ReferenceError typeof newConstVariable; // ReferenceError typeof newClass; // ReferenceError let newLetVariable; const newConstVariable = 'hello'; class newClass{}; ~~~ >[danger] ##### 案例說明 ~~~ var num = 10; var str = "小白"; var flag = true; var nll = null; var undef; var obj = new Object(); var a = function(){} //是使用typeof 獲取變量的類型 console.log(typeof num); // number console.log(typeof str); // string console.log(typeof flag); // boolean console.log(typeof nll); // object console.log(typeof undef); // undefined console.log(typeof obj); // object console.log(typeof a); // function // 這個小案例 typeof object // undefined 未定義 他就是一個變量名 typeof Object // function 他是一個構造函數 / 除 Function 外的所有構造函數的類型都是 'object' var str = new String('String'); var num = new Number(100); typeof str; // 返回 'object' typeof num; // 返回 'object' var func = new Function(); typeof func; // 返回 'function' ~~~ >[danger] ##### 為什么 typeof null === 'object' 最開始的設計bug ~~~ 1.所有的數據類型值,在計算機底層中都是以2進制形式存儲的{64位},并且相對的二進制檢測類型效率更高, 在js 中這也類型相應的儲存形式信息: 000:對象 1:整數 010:浮點數 100:字符串 110:布爾 000000…. null 可以發現由于 null 的存儲單元(全是 0)最后三位和 object 完全一樣是 000 因此判斷null 也為 Object但是內部識別為對象后,會再次檢測這個對象有沒有內部實現[[call]],如果實現了,結果 是'function',沒有實現就是'object' ~~~ [參考鏈接](https://segmentfault.com/q/1010000011846328) [參考鏈接](https://2ality.com/2013/10/typeof-null.html) >[danger] ##### 判斷是否是對象 ~~~ 1.在function 也是對象但是typeof function 得到是function ,當想對是否為對象判斷時候 并且包含function 可以寫成 if (val !== null && /^(object|function)$/i.test(typeof val)) { // ... } ~~~ >[info] ## instanceof -- 檢測引用類型 ~~~ 1.a instanceof B a是不是B的實例,即a的原型鏈上是否有B var a = [1,2,3] console.log(a instanceof Array) // 變量 A 是數組么 打印結果: true 2.在`ECMAScript7`規范中的`instanceof`操作符則是根據'Symbol.hasInstance' 進行,用于判斷某對象是否為某構 造器的實例。因此你可以用它自定義 instanceof 操作符在某個類上的行為。'Symbol.hasInstance' 屬性特 點'writable/enumerable/configurable'都為false 不可寫,不可枚舉 不可修改屬性即不可以屬性賦值 var arr = [] Array[Symbol.hasInstance](arr) // true 數組構造函數上的'Symbol.hasInstance' 屬性從哪里來,如圖可以發現是繼承Function 上的,`ECMAScript7`規范中, 在`Function`的`prototype`屬性上定義了`Symbol.hasInstance`屬性 Array[Symbol.hasInstance] = function (){return false } arr instanceof Array // true 上面的案例看起來并不像我們設想的那樣,打印結果為false 因為之前說'Symbol.hasInstance' 屬性 不可寫,不可枚舉 不可修改,即在普通的構造函數上想直接修改是不行的 MDN 中給案例通過class 是可以重寫的 class Fn { static[Symbol.hasInstance](obj) { console.log('OK'); if (Array.isArray(obj)) return true; return false; } } let f = new Fn; let arr = [10, 20, 30]; console.log(f instanceof Fn); //=>false console.log(arr instanceof Fn); //=>true console.log(Fn[Symbol.hasInstance](f)); //=>true 3.如果在沒有Symbol.hasInstance 屬性瀏覽器上則會像以前一樣去原型鏈上中 4.弊端:不能檢測原始值類型的值 console.log(new Number(1) instanceof Number); //=>true console.log(1 instanceof Number); //=>false 5.小提示: O instanceof C在內部會調用InstanceofOperator(O, C)抽象操作,該抽象操作的步驟如下: 如果C的數據類型不是對象,拋出一個類型錯誤的異常 ~~~ * 圖 ![](https://img.kancloud.cn/67/8e/678e67a69f912e724371b2bf80bc73b9_818x607.png) [ 參考ECMAScript7規范中的instanceof操作符](https://segmentfault.com/a/1190000037689078) >[danger] ##### 參考案例 ~~~ class A extends Array{} const a = new A() a instanceof A // true a instanceof Array // true Array[Symbol.hasInstance](a) // true A[Symbol.hasInstance](a) // true A[Symbol.hasInstance](new Map) // false ~~~ >[danger] ##### 實現一個instanceof ~~~ function myInstanceof(left, right) { // 這里先用typeof來判斷基礎數據類型,如果是,直接返回false if(typeof left !== 'object' || left === null) return false; // getProtypeOf是Object對象自帶的API,能夠拿到參數的原型對象 let proto = Object.getPrototypeOf(left); while(true) { //循環往下尋找,直到找到相同的原型對象 if(proto === null) return false; if(proto === right.prototype) return true;//找到相同原型對象,返回true proto = Object.getPrototypeof(proto); } } // 驗證一下自己實現的myInstanceof是否OK console.log(myInstanceof(new Number(123), Number)); // true console.log(myInstanceof(123, Number)); // false ~~~ >[info] ## 利用Object.prototype.toString ~~~ 1.toString() 是 Object 的原型方法,調用該方法,可以統一返回格式為 '[object Xxx]' 的字符串,Xxx 就是對象的類型 Object 對象,直接調用 toString() 就能返回 [object Object];其他對象,需要通過 call 來調用 2.這是JS中唯一一個檢測數據類型沒有任何瑕疵的,可以檢測內置類型例如 "[object Number/String/Boolen/Null/Undefined/Symbol/BigInt/Object/Function/Array/RegExp/Date/Math/Error...]" 3.檢測返回值遵循規則,一般都是返回當前實例所屬的構造函數信息但是如果實例對象擁有 'Symbol.toStringTag' 屬性, 屬性值是啥,最后返回的就是啥,例如:Math[Symbol.toStringTag]="Math" => Object.prototype.toString.call(Math) “[object Math]” 正常沒有重寫'Symbol.toStringTag' class Fn { } let f = new Fn; console.log(Object.prototype.toString.call(f)); // [object Object] 重寫'Symbol.toStringTag' class Fn { [Symbol.toStringTag] = 'Fn'; } let f = new Fn; console.log(Object.prototype.toString.call(f)); //[object Fn] ~~~ ~~~ Object.prototype.toString({}) // "[object Object]" Object.prototype.toString.call({}) // 同上結果,加上call也ok Object.prototype.toString.call(1) // "[object Number]" Object.prototype.toString.call('1') // "[object String]" Object.prototype.toString.call(true) // "[object Boolean]" Object.prototype.toString.call(function(){}) // "[object Function]" Object.prototype.toString.call(null) //"[object Null]" Object.prototype.toString.call(undefined) //"[object Undefined]" Object.prototype.toString.call(/123/g) //"[object RegExp]" Object.prototype.toString.call(new Date()) //"[object Date]" Object.prototype.toString.call([]) //"[object Array]" Object.prototype.toString.call(document) //"[object HTMLDocument]" Object.prototype.toString.call(window) //"[object Window]" ~~~ >[danger] ##### typeof 和 Object.prototype.toString 搭配來判斷數據類型 ~~~ function getType(obj){ let type = typeof obj; if (type !== "object") { // 先進行typeof判斷,如果是基礎數據類型,直接返回 return type; } // 對于typeof返回結果是object的,再進行如下的判斷,正則返回結果或者用slice(8,-1)來截取獲得 return Object.prototype.toString.call(obj).replace(/^\[object (\S+)\]$/, '$1'); // 注意正則中間有個空 } /* 代碼驗證,需要注意大小寫,類型首字母大寫就是toString 小寫就是typeof */ getType([]) // "Array" typeof []是object,因此toString返回 getType('123') // "string" typeof 直接返回 getType(window) // "Window" toString返回 getType(null) // "Null"首字母大寫,typeof null是object,需toString來判斷 getType(undefined) // "undefined" typeof 直接返回 getType() // "undefined" typeof 直接返回 getType(function(){}) // "function" typeof能判斷,因此首字母小寫 getType(/123/g) //"RegExp" toString返回 ~~~ >[danger] #### 為什么不能用 Object.toString.call() ~~~ 1.如果當你使用Object.toString.call 來判斷類型你會發現,會報錯,其中提示內容是報錯內容如下 "Function.prototype.toString requires that 'this' be a Function",內置的Object構造函數是一個 Function (就像所有的原生構造函數一樣),所以它在它自己的原型屬性之前從Function.prototype繼承 'Object[[Prototype]] -> Function.prototype -> Object.prototype -> null'所以實際調用的是 'Function.prototype.toString',可以通過查看 下面的兩個鏈接可以知道 若 'this' 不是 Function 對象,則 toString() 方法將拋出 TypeError ("Function.prototype.toString called on incompatible object") 異常 2.簡單的理解Object.toString 此時是把Object 看作對象,要知道構造函數也是對象(雖然他的typeof 是function) 作為對象時候掉屬性自身沒有會去[[Prototype]]去找此時鏈接查找路線就像第一條說那樣 舉個例子說明 var a = new Object() a.toString.call(1) // '[object Number]' 因為 a 是通過Object 創建的實列,此時a.toString 找到就是Object.prototype.toString ,也可以 得到想要的效果 ~~~ ![](https://img.kancloud.cn/78/2c/782ccdf1718b2463ed1a56fc7a3faa1c_676x568.png) ~~~ console.log(typeof Object); // function console.log(typeof Object.prototype); // object // Object.toString.call([]) // 報錯 function a () { } Object.toString.call(a) // 不報錯因為a 是function ~~~ [ecma-262](http://www.ecma-international.org/ecma-262/5.1/index.html#sec-15.3.4 ) [Mdn-toString](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Function/toString) [階段參考](https://stackoverflow.com/questions/26333923/different-between-object-tostring-and-object-prototype-tostring) >[info] ## constructor ~~~ const array = [] console.log( array.constructor) const num = 1 console.log(num.constructor) 打印結果 ? Array() { [native code] } ? Number() { [native code] } var a = []; a.constructor === Array; ~~~ >[info] ## 總結關于檢測數據類型 ~~~ 1.typeof 在引用類型檢測的時候不能具體,除了function 可以判斷出來,剩下的引用類型和null統一都是'object' 2.instanceof 可以準確地判斷復雜引用數據類型,但是不能正確判斷基礎數據類型; 3.Object.prototype.toString 萬能方法最終解 ~~~
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看