原]JavaScript權威指南第6版 - 學習筆記2014-6-6閱讀182 評論0 注:如果這篇筆記妨礙大家眼睛,,亦或影響大家心情,亦或沒有用處,,請您告知我,,我會把它毫不留情的刪掉,。
var a = [];
a.push(1,2,3);
a.reverse(); //將數組元素的次序反轉
a.sort(); //排序
prompt() 方法用于顯示可提示用戶進行輸入的對話框。 confirm() parseInt
parseFloat
isNaN
isFinite
eval
String.toUpperCase()
String.toLowerCase()
HTML不區(qū)分大小寫,,onclick,onClick
JavaScript區(qū)分大小寫,,onclick 對象
Array
Function
Date
RegExp
Error
Math
Number
String
Infinity 無窮大,
正無窮大,,Number.POSITIVE_INFINITY, Number.MAX_VALUE, 1/0, Infinity
負無窮大,,Number.NEGATIVE_INFINITY, -Number.MAX_VALUE, -1/0, -Infinity
NaN非數字值, Number.NaN, 0/0
負零, -Number.MIN_VALUE/2, -1/Infinity, -0
0 = Number.MIN_VALUE/2 //發(fā)生下溢,計算結果為0
Javascript解釋器有自己的內存管理機制
負號是一元求反運算符
0x或0X十六進制直接量
\u開頭的為Unicode字符
使用0開頭的八進制直接量
JavaScript中的浮點數具有足夠的精度,,并可以及其近似于0.1,。但是事實,浮點數字不能精確表述的確帶來了一些問題,,如下代碼
var x = .3 - .2; // 0.3減去0.2
var y = .2 - .1; // 0.2減去0.1
x==y
// => false:兩值不相等,!
x == .1
// => false:.3-.2 不等于 .1
y == .1
// => true:.2-.1 等于 .1
在JavaScript中字符串是固定不變的,類似replace()和toUpperCase()的方法都返回新字符串,,原字符串本身并沒有發(fā)生改變,。
訪問字符串中的單個字符(16位值):chartAt(), s[0], s[s.length-1]
JaveScript采用Perl中的正則表達式語法
正則表達式
/\bjavascript\b/ig // 匹配單詞"javascript","i"忽略大小寫,,"g"全文搜索,,全文匹配
var text = "testing: 1, 2, 3"; // 文本示范
var pattern = /\d+/g;
// 匹配所有包含一個或多個數字的實例
pattern.test(text);
// => true: 匹配成功
text.search(pattern);
// => 9: 首次匹配成功的位置
text.match(pattern);
// => ["1", "2", "3"]: 所有匹配組成的數組
text.replace(pattern, "#");
// => "testing: #, #, #"
text.split(/\D+/);
// => ["", "1", "2", "3"]: 用非數字字符街區(qū)字符串
對null執(zhí)行typeof運算,結果返回字符串,,也就是說,,可以將null認為是一個特殊的對象值,含義是非對象
undefined: 意思為“未定義”
var global = this; // 定義一個引用全局對象的全局變量
global === window; // => true
global返回全局對象,,在客戶端JavaScript中,,在其表示的瀏覽器窗口中的所有JavaScript代碼中,Window對象充當了全局對象,,這個全局Window對象有一個屬性window引用其自身,,它可以代替this來引用全局對象。Window對象定義了核心全局屬性,,但它也針對Web瀏覽器和客戶端JavaScript定義了一少部分其他全局屬性,。
JavaScript對象是一種復合值:它是屬性或已命名值的集合。通過“.”符號來引用屬性值,。
var s = 'test'; // 創(chuàng)建一個字符串
s.len = 4; // 給它設置一個屬性
var t = s.len; // => t等于undefined 查詢一個屬性
這段代碼說明了在讀取字符串,、數字和布爾值的屬性值(或方法)的時候,表現的像對象一樣,,但如果你試圖給其屬性賦值,,則會忽略這個操作:修改只是發(fā)生在臨時對象身上,而這個臨時對象并未繼續(xù)保留下來,字符串,、數字和布爾值的屬性都是只讀的,,并且不能給它們定義新屬性。
JavaScript中的原始值(undefined,、null,、布爾值、數字和字符串)與對象(包括數組和函數)有著根本區(qū)別,。原始值是不可更改的:任何方式都無法更改一個原始值,。
對象的比較并非值的比較:即使兩個對象包含同樣的屬性及相同的值,它們也是不相等的,。各個索引元素完全相等的兩個數組也不相等,。我們通常將對象稱為引用類型,以此來和JavaScript的基本類型區(qū)分開來,。依照術語的叫法,,對象值都是引用,對象的比較均是引用的比較,,當且僅當引用同一個基對象時,,它們才相等。
包裝對象:存取字符串,、數字或布爾值的屬性時創(chuàng)建的臨時對象
JavaScript運算符合語句期望使用多樣化的數據類型,,并可以相互轉換。if語句將undefined轉換成false,,但“==”運算符從不試圖將其操作數轉換為布爾值,。
在代碼中會經常見到的類型轉換慣用法:
x + "" // 等價于 String(x)
+x // 等價于 Number(x) 也可以寫成 x-0
!!x // 等價于 Boolean(x) 注意是雙嘆號
Number → String
Number類定義的toString()方法可以接收表示轉換基數的可選參數,,如果不指定此參數,,轉換規(guī)則將是基于十進制。同樣,,亦可以將數字轉換為其他進制數(范圍在2~36)之間,,例如:
var n = 17;
binary_string = n.toString(2); // 轉換為 "10001"
octal_string = "0" + n.toString(8); // 轉換為 "021"
hex_string = "0x" + n.toString(16); // 轉換為 "0x11"
parseInt()方法的第二個可選參數類似
var n = 123456.789;
下面的方法都轉為字符串
n.toFixed(0); // "123457"
n.toFixed(2); // "123456.79"
n.toFixed(5); // "123456.78900"
n.toExponential(1); // "1.2e+5"
n.toExponential(3); // "1.235e+5"
n.toPrecision(4); // "1.235e+5"
n.toPrecision(7); // "123456.8"
n.toPrecision(10); // "123456.7890"
parseInt("3 blind mice") // => 3
parseFloat(" 3.14 meters") // => 3.14
parseInt("-12.34")
// => 12
parseInt("0xFF")
// => 255
parseInt("0xff")
// => 255
parseInt("-0XFF")
// => -255
parseFloat(".1")
// => 0.1
parseInt("0.1")
// => 0
parseInt(".1")
// => NaN: 整數不能以"."開始
parseFloat("$72.47"); // => NaN:
數字不能以"$"開始
parseInt()可以接收第二個可選參數,這個參數指定數字轉換的基數,,合法的取值范圍是2~36,,例如:
parseInt("11", 2); // => 3 (1*2 + 1)
parseInt("ff", 16); // => 255 (15*16
+ 15)
parseInt("zz", 36); // => 1295 (35*36
+ 35)
parseInt("077", 8); // => 63 (7*8
+ 7)
parseInt("077", 10); // => 77 (7*10 + 7)
對象到布爾值的轉換非常簡單:所有的對象(包括數組和函數)都轉換為true。對于包裝對象亦是如此:new Boolean(false)是一個對象而不是原始值,,它將轉換為true,。
很多類定義了更多特定版本的toString()方法。例如:
[1,2,3].toString()
// => "1,2,3"
(function(x) { f(x); }).toString() // => "function(x) {\n f(x);\n}"
/\d+/g.toString()
// => "/\\d+/g"
new Date(2010, 0, 1).toString() //
=> "Fri Jan 01 2010 00:00:00 GMT-0800 (PST)"
日期類定義的valueOf()方法會返回它的一個內部表示:1970年1月1日以來的毫秒數,。
var d = new Date(2010, 0, 1); // 2010年1月1日(太平洋時間)
d.valueOf()
// => 1262332800000
對象到字符串的轉換步驟:
1,、如果對象具有toString()方法,則調用這個方法。如果它返回一個原始值,,JavaScript將這個值轉換為字符串(如果本身不是字符串的話),,并返回這個字符串結果。
2,、如果對象沒有toString()方法,,或者這個方法并不返回一個原始值,那么JavaScript會調用valueOf,。如果存在這個方法,,則JavaScript調用它。如果返回值是原始值,,JavaScript將這個值轉換為字符串(如果本身不是字符串的話),。
3、否則,,JavaScript無法從toString()或valueOf()獲得一個原始值,,因此這是它將拋出一個類型錯誤異常。
對象到數字的轉換步驟
1,、如果對象具有valueOf()方法,,后者返回一個原始值,則JavaScript將這個原始值轉換為數字(如果需要的話)并返回這個數字,。
2,、否則,如果對象具有toString()方法,,后者返回一個原始值,,則JavaScript將其轉換并返回。
3,、否則,,JavaScript拋出一個類型錯誤異常。
直接量:在程序中直接顯示的出來的數值,,javascript中的直接量包括字符串直接量,,數字直接量,布爾直接量,,數組直接量,,函數直接量,對象直接量和特殊直接量7種,。
JavaScript的函數作用域是指函數內聲明的所有變量在函數體內始終是可見的,。有意思的是,這意味著變量在聲明之前甚至已經可用,。JavaScript的這個特性被非正式地稱為聲明提前,,即JavaScript函數里聲明的所有變量(但不涉及賦值)都被“提前”至函數體的頂部。
函數定義可以嵌套。
var scope = "global";
function f() {
console.log(scope); // 輸出"undefined",,而不是"global
var scope = "local"; // 變量這這里賦初始值,,但變量本身在函數體內任何地方均是有定義的
console.log(scope); // 輸出"local“
}
解釋:你可能誤以為函數中的第一行輸出”global“,因為代碼還沒有執(zhí)行var語句聲明局部變量的地方,。其實不然,,由于函數作用域的特性,局部變量在整個函數體始終是有定義的,,也就是說,,在函數體內局部變量遮蓋了同名全局變量。盡管如此,,只有在程序執(zhí)行var語句的時候,,局部變量才會被真正賦值。因此,,上述過程等價于:將函數內的變量聲明”提前“至函數體頂部,,同時變量初始化留在原來的位置:
function f() {
var scope;
//
在函數頂部聲明了局部變量
console.log(scope); // 變量存在,但其值是 "undefined"
scope = "local";
// 這里將其初始化并賦值
console.log(scope); // 這里它具有了我們所期望的值
}
在具有塊級作用域的編程語言中,,在狹小的作用域里讓變量聲明和使用變量的代碼盡可能靠近彼此,,通常來講,這是一個非常不錯的編程習慣,。由于JavaScript沒有塊級作用域,,因此一些程序猿特意將變量聲明放在函數體頂部,而不是將聲明靠近放在使用變量之處,。這種做法使得他們的源代碼非常清晰地反映了真實的變量作用域,。
當聲明一個JavaScript全局變量時,實際上是定義了全局對象的一個屬性(見3.5節(jié)),。當使用var聲明一個變量時,,創(chuàng)建的這個屬性是不可配置的(見6.7節(jié)),也就是說這個變量無法通過delete運算符刪除,??赡苣阋呀涀⒁獾搅耍绻銢]有使用嚴格模式并給一個未聲明的變量賦值的話,,JavaScript會自動創(chuàng)建一個全局變量。以這種方式創(chuàng)建的變量時全局對象的正常的可配值屬性,,并可以刪除它們,。
JavaScript全局變量是全局對象的屬性,這是在ECMAScript規(guī)范中強制規(guī)定的,。
最簡單的表達式是“原始表達式”,。原始表達式是表達式的最小單位——它們不再包含其他表達式。JavaScript中的原始表達式包含常量或直接量,關鍵字和變量,。
直接量是直接在程序中出現的常數值,。
1.23 //
數字直接量
"hello" // 字符串直接量
/pattern/ // 正則表達式直接量
一些保留字構成直接表達式
true、false,、null,、this
在方法體內,this返回調用這個方法的對象,,this相關可參考4.5節(jié),、第8章(8.2.2節(jié))和第九章
第三種原始表達式是變量:
i,a,b,undefined(undefined是全局變量,和null不同,,它不是關鍵字)
屬性訪問表達式
expression . identifier
expression [ expression ]
第一種寫法是一個表達式后跟隨一個句點和標識符,。用于訪問對象屬性
第二種寫法是使用方括號,方括號內是另外一個表達式,,用于訪問對象或數組的屬性或元素
在JavaScript中,,所有的數字都是浮點型的,除法運算的結果也是浮點型,,比如,,5/2的結果是2.5,而不是2,。除數為0的運算結果為正無窮大或負無窮大,,而0/0的結果是NaN。
求余運算符的操作數通常都是整數,,但也適用于浮點數,,比如,6.5%2.1結果是0.2,。
“+” 運算符
1 + {}
//
=> "1[object Object]":對象轉換為字符串后進行字符串連接
true + false
//
=> 2:布爾值轉換為數字后做加法
2 + null
//
=> 2:null轉換為0后做加法
2 + undefined
// => NaN:undefined轉換為NaN后做加法
嚴格相等運算符(恒等運算符)“===”首先計算其操作數的值,,然后比較這兩個值,比較過程沒有任何類型轉換:
相等運算符“==”和恒等運算符相似,,但相等運算符的比較并不嚴格,。如果兩個操作數不是同一類型,那么相等運算符會嘗試進行一些類型轉換,,然后進行比較:
比較操作符的操作數可能是任意類型。然而,,只有數字和字符串才能真正執(zhí)行比較操作,,因此那些不是數字和字符串的操作數將進行類型轉換,類型轉換規(guī)則如下:
如果操作數為對象,,那么這個對象將依照3.8.3節(jié)結尾處所描述的轉換規(guī)則轉換為原始值:如果valueOf()返回一個原始值,,那么直接使用這個原始值。否則,,使用toString()的轉換結果進行比較操作,。
在對象轉換為原始值之后,如果兩個操作數都是字符串,,那么將依照字母表的順序對兩個字符串進行比較,,這里提到的“字母表順序”是指組成這個字符串的16位Unicode字符的索引順序。
在對象轉換為原始值之后,,如果至少有一個操作數不是字符串,,那么兩個操作數都將轉換為數字進行數值比較。0和-0相等的,。Infinity比其他任何數字都大(除了Infinity本身),,-Infinity比其他任何數字都小(除了它自身),。如果其中一個操作數是(或轉換后是)NaN,,那么比較操作符總是返回false
對于數字和字符串操作符來說,加號運算符和比較運算符的行為都有所不同,,前者更偏愛字符串,,如果它的其中一個操作數是字符串的話,則進行字符串連接操作,。而比較運算符更偏愛數字,,只有在兩個操作數都是字符串的時候,,才會進行字符串的比較。
最后,,需要注意的是,,“<=”(小于等于)和“>=”(大于等于)運算符在判斷相等的時候,并不依賴與相等運算符和嚴格運算符的比較規(guī)則,,相反,,小于等于運算符只是簡單的“不大于”,大于等于運算符也只是“不小于”,,只有一個例外,,那就是當其一個操作數是(或則轉換后是)NaN的時候,所有4個比較運算符均返回false,。
in運算符
in運算符希望它的左操作數是一個字符串或可以轉換為字符串,,希望它的右操作數是一個對象。如果右側的對象擁有一個名為左操作數值的屬性名,,那么表達式返回true,,例如:
var point = { x:1, y:1}
// 定義一個對象
"x" in point
// => true : 對象有一個名為“x”的屬性
"z" in point
// => false : 對象中不存在名為”z“ 的屬性
"toString" in point
// => true : 對象繼承了toString()方法
var data = [7,8,9];
// 擁有三個元素的數組
"0" in data
// => true : 數組包含元素“0”
1 in data
// => true : 數字轉換為字符串
3 in data
// => false : 沒有索引為3的元素
instanceof運算符
instanceof運算符希望左操作數是一個對象,右操作數標識對象的類,,如果左側的對象是右側類的實例,,則表達式返回true;否則返回false,。第9章將會講到,,JavaScript中對象的類是通過初始化它們的構造函數來定義的。這樣的話,,instanceof的右操作數應當是一個函數,。
var a = [1, 2, 3];
// 通過數組直接量的寫法創(chuàng)建一個數組
a instanceof Array; // 計算結果為true,a是一個數組
a instanceof Object; // 計算結果為true,,所有的數組都是對象
a instanceof RegExp; // 計算結果為false,,數組不是正則表達式
var o = { x : 1 };
var p = null;
o && o.x
// => 1,o是真值,,因此返回值為o.x
p && p.x
// => null,,p是假值,因此將其返回,,而并不去計算p.x
eval()只有一個參數,,如果傳入的參數不是字符串,它直接返回這個參數,,如果參數是字符串,,它會把字符串當成JavaScript代碼進行編譯。
eval使用了調用它的變量作用域環(huán)境,,別名eval使用了全局作用域環(huán)境,。
變量在聲明它們的腳本或函數中都是有定義的,,變量聲明語句會被“提前”至腳本或者函數的頂部,但是初始化的操作則還在原來var語句的位置執(zhí)行,,在聲明語句之前變量的值是undefined
函數聲明語句通常出現在JavaScript代碼的最頂層,,也可以嵌套在其他函數體內,。但在嵌套時,,函數聲明只能出現在所嵌套函數的頂部。也就是說,,函數定義不能出現在if語句,、while循環(huán)或者其他任何語句中,正是由于函數聲明位置的這種限制,,ECMAScript標準規(guī)范并沒有將函數聲明歸類為真正的語句,。有一些JavaScript實現的確允許在出現語句的地方都可以進行函數聲明,但是不同的實現在細節(jié)處理方式上有很大差別,,因此將函數聲明放在其他的語句內的做法并不具備可移植性,。
盡管函數聲明語句和函數定義表達式包含相同的函數名,但二者仍然不同,。兩種方式都創(chuàng)建了新的函數對象,,但函數聲明語句中的函數名是一個變量名,變量指向函數對象,。和通過var聲明變量一樣,,函數定義語句中的函數被顯示地“提前”到了腳本或函數的頂部。因此它們在整個腳本和函數內都是可見的,。使用var的話,,只有變量聲明提前了——變量的初始化代碼仍然在原來的位置。然而使用函數聲明語句的話,,函數名稱和函數體均提前:腳本中所有函數和函數中所有嵌套的函數都會在當前上下文中其他代碼之前聲明,。也就是說,可以在聲明一個JavaScript函數之前調用它,。
switch(n) {
case 1: {
// 如果 n === 1,,從這里開始執(zhí)行
// 執(zhí)行代碼塊 1
break;}
// 停止執(zhí)行switch語句
case 2:
// 如果 n === 2,從這里執(zhí)行
// 執(zhí)行代碼塊 2
break;
//
在這里停止執(zhí)行switch語句
case 3:
// 如果 n === 3,,從這里執(zhí)行
// 執(zhí)行代碼塊 3
break;
//
在這里停止執(zhí)行switch語句
default:
// 如果所有的條件都不匹配
// 執(zhí)行代碼塊 4
break;
//
在這里停止執(zhí)行switch語句
}
break語句可以使解釋器跳出switch語句或循環(huán)語句,。在switch語句中,case只是指明了要執(zhí)行的代碼起點,,但并沒有指明終點,。如果沒有break語句,那么switch語句中的每一個case還包括default中的代碼塊都會執(zhí)行,,直到整個switch代碼塊的結尾,。 ECMAScript標準允許每個case關鍵字跟隨任意的表達式,。
由于JavaScript中的case表達式的值是在運行時(run-time)計算的,這一點使得JavaScript的switch語句和C,、C++,、和Java中的switch語句有很大區(qū)別(并且效率也很低)。
For/in語句,,語法如下:
for (variable in object)
statement
只要 for/in 循環(huán)中 variable 的值可以當做賦值表達式的左值,,它可以是任意表達式。每次循環(huán)都會計算這個表達式,,也就是說每次循環(huán)它計算的值有可能不同,。例如,可以用下面這段代碼將所有對象屬性復制至一個數組中:
var o = {x:1, y:2, z:3};
var a = [], i =0;
for(a[i++] in o) /* empty */;
for/in循環(huán)并不會遍歷對象的所有屬性,,只有 ”可枚舉“ (enumerable)的屬性才會遍歷到,。(參照第6章)
標簽語句
語句是可以添加標簽的,標簽是由語句前的標識符和冒號組成:
identifier : statement
break 和 continue 是 JavaScript 中唯一可以使用語句標簽的語句,。
語句標簽只有在它所起作用的語句(當然也可以在它的子句中)內是有定義的,。
break 可以 “跳出” 任何閉合的語句塊。這里的語句可以是由花括號括起來的一組語句,。
不管 break 語句帶不帶標簽,,它的控制權都無法越過函數的邊界。
不管continue語句帶不帶標簽,,它只能在循環(huán)體內使用,。在其他地方使用將會報語法錯誤。
在不同類型的循環(huán)中,,continue的行為也有所區(qū)別
return 語句語法
return expression;
return 語句只能在函數體內出現,,如果不是的話會報語法錯誤。當調用的函數時,該函數不存在return語句或return語句不帶expression,,則該函數的返回值為undefined,。
|
|