JS紅寶書·讀書筆記 -- 上篇

JavaScript 高級(jí)程序設(shè)計(jì)

個(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ì)象的變量值為nullundefinedfor-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ù)部励背,objperson 引用的是同一個(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è)額外的屬性:indexinput正什。其中,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)格模式下鸭蛙,callapply的第一個(gè)參數(shù)傳遞為nullundefined時(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)用RegExpexec()方法相同徐绑。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 5Object.defineProperty()方法依溯。這個(gè)方法接受三個(gè)參數(shù):屬性所在對(duì)象,屬性名和一個(gè)描述符對(duì)象瘟则。其中描述符對(duì)象的屬性值必須是:configurable黎炉、enumerablewritablevalue醋拧。設(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 5Object.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 5Object.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支持screenXscreenY师抄,其他瀏覽器均支持screenLeftscreenTop教硫。

但是還是需要注意一個(gè)問題:在IE Opera中叨吮,screenLeft screenTop 保存的的是可見區(qū)域的距離辆布,也就是我們?yōu)g覽器中不包含工具欄的區(qū)域與屏幕的距離;在Chrome茶鉴、FirefoxSafariscreenYscreenTop返回的是整個(gè)瀏覽器窗口相對(duì)于屏幕坐標(biāo)的值锋玲。

窗口大小

IE9+、Firefox涵叮、Safari惭蹂、Opera和Chrome均提供了4個(gè)屬性innerWidthinnerHeight割粮、outerWidthouterHeight盾碗。

  • IE9+、Safari和Firefox中舀瓢,outerWidthouterHeight返回瀏覽器窗口本身的尺寸廷雅,而innerWidthinnerHeight則表示該容器中頁面視圖區(qū)的大小(減去邊框?qū)挾龋?/li>
  • Chrome中京髓,inner*outer*返回相同的值航缀,即視口大小而非瀏覽器窗口的大小。
  • 在IE堰怨、Firefox芥玉、Safari、Opera和Chrome中诚些,都能通過document.documentElement.clientWidthdocument.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)绎签。使用previousSiblingnextSibling屬性,可以訪問其他兄弟節(jié)點(diǎn)酝锅。

:列表中第一個(gè)節(jié)點(diǎn)的previousSibling屬性值為null诡必,同理列表中最后一個(gè)節(jié)點(diǎn)的nextSibling屬性也是null。父節(jié)點(diǎn)的firstChildlastChild屬性分別指向其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的話爷光,insertBeforeappendChild執(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è))秉犹、ProcessingInstructionComment
// 通過`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可能是DocumentElement
  • 其子節(jié)點(diǎn)可能是Element崇堵、TextComment客燕、ProcessingInstruction鸳劳、CDATASectionEntityReference

訪問元素的標(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)邊框之間的像素距離。

其中煤伟,offsetLeftoffsetTop屬性與包含元素有關(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ì)返回與offsetLeftoffsetTop相同的值姚建。

客戶區(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)條;但另外一些元素友雳,則需要通過CSSoverflow屬性設(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)位置

scrollWidthscrollHeight主要用于確定元素內(nèi)容的實(shí)際大小流礁。

scrollWidthscrollHeightclientWidthclientHeight 之間的關(guān)系涕俗?

  • Firefox中這兩組屬性始終相等,但大小代表的是文檔內(nèi)容區(qū)域的實(shí)際尺寸崇棠,非視口尺寸
  • Opera Safari Chrome中這兩組屬性有區(qū)別咽袜,其中scrollWidthscrollHeight 等于視口大小,而clientWidthclientHeight 等于文檔內(nèi)容區(qū)域的大小枕稀。
  • IE(在標(biāo)準(zhǔn)模式)中的這兩組屬性不相等询刹,其中scrollWidthscrollHeight 等于文檔內(nèi)容區(qū)域的大小谜嫉,而clientWidthclientHeight 等于視口大小。

