JavaScript 定義了幾種數(shù)據(jù)類型? 哪些是原始類型?哪些是復(fù)雜類型?原始類型和復(fù)雜類型的區(qū)別是什么?
- 七種數(shù)據(jù)類型,分別是Undefined,Null,Boolean,Number,String,Symbol,Object劫扒,其中Object是復(fù)雜類型烈疚,其他六種都是簡單類型吏奸,也稱為原始類型谈飒。
- Undefined: Undefined類型只有一個(gè)值,即特殊的undefined昼接,在使用var聲明變量但未對(duì)其初始化時(shí)這個(gè)變量的值就是undefined灌旧,引入這個(gè)值是為了區(qū)分空對(duì)象指針與未經(jīng)初始化的變量绑咱。
- Null:Null也是只有一個(gè)值的數(shù)據(jù)類型绰筛,這個(gè)特殊的值是null枢泰,null表示空對(duì)象指針,這也正是使用typeof操作符檢測null值時(shí)返回“object”的原因(其實(shí)這就是一個(gè)bug無疑)
- Boolean:使用得最多的一種類型铝噩,只有兩個(gè)值true/false衡蚂,true不一定為1,false也不一定為0,它執(zhí)行的是Boolean轉(zhuǎn)換毛甲,可以對(duì)任何數(shù)據(jù)類型的值調(diào)用Boolean()函數(shù)年叮,而且總會(huì)返回一個(gè)Boolean值,具體返回什么值取決于轉(zhuǎn)換值的數(shù)據(jù)類型及其實(shí)際值玻募。
- Number:使用IEEE754格式來表示整點(diǎn)和浮點(diǎn)數(shù)值只损。
- String:由零或多個(gè)16位Unicode字符組成的字符序列,即字符串七咧。字符串外包裹單引號(hào)和雙引號(hào)都可以跃惫。
- Object:ECMAScript中的對(duì)象是一種數(shù)據(jù)與功能的集合,對(duì)象可通過執(zhí)行new操作符后跟要?jiǎng)?chuàng)建的對(duì)象類型的名稱來創(chuàng)建艾栋,而創(chuàng)建Object類型的實(shí)例并為其添加屬性和/或方法就可以創(chuàng)建自定義對(duì)象爆存。Object類型是所有它的實(shí)例的基礎(chǔ)。
- 區(qū)別
- 基本類型變量存的是值蝗砾,復(fù)雜類型的變量存的是內(nèi)存地址先较。
- 基本類型在賦值時(shí)copy值,復(fù)雜類型在賦值時(shí)只copy地址悼粮,不copy值闲勺。
typeof和instanceof的作用和區(qū)別?
- 作用:
- typeof:檢測給定變量的數(shù)據(jù)類型并返回字符串值,該字符串值用來說明運(yùn)算數(shù)的數(shù)據(jù)類型扣猫。typeof是一個(gè)操作符而不是函數(shù)霉翔,通過typeof操作符來區(qū)分函數(shù)和其他對(duì)象是有必要的。
返回的值有:string苞笨、boolean债朵、number、undefined瀑凝、object序芦、function。 - instanceof:判斷某個(gè)引用類型的值具體是什么類型的對(duì)象粤咪,如果變量是給定的引用類型就返回true谚中,反之返回false。
所有引用類型的值都是Object的實(shí)例寥枝,instanceof操作符檢測引用類型的值和Object構(gòu)造函數(shù)時(shí)始終返回true宪塔,檢測基本類型的值時(shí)始終返回false。
- 區(qū)別:
- typeof用于確定一個(gè)值是字符串囊拜、數(shù)值某筐、布爾值還是undefined,也可用于判斷function冠跷,但不能用來判斷對(duì)象類型的值和null基本類型的值南誊,因?yàn)槎紩?huì)返回Object身诺。typeof也可用來判斷變量是否存在。
- instanceof用來確定引用類型的值究竟是什么類型的對(duì)象抄囚,所以只能用來判斷對(duì)象和函數(shù)霉赡。
如何判斷一個(gè)變量是否是數(shù)字、字符串幔托、布爾穴亏、函數(shù)
用typeof操作符。
示例:
var s = "dot";
var b = true;
var i = 22;
var u;
var f = function () {};
alert(typeof s); //string
alert(typeof b); //boolean
alert(typeof i); //number
alert(typeof u); //undefined
alert(typeof f); //function
NaN是什么? 有什么特別之處?
- NaN即非數(shù)值(Not a Number)重挑,是一個(gè)特殊的數(shù)值迫肖,用于表示一個(gè)本來要返回?cái)?shù)值的操作數(shù)未返回?cái)?shù)值的情況(這樣就不會(huì)拋出錯(cuò)誤了)。在其他編程語言中攒驰,任何數(shù)值除以非數(shù)值都會(huì)導(dǎo)致錯(cuò)誤從而停止代碼執(zhí)行蟆湖,但在ECMAScript中,任何數(shù)值除以非數(shù)值會(huì)返回NaN玻粪,不會(huì)影響其他代碼的執(zhí)行隅津。
- 特別之處:
- 任何涉及NaN的操作(如NaN/10)都會(huì)返回NaN,這個(gè)特點(diǎn)在多步計(jì)算中可能導(dǎo)致問題劲室。
- NaN與任何值都不相等伦仍,包括NaN本身。如
alert(NaN == NaN); //false
如何把非數(shù)值轉(zhuǎn)化為數(shù)值?
3個(gè)函數(shù)可以實(shí)現(xiàn)轉(zhuǎn)換:
Number()——可用于任何數(shù)據(jù)類型
parseInt(),parseFloat()——專用于把字符串轉(zhuǎn)換成數(shù)值
var num1 = Number("hello world"); //NaN
var num2 = Number(""); //0
var num3 = Number("000011"); //11
var num4 = Number("true"); //1
var num5 = Number("0.0001"); //0.0001
var num6 = Number("1.0010"); //1.001
var num7 = parseInt("0xA"); //10,0x表示十六進(jìn)制
var num8 = parseInt("0xf"); //15,0x后的字母不區(qū)分大小寫
var num9 = parseInt("22.5"); //22
var num10 = parseInt("70"); //70
var num11 = parseInt("1234blue"); //1234
var num12 = parseInt(""); //NaN
var num13 = parseInt("0xAF", 16); //175,16代表十六進(jìn)制解析
var num14 = parseInt("AF", 16); //175,指定了16的字符串可以不加0x
var num15 = parseInt("AF"); //NaN
var num16 = parseInt("10", 2); //2,為避免錯(cuò)誤解析很洋,應(yīng)任何時(shí)候都明確指定基數(shù)
var num17 = parseInt("10", 8); //8
var num18 = parseInt("10", 10); //10
var num19 = parseInt("10", 16); //16
var num20 = parseFloat("1234blue"); //1234
var num21 = parseFloat("0xA"); //0
var num22 = parseFloat("22.5"); //22.5
var num23 = parseFloat("22.34.5"); //22.34
var num24 = parseFloat("0908.5"); //0908.5
var num25 = parseFloat("3.125e7"); //31250000
==與===有什么區(qū)別
==表示相等操作符充蓝,先轉(zhuǎn)換再比較,轉(zhuǎn)換之后比較相等則返回true喉磁;===表示全等操作符谓苟,僅比較而不轉(zhuǎn)換,未經(jīng)轉(zhuǎn)換就相等則返回true协怒。
var result1 = ("55" == 55); //true涝焙,轉(zhuǎn)換后相等
var result2 = (null == undefined); //true
var result3 = ("55" === 55); //false,數(shù)據(jù)類型不同所以不相等
var result4 = (null === undefined); //false
break與continue有什么區(qū)別
break和continue語句用于在循環(huán)中精確控制代碼的執(zhí)行孕暇,其中break語句會(huì)立即退出循環(huán)仑撞,強(qiáng)制繼續(xù)執(zhí)行循環(huán)后面的語句;continue雖然也是立即退出循環(huán)妖滔,但退出循環(huán)后會(huì)從循環(huán)的頂部繼續(xù)執(zhí)行并輸出在此之前和之后所有的結(jié)果隧哮。
void 0 和 undefined在使用場景上有什么區(qū)別
先說一下概念,void是個(gè)運(yùn)算符座舍,對(duì)后面給定的表達(dá)式求值并返回undefined沮翔,undefined是一個(gè)值。
undefined并不是保留字簸州,它只是全局對(duì)象的一個(gè)屬性鉴竭,在低版本的IE中或是局部作用域中可能會(huì)被重寫(這是有弊端的歧譬,所以在ES5之后window.undefined被定義為不可寫岸浑、不可配置的屬性)搏存;但void 0返回的值一定是undefined并且不能被重寫。其實(shí)void后面無論跟上什么表達(dá)式矢洲,如void 1璧眠,void (1+1),void (0) 或者 void "hello"读虏,void (new Date()) 等等责静,返回的都是undefined,能夠完美替代undefined盖桥,至于為什么用void 0灾螃,是因?yàn)樗疃蹋瑢懫饋硪卜奖恪?/p>
undefined使用場景:全局作用域揩徊。
void使用場景:局部作用域腰鬼。
- 生成undefined
- 利用 void運(yùn)算符讓 JavaScript 引擎把一個(gè)函數(shù)識(shí)別成函數(shù)表達(dá)式而不是函數(shù)聲明讓函數(shù)立即執(zhí)行。
通常情況下先聲明函數(shù)再進(jìn)行函數(shù)調(diào)用取得結(jié)果:
function dot(){
console.log(12);
}
dot(); //12 undefined
原因:12是打印出來的結(jié)果塑荒,函數(shù)沒有return就會(huì)有undefined
用了void運(yùn)算符之后熄赡,函數(shù)就被識(shí)別成一個(gè)立即執(zhí)行的函數(shù)表達(dá)式(除了void,大多數(shù)運(yùn)算符齿税,如+彼硫,-等都有立即執(zhí)行函數(shù)的作用,但可能會(huì)出現(xiàn)副作用):
void function dot(){
console.log(12);
}() //12 undefined
+ function dot(){
console.log(12);
}() //12 NaN
原因:+undefined就會(huì)出現(xiàn)NaN
- 充當(dāng)javascript:協(xié)議的URL生成undefined凌箕。
javascript:協(xié)議聲明了 URL 的主體是任意的 javascript 代碼拧篮,由 javascript 解釋器編譯執(zhí)行,通常使用 javascript:URL 執(zhí)行某些不改變當(dāng)前頁面文檔的代碼牵舱,要做到這一點(diǎn)他托,必須確保 URL 的最后一條語句沒有返回值,比如使用 void 0仆葡。
對(duì)于網(wǎng)頁中的點(diǎn)贊赏参、收藏等按鈕,如果使用 a 標(biāo)簽來實(shí)現(xiàn)的話沿盅,往往會(huì)用到 href="javascript:void(0)" 等類似的代碼把篓,這段代碼的作用點(diǎn)擊鏈接時(shí)讓頁面不跳轉(zhuǎn)。在 href="javascript:void(0)" 中腰涧,使用了一個(gè)以 javascript: 協(xié)議開頭的 URI韧掩,瀏覽器默認(rèn)會(huì)對(duì)冒號(hào)后面的代碼求值,然后將結(jié)果顯示在新的頁面窖铡,但有一種情況例外疗锐,如果結(jié)果是 undefined坊谁,瀏覽器就不會(huì)刷新頁面渲染新值了。
以下代碼的輸出結(jié)果是?為什么?
console.log(1+1);
//2 原因:1和1都是數(shù)值會(huì)做加法運(yùn)算
console.log("2"+"4");
//"24" 原因:兩個(gè)都是字符串會(huì)拼接
console.log(2+"4");
//"24" 原因:一個(gè)數(shù)值一個(gè)字符串滑臊,數(shù)值會(huì)被轉(zhuǎn)化成字符串然后與另一字符串拼接
console.log(+"4");
. //4 原因:在只有一個(gè)字符串參數(shù)時(shí)會(huì)嘗試將其轉(zhuǎn)換成數(shù)值
以下代碼的輸出結(jié)果是?
var a = 1;
a+++a;
typeof a+2; //"number2"
原因:a+++a等于3口芍,typeof3返回"number"是一個(gè)字符串,字符串與數(shù)值做加法雇卷,數(shù)值會(huì)被轉(zhuǎn)化成字符串然后與另一字符串拼接鬓椭,得到"number2"
以下代碼的輸出結(jié)果是? 為什么
var a = 1;
var b = 3;
console.log( a+++b ); //4
原因:++運(yùn)算符優(yōu)先級(jí)高于+,所以a+++b也可更改為a++(+b),a++結(jié)果仍為1关划,1+3=4
總結(jié):
var a=1;
a+++a; //3
原因:a+++a=(a++)+a,a++仍為1小染,其后置遞增的值留到下次使用,即后面的a值已經(jīng)變?yōu)?贮折,1+2=3
var a=3;
a+++a; //7
原因:與上同理裤翩,是3+4而不是4+3
前置操作符++a,--a,先運(yùn)算后執(zhí)行调榄;后置操作符a++,a--踊赠,先執(zhí)行后運(yùn)算,執(zhí)行后的值留到下一次使用
var a=20;
++a; //21
var a=20;
--a; //19
var b=20;
b++; //20
b+b; //42
var b=20;
b--; //20
b+b; //38
遍歷數(shù)組振峻,打印數(shù)組里每一項(xiàng)的平方
var arr=[3,4,5];
arr.forEach(function(item,index,array){
console.log(item*item);
}); //9 16 25
遍歷 JSON, 打印里面的值
var obj = {
name: 'hunger',
sex: 'male',
age: 28
};
for(var a in obj){
console.log(obj[a]);
} //hunger male 28
以下代碼輸出結(jié)果是? 為什么 (選做題目)
var a = 1, b = 2, c = 3;
var val = typeof a + b || c >0
console.log(val); //"number2" 原因:typeof優(yōu)先級(jí)16臼疫,+優(yōu)先級(jí)13,||優(yōu)先級(jí)5扣孟,>號(hào)優(yōu)先級(jí)11烫堤,所以先運(yùn)算typeof a+b,得到"number2"字符串值凤价,因?yàn)槭欠强兆址圆紶枌傩灾禐閠rue鸽斟,邏輯或運(yùn)算中,如果第一個(gè)操作數(shù)求值為true就不用對(duì)第二個(gè)操作數(shù)求值利诺,所以結(jié)果直接返回"number2"字符串值富蓄。
var d = 5;
var data = d == 5 && console.log('bb')慢逾;
console.log(data); //bb undefined undefined
//原因:=為賦值立倍,優(yōu)先級(jí)3,==等號(hào)優(yōu)先級(jí)10侣滩,&&優(yōu)先級(jí)6口注,所以先運(yùn)算==,得到d==5君珠,值為true寝志,接著執(zhí)行console.log打印出'bb',沒有指明返回值所以返回undefined,接著做邏輯與運(yùn)算,true&&undefined返回undefined并賦值給data材部,最后打印出data為undefined毫缆,所以最終結(jié)果是控制臺(tái)打印出字符串bb和undefined。
var d = 5;
var data2 = d = 0 || console.log('haha');
console.log(data2); //haha undefined
//原因:||優(yōu)先級(jí)最高乐导,先執(zhí)行第一個(gè)運(yùn)算數(shù)0苦丁,即false,所以繼續(xù)看第二個(gè)運(yùn)算數(shù)兽叮,首先打印出haha字符串芬骄,返回undefined猾愿,接著false與undefined做邏輯或運(yùn)算得到undefined(第一個(gè)運(yùn)算數(shù)是false的話直接返回第二個(gè)運(yùn)算數(shù)的值)鹦聪,將undefined賦值給d,將d賦值給data2蒂秘,打印出data2為undefined泽本,所以最終結(jié)果是控制臺(tái)打印出字符串haha和undefined。
var x = !!"Hello" + (!"world", !!"from here!!");
console.log(x); //2
//原因:圓括號(hào)優(yōu)先級(jí)最高姻僧,逗號(hào)優(yōu)先級(jí)最低规丽,所以會(huì)先執(zhí)行括號(hào)里的內(nèi)容并返回表達(dá)式最后一項(xiàng),!后跟非空字符串返回false撇贺,即!"world"返回false(這一項(xiàng)可忽略)赌莺,!!即同時(shí)使用兩個(gè)邏輯非操作符,會(huì)模擬Boolean()轉(zhuǎn)型函數(shù)的行為松嘶,第一個(gè)!返回一個(gè)布爾值艘狭,第二個(gè)邏輯非操作對(duì)該布爾值求反,即 !!"from here!!"和!!"Hello"結(jié)果都為true翠订,所以`var x = !!"Hello" + (!"world", !!"from here!!");`可改寫為`var x = true+true;`調(diào)用toString()方法取得相應(yīng)字符串值并轉(zhuǎn)換巢音,得到`var x = 2;`,所以打印出x值為2,沒有指明返回值則返回undefined尽超。
參考資料: