廖雪峰js教程 查漏補(bǔ)缺
一.基本類(lèi)型和變量
1.注意相等運(yùn)算符
第一種是==比較,它會(huì)自動(dòng)轉(zhuǎn)換數(shù)據(jù)類(lèi)型再比較,很多時(shí)候燕垃,會(huì)得到非常詭異的結(jié)果俏橘;
第二種是===比較允华,它不會(huì)自動(dòng)轉(zhuǎn)換數(shù)據(jù)類(lèi)型掘譬,如果數(shù)據(jù)類(lèi)型不一致削罩,返回false,如果一致轴捎,再比較召耘。
由于JavaScript這個(gè)設(shè)計(jì)缺陷百炬,不要使用==比較,始終堅(jiān)持使用===比較污它。
2.NaN這個(gè)特殊的Number與所有其他值都不相等剖踊,包括它自己:
NaN === NaN; //false
唯一能判斷NaN的方法是通過(guò)isNaN()函數(shù)
isNaN(NaN); //true
3.注意浮點(diǎn)數(shù)的相等比較
1 / 3 === (1 - 2 / 3); // false
這不是JavaScript的設(shè)計(jì)缺陷。浮點(diǎn)數(shù)在運(yùn)算過(guò)程中會(huì)產(chǎn)生誤差衫贬,因?yàn)橛?jì)算機(jī)無(wú)法精確表示無(wú)限循環(huán)小數(shù)德澈。要比較兩個(gè)浮點(diǎn)數(shù)是否相等,只能計(jì)算它們之差的絕對(duì)值固惯,看是否小于某個(gè)閾值:
Math.abs(1 / 3 - (1 - 2 / 3)) < 0.0000001; // true
4.null和undefined
null 表示一個(gè)‘空’的值梆造,它和0以及空字符串''不同,0是一個(gè)數(shù)值葬毫,''表示長(zhǎng)度為0的字符串澳窑,而null表示‘空斧散。
JavaScript的設(shè)計(jì)者希望用null表示一個(gè)空的值,而undefined表示值未定義摊聋。事實(shí)證明鸡捐,這并沒(méi)有什么卵用,區(qū)分兩者的意義不大麻裁。大多數(shù)情況下箍镜,我們都應(yīng)該用null。undefined僅僅在判斷函數(shù)參數(shù)是否傳遞的情況下有用煎源。
5.對(duì)象
JavaScript的對(duì)象是一組由鍵-值組成的無(wú)序集合色迂,例如:
var person = {
name: 'Bob',
age: 20,
tags: ['js', 'web', 'mobile'],
city: 'Beijing',
hasCar: true,
zipcode: null
};
JavaScript對(duì)象的鍵都是字符串類(lèi)型,值可以是任意數(shù)據(jù)類(lèi)型手销。上述person對(duì)象一共定義了6個(gè)鍵值對(duì)歇僧,其中每個(gè)鍵又稱(chēng)為對(duì)象的屬性,例如锋拖,person的name屬性為'Bob'诈悍,zipcode屬性為null。
要獲取一個(gè)對(duì)象的屬性兽埃,我們用對(duì)象變量.屬性名的方式:
person.name; // 'Bob'
person.zipcode; // null
6.變量
在JavaScript中侥钳,使用等號(hào)=對(duì)變量進(jìn)行賦值”恚可以把任意數(shù)據(jù)類(lèi)型賦值給變量舷夺,同一個(gè)變量可以反復(fù)賦值,而且可以是不同類(lèi)型的變量售貌,但是要注意只能用var申明一次给猾,例如:
var a = 123; // a的值是整數(shù)123
a = 'ABC'; // a變?yōu)樽址?
請(qǐng)不要把賦值語(yǔ)句的等號(hào)等同于數(shù)學(xué)的等號(hào)。比如下面的代碼:
var x = 10;
x = x + 2;
如果從數(shù)學(xué)上理解x = x + 2那無(wú)論如何是不成立的颂跨,在程序中耙册,賦值語(yǔ)句先計(jì)算右側(cè)的表達(dá)式x + 2,得到結(jié)果12毫捣,再賦給變量x详拙。由于x之前的值是10,重新賦值后蔓同,x的值變成12饶辙。
JavaScript在設(shè)計(jì)之初,為了方便初學(xué)者學(xué)習(xí)斑粱,并不強(qiáng)制要求用var申明變量弃揽。這個(gè)設(shè)計(jì)錯(cuò)誤帶來(lái)了嚴(yán)重的后果:如果一個(gè)變量沒(méi)有通過(guò)var申明就被使用,那么該變量就自動(dòng)被申明為全局變量:
i = 10; // i現(xiàn)在是全局變量
二.字符串
1.操作字符串
字符串常見(jiàn)的操作如下:
var s = 'Hello, world!';
s.length; // 13
要獲取字符串某個(gè)指定位置的字符,使用類(lèi)似Array的下標(biāo)操作矿微,索引號(hào)從0開(kāi)始:
var s = 'Hello, world!';
s[0]; // 'H'
s[6]; // ' '
s[7]; // 'w'
s[12]; // '!'
s[13]; // undefined 超出范圍的索引不會(huì)報(bào)錯(cuò)痕慢,但一律返回undefined
需要特別注意的是,字符串是不可變的涌矢,如果對(duì)字符串的某個(gè)索引賦值掖举,不會(huì)有任何錯(cuò)誤,但是娜庇,也沒(méi)有任何效果:
var s = 'Test';
s[0] = 'X';
alert(s); // s仍然為'Test'
2.JavaScript為字符串提供了一些常用方法塔次,注意,調(diào)用這些方法本身不會(huì)改變?cè)凶址膬?nèi)容名秀,而是返回一個(gè)新字符串
toUpperCase
toUpperCase() 把一個(gè)字符串全部變?yōu)榇髮?xiě):
var s = 'Hello';
s.toUpperCase(); //返回'HELLO'
toLowerCase
toLowerCase() 把一個(gè)字符串全部變?yōu)樾?xiě)
var s = 'Hello';
var lower = s.toLowerCase();
indexOf()
indexOf() 會(huì)搜索指定字符串出現(xiàn)的位置:
var s = 'hello, world';
s.indexOf('world'); // 返回7
s.indexOf('World'); // 沒(méi)有找到指定的子串励负,返回-1
substring
substring() 返回指定索引區(qū)間的子串
var s = 'hello, world'
s.substring(0, 5); // 從索引0開(kāi)始到5(不包括5),返回'hello'
s.substring(7); // 從索引7開(kāi)始到結(jié)束匕得,返回'world'
三.數(shù)組(Array可以包含任意數(shù)據(jù)類(lèi)型继榆,并通過(guò)索引來(lái)訪(fǎng)問(wèn)每個(gè)元素)
1.length的注意點(diǎn)
要取得Array的長(zhǎng)度,直接訪(fǎng)問(wèn)length屬性:
var arr = [1,2,3,4,'hrllo',null,true];
arr.length; //6
注意汁掠,直接給Array的length賦一個(gè)新的值會(huì)導(dǎo)致Array大小的變化:
var arr = [1,2,3];
arr.length; //3
arr.length = 6;
arr; //arr 變?yōu)?[1,2,3,undefine,undefine,undefine]
arr.length = 2;
arr; //arr 變?yōu)?[1,2]
Array可以通過(guò)索引把對(duì)應(yīng)的元素修改為新的值略吨,因此,對(duì)Array的索引進(jìn)行賦值會(huì)直接修改這個(gè)Array:
var arr = ['a','b','c'];
arr[1] = 99;
arr; //arr現(xiàn)在變成為['a',99,'c']
請(qǐng)注意调塌,如果通過(guò)索引賦值時(shí),索引超過(guò)了范圍惠猿,同樣會(huì)引起Array大小的變化:
var arr = [1,2,3];
arr[5] = 'x';
arr; //arr變?yōu)閇1,2,3,undefine,undefine,'x']
大多數(shù)其他編程語(yǔ)言不允許直接改變數(shù)組的大小羔砾,越界訪(fǎng)問(wèn)索引會(huì)報(bào)錯(cuò)。然而偶妖,JavaScript的Array卻不會(huì)有任何錯(cuò)誤姜凄。在編寫(xiě)代碼時(shí),不建議直接修改Array的大小趾访,訪(fǎng)問(wèn)索引時(shí)要確保索引不會(huì)越界态秧。
2.相關(guān)方法
indexOf
與String類(lèi)似,Array也可以通過(guò)indexOf()來(lái)搜索一個(gè)指定的元素的位置:
var arr = [10,20,'30','xuz'];
arr.indexOf(10); //元素10的索引值為0
arr.indexOf(20); //元素20的索引值為1
arr.indexOf(30); //元素30沒(méi)有找到扼鞋,返回-1
arr.indexOf('30'); //元素'30'的索引值為2
注意了申鱼,數(shù)字30和字符串'30'是不同的元素。
slice()
slice()就是對(duì)應(yīng)String的substring版本云头,它截取Array的部分元素捐友,然后返回一個(gè)新的Array:
var arr = ['a','b','c','d','e','f','g'];
arr.slice(0,3); //從索引0開(kāi)始,到索引3結(jié)束溃槐,但不包括索引3: ['a','b','c']
arr.slice(3); //從索引3開(kāi)始到結(jié)束: ['d','e','f','g']
如果不給slice()傳遞任何參數(shù)匣砖,它就會(huì)從頭到尾截取所有元素,利用這一點(diǎn),我們很容易地復(fù)制一個(gè)Array:
var arr = ['a','b','c'];
var aCopy = arr.slice();
aCopy; //['a','b','c']
aCopy === arr; //false
push()和pop()
push()向Array的末尾添加若干元素猴鲫,pop()則把Array的最后一個(gè)元素刪除掉
var arr = [1,2];
arr.push('a','b'); //返回Arrary新的長(zhǎng)度:4
arr; //[1,2,'a','b']
arr.pop(); //pop()返回'b'
arr; //[1,2,'a']
arr.pop(); arr.pop(); arr.pop(); //連續(xù)pop3次
arr; // []
arr.pop(); //空數(shù)組繼續(xù)pop不會(huì)報(bào)錯(cuò)对人,而是返回undefined
arr; //[]
unshift和shift
如果要往Array的頭部添加若干元素,使用unshift()方法拂共,shift()方法則把Array的第一個(gè)元素刪除:
var arr = [1, 2];
arr.unshift('A', 'B'); // 返回Array新的長(zhǎng)度: 4
arr; // ['A', 'B', 1, 2]
arr.shift(); // 'A'
arr; // ['B', 1, 2]
arr.shift(); arr.shift(); arr.shift(); // 連續(xù)shift 3次
arr; // []
arr.shift(); // 空數(shù)組繼續(xù)shift不會(huì)報(bào)錯(cuò)牺弄,而是返回undefined
arr; // []
sort()
sort() 可以對(duì)當(dāng)前Array進(jìn)行排序,它會(huì)直接修改當(dāng)前Array的元素位置匣缘,直接調(diào)用時(shí)猖闪,按照默認(rèn)順序排序:
var arr = ['c','b','a'];
arr.sort();
arr; // ['a','b','c']
reverse
reverse()把整個(gè)Array的元素?fù)Q轉(zhuǎn),也就是反轉(zhuǎn):
var arr = ['a','b','c'];
arr.reverse();
arr; //['c','b','a']
splice()
splice()方法是修改Array的萬(wàn)能方法肌厨,它可以從指定的索引開(kāi)始刪除若干元素培慌,然后再?gòu)脑撐恢锰砑尤舾稍兀?/p>
var arr = ['Microsoft', 'Apple', 'Yahoo', 'AOL', 'Excite', 'Oracle'];
// 從索引2開(kāi)始刪除3個(gè)元素,然后再添加兩個(gè)元素:
arr.splice(2, 3, 'Google', 'Facebook'); // 返回刪除的元素 ['Yahoo', 'AOL', 'Excite']
arr; // ['Microsoft', 'Apple', 'Google', 'Facebook', 'Oracle']
// 只刪除,不添加:
arr.splice(2, 2); // ['Google', 'Facebook']
arr; // ['Microsoft', 'Apple', 'Oracle']
// 只添加,不刪除:
arr.splice(2, 0, 'Google', 'Facebook'); // 返回[],因?yàn)闆](méi)有刪除任何元素
arr; // ['Microsoft', 'Apple', 'Google', 'Facebook', 'Oracle']
concat()
concat()方法把當(dāng)前的Array和另一個(gè)Array連接起來(lái),并返回一個(gè)新的Array;
var arr = ['a','b','c'];
var added = arr.concat([1,2,3]);
added; //['a','b','c',1,2,3]
arr; //['a','b','c']
注意柑爸。concat() 方法并沒(méi)有修改當(dāng)前的Array,而是返回一個(gè)新的Array.
實(shí)際上吵护,concat()方法可以接收任意個(gè)元素和Array,并且自動(dòng)把Array拆開(kāi)表鳍,然后全部添加到新的Array里面:
var arr = ['a','b','c'];
arr.concat(1,2,[3,4]); //['a','b','c',1,2,3,4]
join()
join()方法是一個(gè)非常實(shí)用的方法馅而,它把當(dāng)前Array的每個(gè)元素都用指定的字符串連接起來(lái),然后返回連接后的字符串:
var arr = ['a','b','c',1,2,3];
arr.join('-'); //'a-b-c-1-2-3'
如果Array的元素不是字符串譬圣,將自動(dòng)轉(zhuǎn)為字符串后再連接瓮恭。
多維數(shù)組
如果數(shù)組的某個(gè)元素又是一個(gè)Array,則可以形成多維數(shù)組,例如:
var arr = [[1,2,3],[400,500,600],'-'];
上述Array包含3個(gè)元素厘熟,其中頭兩個(gè)元素本身也是Array.
四.對(duì)象
JavaScript的對(duì)象是一種無(wú)序集合數(shù)據(jù)類(lèi)型屯蹦,它是由若干鍵值對(duì)組成。
JavaScript的對(duì)象用于描述現(xiàn)實(shí)世界中的某個(gè)對(duì)象绳姨。例如登澜,為了描述"小明"這個(gè)淘氣的小朋友,我們可以用若干鍵值對(duì)來(lái)描述他:
var xiaoming ={
name: '小明',
birth: 1999,
school: 'no.1 middle scholl',
height: 1.70,
weight: 65,
score: null
};
JavaScript用一個(gè){...}表示一個(gè)對(duì)象飘庄,鍵值對(duì)以xxx:xxx形式申明脑蠕,用,隔開(kāi)。注意跪削,最后一個(gè)鍵值對(duì)不需要再末尾加, 如果加了谴仙,有的瀏覽器(如低版本ie)將會(huì)報(bào)錯(cuò)。
上述對(duì)象申明了一個(gè)name屬性碾盐,值是'小明'狞甚,birth屬性,值是1999廓旬,以及其他一些屬性哼审。最后谐腰,把這個(gè)對(duì)象賦值給變量xiaoming后,就可以通過(guò)變量xiaoming來(lái)獲取小明的屬性:
xiaoming.name; //'小明'
xiaoming.birth; //1999
訪(fǎng)問(wèn)是通過(guò).操作符完成的涩盾,但這要求屬性名必須是一個(gè)有效的變量名十气。如果屬性名包含特殊字符,就必須用''括起來(lái):
var xiaoming ={
name: '小孩',
'middle-school' : 'no.1 middle school'
};
xiaohong的屬性名middle-school不是一個(gè)有效的變量春霍,就需要用''括起來(lái)砸西。訪(fǎng)問(wèn)這個(gè)屬性也無(wú)法使用.操作符,必須用['xxx']來(lái)訪(fǎng)問(wèn):
xiaohong['middle-school']; // 'No.1 Middle School'
xiaohong['name']; // '小紅'
xiaohong.name; // '小紅'
也可以用xiaohong['name']來(lái)訪(fǎng)問(wèn)xiaohong的name屬性址儒,不過(guò)xiaohong.name的寫(xiě)法更簡(jiǎn)潔芹枷。我們?cè)诰帉?xiě)JavaScript代碼的時(shí)候,屬性名盡量使用標(biāo)準(zhǔn)的變量名莲趣,這樣就可以直接通過(guò)object.prop的形式訪(fǎng)問(wèn)一個(gè)屬性了鸳慈。
實(shí)際上JavaScript對(duì)象的所有屬性都是字符串,不過(guò)屬性對(duì)應(yīng)的值可以是任意數(shù)據(jù)類(lèi)型喧伞。
如果訪(fǎng)問(wèn)一個(gè)不存在的屬性會(huì)返回什么呢走芋?JavaScript規(guī)定,訪(fǎng)問(wèn)不存在的屬性不報(bào)錯(cuò)潘鲫,而是返回undefined:
var xiaoming = {
name: '小明'
};
xiaoming.age; // undefined
由于JavaScript的對(duì)象是動(dòng)態(tài)類(lèi)型翁逞,你可以自由地給一個(gè)對(duì)象添加或刪除屬性:
var xiaoming = {
name: '小明'
};
xiaoming.age; // undefined
xiaoming.age = 18; // 新增一個(gè)age屬性
xiaoming.age; // 18
delete xiaoming.age; // 刪除age屬性
xiaoming.age; // undefined
delete xiaoming['name']; // 刪除name屬性
xiaoming.name; // undefined
delete xiaoming.school; // 刪除一個(gè)不存在的school屬性也不會(huì)報(bào)錯(cuò)
如果我們要檢測(cè)xiaoming是否擁有某一屬性,可以用in操作符:
var xiaoming = {
name: '小明',
birth: 1990,
school: 'No.1 Middle School',
height: 1.70,
weight: 65,
score: null
};
'name' in xiaoming; // true
'grade' in xiaoming; // false
不過(guò)要小心溉仑,如果in判斷一個(gè)屬性存在挖函,這個(gè)屬性不一定是xiaoming的,它可能是xiaoming繼承得到的:
'toString' in xiaoming; // true
因?yàn)閠oString定義在object對(duì)象中浊竟,而所有對(duì)象最終都會(huì)在原型鏈上指向object怨喘,所以xiaoming也擁有toString屬性。
要判斷一個(gè)屬性是否是xiaoming自身?yè)碛械闹鹕常皇抢^承得到的哲思,可以用hasOwnProperty()方法:
var xiaoming = {
name: '小明'
};
xiaoming.hasOwnProperty('name'); // true
xiaoming.hasOwnProperty('toString'); // false
五.條件判斷
JavaScript把null洼畅、undefined吩案、0、NaN和空字符串''視為false帝簇,其他值一概視為true徘郭,因此上述代碼條件判斷的結(jié)果是true。
六.循環(huán)
for循環(huán)最常用的地方是利用索引來(lái)遍歷數(shù)組:
var arr = ['a','b','c'];
var i,x;
for(i=0;i<arr.length;i++){
x = arr[i];
alert(x);
}
for循環(huán)的3哥條件都是可以省略的丧肴,如果沒(méi)有退出循環(huán)的判斷條件残揉,就必須用break語(yǔ)句退出循環(huán),否則就是死循環(huán):
var x = 0;
for(;;){
//將無(wú)限循環(huán)下去
if(x>100){
break; //通過(guò)if判斷來(lái)退出循環(huán)
}
}
for...in
for循環(huán)的一個(gè)變體是for...in循環(huán)芋浮,它可以把一個(gè)對(duì)象的所有屬性依次循環(huán)出來(lái):
var o = {
name: 'jack',
age: 20,
city: 'beijing'
};
for(var key in o){
alert(key); //'name' ,'age' ,'city'
}
要過(guò)濾掉對(duì)象繼承的屬性抱环,用hasOwnProperty()來(lái)實(shí)現(xiàn):
var o = {
name: 'jack',
age: 20,
city: 'beijing'
};
for (var key in 0){
if(o.hasOwnProperty(key)){
alert(key); //'name','age','city'
}
}
由于Array也是對(duì)象,而他的每個(gè)元素的索引被視為對(duì)象的屬性,以此镇草,for...in循環(huán)可以直接循環(huán)出Array的索引:
var a = ['a','b','c'];
for(var i in a){
alert(i); // '0','1','2'
alert(a[i]); // 'a','b','c'
}
//請(qǐng)注意眶痰,for...in對(duì)Array的循環(huán)得到的是String而不是number.