這篇博客主要包括數據類型、深拷貝&淺拷貝、數據類型的轉換、toString()方法判斷數據、相等與全等的區別。若有錯誤,歡迎指正。javascript
由於上次金山面試問了巨多這一塊的內容,因此作個總結,零碎的知識點不少。這篇原本是上週先發在掘金的,可是掘金的排版器沒有思否用着順手,之後仍是在這裏更。。。(唉出場順序過重要了,我愛思否)html
null是對象類型仍是基本數據類java
1.基本數據類型有 number,string,boolean,null,undefined,symbol(ES6新增的),也稱原始數據類型。面試
2.JS有原始值類型和引用值類型
2.1 原始值類型裏面存儲的都是值,原始值類型是沒法改變的。
2.2 引用值類型指的是由多個值構成的對象。segmentfault
let str = "hello"; str[0] = "z"; //沒法修改
通常狀況下聲明的變量是對象類型的話,會在棧內存中存放着引用地址,該地址會指向堆內存中的內容。
3.JS內存分爲堆內存和棧內存,棧內存保存的都是有固定大小、空間的內容。堆內存中存儲的都是不固定的內容。數組
4.兩者區別
4.1 原始值類型保存在棧內存中,能夠按值直接訪問。
值與值之間是獨立存在的,修改一個變量不會影響到其餘變量。app
var a = 10; var b = a; //將a的值賦給b b = 20; console.log(a); // 10 console.log(b); // 20
① 基本數據類型賦值過程:函數
4.2 引用值類型存放在堆內存中,按照引用訪問。spa
若是兩個變量保存的是同一個對象引用,當經過一個變量修改屬性時,另一個也會受到影響。.net
var obj = new Object(); obj.name = "孫悟空"; var obj2 = obj; obj2.name = "豬八戒"; console.log(obj.name); //豬八戒 console.log(obj2.name); //豬八戒
② 引用數據類型賦值過程:
5.若是兩個對象如出一轍,但也仍是兩個對象
6.null不是引用數據類型,是基本數據類型。
1.深拷貝: 修改新變量的值不會影響原有變量的值,默認狀況下基本數據類型都是深拷貝
let num1 = 123; let num2 = num1; num2 = 666; // 修改新變量的值 console.log(num1); //123 console.log(num2); /666
2.淺拷貝:修改新變量的值會影響原有的變量的值,默認狀況下引用類型都是淺拷貝。
class Person{ name = "jjj"; age = 23; } let p1 = new Person(); let p2 = p1; p2.name = "wdhj"; //修改p2的值影響了p1的值 console.log(p2.name); //wdhj console.log(p1.name); //wdhj
當引用數據類型中保存的都是基本數據類型時
如下三種方法並不能實現真正意義上的深拷貝,由於對象中保存的都是基本數據類型
1.方法一(很差)
淺拷貝的緣由:多個變量指向了同一塊存儲空間,想要實現深拷貝,可讓每一個變量分別指向本身的存儲空間
class Person{ name = "mss"; age = 18; } let p1 = new Person(); let p2 = new Person(); //由於p1裏面的屬性都是基本數據類型,因此能夠取出p1的name賦值給p2 p2.name = p1.name; p2.age = p1.age; p2.name = "mhf"; p2.age = 20; console.log(p1.name); //mss console.log(p2.name); //mhf
2.方法二(很差)
利用循環來遍歷每一個屬性
class Person{ name = "mss"; age = 18; } let p1 = new Person(); let p2 = new Person(); for(let key in p1){ //利用遍從來賦值每一個屬性 p2[key] = p1[key]; } p2.name = "mhf"; console.log(p1.name);//mss console.log(p2.name);//mhf
3.方法三(重點)
Object的assign()方法接收兩個參數,表明含義是將p1中的全部屬性拷貝到p2中
class Person{ name = "mss"; age = 18; } let p1 = new Person(); let p2 = new Person(); Object.assign(p2,p1); p2.name = "mhf"; console.log(p1.name);//mss console.log(p2.name);//mhf
當引用數據類型中保存的都是引用數據類型時
1.方法一:JSON.parse(JSON.stringify(obj))
2.方法二:手寫深拷貝
1.Number(常量或者變量)
1.1 注意:
let str = Number('123'); console.log(str); //123 console.log(typeof str); //number
1.2 轉換規則
2.數學運算符中的「+」、「-」
2.1 注意:
let str = "123"; let num = +str; console.log(num); //123 console.log(typeof num); //number
3.parseInt(字符串)和parseFloat(字符串)
3.1 注意:
let res = true; // let res = "true"; let num = parseInt(res); //把true當作字符串處理,沒有遇到數字因此返回NaN console.log(num); //NaN
1.toString()
Number、Boolean類型可調用toString()轉換爲String類型
格式:變量名稱.toString()
注意:
let value = 123; let str = value.toString(); console.log(str); //123 console.log(typeof str); //string console.log((3).toString()); //影響原有的數據
2.String()方法
格式: String(常量or變量)
注意:
let res = String(3); console.log(res); //3 console.log(typeof res); //string let str = String(undefined); console.log(str); //undefined console.log(typeof str); //string
3.常量/變量 + 「」
利用 常量/變量 加上一個空字符串來轉換,本質上是調用了String()函數, 不會修改原有的值
let value = 123; let str = value + ''; console.log(str); //123 console.log(typeof str); //string
Boolean(變量or常量)
注意:
總結:
空字符串/0/NaN/undefined/null會轉換成false
1.undefined
和null
沒有toString()
方法
console.log(undefined.toString()); //報錯 console.log(null.toString()); //報錯
2.Number
、Boolean
、String
等包裝對象的toString()
方法;本地對象的toString()
方法
console.log(Number.toString()); //function Number() { [native code] } console.log(Boolean.toString()); //function Boolean() { [native code] } console.log(String.toString()); //function String() { [native code] } console.log(Function.toString()); //function Function() { [native code] } console.log(Array.toString()); //function Array() { [native code] } console.log(Object.toString()); //function Object() { [native code] } console.log(RegExp.toString()); //function RegExp() { [native code] } console.log(Date.toString()); //function Date() { [native code] }
3.整數直接跟上.toString()
形式會報錯,提示無效標記,由於整數後的點會被識別爲小數點
String()
方法console.log(3.toString()); //報錯 console.log((3).toString()); //3 console.log(3..toString()); //3 let res = String(3); console.log(res); //3
4.Object.prototype.toString()
來進行類型識別,返回表明該對象的[object Type]字符串表示
toString()
方法,可是不能直接使用,由於對象有可能直接重寫了此方法,必須使用call()或者apply()調用console.log(Object.prototype.toString.call("abc")); //[object String] console.log(Object.prototype.toString.call(1)); //[object Number] console.log(Object.prototype.toString.call(true)); //[object Boolean] console.log(Object.prototype.toString.call(null)); //[object Null] console.log(Object.prototype.toString.call(undefined)); //[object Undefined] console.log(Object.prototype.toString.call({})); //[object Object] console.log(Object.prototype.toString.call(function(){}));//[object Function] console.log(Object.prototype.toString.call([]));//[object Array] console.log(Object.prototype.toString.call(/\s/)); //[object RegExp] console.log(Object.prototype.toString.call(new Date));//[object Date] function Person(){} console.log(Object.prototype.toString.call(new Person));//[object Object]
5.除了類型識別以外,還能夠進行其餘識別,例如識別arguments或DOM元素
(function(){ console.log(Object.prototype.toString.call(arguments));//[object Arguments] })(); console.log(Object.prototype.toString.call(document));//[object HTMLDocument]
6.數組Array類型調用toString()
方法,返回由數組中每一個值的字符串形式拼接而成的一個以逗號分隔的字符串
console.log([1, 2, 3, 4].toString()); //1,2,3,4 console.log([].toString()); // 輸出空
這時咱們能夠用這個思路來將多維數組轉爲一維數組,注意數組中的每一項變爲字符串了
let arr = [1,[2,[3,4],5],6]; // console.log(arr.join(",").split(",")); console.log(arr.toString().split(","));
1.兩個值類型相同
若是兩個值類型相同,再進行三個等號(===)的比較, 與嚴格相等運算符徹底同樣。
2.兩個值類型不一樣
在比較不一樣類型的數據時,相等運算符會先將數據進行類型轉換,而後再用嚴格相等運算符比較。類型轉換規則以下:
(1) 原始類型值比較
原始類型的數據會轉換成數值類型再進行比較
① 若是有一個操做數是布爾值,則在比較相等性以前先將其轉換爲數值; false轉換爲0,而true轉換爲1console.log(true == 1); //true
② 若是一個操做數是字符串,另外一個操做數是數值,在比較相等性以前先將字符串轉換爲數值console.log('123' == 123);//true
(2) 對象與原始類型值比較
若是一個操做數是對象,另外一個操做數不是,則調用對象的toString()方法,用獲得的基本類型值按照前面的規則進行比較
console.log([] == 0); //true console.log([].toString()); //空 console.log({} == 0); //false console.log( {}.toString()); //[object Object]
(3) undefined和null的比較
undefined和null與其餘類型的值比較時,結果都爲false,它們互相比較時結果爲true。
console.log(null == undefined); //true console.log(undefined == 0); //false console.log(null == 0); //false console.log(undefined == undefined); //true console.log(null == null); //true
(4) NaN的比較
若是有一個操做數是NaN,則相等操做符返回 false; 兩個操做數都是NaN,相等操做符也返回 false, NaN不與任何數相等, NaN不等於NaN
console.log(NaN == 0); //false console.log(NaN == NaN); //false
(5) 兩個對象的比較
若是兩個操做數都是對象,則比較它們是否是同一個對象。
① 若是兩個操做數都指向同一個對象,則相等操做符返回 true;不然, 返回false
② 對於引用類型的數據,比較的是地址
console.log([] == []); //false console.log({} == {}); //false let a = []; let b = a; console.log(a == b); //true
3.多益筆試題
console.log('' == 0); //true 空串轉爲數字爲0 console.log([] == 0); //true []調用toString()返回空串,再轉爲數字爲0 console.log({} == 0); //false {}調用toString()返回[object Object],再轉爲數字爲NaN
4.很繞的一題
(剛剛原本寫了很詳細的解析,沒保存,此次不想再寫了。)
關鍵在於:
!可將變量轉換成boolean類型,null、undefined、NaN以及空字符串('')取反都爲true,其他都爲false。
{}調用toString()返回[object Object],再轉爲數字爲NaN
console.log([] == ![]); //true console.log(![]); //false 至關於 console.log([] == 0); //true console.log({} == !{}); //false console.log(!{}); //false 至關於 console.log({} == 0); //false
(相比起來,全等運算符就沒有那麼多條條框框了,相等運算符整理到吐血)
(1)若是類型不一樣,就必定不相等
(2)若是兩個都是數值,而且是同一個值,那麼相等;若是其中至少一個是NaN,那麼不相等。(判斷一個值是不是NaN,只能使用isNaN( ) 來判斷)
(3)若是兩個都是字符串,每一個位置的字符都同樣,那麼相等,不然不相等。
(4)若是兩個值都是true,或者兩個值都是false,那麼相等
(5)若是兩個值都引用同一個對象或是函數,那麼相等,不然不相等
(6)若是兩個值都是null,或者兩個值都是undefined,那麼相等
1.將非數值轉換爲數值類型的函數
Number()
:Number(mix),能夠用於任何數據類型,該函數先將mix的數據類型轉換爲number類型,而後再將mix的值轉換爲數值。parseInt()
:將字符串轉換爲數值,不遵循四捨五入。這裏的string必須是數字類型的開頭字符串,一直遍歷到非數值的那個字符才中止。若不是數字開頭,則會顯示NaN.parseFloat()
:將string轉換爲浮點數。從數字位開始看,直到非數字位結束,用法與parseInt(string)一致。2.將其它類型的數據轉換爲字符串類型的函數
String(mix)
:將mix轉換成字符串類型。該函數能夠將任何數據類型的值轉換爲字符串。toString()
:demo.toString()
將demo轉換成字符串類型。demo不能是null undefined3.將值轉換成布爾值類型Boolean()
方法把undefined、null、-0、+0、NaN、''(空字符串)六個值的轉化爲false,其餘的值所有爲true。
隱式類型的轉換是系統進行運算時自動進行的,可是調用的方法都是顯式類型轉換的方法。
1.遞增和遞減操做符
不只適用於整數,還能夠用於字符串、布爾值、浮點數值和對象。
即先將變量經過Number()
轉換成number的數據類型,而後再進行遞增、遞減操做。
2.正負號
不只適用於整數,還能夠用於字符串、布爾值、浮點數值和對象。
將變量經過Number()
轉換成number的數據類型。
3.isNaN(變量)
執行過程爲:即先將變量經過Number()
轉換,再進行isNaN()
判斷 。
4.加號
加法有兩個做用。
5.- * / % (減號,乘號,除號,取餘)
運算時把數據轉換成number類型後,再進行運算。
6.&& || ! (與或非運算)
將運算符兩邊的值轉換成經過Boolean()
函數轉換成布爾類型,而後再進行運算。
不一樣的是:&& || 返回的是比較後自身的原值,而 !運算返回的是布爾值.
7.< > <= >= == != 比較運算符
當數字和字符串比較大小時,會隱示將字符串轉換成number類型進行比較。
而當字符串和字符串比較大小時,則比較的是ascii碼的大小。最後返回的則是布爾值
1.
var str = 1 + 2 + 'abc'; console.log(str); //3abc
2.
var a; var b = a * 0; //console.log(b); //NaN //console.log(b === b); //false if(b === b){ console.log(b * 2 + "2" - 0 +4) }else{ console.log(!b * 2 + "2" - 0 +4) } //26
3.
var a = 1; //console.log(a); //1 var b = a * 0; //console.log(b); //0 if(b === b){ console.log(b * 2 + "2" -0 + 4) }else{ console.log(!b * 2 + "2" - 0 +4) } //6
4.涉及精度問題
var a = 1.0 - 0.9; if(a == 0.1){ console.log(true); } else{ console.log(false); } // false var b = 0.8 - 0.7; if(a == b){ console.log(true); }else{ console.log(false); } // false
本文參考連接:
toString()方法的討論參考到了這篇:
https://www.cnblogs.com/xiaoh...
==&===的比較參考了這兩篇:
http://javascript.ruanyifeng.com/grammar/operator.html#toc6
https://blog.csdn.net/magic_xiang/article/details/83686224
參考圖片來自:博主:cc_ccc