1、JavaScript允許對(duì)任意數(shù)據(jù)類(lèi)型做比較
第一種是==比較旭贬,它會(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)持使用===比較狭魂。
浮點(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
2、JavaScript的設(shè)計(jì)者希望用null表示一個(gè)空的值镐牺,而undefined表示值未定義炫掐。事實(shí)證明,這并沒(méi)有什么卵用睬涧,區(qū)分兩者的意義不大募胃。大多數(shù)情況下,我們都應(yīng)該用null畦浓。undefined僅僅在判斷函數(shù)參數(shù)是否傳遞的情況下有用摔认。
3、數(shù)組Array
3.1宅粥、直接給Array的length賦一個(gè)新的值會(huì)導(dǎo)致Array大小的變化参袱,即數(shù)組的length屬性是可寫(xiě)的
如果賦一個(gè)比length大的值,數(shù)組多出的部分用undefined代替
如果通過(guò)索引賦值時(shí)秽梅,索引超過(guò)了范圍抹蚀,同樣會(huì)引起Array大小的變化:
var arr = [1,2,3];
arr[5] ='x';
arr;// arr變?yōu)閇1, 2, 3, undefined, undefined, 'x']
如果賦一個(gè)比length小的值,那么多出的部分就會(huì)被截?cái)唷?b>(引申:如果賦0企垦,則是清空數(shù)組)
但是需要注意一點(diǎn)环壤,通過(guò)點(diǎn)屬性的方式及 "att.屬性 " 來(lái)添加內(nèi)容是不會(huì)引起length長(zhǎng)度的變化,即js中的length只用來(lái)描述索引元素的長(zhǎng)度钞诡,忽略關(guān)聯(lián)元素
3.2郑现、對(duì)于Array,如果不給slice()傳遞任何參數(shù)荧降,它就會(huì)從頭到尾截取所有元素接箫。利用這一點(diǎn),我們可以很容易地淺復(fù)制一個(gè)Array:
var arr = ['A','B','C','D','E','F','G'];
var aCopy = arr.slice();
aCopy;// ['A', 'B', 'C', 'D', 'E', 'F', 'G']
aCopy === arr;// false
3.3朵诫、對(duì)于數(shù)組的concat()方法辛友,習(xí)慣上我們認(rèn)為它接收一個(gè)數(shù)組參數(shù),其實(shí)它可以接收任意個(gè)非數(shù)組元素和Array(如果是個(gè)一維數(shù)組剪返,則會(huì)進(jìn)行一次拆分废累,否則不拆分)邓梅,然后全部添加到新的Array里:
var arr = ['A','B','C'];
arr.concat(1,2, [3,4]);// ['A', 'B', 'C', 1, 2, 3, 4]
注意:concat對(duì)添加的數(shù)組只進(jìn)行一次拆分,如果接收的Array是個(gè)多維數(shù)組邑滨,不會(huì)進(jìn)行拆分
3.4日缨、Array的sort()方法默認(rèn)把所有元素先轉(zhuǎn)換為String再排序,如果不知道sort()方法的默認(rèn)排序規(guī)則掖看,直接對(duì)數(shù)字排序殿遂,絕對(duì)栽進(jìn)坑里!
4乙各、對(duì)象
對(duì)象的屬性訪問(wèn)可以通過(guò)兩個(gè)方式進(jìn)行:一種是"對(duì)象.屬性名"墨礁,一種是 對(duì)象[ '屬性名' ]
如果屬性名是個(gè)合常規(guī)的,上邊兩種方式都可以耳峦,但是如果屬性名中含有特殊的字符恩静,如“-” 或者 空格 ,則只能通過(guò)第二種方式進(jìn)行訪問(wèn)
測(cè)試一個(gè)對(duì)象是否擁有某一屬性蹲坷,可以用in操作符 或者 hasOwnProperty()方法驶乾,in會(huì)搜索原型鏈,檢索對(duì)象自己的和繼承過(guò)來(lái)的屬性循签,而hasOwnProperty()方法只會(huì)檢測(cè)是否是自己的屬性
5级乐、for( item ?in target)
如果target是一個(gè)對(duì)象,則item代表的是對(duì)象的屬性
如果target是一個(gè)數(shù)組县匠,由于Array也是對(duì)象风科,而它的每個(gè)元素的索引被視為對(duì)象的屬性的一部分,所以item代表的是索引乞旦,但是如果不通過(guò)Array提供的方法(方法和初始化)向數(shù)組中添加元素贼穆,你在數(shù)組上手動(dòng)添加的屬性不會(huì)被認(rèn)為是索引的,即length是不會(huì)發(fā)生變化的兰粉,但是遍歷的時(shí)候?qū)傩园怂饕吞砑由蟻?lái)的內(nèi)容故痊,如下
var a = ['A','B','C'];
a.name ='Hello';
for(var x in a) {
? ? alert(x);// '0', '1', '2', 'name'
}
a // ['A','B','C']
a.length // 3
6、方法內(nèi)部有關(guān)變量的提升
JavaScript的函數(shù)定義有個(gè)特點(diǎn)玖姑,它會(huì)先掃描整個(gè)函數(shù)體的語(yǔ)句愕秫,把所有申明的變量“提升”到函數(shù)頂部,只是提升聲明焰络,賦值操作是在代碼執(zhí)行到對(duì)應(yīng)位置的時(shí)候才執(zhí)行
functionfoo(){
? ? var x ='Hello, '+ y;
? ? alert(x);
? ? var y ='Bob';
}
等價(jià)于:
functionfoo(){
? ? var y;// 提升變量y的申明
? ? var x ='Hello, '+ y;? ?
? ? alert(x);
? ? y ='Bob';
}
所以在開(kāi)發(fā)中戴甩,應(yīng)嚴(yán)格遵守“在函數(shù)內(nèi)部首先申明所有變量”這一規(guī)則
7、作用域
Javascript的變量范圍是以函數(shù)為基礎(chǔ)的舔琅,每個(gè)函數(shù)都有它自己的變量范圍等恐,Javascript這一點(diǎn)上表現(xiàn)的很酷洲劣,根本不理睬一些無(wú)意義的花括弧包起來(lái)的范圍备蚓。
不在任何函數(shù)內(nèi)定義的變量就具有全局作用域
var a = 1 等價(jià)于 window.a = 1
如果對(duì)象中定義了方法课蔬,要保證方法中this指向正確,必須用obj.xxx()的形式調(diào)用郊尝,否則this會(huì)被調(diào)用方法時(shí)調(diào)用該方法的對(duì)象改寫(xiě)
方法.apply(obj, [ ])二跋、方法.call(obj, arg1, arg2, ...)可以動(dòng)態(tài)改變方法中的this指向,對(duì)于普通方法的調(diào)用,我們可以使用 方法.apply(null, [ ])和 方法.call(null流昏,arg1扎即,arg2,...)的方式况凉,比如調(diào)用Math.max(3, 5, 4)谚鄙,分別用apply()和call()實(shí)現(xiàn)如下:
Math.max.apply(null, [3,5,4]);// 5
Math.max.call(null,3,5,4);// 5
8、閉包
返回閉包時(shí)牢記的一點(diǎn)就是:返回函數(shù)不要引用任何循環(huán)變量刁绒,或者后續(xù)會(huì)發(fā)生變化的變量闷营。
如果一定要引用循環(huán)變量怎么辦?方法是再創(chuàng)建一個(gè)函數(shù)知市,用該函數(shù)的參數(shù)綁定循環(huán)變量當(dāng)前的值(即函數(shù)有一個(gè)參數(shù)來(lái)接收變量)并用“創(chuàng)建一個(gè)匿名函數(shù)并立刻執(zhí)行”的語(yǔ)法將i的值傳入傻盟,無(wú)論該循環(huán)變量后續(xù)如何更改,已綁定到函數(shù)參數(shù)的值不變嫂丙。
閉包的實(shí)質(zhì):閉包就是攜帶狀態(tài)的函數(shù)娘赴!是攜帶狀態(tài)的函數(shù)!是攜帶狀態(tài)的函數(shù)跟啤!并且它的狀態(tài)可以完全對(duì)外隱藏起來(lái)诽表。!
9隅肥、包裝對(duì)象
包裝對(duì)象用new創(chuàng)建:
var n =new Number(123);// 123,生成了新的包裝類(lèi)型
var b =new Boolean(true);// true,生成了新的包裝類(lèi)型
var s =new String('str');// 'str',生成了新的包裝類(lèi)型
雖然包裝對(duì)象看上去和原來(lái)的值一模一樣关顷,顯示出來(lái)也是一模一樣,但他們的類(lèi)型已經(jīng)變?yōu)閛bject了武福!所以议双,包裝對(duì)象和原始值用===比較會(huì)返回false!
所以閑的蛋疼也不要使用包裝對(duì)象捉片!尤其是針對(duì)string類(lèi)型F教怠!伍纫!
如果我們?cè)谑褂肗umber宗雇、Boolean和String時(shí),沒(méi)有寫(xiě)new莹规,那么Number()赔蒲、Boolean()和String()被當(dāng)做普通函數(shù),把任何類(lèi)型的數(shù)據(jù)轉(zhuǎn)換為number、boolean和string類(lèi)型(注意不是其包裝類(lèi)型)
所以閑的蛋疼也不要使用包裝對(duì)象舞虱!尤其是針對(duì)string類(lèi)型;都省!矾兜!
10损趋、字符串型數(shù)值快速轉(zhuǎn)變?yōu)閿?shù)值類(lèi)型,只需在字符串前邊加上“+”
var a = '123.4' ;
var b = +a + 100 // b=223.4
11椅寺、數(shù)值快速取整:數(shù)值|0
總結(jié)一下浑槽,有這么幾條規(guī)則需要遵守:
不要使用new Number()、new Boolean()返帕、new String()創(chuàng)建包裝對(duì)象桐玻;
用parseInt()或parseFloat()來(lái)轉(zhuǎn)換任意類(lèi)型到number;
用String()來(lái)轉(zhuǎn)換任意類(lèi)型到string荆萤,或者直接調(diào)用某個(gè)對(duì)象的toString()方法畸冲;
通常不必把任意類(lèi)型轉(zhuǎn)換為boolean再判斷,因?yàn)榭梢灾苯訉?xiě)if (myVar) {...}观腊;
typeof操作符可以判斷出number邑闲、boolean、string梧油、function和undefined苫耸;
判斷Array要使用Array.isArray(arr);
判斷null請(qǐng)使用myVar === null儡陨;
判斷某個(gè)全局變量是否存在用typeof window.myVar === 'undefined'褪子;
函數(shù)內(nèi)部判斷某個(gè)變量是否存在用typeof myVar === 'undefined'。
12骗村、
event.currentTarget指向事件所綁定的元素嫌褪,
而event.target始終指向事件發(fā)生時(shí)的元素。