一、JavaScript 定義了幾種數據類型? 哪些是原始類型?哪些是復雜類型?
-
最新的 ECMAScript 標準定義了 7 種數據類型:
原始類型
- Number;數值類型;值:整數和小數。
- String;字符串類型;值:字符串組成的文本。
- Boolean;布爾類型;值:true、false。
- Undefined;值:undefined(表示“未定義”或不存在,即由于目前沒有定義)。
- Null;值null(表示無值,即此處的值就是“無”的狀態)。
- Symbol;值:symbol(ECMAScript 6 新定義,表示唯一值)。
復雜類型- Object;對象類型;值:各種 “ key:value ” 組成的集合。
區別
原始類型(基本類型)都是存放著一個確定的值,它們對內存的占用大小是確定的,存放著棧內存中。
復雜類型存放的內容是不確定的,占用的內存也是變化的,它的棧內存用固定的內存存放它在內存中的位置,而可變化的內容存放著堆內存中。
基本類型變量存的是值,復雜類型的變量存的是內存地址。
基本類型在賦值的時候拷貝值,復雜類型在賦值的時候只拷貝地址,不拷貝值。
二、三、如何判斷一個變量是否是數字、字符串、布爾、函數?
JavaScript有三種方法,可以確定一個值到底是什么類型。
- typeof運算符
- instanceof運算符
- Object.prototype.toString方法(以后再做介紹)
- typeof 是用于返回一個值的數據類型,對于常見的幾大數據類型都可以用typeof 數據類型的方式進行判斷。
- 一元運算符,運算格式:
typeof xxx
- 返回結果是類型的字符串
- 數值、字符串、布爾值分別返回number、string、boolean。
typeof 123; //number typeof '123'; //string typeof false; //boolean
- 函數返回function。
function f() {}; typeof f; //function
- undefined返回undefined。
typeof undefined; //undefined
- 除此以外,其他情況都返回object。(局限性)
typeof window; //object typeof {}; //object typeof []; //object typeof null; //object
- instanceof 是用于判斷某個對象是不是構造函數的一個實例,舉例來說就是一個新聲明的變量是不是調用了構造函數的內置屬性或方法,區分狹義對象、數組、日期、函數等。
- 二元運算符
instanceof 是一個二元運算符,左邊a是被運算的值,右邊b是運算的類型。格式是這樣的a instanceof b
- 使用instanceof的都必須是對象。所以不屬于object類型的基本類型是無法應用instanceof的,或者無法得到你想要的結果。
1 instanceof Number //false new Number(1) instanceof Number //true 'string' instanceof String //false new String('string') instanceof String //true
- 返回結果是布爾值(Boolean):true/false
所以instanceof是一個判斷,而typeof是求值var o = {}; var a = []; o instanceof Array; //false a instanceof Array; //true
四、NaN是什么? 有什么特別之處?
- NaN 是一種特殊的 Number 類型值。
通常作為沒有得到預期數值的返回值,如作為 Math 的某個方法的返回值出現的(例如:Math.sqrt(-1))或者嘗試將一個字符串解析成數字但失敗了的時候(例如:parseInt("blabla")) - NaN是JavaScript之中唯一不等于自身的值。
typeof NaN // "number"
NaN !== NaN // true
NaN === NaN // false
- 任何涉及NaN的數值操作都會返回NaN,如NaN+10返回NaN
五、如何把非數值轉化為數值?
在JavaScript中,有3個函數可以把非數值轉換為數值,這三個函數分別是:Number() 、parselnt() 和 parseFloat()。第一個函數,即轉型函數 Nurnber() 可以用于任何數據類型,而另兩個函數則專門用于把字符串轉換成數值。這3個函數對于同樣的輸入會返回不同的結果。
Number() 函數
- 如果是 Boolean 值,true 和 false 將分別被轉換為 1 和0;
- 如果是數字值,只是簡單的傳入和返回;
- 如來是null 值,返回 0;
- 如果是 undefined,返回NaN ;
- 如果是字符串,遵循下列規則:
如果字符串中只包含數字,則將其轉換為十進制數值,即"1"會變成1 , "123"會變成123,而"011"會變成11(注意,前導的0被忽略了);
如果字符串中包含有效的浮點格式, 如"1.1",則將其轉換為對應的浮點數值(同樣,也會忽略前導零);
如果字符串中包含有效的十六進制格式,例如"0xf",則將其轉換為相同大小的十進制整數值;
如果字符串是空的(包含空字符) ,則將其轉換為0;
如果字符串中包含除上述格式之外的字符,則將其轉換為 NaN。
- 如果是對象,則調用對象的 valueOf() 方法,然后依照前面的規則轉換返回的值。如果轉換的結果是 NaN,則調用對象的 toString() 方法,然后再次依照前面的規則轉換返回的字符串值。
var num1 = Number("Hello world!"); // NaN
var num2 = Number(" "); // 0
var num3 = Numberl("000011"); // 11
var num4 = Number(true); // 1
parseInt() 函數
- 由于 Number() 函數在轉換字符串時比較復雜而且不夠合理,因此在處理整數的時候更常用的是 parseInt() 函數。
- parselnt() 函數在轉換字符串時,更多的是看其是否符合數值模式,它會忽略字符串前面的空格,直至找到第一個非空格字符;如果第一個字符不是數字字符或者負號,parseInt() 就會返回 NaN;也就是說,用parselnt() 轉換空字符時會返回 NaN(Nurnber() 對空字符返回 0); 如果第一個字符是數字字符,parselnt() 會繼續解析第二個字符,直到解析完所有后續字符或者遇到了一個非數字字符。例如,"1234blue"會被轉換為1234 ,因為"blue"會被完全忽略;類似地,"'22.5"會被轉換為22 ,因為小數點并不是有效的數字字符。
- 如果字符串中的第一個字符是數字字符,parselnt() 也能夠識別出各種整數格式(即前面討論的十進制、八進制和十六進制數) 。也就是說,如果字符以"0x"開頭且后跟數字字符,就會將其當作一個十六進制整數;如果字符串以"0"開頭且后跟數字字符,則會將其當作一個八迸制數來解析。
ES5不再允許將帶有前綴0的數字視為八進制數,而是要求忽略這個0。但是,為了保證兼容性,大部分瀏覽器并沒有部署這一條規定。
var num1 = parselnt ("1234blue") ; // 1234
var num2 = parselnt (" ") ; // NaN
var num3 = parselnt ("0xA") ; // 10(十六進制數)
var num4 = parseInt(22.5); // 22
var num5 = parselnt ("070") ; // 56(八進制數)
var num6 = parselnt("70"); //70(十進制數)
var num7 = parselnt ("0xf") ; // 15(十六進制數)
- 如果知道被解析的是十六進制格式的字符串,那么指定基數16 作為第二個參數,可以保證得到正確的結果,例如:
var num = parselnt("0xAF", 16); //175
- 實際上,如果指定了16 作為第二個參數,字符串可以不帶前面的"0x",如下所示:
var num1 = parseInt( 'AF' , 16); //175
var num2 = parselnt ("AF") ; // NaN
- 指定基數會影響到轉換的輸出結果。例如:
var num1 = parselnt ("10", 2); // 2(按照二進制解析)
var num2 = parseInt("10", 8); // 8(按照八進制解析)
var num3 = parselnt("10", 10); // 10(按照十進制解析)
var num4 = parselnt("10", 16); // 16(按照十六進制解析)
parseFloat() 函數
- 與 parseInt () 函數類似,parseFloat () 也是從第一個字符(位置0)開始解析每個字符。而且也是一直解析到字符串末尾,或者解析到遇見一個無效的浮點數字字符為止。也就是說,字符串中的第一個小數點是有效的,而第二個小數點就是無效的了,因此它后面的字符串將被忽略。舉例來說,"22.34.5"將會被轉換為22.34 。
- 除了第一個小數點有效之外, parseFloat () 與 parselnt() 的第二個區別在于它始終都會忽略前導的零。parseFloat() 可以識別前面討論過的所有浮點數值格式,也包括十迸制整數格式,但十六進制格式的字符串則始終會被轉換成0。由于 parseFloat() 只解析十進制值,因此它沒有用第二個參數指定基數的用法。最后還要注意一點:如果字符串包含的是一個可解析為整數的數(沒有小數點,或者小數點后都是零),parseFloat() 會返回整數。以下是使用 parseFloat() 轉換數值的幾個典型示例:
var num1 = parseFloat ("1234blue") ; // 1234(整數)
var num2 = parseFloat("0xA"); // 0
var num3 = parseFloat("22.5"); // 22.5
var num4 = parseFloat("22.34.5"); // 22.5
var num5 = parseFloat("0908.5"); // 908
var num6 = parseFloat("3.125e7"); // 31250000
六、==與===有什么區別?
- x == y 在對比 x 和 y 的值之前,會嘗試對 x 和 y 做類型轉換,變成同一種類型后,再對比。
- x===y會對比x和y是否同類型,不同類型會返回false,不會發生轉換。
== 會做類型轉換,=== 不做類型轉化
七、break與continue有什么區別
- 都是為了控制代碼循環執行,執行到之后都會立即跳出循環
- break退出循環后,會繼續執行后續的語句
for(var i=0;i<3;i++){
for(var j=0;j<3;j++){
console.log(j)
break
}
console.log('我')
}
//0
//'我'
//0
//'我'
//0
//'我'
- continue退出循環后,會再從最外層循環開始執行(注意外層循環次數沒有累加)
for(var i=0;i<2;i++){
for(var j=0;j<3;j++){
console.log(j)
continue
}
console.log('我')
}
//0
//1
//2
//"我"
//0
//1
//2
//"我"
八、void 0 和 undefined在使用場景上有什么區別
- undefined 全局作用域下不能被重寫,但是在局部作用域中,可以被重寫的。所以undefined現常用于全局環境。
- void 運算符通常只用于獲取 undefined 的原始值,一般使用 void(0)(等同于 void 0)。在上述情況中,也可以使用全局變量undefined 來代替(假定其仍是默認值)。
- 而 void 可以給任何給定的表達式求值,并返回 undefined,并且 void 不可被重寫,因此void 0是在局部作用域中替代undefined的最佳選擇
九、以下代碼的輸出結果是?為什么?
- console.log(1+1);
console.log(1+1); // 2
"+" 兩邊都是數值類型,做數值運算。 - console.log("2"+"4");
console.log("2"+"4"); //24
"+" 兩邊都是字符串類型,直接拼接。 - console.log(2+"4");
console.log(2+"4"); //24
"+" 一邊是數值類型,另一邊是字符串類型,數值類型轉為字符串類型后拼接。 - console.log(+"4");
console.log(+"4"); //4
"+" 只有右側一個操作數,轉換我數值類型。
十、 以下代碼的輸出結果是?
- var a = 1;
a+++a;
typeof a+2;
var a = 1;
console.log(a+++a); //3
console.log(typeof a+2); //number2
因為"…++"優先級高于"+"優先級高于"++…","a+++a" 相當于"(a++)+a",即"1+2"返回 3 ;
"typeof a+2"相當于"(typeof a)+2",即"number+2",做字符串拼接返回number2。
十一、 以下代碼的輸出結果是? 為什么
var a = 1;
var b = 3;
console.log( a+++b ); //4
因為"…++"優先級高于"+"優先級高于"++…","a+++b" 相當于"(a++)+b",即"1+3"返回 4;
十二、遍歷數組,把數組里的打印數組每一項的平方
var arr=[3,4,5]
for(var i in arr){
console.log(arr[i]*arr[i])
}
//9
//16
//25
十三、 遍歷 JSON, 打印里面的值
var obj = {
name: 'hunger',
sex: 'male',
age: 28
}
for(var key in obj){
console.log(key+':'+obj[key])
}
//"name:hunger"
//"sex:male"
//"age:28"
十四、 以下代碼輸出結果是? 為什么
var a = 1, b = 2, c = 3;
var val = typeof a + b || c >0
console.log(val)
//"number2"
優先級:typeof>"+">"||",所以相當于"number2" || c>0,返回"number2"。
var d = 5;
var data = d ==5 && console.log('bb')
console.log(data)
//"bb"
//undefined
優先級:"==">"+"&&",所以相當于true && undefined,返回undefined。
var data2 = d = 0 || console.log('haha')
console.log(data2)
//"haha"
//undefined
相當于data2=d=0|| undefined
,0布爾值為false,所以返回undefined。
var x = !!"Hello" + (!"world", !!"from here!!");
console.log(x)
//2
優先級:"=">"!">"+",相當于var x=true + (false,true)
,加號優先將操作數轉為數字,所以得到2。