整合營銷服務商

          電腦端+手機端+微信端=數據同步管理

          免費咨詢熱線:

          JavaScript的數據類型及判斷

          JavaScript的數據類型及判斷

          文同步本人掘金平臺的文章:https://juejin.cn/post/6844903858112577549

          最近自己回歸基礎看了下javascript的相關知識點,想著看都看了,寫出來記錄下足跡也是一件好事,遂記錄~

          在javascript中有兩種類型,一種是基本數據類型,一種是引用類型。

          基本類型

          基本數據類型,也稱為簡單數據類型,在ES5中有以下五種:Undefined、Null、Boolean、Number和String,在ES6中新增了一種簡單的數據類型Symbol。

          Undefined類型

          Undefined類型只有一個值undefined。在進行相關變量定義的時候,未賦值的情況下,默認是賦值為undefined了。但是也是有些特殊的情況下會報錯的。情況我大致羅列下:

          # 情況1??:變量聲明了,但是沒有賦值
          var message;
          console.log(message); // undefined
          
          # 情況2??:變量聲明并賦值了,但是在console運行之后
          console.log(message); // undefined
          var message='find a frontend job in Canton!';
          
          # 情況3??:變量沒聲明,報引用報錯
          // var message;
          console.log(message); // Uncaught ReferenceError: message is not defined
          
          # 情況4??:不通過var聲明,直接寫變量,報引用錯誤
          message; // 不等價 var message;
          console.log(message); // Uncaught ReferenceError: message is not defined
          
          # 情況5??:不通過var聲明,直接寫變量賦值
          message='find a frontend job in Canton!'; // 默認在message前添加了var
          console.log(message); // find a frontend job in Canton!
          
          # 情況6??:不通過var聲明,直接寫賦值,但是在console運行之后,報引用錯誤
          console.log(message);
          message='find a frontend job in Canton!'; // 相當于沒message變量
          復制代碼


          上面羅列的是ES5中通過var聲明的情況。也許你會對情況2??產生疑惑:我都給message賦值了啊,但是打印出undefined,這就有點尷尬了?


          因為在js中執行上下文分為兩個階段,第一個階段是創建階段,第二個階段才是執行階段。

          上面情況2??的執行情況如下:

          1. 創建階段:

          executionContextObj={
          	scopeChain: { ... },
          	variableObject: {
          		message: undefined
          	},
          	this: { ... }
          }
          復制代碼

          2. 執行階段:

          executionContextObj={
          	scopeChain: { ... },
          	variableObject: {
          		message: 'find a frontend job in Canton!'
          	},
          	this: { ... }
          }
          復制代碼

          詳細的解析可以看下我之前翻譯的一篇文章JS的執行上下文和環境棧是什么?。

          上面講到的是var,我們引入ES6的let 和 const來演示下:

          # 情況7??:let聲明變量賦值
          let message;
          console.log(message); // undefined
          
          # 情況8??:let聲明變量但是不賦值,在console運行之后
          console.log(message); // Uncaught ReferenceError: Cannot access 'message' before initialization
          let message='find a frontend job in Canton!';
          
          # 情況9??:const聲明變量但是不賦值,報語法錯誤
          const message;
          console.log(message); // Uncaught SyntaxError: Missing initializer in const declaration
          復制代碼

          let和const改變了var命令會發生變量提升的現象,即變量可以在聲明之前使用,值為undefined。它們改變了這種奇怪的現象,聲明的變量一定要在聲明之后使用,否則報錯。

          當然還有其他聲明變量的方法,比如function命令等,這里不一一列舉,只是探討下undefined的值而已~

          Null類型

          Null類型的值是null。從邏輯角度來看,null值表示一個空對象指針。

          如果定義的變量準備在將來用來保存對象,那么最好就是將變量初始化為null,而不是其他的數據值。這樣,只要直接檢查null值就可以知道相應的變量是否已經保存了一個對象的引用。如下面的例子:

          if(car !=null) {
          	// 對car對象執行某些操作
          }
          復制代碼

          undefined值是派生自null值的。雖然兩者在==比較時候是相等的,如下:

          console.log(null==undefined); // true
          復制代碼

          當變量不確定類型的時候,可以不用為變量賦值,也就是默認賦值undefined了。但是如果你知道你的變量要保存對象但是還沒有真正保存對象的時候就要賦值null了。

          Boolean類型

          Boolean類型在日常生活中使用頻繁了,其值是true和false,對應我們口頭的是和否。

          將布爾值的true和false轉換為數值的話,可以用非0和0數字表示。

          console.log( 1==true); // true
          
          console.log( 0==false); // true
          復制代碼

          如果是恒等的比較方式===,那數字表示法是要涼涼的~

          Number類型

          Number類型有二進制表示法,八進制表示法,十六進制表示法和十進制表示法。這里只討論十進制表示法,因為在平常的開發中,用到十進制的情況居多

          這個類型用來表示整數值和浮點數值(即帶小數點的值)。

          整數值的基本操作很是簡單,而且沒啥bug好說,除非不在Number.MIN_VALUE和Number.MAX_VALUE范圍內。帶小數點的還是要留意下的,比如:

          let a=13.04;
          let b=2.5;
          console.log(a + b); // 15.54
          console.log(a * b); // 32.599999999999994
          console.log(a - b); // 10.54
          復制代碼

          咦咦,真是讓人尷尬,怎么上面代碼中兩個浮點數相乘會出現那么多位的數字啊,不是等于32.6嗎?

          所以在進行浮點數的運算的時候還是得慎重點,先轉換成整數計算,之后再切換回去浮點數,比如上面的a * b可以考慮寫成(a * 100 * (b * 10))/1000。

          當你要判斷一個值是否是數值,可以使用isNaN來表示,其返回一個布爾值,如下:

          console.log(isNaN(NaN)); // true
          console.log(isNaN(10)); // false
          console.log(isNaN('10'); // false , '10'會被轉化為10
          console.log('blue'); // true , 不能轉化為數值
          console.log(true); // false, 可被轉化為數值1
          復制代碼

          還有將非數值轉化為數值的三個方法:Number()、parseInt()和parseFloat()。見名思義:

          **Number()是將傳入的內容轉換為數字(整數)或NaN。但是在轉換字符串的時候比較復雜,一般用parseInt()**居多。**parseFloat()**就是轉化成浮點數的方法啦。

          String類型

          String類型也就是字符串類型啦。

          字符串類型包含一些特殊的字符字面量,也叫轉義序列,用來表示非打印字符串。比如換行符\n啦。

          在實際的開發中,我們需要將數字類型或對象類型轉換成字符串類型,那么我們可以直接使用toString()方法進行操作啦。好吧,這api的東西大家都會用,就不說了

          Symbol類型

          Symbol類型是ES6引入的新類型,為了防止對象中屬性名沖突的問題。

          Symbol值通過Symbol函數生成。這就是說,對象的屬性名現在可以有兩種類型,一種是原來就有的字符串,另一種就是新增的Symbol類型。凡是屬性名屬于Symbol類型,就都是獨一無二的,可以保證不會與其他屬性名產生沖突。

          具體的看下阮一峰的es6入門中Symbol部分。

          上面說到的是6種基本的數據類型,還有一種是引用類型。

          引用類型

          引用類型:當復制保存對象的某個變量時,操作的是對象的引用,但是在為對象添加屬性時,操作的是實際的對象。引用類型值指那些可能有多個值構成的對象。

          引用類型有這幾種:Object、Array、RegExp、Date、Function、特殊的基本包裝類型(String、Number、Boolean)以及單體內置對象(Global、Math)。

          基本包裝類型這個有點好玩,咦?上面的基本數據類型都有String、Number和Boolean啦,怎么這里還有這些。是的,上面的基本類型是通過基本包裝類型來創建的。如下:

          var s1='find a frontend job in Canton';
          var s2=s1.substring(2);
          復制代碼

          上面的代碼實際進行了下面的步驟:

          (1)創建String類型的一個實例;

          (2)在實例中調用指定的方法;

          (3)銷毀這個實例。

          上面的三個步驟轉化為代碼如下:

          var s1=new String('find a frontend job in Canton');
          var s2=s1.substring(2);
          s1=null;
          復制代碼

          (正規)的引用類型和基本包裝類型的主要區別就是對象的生存期。使用new操作符創建的引用類型的實例,在執行流離開當前作用域之前都一直保存在內存中。而自動創建的基本包裝類型的對象,則只存在于下一行代碼的執行瞬間,然后立即被銷毀。這意味著我們不能在運行時為基本類型值添加屬性和方法。來看下下面的例子:

          var s1='find a frontend job in Canton';
          s1.name='jia ming';
          console.log(s1.name); // undefined
          復制代碼

          只能通過基本包裝類的原型來添加了,比如改寫toString方法:

          var s1='find a frontend job in Canton';
          String.prototype.toString=function() {
              console.log('my name is jia ming');
          }
          console.log(s1.toString()); // my name is jia ming
          復制代碼

          嗯~苦口婆心介紹了javascript的數據類型,那么下面才是重頭戲。我們在實際的開發中,如何識別不同的數據類型呢?

          數據類型判斷

          數據類型有上面的7種類型,其中基本類型是Undefined、Null、Boolean、Number、String和Symbol,還有一種引用類型。引用類型又包含比較多種的對象,比如Object、Array等。

          我們首先想到的是通過typeof來判斷,直接上代碼來試下吧:

          let symbol=Symbol('jia ming');
          let str='find a frontend job in Canton!';
          let flag=true;
          let height=99;
          let job;
          let obj=null;
          console.log(typeof symbol); // symbol
          console.log(typeof str); // string
          console.log(typeof flag); // boolean
          console.log(typeof height); // number
          console.log(typeof job); // undefined
          console.log(typeof obj); // object
          復制代碼

          嗯~很ok啦,對基本的數據類型都能判斷到啦,這個null得到的結果是object,你可以當成特殊情況來處理啦 -- 無中生有,一生萬物嘛。

          我們再來看下引用類型打印出來的是什么東東

          let person={
              name: 'jia ming',
              info: 'find a frontend job in Canton!',
          };
          let arr=['jia ming', 'find a frontend job in Canton!'];
          let reg=new RegExp('jia ming', 'g');
          let date=new Date();
          let fn=()=> {
              return 'find a frontend job in Canton!';
          }
          let math=Math.min(2, 4, 8);
          console.log(typeof person); // object
          console.log(typeof arr); // object
          console.log(typeof reg); // object
          console.log(typeof date); // object
          console.log(typeof fn); // function
          console.log(typeof math); // number
          復制代碼

          咦咦~著實讓人尷尬啊,這個為啥那么多object啊,我的小心臟。我們只是簡單通過typeof校驗比較尷尬啊,我們換個思路,我們來結合call改變下上下文對象,改寫一個方法進行判斷,如下:

          let person={
              name: 'jia ming',
              info: 'find a frontend job in Canton!',
          };
          let arr=['jia ming', 'find a frontend job in Canton!'];
          let reg=new RegExp('jia ming', 'g');
          let date=new Date();
          function handleType(obj, type) {
              if(typeof obj==='object') {
                  return Object.prototype.toString.call(obj)===`[object ${type}]`;
              }
              return false;
          }
          console.log(handleType(person, 'Object')); // true
          console.log(handleType(arr, 'Array')); // true
          console.log(handleType(reg, 'RegExp')); // true
          console.log(handleType(date, 'Date')); // true
          復制代碼

          美滋滋,可以實現區別判斷的哈。可是上面的基本類型中null也是object啊,然后是Math類型的typeof也是number啊,這個你可以自己做下處理啦。這里就不考慮了~

          參考

          • 《JavaScript高級程序設計》
          • 阮一峰 ECMAScript 6 入門
          npm install type-yes
          

          目地址:github.com/liutaigang/…

          About

          首先通過一個例子來認識下 Ty:

          一個方法的參數類型判斷的例子,如:

          function func(value) {
              if( value 為 string 或 number 或 為空時 ) {
                  ... do something
              }
          }
          


          判斷方式:

          // 方式一:常規版
          typeof value==='string' || typeof value==='number' || value==null
          
          // 方式二:Lodash 版
          _.isString(value) || _.isNumber(value) || _.isNil(value)
          
          // 方式三:Ty 版
          Ty(value).str.num.nil.or
          


          Ty 版的判斷是最簡潔的!!!,但是也會讓人有些疑惑——上述表達式:Ty(value).str.num.nil.or,它如何實現判斷的?下面分析下:

          • 判斷參數:需要判斷的量,可以是任意類型
          • 類型標識符:類型的“符號”。str—— string,num —— number, nil —— null or undefined
          • 邏輯運算符:最終邏輯運算方式。or —— 或運算

          上述表達式可以簡單理解為:

          // 當 value=123
          
          [[value, 'str'], [value, 'num'], [value, 'nil']]==(判斷類型)==> [false, true, false]==(或運算)==> true
          


          到了這里,你大概已經了解 Ty 的邏輯符 or 的使用,除了 or , Ty 還有 is,not,and,nor,nand

          Usage

          is

          邏輯”是“判斷

          // 常規
          typeof value==='number'
          // Ty
          Ty(value).num.is
          
          // Ty error, 當進行 is 判斷時,如果判斷參數(或判斷標識符)輸入多個值時,會報錯
          Ty(value01, value02).num.is // error
          Ty(value).num.str.is // error
          


          not

          邏輯”否“判斷, is 的取反

          // 常規
          typeof value !='number'
          // Ty
          Ty(value).num.not
          
          // Ty error, 當進行 not 判斷時,如果判斷參數(或判斷標識符)輸入多個值時,會報錯。與 is 判斷相同
          


          or

          邏輯”或“判斷

          // 常規
          typeof value==='string' || typeof value==='number'
          // Ty
          Ty(value).str.num.or
          
          // 等價于:
          Ty(value, value).str.num.or // 參數會自動補全,所以這樣寫就“沒必要”了
          


          nor

          邏輯”或非“判斷, or 的取反

          // 常規
          !(typeof value==='string' || typeof value==='number')
          // Ty
          Ty(value).str.num.nor
          


          and

          邏輯“與”判斷

          示例一:

          // 常規
          typeof value01==='string' && typeof value02==='number'
          // Ty
          Ty(value01, value02).str.num.and
          


          示例二:

          // 常規
          typeof value01==='string' && typeof value02==='string'
          // Ty
          Ty(value01, value02).str.and
          
          // 等價于:
          Ty(value01, value02).str.str.and // 標識符也會自動補全,所以這樣寫就“沒必要”了
          


          nand

          邏輯“與非”判斷,and 的取反

          // 常規
          !(typeof value01==='string' && typeof value02==='number')
          // Ty
          Ty(value01, value02).arr.num.nand
          


          上述的判斷中,除了所有的邏輯操作符的使用方法,我還認識了 num、str 、nil 等類型標識符。在 Ty 中,類型標識符共有 60+,其中包括:簡寫類型標識符、特殊類型標識符常規類型標識符,下面我們將一一介紹:

          簡寫類型標識符

          簡寫標識符

          對應的常規標識類

          實際類型

          obj

          object

          Object (這里的 object, 不包含 array 和 null )

          arr

          array

          Array

          str

          string

          String

          num

          number

          Number

          bool

          boolean

          Boolean

          undef

          undefined

          undefined

          func

          function

          Function

          特殊類型標識符

          標識符

          實際類型

          nil

          null 或 undefined

          empty

          [] 或 {}

          emptyobject

          {} —— 沒有任何屬性的空對象

          emptyarray

          [] —— 沒有任何元素的空數組

          NaN

          NaN

          infinity

          Infinity 無窮大

          primitive

          原始類型: null, undefined, boolean, number, bigint, string, symbol

          示例:

          const isPrimitive=Ty(value).primitive.is // value=Symbol()
          const isEmpty=Ty(value).empty.is // value=[]
          


          常規類型標識符

          標識符

          實際類型

          null

          null (不包含 undefined)

          undefined

          undefined

          boolean

          Boolean

          number

          Number

          string

          String

          bigint

          BigInt

          symbol

          Symbol

          object

          Object (這里的 object, 不包含 array 和 null )

          array

          Array

          function

          Function

          promise

          Promise

          date

          Date

          regexp

          RegExp

          map

          Map

          set

          Set

          ......更多的請看附錄


          示例:

          const isIterator=Ty(value).array.map.set.or
          cosnt isPrimitive=Ty(value).null.undefined.boolean.number.string.bigint.symbol.or
          


          More

          擴展的 Ty 的類型標識符

          如果已有的類型標識符不滿足時, Ty 支持擴展,只要提供一個 TypeMatcher , 即類型匹配器:

          type TypeMatcher<T extends string>=(parameter: any, typeFlag: T)=> boolean;
          


          示例(ts):

          import { Ty, TypeMatcher, TypeFlag, buildinTypeMatcher } from 'type-yes';
          
          type MyType='element' | 'finite' | TypeFlag; // TypeFlag 是 Ty 的所有的類型標識符的一個聯合類型
          const typeMather: TypeMatcher<MyType>=(parameter, typeFlag)=> {  // parameter —— 判斷參數, typeFlag —— 類型標識符
            switch (typeFlag) {
              case 'element':
                return parameter instanceof Element;
              case 'finite':
                return Number.isFinite(parameter);
              default:
                return buildinTypeMatcher(parameter, typeFlag); // buildinTypeMatcher —— Ty 內置的類型匹配器
            }
          };
          
          const tty=new Ty(typeMather);
          


          使用效果(element 和 finite 會出現在拼寫提示中):

          Proxy 如何判斷

          Proxy 類型是難以判斷的——Proxy 代理的對象是什么類型,proxy 實例就判定為相應的類型,如:

          const arr=['a', 'b', 'c'];
          const arrProxy=new Proxy(arr, {});
          typeof arrProxy; // array
          Object.prototype.toString.call(arrProxy); // [object Array]
          


          Ty 中,繼承 Proxy 實現了一個子類:IdentifiableProxy,這個子類的類型是可以判斷的,如:

          const arr=['a', 'b', 'c'];
          const arrProxy=new IdentifiableProxy(arr, {});
          Object.prototype.toString.call(arrProxy); // [object Proxy-Array]
          
          // 使用 Ty 判斷
          Ty(arrProxy).proxy.is; // true —— 做 proxy 判斷時,arrProxy 判定為 proxy
          Ty(arrProxy).array.is; // true —— 做 array 判斷時,arrProxy 判定為 array
          Ty(arrProxy).array.proxy.and; // true
          


          類型標識符的“否運算“

          如何使用 Ty 實現下面這樣一個類型判斷:

          typeof value01==='object' && typeof value02 !='number'
          


          在 Ty 中,可以對單個類型標識符進行否運算:! + 類型標識符,如:

          Ty(value01, value02).obj['!num'].and
          


          Appendix

          常規類型標識符附錄

          標識符

          對應類型

          error

          Error

          reflect

          Reflect

          json

          JSON

          math

          Math

          int8array

          Int8Array

          uint8array

          Uint8Array

          uint8clampedarray

          Uint8ClampedArray

          int16array

          Int16Array

          uint16array

          Uint16Array

          int32array

          Int32Array

          uint32array

          Uint32Array

          bigint64array

          BigInt64Array

          biguint64array

          BigUint64Array (en-US)

          float32array

          Float32Array

          float64array

          Float64Array

          weakmap

          WeakMap

          weakset

          WeakSet

          arraybuffer

          ArrayBuffer

          atomics

          Atomics

          dataview

          DataView

          weakref

          WeakRef

          finalizationregistry

          FinalizationRegistry (en-US)

          iterator

          Iterator

          proxy

          Proxy

          intl

          Intl

          intl.collator

          Intl.Collator

          intl.datetimeformat

          Intl.DateTimeFormat

          intl.displaynames

          Intl.DisplayNames

          intl.listformat

          Intl.ListFormat

          intl.locale

          Intl.Locale

          intl.numberformat

          Intl.NumberFormat

          intl.pluralrules

          Intl.PluralRules

          intl.relativetimeformat

          Intl.RelativeTimeFormat

          intl.segmenter

          Intl.Segmenter

          global

          node 環境下的 globalThis

          window

          window 環境下的 globalThis 或 window


          作者:_code_bear_
          鏈接:https://juejin.cn/post/7351321160809725990


          JavaScript中,有多種方法可以判斷一個變量的數據類型。以下是一些常見的方法:

          1. typeof 操作符

          typeof 是JavaScript中的一元操作符,返回一個表示未計算變量類型或已計算對象類型的字符串。但是,需要注意的是 typeof 對于 null 和 array 的處理可能不是你所期望的:


          console.log(typeof undefined);    // "undefined"  
          console.log(typeof 123);          // "number"  
          console.log(typeof 'hello');      // "string"  
          console.log(typeof true);         // "boolean"  
          console.log(typeof {});           // "object"  
          console.log(typeof []);           // "object" 而不是 "array"  
          console.log(typeof null);         // "object" 而不是 "null"  
          console.log(typeof function(){}); // "function"
          1. instanceof 操作符

          instanceof 操作符用于檢測構造函數的 prototype 屬性是否出現在對象的原型鏈中的任何位置。這主要用于檢測對象是否屬于某個類。

          console.log([] instanceof Array);  // true  
          console.log(null instanceof Object); // false,因為 null 不是一個對象
          
          1. Array.isArray() 方法

          這是檢測一個值是否為數組的最佳方法。

          console.log(Array.isArray([]));  // true  
          console.log(Array.isArray({}));  // false
          
          1. Object.prototype.toString.call() 方法

          這個方法返回表示該對象的字符串。對于檢測原始值類型,特別是當 typeof 給出不直觀的結果時(如 null 和 array),這是一個很有用的方法。

          function getType(obj) {  
              return Object.prototype.toString.call(obj).slice(8, -1);  
          }  
            
          console.log(getType(null));       // "Null"  
          console.log(getType([]));         // "Array"  
          console.log(getType({}));         // "Object"  
          console.log(getType(123));        // "Number"  
          console.log(getType('hello'));    // "String"  
          console.log(getType(true));       // "Boolean"  
          console.log(getType(undefined));  // "Undefined"
          1. constructor 屬性

          每個JavaScript對象都有一個 constructor 屬性,它指向創建該對象的構造函數。但請注意,如果 constructor 被手動修改,則可能不準確。

          console.log(([]).constructor===Array);  // true  
          console.log(({}).constructor===Object); // true
          
          1. ES6 中的 Symbol.toStringTag

          某些內置對象(如 Array、Date、RegExp 等)的 @@toStringTag 屬性值是一個字符串,該字符串用于定制 Object.prototype.toString.call(obj) 的默認行為。但通常你不需要直接使用這個屬性,除非你在實現自定義對象并希望改變 Object.prototype.toString.call(obj) 的默認行為。


          主站蜘蛛池模板: 亚洲一区二区三区乱码A| 中文字幕视频一区| 免费一本色道久久一区| 日本高清成本人视频一区| 国产精品视频一区| 亚洲精品一区二区三区四区乱码| 亚洲一区二区三区乱码A| 无码丰满熟妇浪潮一区二区AV| 亚洲欧洲∨国产一区二区三区| 无码精品人妻一区二区三区免费| 日韩一区二区视频在线观看| 免费无码一区二区三区| 日本在线一区二区| 国产一区二区三区久久精品| 国产在线精品一区二区夜色| 无码日韩精品一区二区人妻| 波多野结衣一区二区免费视频 | 精品一区高潮喷吹在线播放| 无码人妻精品一区二区三区夜夜嗨| 国产精品自在拍一区二区不卡| 视频一区二区精品的福利| 日韩精品中文字幕视频一区| 女人18毛片a级毛片一区二区| 亚洲精品伦理熟女国产一区二区 | 少妇特黄A一区二区三区| 国产婷婷色一区二区三区| 东京热无码一区二区三区av| 国产一区三区二区中文在线| 好爽毛片一区二区三区四| 东京热无码av一区二区| 中文字幕人妻丝袜乱一区三区| 国产成人高清视频一区二区 | 国产剧情一区二区| 制服美女视频一区| 成人乱码一区二区三区av| 国产一区二区免费视频| 精品亚洲AV无码一区二区| 成人区人妻精品一区二区三区| 在线播放精品一区二区啪视频| 国产主播一区二区三区在线观看| 日韩精品一区二区三区在线观看|