關(guān)于省略分號的換行
javascript在解析時,會把省略分號的行與下一行一起解析,當(dāng)不構(gòu)成語法錯誤時回合為一行,因此類庫的保守寫法,會在已開始前添加分號,以防出現(xiàn)上述問題。
關(guān)于分?jǐn)?shù)的精度問題
javascript可以精確地表示分?jǐn)?shù)1/2、1/8等,通常所用的1/10、1/100不能被精確地表示出來。
var x=.3-.2;
var y=.2-.1;
x==y //false
x==.1 //false
y==.1 //true
解決方案,當(dāng)進(jìn)行相關(guān)計算可以換算成整數(shù)計算,最后使用科學(xué)計數(shù)法或單位換算進(jìn)行結(jié)果的應(yīng)用。
關(guān)于進(jìn)制的問題
嚴(yán)格模式下禁止8禁止模式。ECMAscript不支持八進(jìn)制的直接量。
多行字符串
JS中多遇到拼接字符串的問題,通常情況下會拼接一個超長字符串在一行,使文檔可讀性下降,可以使用換行符,使得一個字符串可以在多行寫出。
在ECMAscript 3 中,字符串必須寫在一行,但是在ESMAscript5 中字符串可以被拆成多行,每行一反斜線()結(jié)束,反斜線和行結(jié)束符都不算是字符串直接量的內(nèi)容。如果希望再字符串直接量中另起一行,可以使用轉(zhuǎn)義字符\n
"on
\line"
//輸出為online
關(guān)于轉(zhuǎn)義字符
反斜杠使我們避免使用常規(guī)方式解釋單引號,當(dāng)單引號不是用來標(biāo)記字符串結(jié)尾時,他只是一個‘。
ESMAScript5,允許在一個多行字符串直接量里的每行結(jié)束處使用反斜杠。
You\'re right, it can\'t be a quote.
關(guān)于模式匹配
盡管RegExp并不是語言中的基本數(shù)據(jù)類型,但是他們依然具有直接量寫法,可以直接在javascript程序中使用。在兩條斜線之間的文本它構(gòu)成了一個正則表達(dá)式直接量。第二條斜線之后也可以跟隨一個或多個字母,用來修飾匹配模式的含義
var text = "testing:1,2,3";
var pattern=/\d+/g
partten.test(text) // 匹配成功
text.search(pattern) //9 首次匹配成功的位置
text.match(pattern) //["1","2","3"]所有匹配組成的數(shù)組
text.replace(pattern,"#"); //"testing:#,#,#"
text.split(/\D+/);//["","1","2","3"]用非數(shù)字字符截取字符串
關(guān)于全局對象
全局屬性: undefined infinity NaN
全局函數(shù): isNaN() parseInt() eval()
構(gòu)造函數(shù) : Date() RegExp() String() Object() Array()
全局對象:Math JSON
關(guān)于包裝對象
對于string、bollen、num為什么會有屬性呢,只要應(yīng)用了字符串的屬性,javascript就會將字符串值通過調(diào)用new String(s)的方式注冊能換成為對象,這個對象繼承了字符串的方法。并被用來處理屬性的引用,一旦屬性引用結(jié)束,這個新創(chuàng)建的對象就會銷毀。
??當(dāng)讀取字符串、數(shù)字、和布爾值的屬性值的時候,表現(xiàn)的想對象一樣,但是如果你試圖給屬性賦值,則會忽略這個操作;修改只是發(fā)生在臨時對象上,而這個臨時對象并沒有被保留下來。
- 存取字符串和數(shù)字布爾值的屬性時創(chuàng)建的臨時對象稱為包裝對象。
- 字符串?dāng)?shù)字和布爾值的屬性值是只讀的,并且不能定義新屬性。
關(guān)于對象的轉(zhuǎn)換
對象到字符串
- 調(diào)用toString()方法,把返回值進(jìn)行字符串的隱式轉(zhuǎn)換。
- 沒有toString()方法,調(diào)用valueOf(),并隱式轉(zhuǎn)換返回值。
- 否則拋出類型異常
對象到數(shù)字
- 對象具有valueOf()方法,把返回值進(jìn)行數(shù)字的隱性轉(zhuǎn)換。
- 沒有valueOf()方法,調(diào)用toString()方法,把返回值進(jìn)行數(shù)字的隱形轉(zhuǎn)換
- 否則拋出類型異常
空數(shù)組返回0的原因:
數(shù)組繼承了默認(rèn)的valueOf()方法,這個方法返回一個對象而不是一個原始值,因此數(shù)組到數(shù)字的轉(zhuǎn)換則調(diào)用toString方法??諗?shù)組轉(zhuǎn)換成為空字符串,空字符串轉(zhuǎn)換為數(shù)字0.
關(guān)于作為屬性的變量
var trunevar = 1; //聲明一個不可刪除的全局變量
fakevar = 2;//創(chuàng)建全局對象的一個可刪除的屬性
this.fakevar2 = 3;
delete trunevar //false
delete fakevar //true
delete this.fakevar2 //true
關(guān)于運(yùn)算符
運(yùn)算要求操作的數(shù)是整數(shù),這些整數(shù)表示32位整型
按位非:
~ox0F = oxFFFFFFF0 表示為-16
左移和右移的位數(shù)是0~31之間的一個整數(shù)
帶符號右移:
右邊溢出將忽略,左邊按照原有操作數(shù)符號來補(bǔ)位,補(bǔ)成一致的。
無符號右移:
最高位總是由0填補(bǔ)
-1>>>4=ox0FFFFFFF
關(guān)于相等和嚴(yán)格相等
嚴(yán)格相等:
- 明確類型不進(jìn)行類型轉(zhuǎn)換
- null ===null //false
- undefined ===undefined //false
- NaN === NaN //false
相等:
- null ==undefined //true
- '1' == true //true
關(guān)于邏輯非
恒等式
!(p&&q) === !p||!q
!(p||q) === !p&&!q
關(guān)于eval()
var geval = eval;
var x ='global',y='global';
function f(){
var x='local';
eval("x+='change';");//改變局部變量
return x;
}
function g(){
var y='local';
geval("y+='change';");//改變?nèi)肿兞? return y;
}
console.log(f(),x); //"local changeglobal"
console.log(g(),y); //"local globalchange"
關(guān)于 typeof
| 數(shù)據(jù)類型 | 計算值 |
|---|---|
| NaN | number |
| 函數(shù) | function |
| 宿主對象 | 由編譯器各自實(shí)現(xiàn)的字符串 |
本地對象、內(nèi)置對象和 宿主對象
1、本地對象
ECMA-262 把本地對象(native object)定義為“獨(dú)立于宿主環(huán)境的 ECMAScript 實(shí)現(xiàn)提供的對象”。
再來看一下,“本地對象”包含哪些內(nèi)容:
Object、Function、Array、String、Boolean、Number、Date、RegExp、Error、EvalError、RangeError、ReferenceError、SyntaxError、TypeError、URIError
由此可以看出,簡單來說,本地對象就是 ECMA-262 定義的類(引用類型)。
2、內(nèi)置對象
ECMA-262 把內(nèi)置對象(built-in object)定義為“由 ECMAScript 實(shí)現(xiàn)提供的、獨(dú)立于宿主環(huán)境的所有對象,在 ECMAScript 程序開始執(zhí)行時出現(xiàn)”。這意味著開發(fā)者不必明確實(shí)例化內(nèi)置對象,它已被實(shí)例化了。
同樣是“獨(dú)立于宿主環(huán)境”。根據(jù)定義我們似乎很難分清“內(nèi)置對象”與“本地對象”的區(qū)別。而ECMA-262 只定義了兩個內(nèi)置對象,即 Global 和 Math (它們也是本地對象,根據(jù)定義,每個內(nèi)置對象都是本地對象)。
如此就可以理解了。內(nèi)置對象是本地對象的一種。而其包含的兩種對象中,Math對象我們經(jīng)常用到,可這個Global對象是啥東西呢?
Global 對象是ECMAScript中最特別的對象,因?yàn)閷?shí)際上它根本不存在,但大家要清楚,在ECMAScript中,不存在獨(dú)立的函數(shù),所有函數(shù)都必須是某個 對象的方法。類似于isNaN()、parseInt()和parseFloat()方法等,看起來都是函數(shù),而實(shí)際上,它們都是Global對象的方 法。而且Global對象的方法還不止這些。有關(guān)Global對象的具體方法和屬性,感興趣的同學(xué)可以看一下這里:JavaScript 全局對象參考手冊
3、 宿主對象
由ECMAScript實(shí)現(xiàn)的宿主環(huán)境提供的對象,可以理解為:瀏覽器提供的對象。所有的BOM和DOM都是宿主對象。
關(guān)于void 運(yùn)算符
出現(xiàn)在操作數(shù)之前,操作數(shù)可以是任意類型。void會忽略操作數(shù)的值,因此在操作數(shù)據(jù)有副作用的時候使用void來讓程序更具有語意。
運(yùn)算符用于客戶端的URL——javascript:URL中,在URL中可以寫帶有副作用的表達(dá)式,而void則讓瀏覽器不必顯示這個表達(dá)式的計算結(jié)果
<a href='javascript:void window.open();'>打開一個新的窗口</a>
關(guān)于switch
- 查找case中的表達(dá)式和expression的值全等于(===)進(jìn)行匹配,表達(dá)式和case不會做模式的轉(zhuǎn)換。
- 如果匹配不成功的話會執(zhí)行default,如果沒有default則會跳過所有的代碼塊。
- case只表明了起點(diǎn),并沒有標(biāo)明終點(diǎn),因此需要使用break使解釋器跳出switch語句或循環(huán)語句,否則程序?qū)?zhí)行下一個case。
關(guān)于循環(huán)
循環(huán)變量多是數(shù)字,下例為使用for循環(huán)來遍歷鏈表數(shù)據(jù)結(jié)構(gòu),并返回鏈表中的最后一個對象。
function tail(o) {
for( ; o.next; o=o.next)
return o
}
關(guān)于for in 循環(huán)
for(variable in object)
statement
- 解釋器先計算object表達(dá)式,如果表達(dá)式為null或者undefined,javascript解釋器回調(diào)過循環(huán)并執(zhí)行后續(xù)代碼。
- 每次循環(huán)之前,都會計算variable表達(dá)式的值,并將屬性名復(fù)制給他。
break&containue
break labelname //適用于嵌套多層的循環(huán)
containue labelname //適用于嵌套的循環(huán)中,用以跳出多層次嵌套的循環(huán)體邏輯
當(dāng)break和標(biāo)簽一起使用的時候,程序?qū)⑻D(zhuǎn)到這個標(biāo)簽所表示的語句塊的結(jié)束,或者直接終止這個閉合語句塊的執(zhí)行。
try/catch/finally
try{
//通常來講,這里的代碼不會出現(xiàn)問題
//有時拋出一個異常,要么由throw語句直接拋出異常
//要么通過調(diào)用一個方法間接拋出異常
}catch (e){
//當(dāng)且僅當(dāng)try語句拋出異常,才會執(zhí)行的代碼
//這里可以通過局部變量e來獲取error對象或者拋出的其他值引用
//這里的代碼可以給予某種原因處理這個異常
//可以通過throw重新拋出異常
}finally{
//不管try語句塊是否拋出異常,這里的邏輯總是會執(zhí)行的,終止try語句塊的方式有
//正常終止,執(zhí)行完語句塊的最后一條語句
//通過break、containeu、return語句終止
//拋出一個異常,異常被catch從句捕捉
//拋出一個異常,異常未被捕獲,繼續(xù)向上傳播
}
try中產(chǎn)生的異常沒有catch進(jìn)行處理,就會先執(zhí)行finally之后,然后向上傳播這個異常,知道找到能處理這個異常的catch從句。
關(guān)于嚴(yán)格模式
- 禁止使用with
- 所有變量需要聲明
- 調(diào)用函數(shù)中的this值為undefined,可以使用這個特性來檢測是否為嚴(yán)格模式
var hasStrictMode = (function(){
"use strict";
return this === undefined
}());
關(guān)于檢測對象
檢測集合中成員的所屬關(guān)系——判斷某個屬性是否存在于某個對象中。
可以通過in運(yùn)算符、hasOwnPreperty()和propertyIsEnumerable()方法來完成這個工作,甚至僅通過屬性查找也可以得到結(jié)果。
propertyIsEnumer(),當(dāng)屬性為自有的并且是可枚舉的,才會返回true。
檢測P是否是O的原型
` p.isPrototypeOf(o);
關(guān)于序列化對象
對象序列化是指將對象轉(zhuǎn)換為JSON格式的字符串。
JSON.stringify() //把對象撞換為字符串
JSON.parse() //把JSON格式字符串轉(zhuǎn)換為對象
支持對象、數(shù)組、字符串、無窮大數(shù)字、bollen和null。
函數(shù)、RegExp、Error、undefined不能被序列化和還原。
NaN、Infinity的序列化結(jié)果是null。
關(guān)于toString()與toLocalString方法
在需要將對象轉(zhuǎn)換為字符串的時候,javaScript會調(diào)用這個方法。比如說遇上+時。默認(rèn)的該方法對于監(jiān)測對象十分有用。
var s = {x:1,y:2}.toString(); //返回的是[Object,Object]
- Object的toLocalString方法,只是調(diào)用了toString而已。
- Date和Number對toLocalString方法做了定制,可以用它對數(shù)字日期和時間做本地化的轉(zhuǎn)換
- 數(shù)組元素的tolocalstring方法和toString方法很像,唯一的不同是每個數(shù)組元素會調(diào)用各自的tolocalstring完成字符串的轉(zhuǎn)換,而不是點(diǎn)用各自的tostring方法。
關(guān)于數(shù)組的聲明
var udf = [,,] //數(shù)組的長度為2,原因是最后一個逗號可以省略也可以加上
關(guān)于稀疏數(shù)組
只包含從0開始的不連續(xù)索引的數(shù)組,即數(shù)組的長度大于數(shù)組元素的個數(shù)。
數(shù)組的長度
數(shù)組的長度是可配置的,通過改變數(shù)組的長度,刪掉相關(guān)的索引值。使得數(shù)組相關(guān)的push和shift方法不能使用。
數(shù)組的相關(guān)操作
Slice
當(dāng)出現(xiàn)負(fù)數(shù)的時候就是用數(shù)組的長度加上相應(yīng)的負(fù)數(shù),接收兩個參數(shù),第一個參數(shù)表示復(fù)制的起點(diǎn),第二個表示終點(diǎn)。
splics
接收三個參數(shù),操作位置,刪除個數(shù),插入元素,與concat不同,該方法接収元素而非數(shù)組
for-each
function foreach(a,f,t){
try{ a.forEach(f,t)}
catch(e) {
if( e=== foreach.break) return;
else throw e;
}
}
foreach.break = new Error ("stopIteration");
reduce&reduceRight
接受兩個參數(shù)分別是在每一項(xiàng)上調(diào)用的函數(shù)和作為歸并基礎(chǔ)值。
提供給內(nèi)函數(shù)的四個參數(shù)分別是,此項(xiàng),下一項(xiàng),此項(xiàng)索引,以及數(shù)組。
檢測數(shù)組
Array.isArray() //ECMAScript5之前
instanceof 不準(zhǔn)
//兼容3
var isArray = function.isArray || fucntion(o){
return typeof o ===="object" &&
Object.prototype.toString.call(o) === "[object Array]";
};
關(guān)于類數(shù)組
類數(shù)組的條件:
- 自動更新length屬性
- 設(shè)置length為一個較小值將截斷數(shù)組
- 從Array.prototype中繼承一些有用的方法
- 其類屬性為Array
function isArrayLike(o) {
if(o &&
typeof o === 'object' &&
isFinite(o.length) &&
o.length >= 0 &&
o.length === Math.floor(o.length) &&
o.length < 4294967296++)
return true
else
return false
}
類數(shù)組的操作
var a={'0':a, '1':b, '2':c, length:3};
Array.prototype.join.call(a,"+")
Array.prototype.map.call(a,function(x) {
return x.toUpperCase();
}) //["A","B","C"]
關(guān)于作為數(shù)組操作的字符串
字符串是不可變值的,只是可讀的,所以使用push、sort、reverse、splice等方法是無效的,BUT不會報錯。
關(guān)于數(shù)組的操作的分類
| 不改變數(shù)組值的 | 改變數(shù)組的值 |
|---|---|
| forEach()等迭代方法 | 棧、隊列方法 |
| reduce、reduceRight歸并方法 | reverse |
| concat連接方法 | splice |
| slice | ----- |
關(guān)于函數(shù)的概念
- 形參相當(dāng)于函數(shù)中定義的變量,實(shí)參是調(diào)用函數(shù)時傳入的參數(shù)。
- javaScript中的函數(shù)是參數(shù)化的,函數(shù)定義的時候會包含 一個稱為形參的標(biāo)示符列表,這些參數(shù)在函數(shù)體重向局部變量一樣工作。
- 每次調(diào)用還會擁有另一個值,本次調(diào)用的上下文——this。
- 如果通過訪問對象方法調(diào)用函數(shù),this指向該對象。
- javascript 的函數(shù)嵌套在其他函數(shù)中定義,他們就可以訪問他們被定義時所處的作用域中的任何變量,這意味這閉包。
關(guān)于函數(shù)定義
函數(shù)名稱--name
function name (arguments){
coments
}
表達(dá)式定義函數(shù)只適用于它作為一個大的表達(dá)式的一部分,比如在賦值和調(diào)用過程中定義函數(shù)。函數(shù)表達(dá)式定義函數(shù)之前無法調(diào)用函數(shù),沒有函數(shù)聲明提升的過程。
如果一個函數(shù)定義表達(dá)式包含名稱,函數(shù)的局部作用域?qū)粋€綁定到函數(shù)對象的名稱,函數(shù)名稱將成為函數(shù)內(nèi)部的一個局部變量。
var f = function fact(x){
if(x <= 1)
return 1;
else
return x*fact(x-1); //在函數(shù)外部將不能訪問fact
}
fact(5); //fact is not defined
關(guān)于函數(shù)中的this
- 當(dāng)函數(shù)作為方法調(diào)用,this指向的是擁有該方法的對象。
- 當(dāng)函數(shù)作為函數(shù)調(diào)用,this指向的是全局對象,嚴(yán)格模式下為undefined。
- 當(dāng)函數(shù)是構(gòu)造函數(shù),this指向構(gòu)造函數(shù)新創(chuàng)建的對象。
- this不存在于作用域中,無法通過閉包的方式訪問,如需訪問可以把this的值付給你一個變量,使其存在于作用域中。
- this無法被賦值。
構(gòu)造函數(shù)的return
- 構(gòu)造函數(shù)一般沒有return
- 顯示使用return 返回一個對象,這個對象會代替構(gòu)造函數(shù)創(chuàng)建的對象復(fù)制給new操作符左側(cè)的變量。
- 如果return 為一個空語句或者返回值為原始值,那么這時將被忽略,同時把新生成的對象返回。
關(guān)于函數(shù)參數(shù)
- 對于有需要的實(shí)參進(jìn)行判斷和賦值,對于可選參數(shù)使用/optional/來表示。
- 對于不定實(shí)參函數(shù),實(shí)參個數(shù)不能為零。
- Argument.callee指向正在執(zhí)行的函數(shù),可以使用這個來進(jìn)行函數(shù)內(nèi)部的解耦。
- 使用傳入對象代替零散的參數(shù),避免多參數(shù)函數(shù)調(diào)用時參數(shù)位置與參數(shù)對應(yīng)的困難,提升語義性。
- arguments.length (實(shí)際傳入的實(shí)參個數(shù))
- arguments.callee.length(期望傳入的實(shí)參個數(shù))
關(guān)于用作命名空間的函數(shù)
利用作用域關(guān)系,定義一個函數(shù)用作臨時的命名空間,在這個命名空間里定義的變量不會污染全局作用域。
(function(){
//coding
}());
第一個左側(cè)括號是必須的,否則解釋器會試圖將關(guān)鍵字function 解析為函數(shù)聲明語句。
關(guān)于閉包
- 同一個作用域鏈中定義的兩個閉包,這兩個閉包共享同樣的私有變量。
function People(name){
this.name = name;
this.sayName = function(){name+=' hello';return name};
this.sayNameAgain = function(){return name};
};
var lixinyue = new People('lixinyue');
lixinyue.sayName(); //lixinyue hello
lixinyue.sayNameAgain();//lixinyue hello
lixinyue.sayName();//lixinyue hello hello
lixinyue.sayNameAgain();//lixinyue hello hello
lixinyue.name //lixinyue
關(guān)聯(lián)到閉包的作用域都是活動的,記住這一點(diǎn)非常重要。嵌套函數(shù)不會將作用域內(nèi)的私有成員復(fù)制一份,也不會對綁定的變量生成靜態(tài)快照。
閉包無法訪問父級函數(shù)this和arguments,如果有這個需要在定義父級函數(shù)時就要將this和arguments賦給一個變量保存起來。
關(guān)于使用call和apply
- call和apply的第一個實(shí)參是要調(diào)用函數(shù)的母對象
- 其后傳入的參數(shù)數(shù)組可以是真實(shí)數(shù)組也可以是類數(shù)組
關(guān)于bind()
- bind方法不僅僅是將函數(shù)綁定至一個對象,他還把傳入的參數(shù)綁定到this??梢岳斫鉃榘押瘮?shù)的形參在用函數(shù)內(nèi)用綁定的值進(jìn)行賦值。
- 因此bind返回的函數(shù)length,是原函數(shù)對象的形參個數(shù)減去bind綁定的實(shí)參個數(shù)。
- 當(dāng)返回函數(shù)用于構(gòu)造函數(shù)時,其所創(chuàng)建的對象從原始的未綁定的函數(shù)對象中繼承prototype。
this 指針
- 函數(shù)在被調(diào)用時,this指針是由調(diào)用者所決定的。
- 直接調(diào)用時,this指針為Globel Object,瀏覽器端為window。
- 方法調(diào)用時,this指針為方法所屬對象。如a.b.c(),this指針為a.b。
- 構(gòu)造器調(diào)用時,解析器會創(chuàng)建一個Object,this指針為這個Object,默認(rèn)這個Object會被返回
apply或call可以通過第一個參數(shù)指定調(diào)用時的this指針。