摘要:返回布爾值,表示參數字符串是否在原字符串的頭部。布爾值中布爾值有兩個和和都表示值的空缺,但事從背后更深遠的角度考慮,他們的還是有差別的。首先我們來看一下類型轉化表任意的值都可以轉換為布爾值,只有會被轉換為,其他所有值都會被轉換成。
開辟了一個關于javascript的基礎系列,更加深入、細致的了解這門語言。今天分享的是js的數據類型。
javascript的數據類型可以分為兩類:原始類型(基礎數據類型)和對象類型(引用數據類型)
原始類型包括:數字、字符串、布爾值、以及特殊的undefined和null
除了以上的數據類型,其他就都是對象類型了
具有代表性的對象類型有:對象(object)、數組(array)、函數(function)
本次我們著重介紹原始數據類型
兩個小注意點:
1.js語言是弱類型語言(并不是沒有數據類型)
2.在js語言中所聲明的變量是沒有數據類型的,因此可以被賦予任何類型的值
和其他變成語言不同,js不區分正整數值和浮點數值,js中所有數字都是用浮點數值表示的。
數字的算術運算符方法有+,-,*,/,%(加,減,乘,除,余)。
除此之外,js還支持更復雜的算術運算,這些復雜運算通過作為Math對象的屬性定義和常量來實現:
// 2的53次冪 Math.pow(2, 53) // 0.6的四舍五入值 Math.round(0.6) // 向上取整 Math.ceil(0.6) // 向下取整 Math.floor(0.6) // 取絕對值 Math.abs(-5) // 求出x,y,z的最大值 Math.max(x, y, z) // 求出x,y,z的最小值 Math.min(x, y, z) // 生成一下大于等于0小于1的隨機數 Math.random() // 圓周率 Math.PI // e自然對數的底數 Math.E // 3的開平方根 Math.sqrt(3) // 3的開立方根 Math.pow(3, 1/3) // 三角函數 Math.sin(0) // 求10的自然對數 Math.log(10) // 以10為底數的100的對數 Math.log(100)/Math.LN10 // 以2為底數的512的對數 Math.log(512)/Math.LN2 // e的3次方冪 Math.exp(3)
js的數字表示范圍是有限制的(能否表示的限制、能否滿足精度到個位的限制以及能否作為數組索引的限制)
具體的情況如下圖:
(圖片來自網絡,侵刪)
因此javascript在進行數學運算時,會出現溢出和下溢兩種情況,
溢出的情況為:
當運算結果超出了js語言所能表示的上線(即圖中1.8e308—正無窮的區域),結果會返回Infinity(表示無窮大)
同樣的,當計算的負數的值超過了能表示的負數范圍(即圖中-1.8e308—負無窮的區域),結果會返回-Infinity(表示負無窮大)
下溢的情況為:
當運算的結果無限接近于0,并比js能表示的最小值還小的情況(即圖中0—5e-324的區域)。這樣結果會返回0。
同樣的,當一個負數發生下溢(即圖中0—-5e-324的區域),這時結果會返回一個-0。
上文,我們介紹數字中預定義的全局變量Infinity,此外還有一個預定義的全局變量NaN(表示非數字,not-a-number,當運算的結果并不是一個數字值的時候,會返回NaN)
在js中,NaN有特殊的一點,就是它和任何值都不相等(包括自身),因此想要判斷一個值是否為NaN,可以使用x != x判斷
var x = 1 - "a" x != x //true
除此之外,我們還可以調用全局預定好的函數isNaN
// 當傳入的參數只要不是一個數字,就返回true isNaN(5 - "a") // true isNaN("1") // true isNaN("a") // true isNaN({a: 2}) // true isNaN(1) //false isNaN(Infinity) //false
另外,全局還有一個預定好的函數isFinite
// 當傳入的參數只要不是NaN, Infinity, -Infinity就返回true isFinite(5 - "a") // false isFinite("1") // false isFinite("a") // false isFinite({a: 2}) // false isFinite(1) // true isFinite(Infinity) //false
數學中實數有無限多個,而在javascript語言中能通過浮點數的形式只能表現其中的有限個,因此在js中使用實數的時候,我們往往都是使用的一個近似值。
javscript所采用的浮點數表示發,是一種二進制表示法,因此我們可以精確的表示1/2、1/8、1/1024。但是在數學中,我們常用的都是十進制分數1/10。所以js中并不能精確的表示像0.1這樣簡單的數字。
var x = 0.3-0.2 var y = 0.2-0.1 x == y // false
因此要避免在js中用浮點數進行計算(盡量使用整數)
文本javascript中的字符串采用的是UTF-16編碼的Unicode字符集,字符串的長度是其含有16位值的個數,如下:
var a = "z" var b = "?" // 注意,這個字不是“吉祥”的吉 a.length // => 1: a包含的一個16位值 u007A b.length // => 2: b包含兩個16位值 uD842uDFB7
在js語言中,字符串是由單引號或雙引號括起來的字符序列,定義的由單引號定界的字符串中可以包含雙引號,同樣,定義的由雙引號定界的字符串中也可以包含單引號。
字符串可以拆分為數行,每行必須以結束,如果希望在字符串中再起一行可以使用轉義字符
全部的轉義字符如下:
測試輸出結果如下:
但是,在ES6中,新增了模板字符串,模板字符串是用反勾號`將字符括起
在模板字符串中換行就簡單很多:
` hello world ` // 等價于 "hello world"
除此之外,模板字符串還支持元素注入
var str = "world" `hello ${world}` // 等價于 "hello " + str
除了字符串的length屬性之外,字符串還有很多可以調用的方法
var str = "Hello, World" str.charAt(0) // H, 返回第一個位置的字符 str.charAt(s.length - 1) // t, 返回最后一個位置的字符 str.substring(1,4) // ell, 返回位置2-4的字符 str.slice(1,4) // ell, 同上 str.slice(-3) // rld, 返回最后三個字符 str.indexOf("l") // 2, 返回首次出現l的位置 str.lastIndexOf("l") // 10,返回最后一次出現l的位置 str.split(", ") // ["Hello", "World"], 分割為數組 str.replace("H", "h") // "hello, World", 將h替換為H str.toUpperCase() // "HELLLO, WORLD", 將字符串所有字母變為大寫 str.toLowerCase() // "hello, world", 將字符串所有字母變為小寫 // es6新增方法 let s = "Hello world!"; s.startsWith("Hello") // true s.endsWith("!") // true s.includes("o") // true // includes():返回布爾值,表示是否找到了參數字符串。 // startsWith():返回布爾值,表示參數字符串是否在原字符串的頭部。 // endsWith():返回布爾值,表示參數字符串是否在原字符串的尾部。 "x".repeat(3) // "xxx" "hello".repeat(2) // "hellohello" "na".repeat(0) // "" // repeat方法返回一個新字符串,表示將原字符串重復n次
需要注意的是,對于字符串的任何方法都會返回一個新的字符串,而不會在原字符串上修改。
布爾值javascript中布爾值有兩個true和false
null&undefinednull和undefined都表示”值的空缺“,但事從背后更深遠的角度考慮,他們的還是有差別的。
對null進行typeof檢測,返回值是object
對undefined進行typeof檢測,返回值是undefined
undefined表示,對這個值還未定義,還沒有進行初始化。比如,當我們聲明一個變量,但是卻未賦值,此時會返回undefined,當我們獲取一個對象未定義的屬性,此時會返回undefined,當我們調用一個函數,卻未傳參,參數會返回undefined。
null表示,沒有對象,此處沒有值,此處不應該有值。比如,原型鏈的重點就是null。
后面會從棧和堆的角度進行另一番解釋。
我們可以這么理解,undefined是系統級的、出乎意料的、類似錯誤的空缺。而null是程序級的、正常的、在意料之中的值的空缺。在某些場景下,比如想賦值給一個變量,想表示變量為空,或作為參數傳入一個函數,這是,最佳的選擇是null。
包裝對象了解包裝對象之前,我們首先思考這么一個問題。
var a = "test" a.length //4
我們知道上面代碼中的a是一個字符串,字符串不是一個對象,不能進行.關鍵字的操作。但是,為什么我們可以得到a.length呢?
因為只要存在包裝對象的概念,在上述代碼執行的過程中,js會將字符串通過new String的方式生成一個包裝對象,這個對象繼承了String的方法,因為可以通過.的方式訪問到。一旦屬性的引用結束,這個包裝對象就會被銷毀(其實在js語言內部的實現上不一定創建或銷毀這個對象,但是整個過程在執行層面看起來是這樣的,我們也可以這么進行理解)
原始類型和引用類型的變與不變關系想要深入理解原始類型和引用類型的變與不變,相等比較等問題的時候,我們需要借助棧和堆的思想來理解,我們可以這么思考:
(圖片來自網絡,侵刪)
這張圖闡述了原始類型和引用類型的關系:
原始類型保存在棧內存中,原始類型(包括字符串、數字、布爾型、undefined)是保存在棧內存中,是不可以修改的(我們所看到的修改,其實都是刪除后重新賦值),當復制一個原始類型的時候,其實就是在內存中復制這么值。其中,undefined代表的就是未被賦值的一個棧內存的區域。
引用類型保存在堆內存中,但是在棧內存中存了一個引用類型的地址,棧內存中的地址有一個指針指向堆內存的引用類型。這個引用類型是可以進行修改的,比如我們可以向數組中push一個新值。如果我們只是簡單的復制一個引用類型(淺拷貝),那么其實復制的是這個在棧內存中的地址,復制后的值發生修改,那么之前被復制的值也同樣會被修改,因此在復制引用類型的時候,最好要進行深拷貝。其中,null很特殊,表示的是在棧內存中,有一個指針指向堆內存中的引用類型,一旦這個指針掉了,就是null。
類型轉換jacascript中的類型轉換非常常見,也是javascript語言中非常重要的一點。
首先我們來看一下類型轉化表:
任意JavaScript的值都可以轉換為布爾值,只有undefine、null、0、NaN、""會被轉換為false,其他所有值都會被轉換成true。
當字符串轉化為數字數字時,那些數字表示的字符串可以轉化為數字,也允許在開始和結尾處有空格,但是其他含有非空非數字字符都不會完成到數字的轉化,他們會轉化為NaN。
原始值到對象的轉換也非常簡單,原始值通過調用構造函數,轉化為包裝對象。
null和undefined除外,他們太特殊了,他們不會到對象進行正常的轉化。
其他類型的原始值會按照上表的方式進行轉換。
下面我們介紹一下,由對象轉化為原始值的過程:
JavaScript中對象到字符串的轉換經過如下步驟:
1.如果對象具有toString(),則調用這個方法,如果該方法返回一個原始值,則最后轉換成字符串。
2.如果對象沒有toString()方法,或者這個方法并不返回一個原始值,那么JavaScript會調用valueOf()方法,如果返回的是原始值,最后就轉換為字符串。
如果JavaScript無法從toString()和valueOf()中獲得一個原始值,就會拋出類型錯誤的異常。
對象到數字的轉換過程中:
JavaScript優先調用valueof()方法,再調用toString()。
我們可以知道,利用!,+,==進行隱式類型轉換
在這里,我們有必要了解==的類型轉換機制,如下:
1.如果兩個操作數的類型相同,則和上文所述的嚴格相等的比較規則一樣。如果嚴格相等,那么比較結果為相等。如果它們不嚴格相等,則比較結果為不相等。
2.如果兩個操作數類型不同,“==”相等操作符也可能會認為它們相等。檢測相等將會遵守如下規則和類型轉換:
如果一個值是null,另一個是undefined,則它們相等。
如果一個值是數字,另一個是字符串,先將字符串轉換為數字,然后使用轉換后的值行比較。
如果其中一個值是true,則將其轉換為1再進行比較。如果其中一個值是false,則將其轉換為0再進行比較。
如果一個值是對象,另一個值是數字或字符串,則使用上面講到的規則先將對象(先調用valueof()方法,再調用toString())轉化為原始值,再進行下一步的比較。
說完了,隱式的類型轉換,我們再看一下js語言提供的顯式類型轉換:
首先就是最簡單的Boolean(),Number(),String()和Object(),此外我們知道的toString()方法和String()返回的結果是一樣的。
Number("3") // => 3 String({}) // => "[object Object]" String([]) // => "" Boolean([]) // => true Boolean("0") // => true Boolean(0) // => false Object(3) // => new Number(3)
其次就是我們知道的一些全局函數:toFixed,toExponential,toPrecision,parseInt,parseFloat
var n = 123.45 n.toFixed(0) // => "123" n.toFixed(2) // => "123.45" // 根據指定小數點后的位數,返回字符串 n.toExponential(1) // => "1.2e+5" // 將數字進行科學計數法,傳入參數為小數點后數字個數,返回一個字符串 n.toPrecision(4) // => "123.4" // 傳入參數為保留數字的個數,返回一個字符串類型檢測
首先介紹一下typeof
typeof運算符返回的不是該變量的類型,而是該變量持有值的類型。在js中直接訪問一個未聲明的變量,會拋出異常,但是在typeof a中,不會拋出異常,并且返回undefined。這樣就能通過判斷是否存在該變量而安全使用該變量。typeof運算符適合于檢測原始類型和函數。
typeof undefined === "undefined" typeof true === "boolean" typeof 42 === "number" typeof "str" === "string" typeof Symbol() === "symbol" typeof null === "object" typeof function () {} === "function"
其次介紹一下instanceof
{a: 1} instanceof Object:右操作符是一個函數構造器,其原理是判斷左邊對象的原型鏈上是否有右邊構造器的prototype屬性。不同window或iframe間的對象不能使用instanceof。
[1,2] instanceof Array // => true [1,2] instanceof Object // => true "3" instanceof String // => false new String("3") instanceof String // => true new String("3") instanceof Object // => true
因此我們看出instanceof的問題,他對于原始數據類型根本無法檢測,對引用數據類型也不能很清楚的判定類別。而且,一旦修改了原型鏈環節上的prototype,檢測就無法使用。
然后我們再來看一下constructor
我們首先明確一下這個概念:
Object.prototype.constructor === Object // => true String.prototype.constructor === String // => true
構造函數的prototype中的constructor屬性指向的是這個構造函數本身,因此我們可以利用這個特點。
"1".constructor === String // => true (1).constructor === Number // => true [1,2,3].constructor === Array // => true
除了undefined和null,其他類型的變量均能使用constructor判斷出類型。
但是constructor可以被靠前的原型鏈覆蓋。
var a = [1,2,3] a.constructor = Object a.constructor === Array // => false
所以這個也不是很靠譜
最后我們來看一下Object.prototype.toString.call
這個方法百試百靈,是目前公認的最靠譜檢測數據類型的方法
var toString = Object.prototype.toString; console.log(toString.call(new Date) === "[object Date]") //true console.log(toString.call(new String) ==="[object String]") //true console.log(toString.call(new Function) ==="[object Function]") //true console.log(toString.call(Type) ==="[object Function]") //true console.log(toString.call("str") ==="[object String]") //true console.log(toString.call(Math) === "[object Math]") //true console.log(toString.call(true) ==="[object Boolean]") //true console.log(toString.call(/^[a-zA-Z]{5,20}$/) ==="[object RegExp]") //true console.log(toString.call({name:"wenzi", age:25}) ==="[object Object]") //true console.log(toString.call([1, 2, 3, 4]) ==="[object Array]") //true console.log(toString.call(undefined) === "[object Undefined]") //true console.log(toString.call(null) === "[object Null]") //true
建議使用這個方法!
最后,最近一段時間我的博客會保持長時間更新,針對文章有什么問題,大家可以在下方留言,感謝!
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/92983.html
摘要:只是瀏覽器只是實現可能的宿主環境之一,其他宿主環境包括和。級別級由兩個模塊組成核心和。有效不推薦有一點必須注意,即用操作符定義的變量將成為定義該變量的作用域的局部變量。會返回判斷相等符認為兩者相等。顯示因此盡量避免這樣運算。 一:JavaScript組成部分 JavaScript是由三個不同部分組成的,核心(ECMAScript) 、文檔對象模型(DOM)和瀏覽器對象模型(BOM)。 ...
摘要:以和為例,說明中的數字數據如何轉換為二進制數據。對象用來表示通用的固定長度的原始二進制數據緩沖區。中的數字數據如何轉換為二進制數據對和有了一個大概的了解,下面讓我們來看下它是如何進行二進制數據操作的。 概述 本文主要通過對JavaScript中數字數據與二進制數據之間的轉換,讓讀者能夠了解在JavaScript中如何對數字類型(包括但不限于Number類型)進行處理。 二進制數據在日常...
摘要:對象類型除了原始類型的值以外,其他都是對象。例如對象有屬性,值為,還有屬性,值為重要的特殊對象特殊對象函數數組日期正則全局錯誤。重新鞏固JS系列,都是比較基礎的東西,可以進行查漏補缺,很快看完,這是第一篇。 其他JS重新鞏固系列: 重新鞏固JS(二)——JavaScript操作符與表達式 重新鞏固JS(三)——JavaScript語句 JavaScript基本類型 在編程領域中,數據類型...
摘要:同一類的復合類型值兩個復合類型對象數組函數的數據比較時,不是比較它們的值是否相等,而是比較它們是否指向同一個對象。寬松相等雙等號將執行類型轉換原始類型的值原始類型的數據會轉換成數值類型再進行比較。 事件這塊知識點雖然是老生長談的,但對于我來說多多整理,多多感悟,溫故知新,每次看看這塊都有不同的收獲.(在這里我不會長篇大論,只會挑重點;具體的小伙伴們自行查找)參考:https://dev...
摘要:同一類的復合類型值兩個復合類型對象數組函數的數據比較時,不是比較它們的值是否相等,而是比較它們是否指向同一個對象。寬松相等雙等號將執行類型轉換原始類型的值原始類型的數據會轉換成數值類型再進行比較。 事件這塊知識點雖然是老生長談的,但對于我來說多多整理,多多感悟,溫故知新,每次看看這塊都有不同的收獲.(在這里我不會長篇大論,只會挑重點;具體的小伙伴們自行查找)參考:https://dev...
閱讀 2100·2023-04-26 00:09
閱讀 3121·2021-09-26 10:12
閱讀 3490·2019-08-30 15:44
閱讀 2866·2019-08-30 13:47
閱讀 927·2019-08-23 17:56
閱讀 3230·2019-08-23 15:31
閱讀 480·2019-08-23 13:47
閱讀 2516·2019-08-23 11:56