1.JavaScript 定義了幾種數(shù)據(jù)類型? 哪些是原始類型?哪些是復(fù)雜類型?原始類型和復(fù)雜類型的區(qū)別是什么?
JavaScript 定義了7種數(shù)據(jù)類型
-
6種原始類型
- boolean :true(真)和false(假)兩個特定值
- null :表示空缺,即此處應(yīng)該有一個值塔逃,但目前為空
- undefined :表示“未定義”或不存在,即此處目前沒有任何值
- string :字符組成的文本(比如"Hello World")
- number: 整數(shù)和小數(shù)(比如1和3.14)
- symbol(ECMAScript 6 新定義)
-
object類型即復(fù)雜類型(eg:Object,Array,Function,Data)
區(qū)別:
一料仗、原始類型(基本類型)
- 基本數(shù)據(jù)類型的值是不可變的
var name = "change";
name.substr();//hang
console.log(name);//change - 基本數(shù)據(jù)類型不可以添加屬性和方法
var p = "change";
p.age = 29;
p.method = function(){console.log(name)};
console.log(p.age)//undefined
console.log(p.method)//undefined - 基本數(shù)據(jù)類型的賦值是簡單賦值
如果從一個變量向另一個變量賦值基本類型的值湾盗,會在變量對象上創(chuàng)建一個新值,然后把該值復(fù)制到為新變量分配的位置上
var a = 10;
var b = a;
a++;
console.log(a)//11
console.log(b)//10 - 基本數(shù)據(jù)類型的比較是值的比較
var person1 = '{}';
var person2 = '{}';
console.log(person1 == person2); // true -
基本數(shù)據(jù)類型是存放在棧區(qū)的
var name = "jozo";var city = "guangzhou";var age = 22;
那么它的存儲結(jié)構(gòu)如下圖:
二立轧、復(fù)雜類型(引用類型)
1. 引用類型的值是可以改變的
var a = [1,2,3];
a[0] = 0;//更改數(shù)組的一個元素
a[3] = 4;//給數(shù)組增加一個元素
- 引用類型可以添加屬性和方法
var person = {};
person.name = "change";
person.say = function(){alert("hello");}
console.log(person.name)//change
console.log(person.say)//function(){alert("hello");} -
引用類型的賦值是對象引用
var a = {};
var b= a;
a.name = "change";
console.log(a.name)//change;
console.log(b.name)//change
b.age = 29;
console.log(a.age)//29
console.log(b.age)//29
引用類型保存在變量中的是對象在堆內(nèi)存中的地址格粪,所以,與基本數(shù)據(jù)類型的簡單賦值不同氛改,這個值的副本實際上是一個指針帐萎,而這個指針指向存儲在堆內(nèi)存的一個對象.那么賦值操作后,兩個變量都保存了同一個對象地址胜卤,而這兩個地址指向了同一個對象.因此疆导,改變其中任何一個變量,都會互相影響
-
引用類型的比較是引用的比較
var person1 = {};
var person2 = {};
console.log(person1 == person2)//false
因為引用類型的比較是引用的比較葛躏,換句話說澈段,就是比較兩個對象保存在棧區(qū)的指向堆內(nèi)存的地址是否相同,此時舰攒,雖然p1和p2看起來都是一個"{}"败富,但是他們保存在棧區(qū)中的指向堆內(nèi)存的地址卻是不同的,所以兩個對象不相等
-
引用類型是同時保存在棧區(qū)和堆區(qū)中的
var person1 = {name:"change1"};
var person2 = {name:"change2"};
var person3 = {name:"change3"};
則這三個對象在內(nèi)存中保存的情況如下圖:
2.typeof和instanceof的作用和區(qū)別?
1.typeof操作符是確定一個變量是字符串摩窃、數(shù)值兽叮、布爾、還是undefined的最佳工具猾愿,但在檢測引用類型的值時鹦聪,這個操作符的用處不大。
類型 | 結(jié)果 |
---|---|
Undefined | "undefined" |
Null | "object" |
Boolean | "boolean" |
Number | "number" |
String | "string" |
任何其他對象 | "object" |
2.instanceof運算符用來測試一個對象在其原型鏈中是否存在一個構(gòu)造函數(shù)的 prototype 屬性匪蟀,即用來知道是什么類型的對象椎麦。
person instanceof Object //person是Object嗎
function C(){}
function D(){}
var o = new C(); o instanceof C;// true,因為 Object.getPrototypeOf(o) === C.prototype var a=[]; a instanceof Array;//true
3.如何判斷一個變量是否是數(shù)字材彪、字符串观挎、布爾、函數(shù)
使用typeof判斷
4.NaN是什么? 有什么特別之處?
NaN是JavaScript的特殊值段化,表示“非數(shù)字”(Not a Number)
特點:
1.NaN不是數(shù)字嘁捷,但是它的數(shù)據(jù)類型是數(shù)字
typeof NaN; //number
2.NaN是JavaScript之中唯一不等于自身的值,不等于任何值显熏,包括它本身
NaN == NaN; //false NaN === NaN; //false
3.NaN在布爾運算時被當作false
Boolean(NaN); //false
4.NaN與任何數(shù)(包括它自己)的運算雄嚣,得到的都是NaN
NaN + 32 //NaN NaN - 32 //NaN NaN * 32 //NaN NaN / 32 //NaN
5.判斷NaN的方法
isNaN()原理:isNaN()會將括號內(nèi)的參數(shù)利用Number()進行一次轉(zhuǎn)換.
由于會對參數(shù)用Number()進行一次數(shù)據(jù)轉(zhuǎn)換,故對于字符串、部分對象缓升、部分數(shù)組鼓鲁、undefined等,isNaN()會返回true
isNaN('NaN'); //true 等同于isNaN(Number('NaN')); isNaN({}); //true 等同于isNaN(Number({})); isNaN(['xzy']); //true 等同于isNaN(Number(['xzy'])); isNaN(undefined); //true 等同于isNaN(Number(undefined)); Number(undefined)的結(jié)果為NaN
但是港谊,對于空數(shù)組骇吭、只有一個數(shù)值成員的數(shù)組、null等歧寺,isNaN()返回false
isNaN([]); //false isNaN([123]); //false isNaN(['123']); //false isNaN(null); //false Number(null)的結(jié)果為0
5.如何把非數(shù)值轉(zhuǎn)化為數(shù)值?
javascript有3個函數(shù)可以把非數(shù)值轉(zhuǎn)換為數(shù)值:Number()燥狰、parseInt()、parseFloat()斜筐。
Number()可以用于任何數(shù)據(jù)類型(此函數(shù)平時很少使用)龙致。
parseInt()、parseFloat()專門用于把字符串轉(zhuǎn)換成數(shù)值(比較常用的)顷链。
- parseInt(string, radix):識別整數(shù)格式目代。
如果字符串中的第一個字符是數(shù)字字符,parselnt() 也能夠識別出各種整數(shù)格式(即前面討論的十進制嗤练、八進制和十六進制數(shù)) 像啼。也就是說,如果字符以"0x"開頭且后跟數(shù)字字符潭苞,就會將其當作一個十六進制整數(shù)忽冻;如果字符串以"0"開頭且后跟數(shù)字字符,則會將其當作一個八迸制數(shù)來解析此疹。
var num1 = parselnt ("1234blue") ; // 1234 var num2 = parselnt (" ") ; // NaN var num3 = parselnt ("0xA") ; // 10(十六進制數(shù)) var num4 = parseInt(22.5); // 22 var num5 = parselnt ("070") ; // 56(八進制數(shù)) var num6 = parselnt("70"); //70(十進制數(shù)) var num7 = parselnt ("0xf") ; // 15(十六進制數(shù))
- parseFloat() :識別浮點僧诚,且第一個浮點有效
var num1 = parseFloat ("1234blue") ; // 1234(整數(shù)) 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
- Number()轉(zhuǎn)換規(guī)則:
1.如果是 Boolean 值,true 和 false 將分別被轉(zhuǎn)換為 1 和0蝗碎;Number(true) //1
2.如果是數(shù)字值湖笨,只是簡單的傳入和返回;
Number(12) //12
3.如來是null 值蹦骑,返回 0慈省;
Number(null) //0
4.如果是 undefined,返回NaN 眠菇;
Number(undefined)//NaN
5.如果是字符串边败,遵循下列規(guī)則:
a.如果字符串中只包含數(shù)字,則將其轉(zhuǎn)換為十進制數(shù)值捎废,即"1"會變成1 笑窜, "123"會變成123,而"011"會變成11(注意登疗,前導(dǎo)的0被忽略了)排截;
b.如果字符串中包含有效的浮點格式嫌蚤, 如"1.1",則將其轉(zhuǎn)換為對應(yīng)的c.浮點數(shù)值(同樣断傲,也會忽略前導(dǎo)零)脱吱;
d.如果字符串中包含有效的十六進制格式,例如"0xf"认罩,則將其轉(zhuǎn)換為相同大小的十進制整數(shù)值急凰;
Number(0xf)//15
e如果字符串是空的(不包含任何字符) ,則將其轉(zhuǎn)換為0猜年;
Number("")//0
f.如果字符串中包含除上述格式之外的字符,則將其轉(zhuǎn)換為 NaN疾忍。
g.如果是對象乔外,則調(diào)用對象的 valueOf() 方法,然后依照前面的規(guī)則轉(zhuǎn)換返回的值一罩。如果轉(zhuǎn)換的結(jié)果是 NaN杨幼,則調(diào)用對象的 toString() 方法,然后再次依照前面的規(guī)則轉(zhuǎn)換返回的字符串值
6.==與===有什么區(qū)別
==:等于運算(值的比較)聂渊,但是不比較值的類型差购, 兩邊值類型不同的時候,要先進行類型轉(zhuǎn)換汉嗽,再比較欲逃。
===:完全等于運算(值和類型的比較),不僅比較值饼暑,而且還比較值的類型稳析,當兩邊類型不一致時,不做類型轉(zhuǎn)換弓叛,類型不同的一定不等彰居,只有兩者一致才為真。
7.break與continue有什么區(qū)別
- Break 語句:用于跳出循環(huán)撰筷。
break 語句跳出循環(huán)后陈惰,會繼續(xù)執(zhí)行該循環(huán)之后的代碼(如果有的話)
for(var i = 1; i< 10; i++){
if(i % 4 === 0){
break;
}
console.log(i); // 1 2 3
}
- Continue 語句
continue 語句中斷循環(huán)中的迭代,如果出現(xiàn)了指定的條件毕籽,然后繼續(xù)循環(huán)中的下一個迭代抬闯。
for(var i = 1; i<6; i++){
if(i % 4 === 0){
continue;
}
console.log(i);//1 2 3 5
}
8.void 0 和 undefined在使用場景上有什么區(qū)別
void 會執(zhí)行后面的表達式并返回 undefined,但是某些情境下undefined是可以被賦值的关筒,比如在函數(shù)中画髓,這樣的話就不能用undefined來進行判斷了。所以用void 0返回undefined來進行判斷平委。既減少了在原形鏈上查找 window.undefined 的時間奈虾,也避免了誤用被修改過的 undefined。
9.以下代碼的輸出結(jié)果是?為什么?
console.log(1+1); // 返回 2同為number類型相加,返回正常運算 console.log("2"+"4"); //返回24 ,字符串拼接 console.log(2+"4"); //返回24 ,number 和字符串相加肉微,number轉(zhuǎn)為字符串 console.log(+"4");//返回4 ,只有一個字符串會轉(zhuǎn)換成數(shù)字輸出
10. 以下代碼的輸出結(jié)果是?
var a = 1; a+++a; //返回3匾鸥;(a++)+a=> 1 +2=3; typeof a+2;//返回number2,typeof優(yōu)先級最高 (typeof a)+2=> number2
11. 以下代碼的輸出結(jié)果是? 為什么
var a = 1; var b = 3; console.log( a+++b );//返回4碉纳,(a++)+b=>1+3=4;
12. 遍歷數(shù)組勿负,把數(shù)組里的打印數(shù)組每一項的平方
var arr = [3,4,5]
var arr = [3,4,5]; //方法一 for(var i=0;i<arr.length;i++){ console.log(arr[i]+"的平方是"+Math.pow(arr[i],2)) } //方法二 for(var i=0;i<arr.length;i++){ console.log(arr[i]+"的平方是"+arr[i]*arr[i]) }
13. 遍歷 JSON, 打印里面的值
var obj = {
name: 'hunger',
sex: 'male',
age: 28
}
for(key in obj){ console.log(obj[key]) }
14. 以下代碼輸出結(jié)果是? 為什么 (選做題目)
var a = 1, b = 2, c = 3;
var val = typeof a + b || c >0
console.log(val)//number2 ``
expr1 || expr2: 短路邏輯,如果expr1為``true`` ,返回expr1;
以上運算中 Boolean(typeof a + b)=>Boolean("number2") 為true ,所以返回number2
`
var d = 5;
var data = d ==5 && console.log('bb')
console.log(data)//返回undefined``
expr1 && expr2: 短路邏輯,如果expr1為``false ``,返回expr1;
d ==5 為true劳曹,所以返回 console.log('bb')
但是最后一步console.log(console.log('bb')) 返回 undefined
原因:內(nèi)部的console.log()為console對象內(nèi)的log方法奴愉,但是沒有返回值
例如:
var obj={
log:function log () { }
}
console.log(obj.log() )//undefined
var obj={
log:function log () { return "123" }
}
console.log(obj.log() )//123
`
var data2 = d = 0 || console.log('haha')
console.log(data2)//返回 undefined
邏輯或的短路邏輯,Boolean(0) 為false,所以返回后者console.log('haha')
最后一步console.log(console.log('haha'))返回undefined铁孵;原因:內(nèi)層console.log(‘haha’)方法沒有返回值
`
var x = !!"Hello" + (!"world", !!"from here!!");
console.log(x)//2``
!expr 如果單個表達式能轉(zhuǎn)換為true的話返回false,否則返回true.
1. (!"world", !!"from here!!") 逗號操作符返回返回表達式的最后一項 !!"from here!!" =>true;
2. !!"Hello"=>true
true + true =2;