JS有哪些資料型別?
這裡是修真院前端小課堂,每篇分享文從
【背景介紹】【知識剖析】【常見問題】【解決方案】【編碼實戰】【擴充套件思考】【更多討論】【參考文獻】
八個方面深度解析前端知識/技能,本篇分享的是:
【JS有哪些資料型別?】
大家好,我是IT修真院武漢分院web第17期的學員吳三水,一枚正直純潔善良的web程式設計師
今天給大家分享一下,修真院官網js(職業)任務一,深度思考中的知識點——JS有哪些資料型別?
1.背景介紹
JS有哪些資料型別?
JS中有兩種資料型別
1.簡單資料型別(也稱基本資料型別):Undefined;Null;Boolean;Number和String。
2.引用資料型別(也稱複雜資料型別),其中包括Object;Array;Function等等。
PS:在引用資料型別中,又有三個特殊的引用型別,和基本資料型別相似。
2.知識剖析
辨別資料
一般情況下我們可以用typeof()來辨別一些資料的型別
typeof ( 123 ) //Number typeof ( 'abc' ) //String typeof ( true ) //Booleant ypeof ( undefined ) //Undefined typeof ( null ) //Object typeof ( { } ) //Object typeof ( [ ] ) //Object typeof ( function (){} ) //Function12345678
經過試驗後發現,typeof雖然能夠辨別出資料的型別,但是因為null、{}、[]都是算是一個空的物件,所以它返回的都是Object,typeof 返回值有6中型別: “number,” “string,” “boolean,” “object,” “function,” 和 “undefined.”。
PS:因此使用typeof()無法細緻辨別出arry、null和object。
基本資料和引用資料的特點和區別
基本資料型別:
基本資料型別的值是不可變的
任何方法都無法改變一個基本型別的值,比如一個字串:
var s = "hello"; s.toUpperCase()//HELLO; alert(s.toUpperCase())//HELLO; alert(s)//hello1234
雖然s.toUpperCase()將hello改變為了HELLO,但是s的值沒有變化,可得知:這裡呼叫toUpperCase()方法後返回的只是一個新的字串,跟原先定義的變數s並沒有關係。
基本資料型別不可以新增屬性和方法
var p = "change"; p.age = 29; p.method = function(){console.log(name)}; alert(p.age)//undefinedalert(p.method)//undefined
通過上面的程式碼,我們發現不能給基本型別新增屬性和方法 ,也再次說明基本型別是不可變的
基本資料型別的賦值是簡單賦值
如果從一個變數向另一個變數賦值基本型別的值,會在變數物件上建立一個新值, 然後把該值複製到為新變數分配的位置上
var a = 10; var b = a; a++; alert(a)//11alert(b)//10
上面的程式碼中,a中儲存的值是10.當使用a的值來初始化b時, b中也儲存了值10.但b中的10和a中的10是沒有任何關聯的。
b值中的10只是a值中的一個副本. 所以這a,b兩個變數可以參與任何操作而不會相互影響。
基本資料型別的比較是值的比較
var person1 = 'abc'; var person2 = 'abc'; alert(person1 == person2); // true; var person1 = 'abc'; var person2 = 'abcd'; alert(person1 == person2); // false; var person1 = 1; var person2 = true; alert(person1 == person2); // true;
從person1 和person2的3個對比,我可以發現,它們的資料對比是它們值的比較,而不是資料型別的比較。
引用資料型別
引用資料型別的特點和基本資料型別相反。
引用資料型別引用型別的值是可以改變的
var a = [1,2,3]; a[0] = 0;//更改陣列的一個元素 a[3] = 4;//給陣列增加一個元素 alert(a);//0.2.3.4;
上面程式碼中可以看到,a的陣列第一個1更改為了0,而且還新增一個a原來沒有的第四個值4.我們可得知引用型別的值是可以改變的。
引用型別可以新增屬性和方法
var person = {}; person.name = "change"; person.say = function(){alert("hello");} alert(person.name)//change alert(person.say)//function(){alert("hello");}
上面程式碼中可以得知,引用型別的資料可以給其新增屬性和方法。
引用型別的賦值是物件引用
var a = {}; var b= a; a.name = "change"; alert(a.name)//change; alert(b.name)//change; b.age = 29;alert(a.age)//29 alert(b.age)//29
當從一個變數向另一個變數賦值引用型別的值時, 同樣也會將儲存在變數中物件的值複製一份放到為新變數分配的空間中. 因為引用型別儲存在變數中的值是物件在堆記憶體中的地址(這個地址就是指向物件在堆記憶體裡的指標),所以兩個變數都儲存了同一個物件的地址,而這兩個地址指向了同一個物件,因此,對於這2個變數,我們改變任何一個變數,都會互相影響。
引用型別的比較是引用的比較
var person1 = {}; var person2 = {}; alert(person1 == person2)//false
引用型別的比較是引用的比較,換句話說,就是比較兩個物件儲存在棧區的指向堆記憶體的地址是否相同,此時,雖然p1和p2看起來 都是一個字串,但是他們儲存在棧區中的指向堆記憶體的地址卻是不同的,所以兩個物件不相等。
3.常見問題
jAVAScirpt資料能否轉換?
4.解決方案
js中的不同型別資料在運算過程中會自動進行轉換。
我們先來看一串程式碼;
var str1 = "a"; var num1 = "1"; var bool1 = "true"; var bool2 = "false"; alert(str1 + num1);//string; alert(str1 + bool1);//string; alert(num1 + bool1);//number; alert(bool1 + bool2);//number//
js運算時資料轉換的運算規則為:
Number+String=String
數值和字串相加等於字串。
Number+Boolean=Number
數值和布林值相加等於數值。
String+Boolean=String
字串和布林值相加等於字串。
Boolean+Boolean=Number
布林值和布林值相加等於數值。
陣列和其他型別的變數進行運算時都轉化成string
數值和陣列運算時 var arr=[1,2,3]; var a= "789"; alert(typeof(arr+a)); 布林值和陣列運算時 var arr=[1,2,3]; var a= "true"; alert(typeof(arr+a)) 物件和陣列運算時 var arr=[1,2,3]; var a= {name:"my"} alert(typeof(arr+a))
上面三組運算無一列外得到的結果都是string,證實了陣列和其他型別的變數進行運算都會轉化為string。
5.編碼實戰
6.拓展思考
棧,堆是什麼?
在ECMAScript中,變數可以存放兩種型別的值,即原始值和引用值。
原始值指的就是代表原始資料型別(基本資料型別)的值,
引用值指的就是複合資料型別(引用資料型別)的值。
原始值與引用值對應存在兩種結構的記憶體即棧和堆。
棧是一種後進先出的資料結構。原始值是儲存在棧中的簡單資料,它們的值直接儲存在變數訪問的位置
堆是基於雜湊演算法的資料結構。
在javascript中,引用值是用來引用儲存在堆中的物件,引用出來的物件是存放在堆中的。
也就是說,儲存在變數處的值(即指向物件的變數,儲存在棧中)是一個指標,指向儲存在堆中的實際物件.
我看來下面這串程式碼
var obj = new Object();
obj儲存在棧中,它指向於new Object()這個物件,
而new Object()是存放在堆中的。
7.參考文獻
js的資料型別
引用型別與原始型別的區別
https://www.cnblogs.com/chaoyuehedy/p/7894971.html
js常見問題總結(1)——資料型別相關
https://blog.csdn.net/weixin_42392456/article/details/81213864
JavaScript基礎心法 資料型別
https://www.jb51.net/article/135920.htm
8.更多思考
那為什麼引用值要放在堆中,而原始值要放在棧中.
js中有一句話:能量是守衡的,無非是時間換空間,空間換時間的問題。
堆比棧大,棧比堆的運算速度快。
引用資料型別是一個複雜的結構,並且可以自由擴充套件,如:陣列 可以無限擴充,物件可以自由新增屬性。將他們放在堆中是為了不影響棧的效率。而是通過引用的方式查詢到堆中的實際物件再進行操作。
相對於引用資料型別而言,簡單資料型別就比較穩定,並且它只佔據很小的記憶體。不將簡單資料型別放在堆是因為通過引用到堆中查詢實際物件是要花費時間的,而這個綜合成本遠大於直接從棧中取得實際值的成本。所以簡單資料型別的值直接存放在棧中。
更多內容,可以加入IT交流群565734203與大家一起討論交流
這裡是技能樹·IT修真院:http://www.jsnhu.com,初學者轉行到網際網路的聚集地