通過scrollLeftscrollTop 屬性既可以確定元素當(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è)置的量窘,因此將元素的scrollLeftscrollTop 設(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
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末展箱,一起剝皮案震驚了整個(gè)濱河市旨枯,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌混驰,老刑警劉巖攀隔,帶你破解...
    沈念sama閱讀 219,427評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異栖榨,居然都是意外死亡昆汹,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,551評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門婴栽,熙熙樓的掌柜王于貴愁眉苦臉地迎上來满粗,“玉大人,你說我怎么就攤上這事愚争∮辰裕” “怎么了挤聘?”我有些...
    開封第一講書人閱讀 165,747評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)捅彻。 經(jīng)常有香客問我组去,道長(zhǎng),這世上最難降的妖魔是什么步淹? 我笑而不...
    開封第一講書人閱讀 58,939評(píng)論 1 295
  • 正文 為了忘掉前任从隆,我火速辦了婚禮,結(jié)果婚禮上缭裆,老公的妹妹穿的比我還像新娘键闺。我一直安慰自己,他們只是感情好澈驼,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,955評(píng)論 6 392
  • 文/花漫 我一把揭開白布艾杏。 她就那樣靜靜地躺著,像睡著了一般盅藻。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上畅铭,一...
    開封第一講書人閱讀 51,737評(píng)論 1 305
  • 那天氏淑,我揣著相機(jī)與錄音,去河邊找鬼硕噩。 笑死假残,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的炉擅。 我是一名探鬼主播辉懒,決...
    沈念sama閱讀 40,448評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼谍失!你這毒婦竟也來了眶俩?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,352評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤快鱼,失蹤者是張志新(化名)和其女友劉穎颠印,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體抹竹,經(jīng)...
    沈念sama閱讀 45,834評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡线罕,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,992評(píng)論 3 338
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了窃判。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片钞楼。...
    茶點(diǎn)故事閱讀 40,133評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖袄琳,靈堂內(nèi)的尸體忽然破棺而出询件,到底是詐尸還是另有隱情燃乍,我是刑警寧澤,帶...
    沈念sama閱讀 35,815評(píng)論 5 346
  • 正文 年R本政府宣布雳殊,位于F島的核電站橘沥,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏夯秃。R本人自食惡果不足惜座咆,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,477評(píng)論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望仓洼。 院中可真熱鬧介陶,春花似錦、人聲如沸色建。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,022評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽箕戳。三九已至某残,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間陵吸,已是汗流浹背玻墅。 一陣腳步聲響...
    開封第一講書人閱讀 33,147評(píng)論 1 272
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留壮虫,地道東北人澳厢。 一個(gè)月前我還...
    沈念sama閱讀 48,398評(píng)論 3 373
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像囚似,于是被迫代替她去往敵國(guó)和親剩拢。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,077評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • 第5章 引用類型(返回首頁) 本章內(nèi)容 使用對(duì)象 創(chuàng)建并操作數(shù)組 理解基本的JavaScript類型 使用基本類型...
    大學(xué)一百閱讀 3,237評(píng)論 0 4
  • 最近小區(qū)社群里討論一件事:有個(gè)小區(qū)的一條狗因狗主人未拴住導(dǎo)致咬傷一個(gè)小孩,小區(qū)業(yè)主一氣之下也把狗主人打傷的事募狂,譴責(zé)...
    享讀光陰閱讀 288評(píng)論 0 1
  • author:圣·昂浅浚克蘇佩里 (Saint-Exupery) 久聞大名的一本書,看完之后確實(shí)沒看懂的一本書熬尺。 書中...
    robotor閱讀 400評(píng)論 1 1
  • 1摸屠、 五月,我和小伙伴們?cè)邳S海和渤海灣里盡情地游玩粱哼。這時(shí)的海里季二,不冷不熱,魚蝦豐富,正適合我的胃口胯舷。 我叫歡歡刻蚯,是...
    春山雨閱讀 478評(píng)論 13 5