個(gè)人博客:https://yeaseonzhang.github.io
花了半個(gè)多月的時(shí)間,終于又把“JS紅寶書”又?jǐn)]了一遍铸豁。
第一次讀“JS紅寶書”還是2015年初學(xué)JS的時(shí)候蜈垮,那時(shí)候只是把語法部分讀了一遍耗跛,還有一些瀏覽器相關(guān)知識(shí)做了下了解,大概也就讀了半本的樣子攒发,
就開始了用JS進(jìn)行開發(fā)了调塌,在成長(zhǎng)的道路上遇見了JQuery,當(dāng)時(shí)真的是感覺到JQuery太友好了惠猿,慢慢放下了原生開發(fā)羔砾。
現(xiàn)在呢,更多的時(shí)候是在用框架進(jìn)行開發(fā),越來越覺得自己的JS基礎(chǔ)很缺乏姜凄,然后就開啟了“JS紅寶書”二刷之路政溃。
下面就把書中自己覺得重要的、沒有掌握的知識(shí)整理出來檀葛。因?yàn)槲矣X得還是會(huì)三刷“JS紅寶書”玩祟,希望把這本700多頁的書越讀越薄腹缩,勉勵(lì)屿聋。
章節(jié)
- 在HTML中使用JavaScript
- 基本概念
- 變量、作用域和內(nèi)存問題
- 引用類型
- 面向?qū)ο蟮某绦蛟O(shè)計(jì)
- 函數(shù)表達(dá)式
- BOM
- DOM
- DOM 擴(kuò)展
- DOM2 和 DOM3
在HTML中使用JavaScript
async
加載外部腳本文件藏鹊,通知瀏覽器立即下載润讥,異步執(zhí)行。
noscript 元素
noscript
標(biāo)簽顯示條件:
- 瀏覽器不支持腳本
- 瀏覽器支持腳本盘寡,但是腳本被禁用
基本概念
語法
標(biāo)識(shí)符
- 第一個(gè)字符必須是一個(gè)字母楚殿、下劃線或者一個(gè)美元符號(hào)
- 其他字符可以是字母、下劃線竿痰、美元或者數(shù)字
嚴(yán)格模式
支持嚴(yán)格模式的瀏覽器包括:IE10+脆粥、Firefox4+、Safari 5.1+影涉、Opera 12+和Chrome变隔。
數(shù)據(jù)類型
undefined
對(duì)未初始化的變量執(zhí)行typeof
操作會(huì)返回undefined
值,而對(duì)于未聲明的變量執(zhí)行typeof
操作同樣會(huì)返回undefined
值蟹倾。
null
typeof null // -> object
undefined值派生自null
值匣缘。
console.log(null == undefind) // -> true
isFinite()
測(cè)試一個(gè)數(shù)值是不是無窮值。
Number.NEGATIVE_INFINITY
:負(fù)無窮
Number.POSITION_INFINITY
:正無窮
NaN
在ECMAScript中鲜棠,任何數(shù)值除以0會(huì)返回NaN
肌厨。
isNaN()
接受一個(gè)參數(shù),確定這個(gè)參數(shù)是否"不是數(shù)值"豁陆。
數(shù)值轉(zhuǎn)換
Number()
- 如果是
null
柑爸,返回0
- 如果是
undefined
,返回NaN
parseInt()
在ES5 中不支持解析八進(jìn)制的能力盒音。
parseInt('070'); // -> 70 not 56
通過第二個(gè)參數(shù)表鳍,指定轉(zhuǎn)換基數(shù)(進(jìn)制)默認(rèn)十進(jìn)制。
字符串
- ECMAScript中的字符串是不可變的
toString()
在調(diào)用數(shù)值的toString
方法里逆,可以傳遞一個(gè)參數(shù):輸出數(shù)值的基數(shù)进胯。沒有toString
方法的則返回該值的字面量
var num = 10;
console.log(num.toString(2)); // -> '1010'
object類型
Object類型的屬性方法:
- constructor
- hasOwnProperty(propertyName)
- isPrototypeOf(obj)
- propertyIsEnumerable(propertyName)
- toLocalString()
- toString()
- valueOf()
操作符
-
++
or--
前置與后置的區(qū)別
var num1 = 2;
var num2 = 20;
var num3 = --num1 + num2; // 21
var num4 = num1 + num2; // 21
var num5 = 2;
var num6 = 20;
var num7 = num5-- + num6; // 22
var num8 = num5 + num6; // 21
- 一元加操作符用于強(qiáng)制類型轉(zhuǎn)換,隱式
Number()
效果
for-in 語句
for-in
語句是一種精確的迭代語句原押,可以用來枚舉對(duì)象的屬性胁镐。
通過for-in
循環(huán)輸出的屬性名的順序是不可預(yù)測(cè)的。
如果要迭代的對(duì)象的變量值為null
或undefined
,for-in
語句會(huì)拋出錯(cuò)誤盯漂。ES5更正了這一行為颇玷,不再拋出錯(cuò)誤,只是不再執(zhí)行循環(huán)體就缆。
建議:在是使用for-in
循環(huán)之前帖渠,先檢查對(duì)象值是不是null
或者undefined
。
變量竭宰、作用域和內(nèi)存問題
基本類型和引用類型
復(fù)制變量值
- 復(fù)制基本類型值空郊,這兩個(gè)變量相互獨(dú)立,互不影響切揭。
- 復(fù)制引用類型(對(duì)象)狞甚,值引用是一個(gè)指針,改變其中一個(gè)對(duì)象廓旬,會(huì)影響另一個(gè)對(duì)象哼审。
傳遞參數(shù)
function setName(obj) {
obj.name = "Nicholas";
}
var person = new Object();
setName(person);
alert(person.name); //"Nicholas"
以上代碼中創(chuàng)建一個(gè)對(duì)象,并將其保存在了變量person
中孕豹。然后涩盾,這個(gè)變量被傳遞到setName()
函數(shù)中之后就被復(fù)制給了obj
。在這個(gè)函數(shù)部励背,obj
和person
引用的是同一個(gè)對(duì)象春霍。換句話說,即使這個(gè)變量是按值傳遞的椅野,obj
也會(huì)按引用來訪問同一個(gè)對(duì)象终畅。于是,當(dāng)在函數(shù)內(nèi)部為obj
添加name
屬性后竟闪,函數(shù)外部的person
也將有所反映离福;因?yàn)?code>person 指向的對(duì)象在堆內(nèi)存中只有一個(gè),而且是全局對(duì)象炼蛤。有很多開發(fā)人員錯(cuò)誤地認(rèn)為:在局部作用域中修改的對(duì)象會(huì)在全局作用域中反映出來妖爷,就說明參數(shù)是按引用傳遞的。為了證明對(duì)象是按值傳遞的理朋,我們?cè)倏匆豢聪旅孢@個(gè)經(jīng)過修改的例子:
function setName(obj) {
obj.name = "Nicholas";
obj = new Object();
obj.name = "Greg";
}
var person = new Object();
setName(person);
alert(person.name); //"Nicholas"
這個(gè)例子與前一個(gè)例子的唯一區(qū)別絮识,就是在setName()
函數(shù)中添加了兩行代碼:一行代碼為obj
重新定義了一個(gè)對(duì)象,另一行代碼為該對(duì)象定義了一個(gè)帶有不同值的name
屬性嗽上。在把person
傳遞給setName()
后次舌,其name
屬性被設(shè)置為"Nicholas"。然后兽愤,又將一個(gè)新對(duì)象賦給變量obj
彼念,同時(shí)將其name
屬性設(shè)置為"Greg"挪圾。如果person
是按引用傳遞的,那么person
就會(huì)自動(dòng)被修改為指向其name
屬性值為"Greg"的新對(duì)象逐沙。但是哲思,當(dāng)接下來再訪問person.name
時(shí),顯示的值仍然是"Nicholas"吩案。這說明即使在函數(shù)內(nèi)部修改了參數(shù)的值棚赔,但原始的引用仍然保持未變。實(shí)際上徘郭,當(dāng)在函數(shù)內(nèi)部重寫obj
時(shí)靠益,這個(gè)變量引用的就是一個(gè)局部對(duì)象了。而這個(gè)局部對(duì)象會(huì)在函數(shù)執(zhí)行完畢后立即被銷毀崎岂。
檢測(cè)類型
雖然在檢測(cè)基本數(shù)據(jù)類型時(shí)typeof
是非常得力的助手捆毫,但在檢測(cè)引用類型的值時(shí),這個(gè)操作符的用處不大冲甘。通常肆捕,我們并不是想知道某個(gè)值是對(duì)象乌企,而是想知道它是什么類型的對(duì)象育灸。為此串前,ECMAScript提供了instanceof
操作符虏缸。
延長(zhǎng)作用域
-
try-catch
語句中的catch
塊 -
with
語句
小結(jié)
- 基本類型值在內(nèi)存中占據(jù)固定大小的空間挽懦,因此被保存在棧內(nèi)存中浦译;
- 從一個(gè)變量向另一個(gè)變量復(fù)制基本類型的值常侣,會(huì)創(chuàng)建這個(gè)值的一個(gè)副本裆站;
- 引用類型的值是對(duì)象条辟,保存在堆內(nèi)存中;
- 包含引用類型值的變量實(shí)際上包含的并不是對(duì)象本身宏胯,而是一個(gè)指向該對(duì)象的指針羽嫡;
引用類型
Array類型
檢測(cè)數(shù)組
if (value instanceof Array) {
}
ECMAScript5新增了 Array.isArray()
方法
if (Array.isArray(value)) {
}
sort方法
該方法有缺陷,sort()
方法會(huì)調(diào)用每個(gè)數(shù)組項(xiàng)的toString()
轉(zhuǎn)型方法肩袍,然后比較字符串進(jìn)行排序杭棵。
var values = [0, 1, 5, 10, 15];
values.sort();
alert(values); //0,1,10,15,5
因此sort()
方法接受一個(gè)比較函數(shù)作為參數(shù)。
function compare(value1, value2) {
if (value1 < value2) {
return -1;
} else if (value1 > value2) {
return 1;
} else {
return 0;
}
}
var values = [0, 1, 5, 10, 15];
values.sort(compare);
alert(values); //0,1,5,10,15
splice方法
splice
方法始終返回一個(gè)數(shù)組氛赐,該數(shù)組包含了從原始數(shù)組中刪除的項(xiàng)魂爪。
var colors = ["red", "green", "blue"];
var removed = colors.splice(0,1); // 刪除第一項(xiàng)
alert(colors); // green,blue
alert(removed); // red,返回的數(shù)組中只包含一項(xiàng)
removed = colors.splice(1, 0, "yellow", "orange"); // 從位置1 開始插入兩項(xiàng)
alert(colors); // green,yellow,orange,blue
alert(removed); // 返回的是一個(gè)空數(shù)組
removed = colors.splice(1, 1, "red", "purple"); // 插入兩項(xiàng)艰管,刪除一項(xiàng)
alert(colors); // green,red,purple,orange,blue
alert(removed); // yellow滓侍,返回的數(shù)組中只包含一項(xiàng)
迭代方法
ECMAScript5為數(shù)組定義了5個(gè)迭代方法。
-
every()
: 對(duì)數(shù)組中的每一項(xiàng)運(yùn)行給定函數(shù)牲芋,如果該函數(shù)對(duì)每一項(xiàng)都返回true撩笆,則返回true尔破。 -
filter()
: 對(duì)數(shù)組中的每一項(xiàng)運(yùn)行給定函數(shù),返回該函數(shù)會(huì)返回true 的項(xiàng)組成的數(shù)組浇衬。 -
forEach()
: 對(duì)數(shù)組中的每一項(xiàng)運(yùn)行給定函數(shù)懒构。這個(gè)方法沒有返回值。 -
map()
: 對(duì)數(shù)組中的每一項(xiàng)運(yùn)行給定函數(shù)耘擂,返回每次函數(shù)調(diào)用的結(jié)果組成的數(shù)組胆剧。 -
some()
: 對(duì)數(shù)組中的每一項(xiàng)運(yùn)行給定函數(shù),如果該函數(shù)對(duì)任一項(xiàng)返回true醉冤,則返回true秩霍。
歸并方法
ECMAScript 5 還新增了兩個(gè)歸并數(shù)組的方法。
reduce()
reduceRight()
reduce()
和reduceRight()
的函數(shù)接收4 個(gè)參數(shù):前一個(gè)值蚁阳、當(dāng)前值铃绒、項(xiàng)的索引和數(shù)組對(duì)象。
var values = [1, 2, 3, 4, 5];
var sum = values.reduce((prev, cur, index, array) => {
return prev + cur;
});
console.log(sum);
RegExp類型
正則表達(dá)式中的元字符
( [ { \ ^ $ | ) ? * + . ] }
注:匹配元字符必須轉(zhuǎn)義
RegExp
構(gòu)造函數(shù)
接受兩個(gè)參數(shù): 一個(gè)是要匹配的字符串模式螺捐,另一個(gè)是可選的標(biāo)志字符串颠悬。
var pattern1 = /[bc]at/i;
// 等價(jià)于
var pattern2 = new RegExp('[bc]at', 'i');
注:由于RegExp構(gòu)造函數(shù)的模式是字符串,所以在某些情況下要對(duì)字符串進(jìn)行雙重轉(zhuǎn)義定血,所有元字符都必須雙重轉(zhuǎn)義赔癌。例如\n
在字符串中被轉(zhuǎn)義為\\n
,而在正則表達(dá)式字符串中就會(huì)變成\\\\n
澜沟。
RegExp
實(shí)例方法
exex()
方法
該方法是專門為捕獲組而設(shè)計(jì)的灾票。exec()
接受一個(gè)參數(shù),即要應(yīng)用模式的字符串茫虽,然后返回包含第一個(gè)匹配項(xiàng)信息的數(shù)組刊苍;或者在沒有匹配項(xiàng)的情況下返回null
。返回的數(shù)組雖然是Array 的實(shí)例濒析,但包含兩個(gè)額外的屬性:index
和input
正什。其中,index
表示匹配項(xiàng)在字符串中的位置悼枢,而input
表示應(yīng)用正則表達(dá)式的字符串埠忘。在數(shù)組中,第一項(xiàng)是與整個(gè)模式匹配的字符串馒索,其他項(xiàng)是與模式中的捕獲組匹配的字符串(如果模式中沒有捕獲組莹妒,則該數(shù)組只包含一項(xiàng))。
var text = "mom and dad and baby";
var pattern = /mom( and dad( and baby)?)?/gi;
var matches = pattern.exec(text);
alert(matches.index); // 0
alert(matches.input); // "mom and dad and baby"
alert(matches[0]); // "mom and dad and baby"
alert(matches[1]); // " and dad and baby"
aler t(matches[2]); // " and baby"
對(duì)于exec()
方法而言绰上,即使在模式中設(shè)置了全局標(biāo)志(g
)旨怠,它每次也只會(huì)返回一個(gè)匹配項(xiàng)。在不設(shè)置全局標(biāo)志的情況下蜈块,在同一個(gè)字符串上多次調(diào)用exec()
將始終返回第一個(gè)匹配項(xiàng)的信息鉴腻。而在設(shè)置全局標(biāo)志的情況下迷扇,每次調(diào)用exec()
則都會(huì)在字符串中繼續(xù)查找新匹配項(xiàng)。
test()
方法
接受一個(gè)字符串參數(shù)爽哎。在模式與該參數(shù)匹配的情況下返回true
蜓席;否則,返回false
课锌。
var text = "000-00-0000";
var pattern = /\d{3}-\d{2}-\d{4}/;
if (pattern.test(text)){
alert("The pattern was matched.");
}
RegExp實(shí)例繼承的toLocaleString()
和toString()
方法都會(huì)返回正則表達(dá)式的字面量厨内,與創(chuàng)建正則表達(dá)式的方式無關(guān)。
var pattern = new RegExp("\\[bc\\]at", "gi");
alert(pattern.toString()); // /\[bc\]at/gi
alert(pattern.toLocaleString()); // /\[bc\]at/gi
Function類型
函數(shù)聲明與函數(shù)表達(dá)式
解析器會(huì)率先讀取函數(shù)聲明渺贤,并使其在執(zhí)行任何代碼之前可用雏胃;至于函數(shù)表達(dá)式,則必須等到解析器執(zhí)行到它所在的代碼行志鞍,才會(huì)真正被解釋執(zhí)行瞭亮。
// ok
alert(sum(10,10));
function sum(num1, num2){
return num1 + num2;
}
// unexpected identifier(意外標(biāo)識(shí)符)
alert(sum(10,10));
var sum = function(num1, num2){
return num1 + num2;
};
注:要訪問函數(shù)的指針而不執(zhí)行函數(shù)的話,必須去掉函數(shù)名后的那對(duì)圓括號(hào)固棚。
函數(shù)內(nèi)部屬性
arguments
this
arguments
具有一個(gè)callee
屬性统翩,該屬性是一個(gè)指針,指向擁有這個(gè)arguments
對(duì)象的函數(shù)玻孟。
function factorial(num){
if (num <=1) {
return 1;
} else {
return num * factorial(num-1)
}
}
等價(jià)于
function factorial(num){
if (num <=1) {
return 1;
} else {
return num * arguments.callee(num-1)
}
}
達(dá)到一種解耦的效果唆缴。
ECMAScript 5也規(guī)范了一個(gè)函數(shù)對(duì)象屬性:caller
(看著很像callee
),這個(gè)屬性中保存著調(diào)用當(dāng)前函數(shù)的函數(shù)的引用黍翎,如果實(shí)在全局作用域中調(diào)用當(dāng)前函數(shù),它的值為null
艳丛。
function outer(){
inner();
}
function inner(){
alert(inner.caller);
}
outer();
inner.caller
指向outer()
匣掸。為了實(shí)現(xiàn)更松散的耦合,也可以通過argument.callee.caller
來訪問相同的信息氮双。
function outer() {
inner();
}
function inner() {
alert(arguments.callee.caller);
}
outer();
注:當(dāng)函數(shù)在嚴(yán)格模式下運(yùn)行時(shí)碰酝,訪問arguments.callee
會(huì)導(dǎo)致錯(cuò)誤。ECMAScript 5 還定義了arguments.caller
屬性戴差,但在嚴(yán)格模式下訪問它也會(huì)導(dǎo)致錯(cuò)誤送爸,而在非嚴(yán)格模式下這個(gè)屬性始終是undefined
。定義這個(gè)屬性是為了分清arguments.caller
和函數(shù)的caller
屬性暖释。以上變化都是為了加強(qiáng)這門語言的安全性袭厂,這樣第三方代碼就不能在相同的環(huán)境里窺視其他代碼了。
嚴(yán)格模式還有一個(gè)限制:不能為函數(shù)的caller
屬性賦值球匕,否則會(huì)導(dǎo)致錯(cuò)誤纹磺。
函數(shù)屬性和方法
每個(gè)函數(shù)都包含兩個(gè)屬性:
-
length
: 表示函數(shù)希望接收的命名參數(shù)的個(gè)數(shù) -
prototype
: 保存實(shí)例方法
每個(gè)函數(shù)都包含兩個(gè)非繼承而來的方法:
apply()
-
call()
這兩個(gè)方法的用途都是在特定的作用域中調(diào)用函數(shù),實(shí)際上等于設(shè)置函數(shù)體內(nèi)this
對(duì)象的值亮曹。首先橄杨,apply()
方法接收兩個(gè)參數(shù):一個(gè)是在其中運(yùn)行函數(shù)的作用域秘症,另一個(gè)是參數(shù)數(shù)組。其中式矫,第二個(gè)參數(shù)可以是Array
的實(shí)例乡摹,也可以是arguments
對(duì)象。
call()
方法與apply()
方法的作用相同采转,它們的區(qū)別僅在于接收參數(shù)的方式不同聪廉。對(duì)于call()
方法而言,第一個(gè)參數(shù)是this
值沒有變化氏义,變化的是其余參數(shù)都直接傳遞給函數(shù)锄列。換句話說,在使用call()
方法時(shí)惯悠,傳遞給函數(shù)的參數(shù)必須逐個(gè)列舉出來邻邮。
注:在嚴(yán)格模式下,未指定環(huán)境對(duì)象而調(diào)用函數(shù)克婶,則this
值不會(huì)轉(zhuǎn)型為window
筒严。除非明確把函數(shù)添加到某個(gè)對(duì)象或者調(diào)用apply()
或call()
,否則this 值將是undefined
情萤。
在非嚴(yán)格模式下鸭蛙,call
、apply
的第一個(gè)參數(shù)傳遞為null
或undefined
時(shí)筋岛,函數(shù)體內(nèi)的this
會(huì)指向默認(rèn)的宿主對(duì)象娶视,在瀏覽器中則是window
。
ECMAScript 5定義了一個(gè)方法bind()
睁宰,這個(gè)方法會(huì)創(chuàng)建一個(gè)函數(shù)的實(shí)例肪获,其this
值會(huì)被綁定到傳給bind()
函數(shù)的值。
基本包裝類型
使用new
調(diào)用基本包裝類型的構(gòu)造函數(shù)柒傻,與直接調(diào)用同名的轉(zhuǎn)型函數(shù)是不一樣的孝赫。
var value = '25';
var number = Number(value); // 轉(zhuǎn)型函數(shù)
console.log(typeof number); // 'number'
var obj = new Number(value); // 構(gòu)造函數(shù)
console.log(typeof obj); // 'object'
Number類型
Number類型的toString()
方法很特別,可以傳遞一個(gè)表示基數(shù)的參數(shù)红符。
var num = 10;
alert(num.toString()); //"10"
alert(num.toString(2)); //"1010"
alert(num.toString(8)); //"12"
alert(num.toString(10)); //"10"
alert(num.toString(16)); //"a"
String類型
字符方法
charAt()
charCodeAt()
var stringValue = "hello world";
alert(stringValue.charAt(1)); //"e"
alert(stringValue.charCodeAt(1)); //輸出字符編碼"101"
字符串操作方法
concat()
slice()
substr()
substring()
這些方法對(duì)原字符均沒有任何影響青柄。
var stringValue = "hello ";
var result = stringValue.concat("world", "!");
alert(result); //"hello world!"
var stringValue = "hello world";
alert(stringValue.slice(3)); //"lo world"
alert(stringValue.substring(3)); //"lo world"
alert(stringValue.substr(3)); //"lo world"
alert(stringValue.slice(3, 7)); //"lo w"
alert(stringValue.substring(3,7)); //"lo w"
alert(stringValue.substr(3, 7)); //"lo worl"
// 參數(shù)是負(fù)值的情況下,它們的行為就不盡相同了预侯。
// 其中致开,slice()方法會(huì)將傳入的負(fù)值與字符串的長(zhǎng)度相加,
// substr()方法將負(fù)的第一個(gè)參數(shù)加上字符串的長(zhǎng)度雌桑,而將負(fù)的第二個(gè)參數(shù)轉(zhuǎn)換為0喇喉。
// 最后,substring()方法會(huì)把所有負(fù)值參數(shù)都轉(zhuǎn)換為0校坑。
alert(stringValue.slice(-3)); //"rld"
alert(stringValue.substring(-3)); //"hello world"
alert(stringValue.substr(-3)); //"rld"
alert(stringValue.slice(3, -4)); //"lo w"
alert(stringValue.substring(3, -4)); //"hel"
alert(stringValue.substr(3, -4)); //""(空字符串)
字符串位置方法
indexOf()
lastIndexOf()
兩個(gè)方法的第二個(gè)參數(shù)拣技,表示從字符串中哪個(gè)位置開始搜索千诬。
trim()方法
ECMAScript 5方法
字符串轉(zhuǎn)換大小寫方法
toLowerCase()
toLocaleLowerCase()
toUpperCase()
toLocaleUpperCase()
字符串的模式匹配方法
match()
search()
replace()
split()
match()
方法,在字符串上調(diào)用這個(gè)方法膏斤,本質(zhì)上和調(diào)用RegExp
的exec()
方法相同徐绑。match()
方法只接受一個(gè)參數(shù),要么是一個(gè)正則表達(dá)式莫辨,要么是一個(gè)RegExp對(duì)象傲茄。
var text = 'cat, bat, sat, fat';
var pattern = /.at/;
// 等價(jià)于 pattern.exec(text)
var matches = text.match(pattern);
alert(matches.index); //0
alert(matches[0]); //"cat"
alert(pattern.lastIndex); //0
search()
方法的參數(shù)與match()
方法相同,該方法返回字符串中第一個(gè)匹配項(xiàng)的索引沮榜,沒有匹配項(xiàng)返回-1
盘榨;個(gè)人認(rèn)為serch()
就是正則版的indexOf()
。
var text = "cat, bat, sat, fat";
var pos = text.search(/at/);
aler t(pos); //1
ECMAScript提供了replace()
方法蟆融,該方法接受兩個(gè)參數(shù)草巡,第一個(gè)參數(shù)可以是RegExp對(duì)象或者是一個(gè)字符串,第二個(gè)參數(shù)可以是一個(gè)字符串或者一個(gè)函數(shù)型酥。
var text = "cat, bat, sat, fat";
var result = text.replace("at", "ond");
alert(result); //"cond, bat, sat, fat"
result = text.replace(/at/g, "ond");
aler t(result); //"cond, bond, sond, fond"
| 字符序列 | 替換文本 |
| : - : | : -- : |
| $$
| $
|
| $&
| 匹配整個(gè)模式的子字符串山憨。RegExp.lastMatch |
| $'
| 匹配子字符串之前的字符串。RegExp.leftContext |
| $
` | 匹配的子字符串之后的字符串弥喉。 RegExp.rightContext |
| $n
| 匹配第n個(gè)捕獲組的子字符串 n: 0~9 |
| $nn
| 匹配第nn個(gè)捕獲組的子字符串 nn: 01~99 |
var text = "cat, bat, sat, fat";
result = text.replace(/(.at)/g, "word ($1)");
alert(result); //word (cat), word (bat), word (sat), word (fat)
split()
方法可以基于指定的分隔符(字符串 or RegExp對(duì)象)將一個(gè)字符串分割成多個(gè)子字符串郁竟,并將結(jié)構(gòu)放在一個(gè)數(shù)組中∮删常可以接受可選的第二個(gè)參數(shù)棚亩,用于指定數(shù)組的大小。
var colorText = "red,blue,green,yellow";
var colors1 = colorText.split(","); //["red", "blue", "green", "yellow"]
var colors2 = colorText.split(",", 2); //["red", "blue"]
var colors3 = colorText.split(/[^\,]+/); //["", ",", ",", ",", ""]
localeCompare()方法
比較兩個(gè)字符串虏杰,并返回下列值中的 一個(gè):
- 如果字符串在字母表中應(yīng)該排在字符串參數(shù)之前蔑舞,則返回一個(gè)負(fù)數(shù)
- 如果字符串等于字符串參數(shù),則返回0嘹屯;
- 如果字符串在字母表中應(yīng)該排在字符串參數(shù)之后,則返回一個(gè)正數(shù)
var stringValue = "yellow";
alert(stringValue.localeCompare("brick")); //1
alert(stringValue.localeCompare("yellow")); //0
alert(stringValue.localeCompare("zoo")); //-1
fromCharCode()方法
這個(gè)方法的任務(wù)是接收一個(gè)或多個(gè)字符編碼从撼,然后將它們轉(zhuǎn)換成一個(gè)字符串州弟。相當(dāng)于charCodeAt()
反操作。
alert(String.fromCharCode(104, 101, 108, 108, 111)); //"hello"
Math 對(duì)象
min()
max()
ceil()
floor()
round()
random()
面向?qū)ο蟮某绦蛟O(shè)計(jì)
理解對(duì)象
屬性類型
數(shù)據(jù)類型
-
[[Configurable]]
: 表示能否通過delete
刪除屬性從而重新定義屬性低零,能夠修改屬性的特性婆翔,或者能否把屬性修改為訪問器屬性 -
[[Enumerable]]
: 表示能否通過for-in
循環(huán)返回屬性 -
[[Writable]]
: 表示能否修改屬性的值 -
[[Value]]
: 包含這個(gè)屬性的數(shù)據(jù)值。讀取屬性值的時(shí)候掏婶,從這個(gè)位置讀啃奴;寫入屬性值的時(shí)候,把新值保存在這個(gè)位置雄妥。默認(rèn)值undefined
要修改屬性默認(rèn)的特性最蕾,必須使用ECMAScript 5的Object.defineProperty()
方法依溯。這個(gè)方法接受三個(gè)參數(shù):屬性所在對(duì)象,屬性名和一個(gè)描述符對(duì)象瘟则。其中描述符對(duì)象的屬性值必須是:configurable
黎炉、enumerable
、writable
和value
醋拧。設(shè)置其中一個(gè)或多個(gè)慷嗜。
var person = {};
Object.defineProperty(person, 'name', {
writable: false,
value: 'Yeaseon'
});
Object.defineProperty()
方法不能對(duì)configurable: false
的對(duì)象進(jìn)行修改。
訪問器屬性
-
[[Configurable]]
: 表示能否通過delete
刪除屬性從而重新定義屬性丹壕,能否修改屬性的特性庆械,或者能否把屬性修改為數(shù)據(jù)屬性。 -
[[Enumerable]]
: 表示能否通過for-in
循環(huán)返回屬性菌赖。 -
[[Get]]
: 在讀取屬性時(shí)調(diào)用的函數(shù)缭乘,默認(rèn)undefined
-
[[Set]]
: 在寫入屬性時(shí)調(diào)用的函數(shù),默認(rèn)undefined
var book = {
_year: 2004,
edition: 1
};
Object.defineProperty(book, "year", {
get: function(){
return this._year;
},
set: function(newValue){
if (newValue > 2004) {
this._year = newValue;
this.edition += newValue - 2004;
}
}
});
book.year = 2005;
alert(book.edition); //2
讀取屬性的特性
ECMAScript 5的Object.getOwnPropertyDescriptor()
方法盏袄,可以取得給定屬性的描述符忿峻。該方法接收兩個(gè)參數(shù):屬性所在的對(duì)象和要讀取器描述符的屬性名稱,返回值是對(duì)象辕羽。
創(chuàng)建對(duì)象
工廠模式
function createPerson(name, age, job){
var o = new Object();
o.name = name;
o.age = age;
o.job = job;
o.sayName = function(){
alert(this.name);
};
return o;
}
var person1 = createPerson("Nicholas", 29, "Software Engineer");
var person2 = createPerson("Greg", 27, "Doctor");
構(gòu)造函數(shù)模式
function Person(name, age, job){
this.name = name;
this.age = age;
this.job = job;
this.sayName = function(){
alert(this.name);
};
}
var person1 = new Person("Nicholas", 29, "Software Engineer");
var person2 = new Person("Greg", 27, "Doctor");
原型模式
function Person(){
}
Person.prototype.name = "Nicholas";
Person.prototype.age = 29;
Person.prototype.job = "Software Engineer";
Person.prototype.sayName = function(){
alert(this.name);
};
var person1 = new Person();
person1.sayName(); //"Nicholas"
Person.prototype.constructor
會(huì)指向Person
逛尚,person1
并沒有直接連接到構(gòu)造函數(shù)Person
。
- 可以通過
isPrototypeOf()
方法來確定對(duì)象之間是否存在原型關(guān)系刁愿。從本質(zhì)上講绰寞,[[Prototype]]
指向調(diào)用isPrototypeOf()
方法的對(duì)象Person.prototype
,則會(huì)返回true
铣口。
alert(Person.prototype.isPrototypeOf(person1)); //true
在ECMAScript 5增加了Object.getPrototypeOf()
方法滤钱,該方法返回[[Prototype]]
的值。
alert(Object.getPrototypeOf(person1) == Person.prototype); //true
alert(Object.getPrototypeOf(person1).name); //"Nicholas"
注: 雖然可以通過對(duì)象實(shí)例person1
訪問保存在原型中的值脑题,但卻不能重寫原型中的值件缸。
function Person(){
}
Person.prototype.name = "Nicholas";
Person.prototype.age = 29;
Person.prototype.job = "Software Engineer";
Person.prototype.sayName = function(){
alert(this.name);
};
var person1 = new Person();
var person2 = new Person();
person1.name = "Greg"; //實(shí)質(zhì)是在實(shí)例上增加一個(gè)name屬性
alert(person1.name); //"Greg"——來自實(shí)例
alert(person2.name); //"Nicholas"——來自原型
可以通過delete
刪除實(shí)例屬性,從而繼續(xù)訪問原型中的屬性叔遂。
function Person(){
}
Person.prototype.name = "Nicholas";
Person.prototype.age = 29;
Person.prototype.job = "Software Engineer";
Person.prototype.sayName = function(){
alert(this.name);
};
var person1 = new Person();
person1.name = "Greg";
alert(person1.name); //"Greg"——來自實(shí)例
delete person1.name;
alert(person1.name); //"Nicholas"——來自原型
-
hasOwnProperty()
方法可以檢測(cè)一個(gè)屬性是不是存在于實(shí)例他炊,是則返回true
。
-
in
操作符
(prop in obj)通過in
操作符可以判定對(duì)象是否有該屬性已艰,不論是本身含有還是原型含有痊末,都返回true
。
可以通過in
配合hasOwnProperty()
確定該屬性是存在于對(duì)象中還是原型中:
function detectProperty(obj, name) {
if (name in obj) {
obj.hasOwnProperty(name) ? '在對(duì)象中' : '在原型中';
} else {
console.log('不含有該屬性');
}
}
-
ECMAScript 5
Object.keys()
方法可以取得對(duì)象上所有可枚舉的實(shí)例屬性哩掺。
function Person(){
}
Person.prototype.name = "Nicholas";
Person.prototype.age = 29;
Person.prototype.job = "Software Engineer";
Person.prototype.sayName = function(){
alert(this.name);
};
var keys = Object.keys(Person.prototype);
alert(keys); //"name,age,job,sayName"
var p1 = new Person();
p1.name = "Rob";
p1.age = 31;
var p1keys = Object.keys(p1);
alert(p1keys); //"name,age"
-
Object.getOwnPropertyNames
會(huì)得到所有實(shí)例屬性凿叠,不論是否可枚舉。
var keys = Object.getOwnPropertyNames(Person.prototype);
alert(keys); //"constructor,name,age,job,sayName"
簡(jiǎn)化Person.prototype
寫法:
function Person(){
}
Person.prototype = {
name : "Nicholas",
age : 29,
job: "Software Engineer",
sayName : function () {
alert(this.name);
}
};
這樣寫有一個(gè)缺陷,constructor
屬性則會(huì)等于Object
盒件,我們需要手動(dòng)設(shè)置constructor
蹬碧。
function Person(){
}
Person.prototype = {
constructor : Person,
name : "Nicholas",
age : 29,
job: "Software Engineer",
sayName : function () {
alert(this.name);
}
};
但這同時(shí)也會(huì)導(dǎo)致constructor
的[[Enumerable]]
特性變成了true
,默認(rèn)情況下是false
履恩。再修改下寫法:
function Person(){
}
Person.prototype = {
name : "Nicholas",
age : 29,
job : "Software Engineer",
sayName : function () {
alert(this.name);
}
};
Object.defineProperty(Person.prototype, "constructor", {
enumerable: false,
value: Person
});
原型重寫會(huì)導(dǎo)致構(gòu)造函數(shù)與最初原型之間的聯(lián)系切斷锰茉。
function Person(){
}
var friend = new Person();
Person.prototype = { //重寫
constructor: Person,
name : "Nicholas",
age : 29,
job : "Software Engineer",
sayName : function () {
alert(this.name);
}
};
friend.sayName(); //error
結(jié)合使用構(gòu)造函數(shù)和原型模式
用構(gòu)造函數(shù)模式定義實(shí)例屬性,用原型模式定義方法和共享屬性切心。
function Person(name, age, job){
this.name = name;
this.age = age;
this.job = job;
this.friends = ["Shelby", "Court"];
}
Person.prototype = {
constructor : Person,
sayName : function(){
alert(this.name);
}
}
var person1 = new Person("Nicholas", 29, "Software Engineer");
var person2 = new Person("Greg", 27, "Doctor");
person1.friends.push("Van");
alert(person1.friends); //"Shelby,Count,Van"
alert(person2.friends); //"Shelby,Count"
alert(person1.friends === person2.friends); //false
alert(person1.sayName === person2.sayName); //true
繼承
構(gòu)造函數(shù)飒筑、原型和實(shí)例的關(guān)系:每個(gè)構(gòu)造函數(shù)都有一個(gè)原型對(duì)象,原型對(duì)象都包含一個(gè)指向構(gòu)造函數(shù)的指針绽昏,而實(shí)例都包含一個(gè)指向原型的內(nèi)部指針协屡。
原型鏈
function SuperType () {
this.property = true;
}
SuperType.prototype.getSuperValue = function () {
return this.property;
};
function SubType () {
this.subproperty = false;
}
SubType.prototype = new SuperType();
SubType.prototype.getSubValue = function () {
return this.subproperty;
};
var instance = new SubType();
console.log(instance.getSuperValue()); // true
instanceof
操作符
用來確定原型和實(shí)例之間的關(guān)系。
alert(instance instanceof Object); //true
alert(instance instanceof SuperType); //true
alert(instance instanceof SubType); //true
第二種方式就是isPrototypeOf()
方法全谤,只要原型鏈中出現(xiàn)過的原型肤晓,都可以說是該原型鏈所派生的實(shí)例的原型。
alert(Object.prototype.isPrototypeOf(instance)); //true
alert(SuperType.prototype.isPrototypeOf(instance)); //true
alert(SubType.prototype.isPrototypeOf(instance)); //true
函數(shù)表達(dá)式
由于有聲明提升的存在认然,定義函數(shù)不要放在條件表達(dá)式中
if (condition) {
function sayHi () {
console.log('Hi');
}
} else {
function sayHi () {
console.log('Yo');
}
}
在ECMAScript中屬于無效語法补憾,在不同瀏覽器中修正的做法并不一致。推薦的寫法卷员,如下:
var sayHi;
if (condition) {
sayHi = function () {
console.log('Hi');
}
} else {
sayHi = function () {
console.log('Yo');
}
}
這種函數(shù)表達(dá)式不存在聲明提升盈匾,所以O(shè)K。
遞歸
函數(shù)作用域鏈
當(dāng)某個(gè)函數(shù)被調(diào)用時(shí)毕骡,會(huì)創(chuàng)建一個(gè)執(zhí)行環(huán)境及相應(yīng)的作用域鏈削饵。然后,使用arguments
和其他命名參數(shù)的值來初始化函數(shù)的活動(dòng)對(duì)象未巫。在作用域鏈中窿撬,外部函數(shù)的活動(dòng)對(duì)象始終處于第二位,外部函數(shù)的外部函數(shù)的活動(dòng)對(duì)象處于第三位...叙凡,直到作用域終點(diǎn)的全局執(zhí)行環(huán)境劈伴。
閉包
function createFunctions () {
var result = new Array();
for (var i=0; i < 10; i++){
result[i] = function(){
return i;
};
}
return result;
}
function createFunction () {
var result = new Array();
for (var i = 0; i < 10; i++) {
result[i] = function (num) {
return function () {
return num;
};
}(i);
}
return result;
}
注:在閉包中使用this
對(duì)象可能會(huì)導(dǎo)致一些問題。匿名函數(shù)的執(zhí)行環(huán)境具有全局性握爷,因此其this
對(duì)象通常指向window
宰啦。
var name = 'The window';
var obj = {
name: 'my object',
getNameFunc: function () {
return function () {
return this.nam;
}
}
}
console.log(obj.getNameFunc()()); // The Window (非嚴(yán)格模式)
模仿塊級(jí)作用域
塊級(jí)作用域
(function () {
// 這里是塊級(jí)作用域
})();
BOM
window 對(duì)象
全局作用域
拋開全局變量會(huì)成為window
對(duì)象的屬性不談,定義全局變量與在window
對(duì)象上直接定義屬性還是有一點(diǎn)差別:全局變量不能通過delete
操作符刪除饼拍,而直接定義在window
對(duì)象上的定義的屬性可以。
窗口位置
獲得窗口左邊和上邊的位置田炭。
var leftPos = (typeof window.screenLeft == 'number') ? window.screenLeft : window.screenX;
var topPos = (typeof window.screenTop == 'number') ? window.screenTop : window.screenY;
Firefox支持screenX
和screenY
师抄,其他瀏覽器均支持screenLeft
、screenTop
教硫。
但是還是需要注意一個(gè)問題:在IE
Opera
中叨吮,screenLeft screenTop
保存的的是可見區(qū)域的距離辆布,也就是我們?yōu)g覽器中不包含工具欄的區(qū)域與屏幕的距離;在Chrome
茶鉴、Firefox
和Safari
中screenY
或screenTop
返回的是整個(gè)瀏覽器窗口相對(duì)于屏幕坐標(biāo)的值锋玲。
窗口大小
IE9+、Firefox涵叮、Safari惭蹂、Opera和Chrome均提供了4個(gè)屬性innerWidth
、innerHeight
割粮、outerWidth
和outerHeight
盾碗。
- IE9+、Safari和Firefox中舀瓢,
outerWidth
和outerHeight
返回瀏覽器窗口本身的尺寸廷雅,而innerWidth
和innerHeight
則表示該容器中頁面視圖區(qū)的大小(減去邊框?qū)挾龋?/li> - Chrome中京髓,
inner*
和outer*
返回相同的值航缀,即視口大小而非瀏覽器窗口的大小。 - 在IE堰怨、Firefox芥玉、Safari、Opera和Chrome中诚些,都能通過
document.documentElement.clientWidth
和document.documentElement.clientHeight
中保存了頁面視口信息飞傀。
獲取頁面視口大小
var pageWidth = window.innerWidth,
pageHeight = window.innerHeight;
if (typeof pageWidth != 'number') {
if (document.compatMode == 'CSS1Compat') { // 瀏覽器標(biāo)準(zhǔn)模式
pageWidth = document.documentElement.clientWidth;
pageHeight = document.documentElement.clientHeight;
} else { // IE6 混雜模式
pageWidth = document.body.clientWidth;
pageHeight = document.doby.clientHeight;
}
}
-
resizeTo()
接受瀏覽器窗口的新寬度和新高度 -
resizeBy()
接受新窗口與原窗口的寬度和高度差。
這兩個(gè)方法可能被瀏覽器禁用诬烹。
導(dǎo)航
如果是瀏覽器內(nèi)置的屏蔽程序組織的彈出窗口砸烦,那么window.open()
很可能會(huì)返回null
。
var newWindow = window.open('https://www.google.com.hk', '_blank');
if (newWindow == null) {
console.log('The popup was blocked!');
}
如果是瀏覽器擴(kuò)展或其他程序組織的彈出窗口绞吁,那么window.open()
通常會(huì)拋出一個(gè)錯(cuò)誤幢痘。
var blocked = false;
try {
var newWindow = window.open('https://www.google.com.hk', '_blank');
if (newWindow == null) {
blocked = true;
}
} catch (ex) {
blocked = true;
}
if (blocked) {
console.log('The popup was blocked');
}
location 對(duì)象
location
對(duì)象的屬性
hash
host
-
hostname
:與host
不同的是,不帶端口號(hào) href
-
pathname
: 返回URL中的目錄和(或)文件名 port
protocol
-
search
:返回URL的查詢字符串家破,這個(gè)字符串?
開頭
navigator 對(duì)象
location
對(duì)象的屬性
-
appCodeName
: 瀏覽器的名稱颜说,通常都是Mozilla -
appMinorVersion
:此版本信息 -
appName
: 完整的瀏覽器名稱 -
appVersion
:瀏覽器的版本 -
buildID
:瀏覽器編譯版本 -
cookieEnabled
:表示cookie
是否可用 -
cpuClass
:客戶端計(jì)算機(jī)中使用的CPU類型 -
javaEnabled()
:表示當(dāng)前瀏覽器中是否啟用了java -
language
: 瀏覽器的主語言 -
mimeTypes
:瀏覽器中注冊(cè)的MIME類型數(shù)組 -
onLine
:表示瀏覽器是都連接到因特網(wǎng) -
oscpu
:客戶端計(jì)算機(jī)的操作系統(tǒng)或使用的CPU -
platform
:瀏覽器所在的系統(tǒng)平臺(tái) -
plugins
:瀏覽器中安裝的插件信息的數(shù)組 -
preference()
:設(shè)置用戶的首選項(xiàng) -
systemLanguage
:操作系統(tǒng)的語言 -
userAgent
:瀏覽器的用戶代理字符串
DOM
節(jié)點(diǎn)層次
Node類型
每個(gè)節(jié)點(diǎn)都有一個(gè)nodeType
屬性,用于表明節(jié)點(diǎn)的類型汰聋。
Node.ELEMENT_NODE(1)
Node.ATTRIBUTE_NODE(2)
Node.TEXT_NODE(3)
Node.CDATA_SECTION_NODE(4)
Node.ENTITY_REFERENCE_NODE(5)
Node.ENTITY_NODE(6)
Node.PROCESSING_INSTRUCTION_NODE(7)
Node.COMMENT_NODE(8)
Node.DOCUMENT_NODE(9)
Node.DOCUMENT_TYPE_NODE(10)
Node.DOCUMENT_FRAGMENT_NODE(11)
Node.NOTATION_NODE(12)
為了確泵欧啵跨瀏覽器兼容,將nodeType
屬性與數(shù)字值進(jìn)行比較:
if (someNode.nodeType == 1) {
console.log('Node is an element');
}
-
nodeName
屬性
if (someNode.nodeType == 1) {
var value = someNode.nodeName; // nodeName的值是元素的標(biāo)簽名
}
節(jié)點(diǎn)關(guān)系
-
childNodes
屬性
每個(gè)節(jié)點(diǎn)都有一個(gè)childNodes
屬性烹困,其中保存著一個(gè)NodeList
對(duì)象玄妈,該對(duì)象是一種類數(shù)組對(duì)象。
-
parentNode
屬性
每個(gè)節(jié)點(diǎn)都有一個(gè)parentNode
屬性,該屬性指向文檔樹中的父節(jié)點(diǎn)拟蜻。包含在childNodes
列表中的每個(gè)節(jié)點(diǎn)相互都是兄弟節(jié)點(diǎn)绎签。使用previousSibling
和nextSibling
屬性,可以訪問其他兄弟節(jié)點(diǎn)酝锅。
注:列表中第一個(gè)節(jié)點(diǎn)的previousSibling
屬性值為null
诡必,同理列表中最后一個(gè)節(jié)點(diǎn)的nextSibling
屬性也是null
。父節(jié)點(diǎn)的firstChild
和lastChild
屬性分別指向其childNodes
列表中的第一個(gè)和最后一個(gè)節(jié)點(diǎn)搔扁。如果不存在則為null
爸舒。
hasChildNodes()
方法在節(jié)點(diǎn)包含一個(gè)或多個(gè)子節(jié)點(diǎn)的情況下返回true
,比查詢childNodes.length
更簡(jiǎn)便阁谆。
最后一個(gè)屬性ownerDocument
碳抄,該屬性指向表示整個(gè)文檔的文檔節(jié)點(diǎn)(root),直接返回根節(jié)點(diǎn)不需要一層層向上回溯场绿。
操作節(jié)點(diǎn)
appendChild()
用于向childNodes
列表的末尾添加一個(gè)節(jié)點(diǎn)剖效。
var returnedNode = someNode.appendChild(newNode);
alert(returnedNode == newNode); //true
alert(someNode.lastChild == newNode); //true
任何DOM節(jié)點(diǎn)不可能同時(shí)出現(xiàn)在多個(gè)位置。
//someNode 有多個(gè)子節(jié)點(diǎn)
var returnedNode = someNode.appendChild(someNode.firstChild);
alert(returnedNode == someNode.firstChild); //false
alert(returnedNode == someNode.lastChild); //true
insertBefore()
把節(jié)點(diǎn)放在指定位置焰盗,該方法接受兩個(gè)參數(shù):要插入的節(jié)點(diǎn)和作為參考的節(jié)點(diǎn)璧尸。插入節(jié)點(diǎn)后,被插入的節(jié)點(diǎn)會(huì)變成參照節(jié)點(diǎn)的前一個(gè)兄弟節(jié)點(diǎn)熬拒。參照節(jié)點(diǎn)是null
的話爷光,insertBefore
與appendChild
執(zhí)行相同的操作,都插入列表末尾澎粟。
//插入后成為最后一個(gè)子節(jié)點(diǎn)
returnedNode = someNode.insertBefore(newNode, null);
alert(newNode == someNode.lastChild); //true
//插入后成為第一個(gè)子節(jié)點(diǎn)
var returnedNode = someNode.insertBefore(newNode, someNode.firstChild);
alert(returnedNode == newNode); //true
alert(newNode == someNode.firstChild); //true
//插入到最后一個(gè)子節(jié)點(diǎn)前面
returnedNode = someNode.insertBefore(newNode, someNode.lastChild);
alert(newNode == someNode.childNodes[someNode.childNodes.length-2]); //true
replaceChild()
替換節(jié)點(diǎn)蛀序,接受兩個(gè)參數(shù):要插入的節(jié)點(diǎn)和要替換的節(jié)點(diǎn)。
//替換第一個(gè)子節(jié)點(diǎn)
var returnedNode = someNode.replaceChild(newNode, someNode.firstChild);
//替換最后一個(gè)子節(jié)點(diǎn)
returnedNode = someNode.replaceChild(newNode, someNode.lastChild);
removeChild()
移除節(jié)點(diǎn)活烙,接受一個(gè)參數(shù):要被移除的節(jié)點(diǎn)徐裸。
//移除第一個(gè)子節(jié)點(diǎn)
var formerFirstChild = someNode.removeChild(someNode.firstChild);
//移除最后一個(gè)子節(jié)點(diǎn)
var formerLastChild = someNode.removeChild(someNode.lastChild);
cloneNode()
復(fù)制節(jié)點(diǎn)陨瘩,接受一個(gè)布爾值犯助,表示是否深復(fù)制。復(fù)制后返回的節(jié)點(diǎn)沒有父節(jié)點(diǎn)声怔,可以通過插入等操作手動(dòng)指定回懦。
var deepList = myList.cloneNode(true);
alert(deepList.childNodes.length); //3(IE < 9)或7(其他瀏覽器)
var shallowList = myList.cloneNode(false);
alert(shallowList.childNodes.length); //0
注:cloneNode
方法不會(huì)復(fù)制DOM節(jié)點(diǎn)的js
屬性气笙。IE存在一個(gè)bug,它會(huì)復(fù)制事件處理程序怯晕。
normalize()
稍后討論
以上方法的返回值潜圃,都是被操作的節(jié)點(diǎn)。
Document類型
Document
節(jié)點(diǎn)具有下列特征:
-
nodeType
的值為9 -
nodeName
的值為#document
-
nodeValue
的值為null
-
parentNode
的值為null
-
ownerDocument
的值為null
- 其子節(jié)點(diǎn)可能是一個(gè)
DocumentType
(最多一個(gè))舟茶、Element
(最多一個(gè))秉犹、ProcessingInstruction
或Comment
// 通過`documentElement`屬性訪問<html>元素
var html = document.documentElement;
// 訪問 <body> 元素
var body = document.body;
// <!DOCTYPE>
var doctype = document.doctype;
// <title>
var title = document.title;
// 完整 url
var url = document.URL;
// domain 域名
var domain = document.domain;
// 取得來源頁面的URL(也就是導(dǎo)航到這頁的頁面)
var referrer = document.referrer;
查找元素的方法:
document.getElementById()
document.getElementsByTagName()
document.getElementsByName()
文檔寫入:
document.write()
-
document.writeln()
在字符串尾加換行符(\n)
<script type="text/javascript">
document.write("<script type=\"text/javascript\" src=\"file.js\">" + "<\/script>");
</script>
Element類型
Element
類型提供了對(duì)元素標(biāo)簽名蛉谜、子節(jié)點(diǎn)及特性的訪問。
-
nodeType
的值為1 -
nodeName
的值為元素的標(biāo)簽名 -
nodeValue
的值為null
-
parentNode
可能是Document
或Element
- 其子節(jié)點(diǎn)可能是
Element
崇堵、Text
、Comment
客燕、ProcessingInstruction
鸳劳、CDATASection
或EntityReference
訪問元素的標(biāo)簽名,可以使用nodeName
屬性也搓,也可以使用tagName
屬性赏廓,后者更直觀。
<div id="myDiv"></div>
var div = document.getElementById("myDiv");
alert(div.tagName); //"DIV"
alert(div.tagName == div.nodeName); //true
操作特性的方法:
getAttribute()
setAttribute()
removeAttribute()
attributes
屬性
Element
類型是使用attributes
屬性的唯一一個(gè)DOM節(jié)點(diǎn)屬性傍妒。attributes
屬性包含一個(gè)NamedNodeMap
幔摸。元素的每一個(gè)特性都由一個(gè)Attr
節(jié)點(diǎn)表示,每個(gè)節(jié)點(diǎn)都保存在NamedNodeMap
對(duì)象中颤练。
NamedNodeMap
對(duì)象的方法:
-
getNamedItem(name)
:返回nodeName
屬性等于name
的節(jié)點(diǎn) -
removeNamedItem(name)
:從列表中移除nodeName
屬性等于name
的節(jié)點(diǎn) -
setNamedItem(node)
:向列表中添加節(jié)點(diǎn)既忆,以節(jié)點(diǎn)的nodeName
屬性為索引 -
item(pos)
:返回位于數(shù)字pos
位置處的節(jié)點(diǎn)
attributes
屬性中包含一系列節(jié)點(diǎn),每個(gè)節(jié)點(diǎn)的nodeName
就是特性的名稱嗦玖,而節(jié)點(diǎn)nodeValue
就是特性的值患雇。
var id = element.attributes.getNamedItem('id').nodeValue;
// 簡(jiǎn)寫
var id = element.attributes['id'].nodeValue;
創(chuàng)建元素
document.createElement()
方法可以創(chuàng)建新元素,這個(gè)方法接受一個(gè)參數(shù)(標(biāo)簽名)
var div = document.createElement('div');
Text類型
文本節(jié)點(diǎn)由Text
類型表示宇挫,包含的是可以照字面解釋的純文本內(nèi)容苛吱。純文本中可以包含轉(zhuǎn)義后的HTML字符,但不能包含HTML代碼器瘪。
-
nodeType
的值為3 -
nodeName
的值為#text
-
nodeValue
的值為節(jié)點(diǎn)所包含的文本 -
parentNode
是一個(gè)Element
操作節(jié)點(diǎn)中的文本:
-
appendData(text)
:將text
添加到節(jié)點(diǎn)的末尾 -
deleteData(offset, count)
:從offset
指定的位置開始刪除count
個(gè)字符 -
insertData(offset, text)
:在offset
指定的位置插入text
-
replaceData(offset, count, text)
:用text
替換從offset
指定的位置開始到offset+count
為止的文本 -
splitText(offset)
:從offset
指定的位置將當(dāng)前文本分成兩個(gè)文本節(jié)點(diǎn) -
substringData(offset, count)
:提取從offset
指定的位置開始到offset+count
為止處的字符串翠储。
在向DOM文檔中插入文本之前,應(yīng)該先對(duì)其進(jìn)行HTML
編碼
創(chuàng)建文本節(jié)點(diǎn)
document.createTextNode()
var textNode = document.createTextNode("<strong>Hello</strong> world!");
DOM 操作技術(shù)
使用函數(shù)實(shí)現(xiàn)加載外部JS
文件
function loadScript(url) {
var script = document.createElement('script');
script.type = 'text/javascript';
script.src = url;
document.body.appendChild(script);
}
loadScirpt('xx.js');
IE將<script>
視為一個(gè)特殊的元素橡疼,不允許DOM訪問其子節(jié)點(diǎn)援所。不過可以使用<script>
元素的text
屬性指定JS
代碼。
操作表格
// create table
var table = document.createElement('table');
table.border = 1;
table.width = '100%';
// create tbody
var tbody = document.createElement('tbody');
table.appendChild(tbody);
// create row1
var row1 = document.createElement('tr');
tbody.appendChild(row1);
var cell1_1 = document.createElement('td');
cell1_1.appendChild(document.createTextNode('Cell 1,1'));
row1.appendChild(cell1_1);
var cell2_1 = document.createElement('td');
cell2_1.appendChild(document.createTextNode('Cell 2,1'));
row1.appendChild(cell2_1);
// create row2
var row2 = document.createElement('tr');
tbody.appendChild(row2);
var cell1_2 = document.createElement('td');
cell1_2.appendChild(document.createTextNode('Cell 1,2'));
row1.appendChild(cell1_2);
var cell2_2 = document.createElement('td');
cell2_2.appendChild(document.createTextNode('Cell 2,2'));
row1.appendChild(cell2_2);
document.body.appendChild(table);
DOM 擴(kuò)展
選擇符 API
-
querySelector()
方法
querySelector()
方法接受一個(gè)CSS選擇符衰齐,返回與該模式匹配的第一個(gè)元素任斋,若沒有,返回null
耻涛。
可以通過Document
類型調(diào)用废酷,也可以通過Element
類型調(diào)用,后者只會(huì)在該元素后代元素的范圍內(nèi)查找匹配的元素抹缕。
-
querySelectorAll()
方法
querySelectorAll()
方法返回的是所有匹配的元素澈蟆,是一個(gè)NodeList
實(shí)例。
-
matchesSelector()
方法
為Element
類型新增的一個(gè)方法卓研,接受一個(gè)參數(shù)CSS
選擇符趴俘,如果調(diào)用元素與該選擇符匹配睹簇,返回true
,否則返回false
寥闪。
元素遍歷
-
childElementCount
:返回子元素(不包含文本節(jié)點(diǎn)和注釋)的個(gè)數(shù) -
firstElementChild
:指向第一個(gè)子元素 -
lastElementChild
:指向最后一個(gè)子元素 -
previousElementSibling
:指向前一個(gè)兄弟元素 -
nextElementSibling
:指向后一個(gè)兄弟元素
不同于前面的返回節(jié)點(diǎn)的方法太惠。
// 節(jié)點(diǎn)版本
var i,
len,
child = element.firstChild;
while(child != element.lastChild){
if (child.nodeType == 1){ //檢查是不是元素
processChild(child);
}
child = child.nextSibling;
}
// 元素版本
var i,
len,
child = element.firstElementChild;
while(child != element.lastElementChild){
processChild(child); //已知其是元素
child = child.nextElementSibling;
}
HTML5
-
getElementsByClassName()
方法 -
classList
屬性,這個(gè)屬性是新集合類型DOMTokenList
的實(shí)例疲憋。add(value)
contains(value)
remove(value)
toggle(value)
div.classList.remove("user");
焦點(diǎn)管理
document.activeElement
屬性凿渊,始終會(huì)引用DOM中前端獲得了焦點(diǎn)的元素。
var button = document.getElementById("myButton");
button.focus();
alert(document.activeElement === button); //true
document.hasFocus()
方法缚柳,可以確定文檔是否獲得了焦點(diǎn)埃脏。
var button = document.getElementById("myButton");
button.focus();
alert(document.hasFocus()); //true
HTMLDocument
的變化
+ `readyState`屬性有兩個(gè)值,`loading`和`complete`
if (document.readyState == 'complete') {
// 加載完成
}
document.charset
字符集屬性
data-
自定義數(shù)據(jù)屬性
<div id="myDiv" data-appId="12345" data-myname="Nicholas"></div>
var div = document.getElementById("myDiv");
//取得自定義屬性的值
var appId = div.dataset.appId;
var myName = div.dataset.myname;
//設(shè)置值
div.dataset.appId = 23456;
div.dataset.myname = "Michael";
innerHTML
屬性
在讀模式下秋忙,innerHTML
屬性返回與調(diào)用元素的所有子節(jié)點(diǎn)(包括元素彩掐、注釋和文本節(jié)點(diǎn))對(duì)應(yīng)
的HTML 標(biāo)記。在寫模式下灰追,innerHTML
會(huì)根據(jù)指定的值創(chuàng)建新的DOM樹堵幽,然后用這個(gè)DOM樹完全
替換調(diào)用元素原先的所有子節(jié)點(diǎn)
outerHTML
屬性
在讀模式下,outerHTML
返回調(diào)用它的元素及所有子節(jié)點(diǎn)的HTML 標(biāo)簽监嗜。在寫模式下谐檀,outerHTML
會(huì)根據(jù)指定的HTML 字符串創(chuàng)建新的DOM 子樹,然后用這個(gè)DOM子樹完全替換調(diào)用元素裁奇。
insertAdjacentHTML()
方法
插入元素的新增方法桐猬,接受兩個(gè)參數(shù),插入的位置和要插入的HTML文本刽肠,第一個(gè)參數(shù)的值:
'beforebegin'
'afterbegin'
'beforeend'
'afterend'
//作為前一個(gè)同輩元素插入
element.insertAdjacentHTML("beforebegin", "<p>Hello world!</p>");
//作為第一個(gè)子元素插入
element.insertAdjacentHTML("afterbegin", "<p>Hello world!</p>");
//作為最后一個(gè)子元素插入
element.insertAdjacentHTML("beforeend", "<p>Hello world!</p>");
//作為后一個(gè)同輩元素插入
element.insertAdjacentHTML("afterend", "<p>Hello world!</p>");
scrollIntoView()
方法
scrollIntoView
方法可以在所有HTML元素上調(diào)用溃肪,通過滾動(dòng)瀏覽器窗口或某個(gè)容器元素,調(diào)用元素就可以出現(xiàn)在視口中音五。如果這個(gè)方法傳入true
作為參數(shù)惫撰,或者不傳參數(shù),那么窗口滾動(dòng)之后就會(huì)讓調(diào)用元素的頂部與視口頂部 盡可能平齊躺涝,如果傳入false
厨钻,調(diào)用元素會(huì)盡可能全部出現(xiàn)在視口中,不過頂部不一定平齊坚嗜。
// 讓元素可見
document.form[0].scrollIntoView();
專有擴(kuò)展
插入文本
-
innerText
屬性 -
outerText
屬性
滾動(dòng)
-
scrollIntoViewIfNeeded(alignCenter)
:只有在當(dāng)前元素不可見的情況下夯膀,才滾動(dòng)瀏覽器或窗口或容器元素最終讓它可見。如果當(dāng)前元素在視口中可見苍蔬,這個(gè)方法什么也不做诱建。 -
scrollByLines(lineCount)
:將元素的內(nèi)容滾動(dòng)指定的行高,lineCount
值可以是正值碟绑,也可以是負(fù)值俺猿。 -
scrollByPages(pageCount)
:將元素的內(nèi)容滾動(dòng)指定的頁面高度茎匠,具體高度由元素的高度決定。
scrollIntoView()
和scrollIntoViewIfNeeded()
的作用對(duì)象是元素的容器押袍,而scrollByLines()
和scrollByPages()
影響的則是元素自身诵冒。
//在當(dāng)前元素不可見的時(shí)候,讓它進(jìn)入瀏覽器的視口
document.images[0].scrollIntoViewIfNeeded();
//將頁面主體往回滾動(dòng)1 頁
document.body.scrollByPages(-1);
DOM2 和 DOM3
樣式
元素大小
偏移量
-
offsetHeight
:元素在垂直方向上占用的空間大小谊惭。包括元素的高度造烁,(可見的)水平滾動(dòng)條的高度,上邊框高度和下邊框高度 -
offsetWidth
:元素在水平方向上占用的空間大小午笛。包括元素的寬度,(可見的)垂直滾動(dòng)條的寬度苗桂,左邊框?qū)挾群陀疫吙驅(qū)挾?/li> -
offsetLeft
:元素的左外邊框至包含元素的左內(nèi)邊框之間的像素距離药磺。 -
offsetTop
:元素的上外邊框至包含元素的上內(nèi)邊框之間的像素距離。
其中煤伟,offsetLeft
和offsetTop
屬性與包含元素有關(guān)癌佩,包含元素的引用保存在offsetParent
屬性中。offsetParent
屬性不一定與parentNode
的值相等便锨。
// 元素上偏移
function getElementLeft (ele) {
var actualLeft = ele.offsetLeft;
var current = ele.offsetParent;
while (current !== null) {
actualLeft += current.offsetLeft;
current = current.offsetParent;
}
return actualLeft;
}
// 元素左偏移同理
一般來說围辙,頁面中所有的元素都被包含在幾個(gè)<div>
元素中,而這些<div>
元素的offsetParent
又是<body>
元素放案,所以getElementLeft()
與getElementTop()
會(huì)返回與offsetLeft
和offsetTop
相同的值姚建。
客戶區(qū)大小
-
clientWidth
:元素內(nèi)容區(qū)寬度加上左右內(nèi)邊距寬度 -
clientHeight
: 元素內(nèi)容區(qū)高度加上上下內(nèi)邊距高度
function getViewport(){
if (document.compatMode == "BackCompat"){ // IE7之前
return {
width: document.body.clientWidth,
height: document.body.clientHeight
};
} else {
return {
width: document.documentElement.clientWidth,
height: document.documentElement.clientHeight
};
}
}
滾動(dòng)大小
滾動(dòng)大小,指的是包含滾動(dòng)內(nèi)容的元素的大小吱殉。有些元素(<html>
)掸冤,即使沒有執(zhí)行任何代碼也能自動(dòng)添加滾動(dòng)條;但另外一些元素友雳,則需要通過CSS的overflow
屬性設(shè)置才能滾動(dòng)稿湿。
-
scrollHeight
:在沒有滾動(dòng)條的情況下,元素內(nèi)容的總高度 -
scrollWidth
:在沒有滾動(dòng)條的情況下押赊,元素內(nèi)容的總寬度 -
scrollLeft
:被隱藏在內(nèi)容區(qū)域左側(cè)的像素?cái)?shù)饺藤,通過設(shè)置這個(gè)屬性可以改變?cè)氐臐L動(dòng)位置 -
scrollTop
:被隱藏在內(nèi)容區(qū)域上方的像素?cái)?shù),通過設(shè)置這個(gè)屬性可以改變?cè)氐臐L動(dòng)位置
scrollWidth
和scrollHeight
主要用于確定元素內(nèi)容的實(shí)際大小流礁。
scrollWidth
和scrollHeight
與clientWidth
和clientHeight
之間的關(guān)系涕俗?
- Firefox中這兩組屬性始終相等,但大小代表的是文檔內(nèi)容區(qū)域的實(shí)際尺寸崇棠,非視口尺寸
-
Opera Safari Chrome中這兩組屬性有區(qū)別咽袜,其中
scrollWidth
和scrollHeight
等于視口大小,而clientWidth
和clientHeight
等于文檔內(nèi)容區(qū)域的大小枕稀。 -
IE(在標(biāo)準(zhǔn)模式)中的這兩組屬性不相等询刹,其中
scrollWidth
和scrollHeight
等于文檔內(nèi)容區(qū)域的大小谜嫉,而clientWidth
和clientHeight
等于視口大小。
通過scrollLeft
和scrollTop
屬性既可以確定元素當(dāng)前滾動(dòng)的狀態(tài)凹联,也可以設(shè)置元素的滾動(dòng)位置沐兰。在元素尚未被滾動(dòng)時(shí),這兩個(gè)屬性的值都等于0蔽挠。如果元素被垂直滾動(dòng)了住闯,那么scrollTop
的值會(huì)大于0,且表示元素上方不可見內(nèi)容的像素高度澳淑。如果元素被水平滾動(dòng)了比原,那么scrollLeft
的值會(huì)大于0,且表示元素左側(cè)不可見內(nèi)容的像素寬度杠巡。這兩個(gè)屬性都是可以設(shè)置的量窘,因此將元素的scrollLeft
和scrollTop
設(shè)置為0,就可以重置元素的滾動(dòng)位置氢拥。下面這個(gè)函數(shù)會(huì)檢測(cè)元素是否位于頂部蚌铜,如果不是就將其回滾到頂部。
function scrollToTop(element){
if (element.scrollTop != 0){
element.scrollTop = 0;
}
}
確定元素大小
-
getBoundingClientRect()
方法嫩海,會(huì)返回一個(gè)矩形對(duì)象冬殃,包含left top right bottom
四個(gè)屬性。這些屬性給出了元素在頁面中相對(duì)于視口的位置叁怪。
遍歷
NodeIterator
可以使用document.createNodeIterator()
方法創(chuàng)建它的新實(shí)例审葬,接受4個(gè)參數(shù)。
-
root
:想要作為搜索起點(diǎn)的樹中的節(jié)點(diǎn) -
whatToShow
:表示要訪問哪些節(jié)點(diǎn)的數(shù)字代碼 -
filter
:是一個(gè)NodeFilter
對(duì)象骂束,或者一個(gè)表示應(yīng)該接受還是拒絕某種特定節(jié)點(diǎn)的函數(shù) -
entityReferenceExpansion
:布爾值耳璧,表示是否要擴(kuò)展實(shí)體引用。
whatToShow
這個(gè)參數(shù)的值以常量形式在NodeFilter
類型中定義:
NodeFilter.SHOW_ALL
NodeFilter.SHOW_ELEMENT
NodeFilter.SHOW_ATTRIBUTE
NodeFilter.SHOW_TEXT
NodeFilter.SHOW_CDATA_SECTION
NodeFilter.SHOW_ENTITY_REFERENCE
NodeFilter.SHOW_ENTITYE
NodeFilter.SHOW_PROCESSING_INSTRUCTION
NodeFilter.SHOW_COMMENT
NodeFilter.SHOW_DOCUMENT
NodeFilter.SHOW_DOCUMENT_TYPE
NodeFilter.SHOW_DOCUMENT_FRAGMENT
NodeFilter.SHOW_NOTATION