上書房之JavaScript(Part2)

第十章 變量、作用域及內(nèi)存

JavaScript的變量與其他語言的變量有很大區(qū)別。JavaScript變量是松散型的(不強(qiáng)制類型),決定了它只是在特定時(shí)間用于保存特定值的一個(gè)名字而已订咸。由于不存在定義某個(gè)變量必須要保存何種數(shù)據(jù)類型值的規(guī)則,變量的值及其數(shù)據(jù)類型可以在腳本的生命周期內(nèi)改變酬诀。

10.1 變量及作用域

(1) 值類型和引用類型
JavaScript的變量包括兩種類型脏嚷,即值類型和引用類型。
值類型:值類型指的是那些保存在內(nèi)存中的簡(jiǎn)單數(shù)據(jù)段瞒御,即這種值完全保存在內(nèi)存中的一個(gè)位置父叙。
引用類型:引用類型值則是指那些保存在內(nèi)存中的對(duì)象,意思是變量中保存的實(shí)際上只是一個(gè)指針,這個(gè)指針指向內(nèi)存中的另一個(gè)位置趾唱,該位置保存對(duì)象涌乳。
將一個(gè)值賦給變量時(shí),解析器必須確定這個(gè)值是值類型甜癞,還是引用類型值夕晓。值類型有以下幾種:Undefined、Null带欢、Boolean运授、Number和String。這些類型在內(nèi)存中分別占有固定大小的空間乔煞,他們的值保存在椨蹼空間,我們是通過按值訪問的渡贾。(在某些語言中逗宜,字符串以對(duì)象的形式來表示,因此被認(rèn)為是引用類型空骚。JavaScript放棄這一傳統(tǒng)纺讲。)
如果賦值的是引用類型的值,則必須在堆內(nèi)存中為這個(gè)值分配空間囤屹。由于這種值的大小不固定熬甚,因此不能把它們保存到棧內(nèi)存中。但內(nèi)存地址大小是固定的肋坚,因此可以將內(nèi)存地址保存在棧內(nèi)存中乡括。這樣,當(dāng)查詢引用類型的變量時(shí)智厌,先從棧中讀取內(nèi)存地址诲泌,然后再通過地址找到堆中的值。對(duì)于這種铣鹏,我們把它叫做按引用訪問敷扫。

值類型引用類型

(2) 動(dòng)態(tài)屬性
定義基本類型值和引用類型值的方式是相似的:創(chuàng)建一個(gè)變量并為該變量賦值。但是诚卸,當(dāng)這個(gè)值保存到變量中以后葵第,對(duì)不同類型值可以執(zhí)行的操作則大相徑庭。

<script>
  //定義一個(gè)對(duì)象合溺,即引用類型
  var car = new Object();
  car.brand = "Mercedes Benz";
  alert(car.brand);
  
  //定義一個(gè)字符串變量羹幸,即值類型
  var cellPhone = "iphone6";
  cellPhone.color = "Gold";
  alert(cellPhone.color);
</script>

(3) 變量復(fù)制
在變量復(fù)制方面,值類型和引用類型也有所不同辫愉。值類型復(fù)制的是值本身,而引用類型復(fù)制的是地址将硝。

//值類型復(fù)制
var car1 = "Mercedes Benz"; //在棧內(nèi)存生成一個(gè)car1的變量恭朗,保存的值為 'Mercedes Benz'
var car2 = car1;    //在棧內(nèi)存再生成一個(gè)car2的變量屏镊,保存的值也是 'Mercedes Benz'
變量復(fù)制

car2是雖然是car1的一個(gè)副本,但從圖示可以看出痰腮,它是完全獨(dú)立的而芥。也就是說,兩個(gè)變量分別操作時(shí)互不影響膀值。

//引用類型復(fù)制
var car1 = new Object();
car.brand = "Mercedes Benz";
var car2 = car1;
car2.brand = "BMW";
alert(car1.brand);
變量復(fù)制

引用類型中棍丐,car2其實(shí)就是car1,因?yàn)樗麄冎赶虻氖峭粋€(gè)對(duì)象沧踏。如果這個(gè)對(duì)象中的name屬性被修改了歌逢,car2.name和car1.name輸出的值都會(huì)被相應(yīng)修改掉了。
(4) 傳遞參數(shù)
JavaScript中所有函數(shù)的參數(shù)都是按值傳遞的翘狱,言下之意就是說秘案,參數(shù)不會(huì)按引用傳遞,雖然變量有基本類型和引用類型之分潦匈。

<script>
  function sum(num){    //按值傳遞阱高,傳遞的參數(shù)是基本類型
    num += 10;      //這里的num是局部變量
    return num;
  }
  
  var num = 10;
  var result = sum(num);
  alert(result);
  alert(num);
</script>

以上的代碼中,傳遞的參數(shù)是一個(gè)值類型茬缩。而函數(shù)里的num是一個(gè)局部變量赤惊,和外面的num沒有任何聯(lián)系癞尚。

<script>
  function setName(obj){    //按值傳遞旋恼,傳遞的參數(shù)是引用類型
    obj.name = "馬云";
    var obj = new Object();
    obj.name = "劉強(qiáng)東";
  }
  
  var obj = new Object();
  setName(obj);
  alert(obj.name);  //馬云
</script>

(5) 檢測(cè)類型
要檢測(cè)一個(gè)變量的類型,我們可以通過typeof運(yùn)算符來判別蛋欣。諸如:

<script>
  var name = "Johnny";
  alert(typeof name);
</script>

雖然typeof運(yùn)算符在檢查值類型的數(shù)據(jù)的時(shí)候非常好用寡夹,但檢測(cè)引用類型的時(shí)候处面,它就不是那么好用了。通常菩掏,我們并不想知道它是不是對(duì)象魂角,而是想知道它到底是什么類型的對(duì)象。因?yàn)閿?shù)組也是object智绸,null也是Object等等野揪。對(duì)于引用類型的檢測(cè),當(dāng)需要知道這個(gè)引用類型具體是什么對(duì)象的時(shí)候瞧栗,應(yīng)該使用instanceof運(yùn)算符斯稳。

<script>
  var obj1 = [1,2,3];
  alert(obj1 instanceof Array); //是否是數(shù)組
  var obj2 = {};
  alert(obj2 instanceof Object);    //是否是對(duì)象
  var obj3 = new String('Lee');
  alert(obj3 instanceof String);    //是否是字符串對(duì)象
</script>

注意:當(dāng)使用instanceof檢查基本類型的值時(shí),它會(huì)返回false迹恐。
(6) 執(zhí)行環(huán)境及作用域
執(zhí)行環(huán)境是JavaScript中最為重要的一個(gè)概念挣惰。執(zhí)行環(huán)境定義了變量或函數(shù)有權(quán)訪問的其他數(shù)據(jù),決定了它們各自的行為。
(1) 全局執(zhí)行環(huán)境(全局作用域)
全局執(zhí)行環(huán)境是最外圍的執(zhí)行環(huán)境憎茂。在Web瀏覽器中珍语,全局執(zhí)行環(huán)境被認(rèn)為是window對(duì)象。因此所有的全局變量和函數(shù)都是作為window對(duì)象的屬性和方法創(chuàng)建的竖幔。全局的變量和函數(shù)板乙,都是window對(duì)象的屬性和方法。

  var color = "blue";
  function showColor(){
    alert(color);
  }
  showColor();

  var color = "blue";
  function showColor(){
    alert(window.color);
  }
  
  window.showColor();

當(dāng)執(zhí)行環(huán)境中的所有代碼執(zhí)行完畢后拳氢,該環(huán)境被銷毀募逞,保存在其中的所有變量和函數(shù)定義也隨之銷毀。如果是全局環(huán)境下馋评,需要程序執(zhí)行完畢放接,或者網(wǎng)頁(yè)被關(guān)閉才會(huì)銷毀。
(2) 局部執(zhí)行環(huán)境(局部作用域)
函數(shù)里的局部作用域里的變量替換全局變量栗恩,但作用域僅限在函數(shù)體內(nèi)這個(gè)局部環(huán)境透乾。

<script>
  var color = "blue"; //全局變量
  function setColor(color){
    color = color; //局部變量
    alert(color);
  }
  setColor("red");
  alert(color);
</script>

(7) 沒有塊及作用域
塊級(jí)作用域表示諸如if語句等有花括號(hào)封閉的代碼塊,所以磕秤,支持條件判斷來定義變量乳乌。

<script>
  if (true) { //if語句代碼塊沒有局部作用域
    var color = 'red';
  }
  alert(color);

  for (var i = 0; i < 10; i ++){  //沒有局部作用域
    var fullName = 'Johnny';
  }
  alert(i);
  alert(fullName);
</script>

<script>
  var color = "red";
  function sum(num1, num2){
    var num = num1 + num2;
    return num;
  }
  
  sum(1, 2);
  alert(num); //報(bào)錯(cuò) num is not defined
</script>

注意:定義及初始化變量的時(shí)候一定要加上var。

10.2 內(nèi)存管理

JavaScript具有自動(dòng)垃圾收集機(jī)制市咆,也就是說汉操,執(zhí)行環(huán)境會(huì)負(fù)責(zé)管理代碼執(zhí)行過程中使用的內(nèi)存。其他語言比如C和C++蒙兰,必須手工跟蹤內(nèi)存使用情況磷瘤,適時(shí)的釋放,否則會(huì)造成很多問題搜变。而JavaScript則不需要這樣采缚,它會(huì)自行管理內(nèi)存分配及無用內(nèi)存的回收。
JavaScript最常用的垃圾收集方式是標(biāo)記清除挠他。垃圾收集器會(huì)在運(yùn)行的時(shí)候給存儲(chǔ)在內(nèi)存中的變量加上標(biāo)記扳抽。然后,它會(huì)去掉環(huán)境中正在使用變量的標(biāo)記殖侵,而沒有被去掉標(biāo)記的變量將被視為準(zhǔn)備刪除的變量贸呢。最后,垃圾收集器完成內(nèi)存清理工作拢军,銷毀那些帶標(biāo)記的值并回收他們所占用的內(nèi)存空間楞陷。
垃圾收集器是周期性運(yùn)行的,這樣會(huì)導(dǎo)致整個(gè)程序的性能問題茉唉。比如IE7以前的版本固蛾,它的垃圾收集器是根據(jù)內(nèi)存分配量運(yùn)行的结执,比如256個(gè)變量就開始運(yùn)行垃圾收集器,這樣魏铅,就不得不頻繁地運(yùn)行昌犹,從而降低的性能。
一般來說览芳,確保占用最少的內(nèi)存可以讓頁(yè)面獲得更好的性能。那么優(yōu)化內(nèi)存的最佳方案鸿竖,就是一旦數(shù)據(jù)不再有用沧竟,那么將其設(shè)置為null來釋放引用,這個(gè)做法叫做解除引用缚忧。這一做法適用于大多數(shù)全局變量和全局對(duì)象悟泵。

第十一章 內(nèi)置對(duì)象

內(nèi)置對(duì)象的定義是:“由JavaScript實(shí)現(xiàn)提供的、不依賴宿主環(huán)境的對(duì)象闪水,這些對(duì)象在JavaScript程序執(zhí)行之前就已經(jīng)存在了糕非。”意思就是說球榆,開發(fā)人員不必顯示地實(shí)例化內(nèi)置對(duì)象朽肥;因?yàn)樗鼈円呀?jīng)實(shí)例化了。JavaScript只定義了兩個(gè)內(nèi)置對(duì)象:Global和Math持钉。

11.1 Global對(duì)象

Global(全局)對(duì)象是JavaScript中一個(gè)特別的對(duì)象衡招,因?yàn)檫@個(gè)對(duì)象是不存在的。在JavaScript中不屬于任何其他對(duì)象的屬性和方法每强,都屬于它的屬性和方法始腾。所以,事實(shí)上空执,并不存在全局變量和全局函數(shù)浪箭;所有在全局作用域定義的變量和函數(shù),都是Global對(duì)象的屬性和方法辨绊。
因?yàn)镴avaScript沒有定義怎么調(diào)用Global對(duì)象奶栖,所以,Global.屬性或者Global.方法()都是無效的邢羔。(Web瀏覽器將Global作為window對(duì)象的一部分加以實(shí)現(xiàn))
Global對(duì)象有一些內(nèi)置的屬性和方法:
(1) URI編碼方法
URI編碼可以對(duì)鏈接進(jìn)行編碼驼抹,以便發(fā)送給瀏覽器。它們采用特殊的UTF-8編碼替換所有無效字符拜鹤,從而讓瀏覽器能夠接受和理解框冀。
encodeURI()不會(huì)對(duì)本身屬于URI的特殊字符進(jìn)行編碼,例如冒號(hào)敏簿、正斜杠明也、問號(hào)和#號(hào)宣虾;而encodeURIComponent()則會(huì)對(duì)它發(fā)現(xiàn)的任何非標(biāo)準(zhǔn)字符進(jìn)行編碼。

<script>
  var parm = "http://Johnny 張";
  alert(encodeURI(parm)); //Johnny%20%E5%BC%A0
  alert(encodeURIComponent(parm)); //%2F%2FJohnny%20%E5%BC%A0
</script>

因?yàn)閑ncodeURIComponent()編碼比encodeURI()編碼來的更加徹底温数,一般來說encodeURIComponent()使用頻率要高一些绣硝。
使用了URI編碼過后,還可以進(jìn)行解碼撑刺,通過decodeURI()和decodeURIComponent()來進(jìn)行解碼鹉胖。

<script>
  var parm = "http://Johnny 張";
  var encode1 = encodeURI(parm);
  var encode2 = encodeURIComponent(parm);
  var decode1 = decodeURI(encode1);
  var decode2 = decodeURIComponent(encode2);
  alert(encode1); //Johnny%20%E5%BC%A0
  alert(encode2); //%2F%2FJohnny%20%E5%BC%A0
  alert(decode1);
  alert(decode1);
</script>

(2) eval()方法
eval()方法主要擔(dān)當(dāng)一個(gè)字符串解析器的作用,他只接受一個(gè)參數(shù)够傍,而這個(gè)參數(shù)就是要執(zhí)行的JavaScript代碼的字符串甫菠。

<script>
  eval('var num = 100'); //解析了字符串代碼
  alert(num);
  eval('alert(100)'); //同上
  
  eval('function num() {return 123}'); //函數(shù)也可以
  alert(num());
</script>

eval()方法的功能非常強(qiáng)大,但也非常危險(xiǎn)冕屯。因此使用的時(shí)候必須極為謹(jǐn)慎寂诱。特別是在用戶輸入數(shù)據(jù)的情況下,非常有可能導(dǎo)致程序的安全性安聘,比如代碼注入等等痰洒。
(3) Global對(duì)象屬性
Global對(duì)象包含了一些屬性:undefined、NaN浴韭、Object丘喻、Array、Function等等囱桨。
(4) window對(duì)象
Global沒有辦法直接訪問仓犬,而Web瀏覽器可以使用window對(duì)象來實(shí)現(xiàn)全局訪問。

11.2 Math對(duì)象

JavaScript還為保存數(shù)學(xué)公式和信息提供了一個(gè)對(duì)象舍肠,即Math對(duì)象搀继。與我們?cè)贘avaScript直接編寫計(jì)算功能相比,Math對(duì)象提供的計(jì)算功能執(zhí)行起來要快得多翠语。
(1) Math對(duì)象的屬性
Math對(duì)象包含的屬性大多是數(shù)學(xué)計(jì)算中可能會(huì)用到的一些特殊值叽躯。

屬性 說明
Math.E 自然對(duì)數(shù)的底數(shù),即常量e的值
Math.LN10 10的自然對(duì)數(shù)
Math.LN2 2的自然對(duì)數(shù)
Math.LOG2E 以2為底e的對(duì)數(shù)
Math.LOG10E 以10為底e的對(duì)數(shù)
Math.PI PI的值
Math.SQRT1_2 1/2的平方根
Math.SQRT2 2的平方根

(2) min()和max()方法
Math.min()用于確定一組數(shù)值中的最小值肌括。Math.max()用于確定一組數(shù)值中的最大值点骑。
(3) 舍入方法
Math.ceil()執(zhí)行向上舍入,即它總是將數(shù)值向上舍入為最接近的整數(shù)谍夭。
Math.floor()執(zhí)行向下舍入黑滴,即它總是將數(shù)值向下舍入為最接近的整數(shù)。
Math.round()執(zhí)行標(biāo)準(zhǔn)舍入紧索,即它總是將數(shù)值四舍五入為最接近的整數(shù)袁辈。

<script>
  alert(Math.ceil(25.9)); //26
  alert(Math.ceil(25.5)); //26
  alert(Math.ceil(25.1)); //26
  
  alert(Math.floor(25.9)); //25
  alert(Math.floor(25.5)); //25
  alert(Math.floor(25.1)); //25
  
  alert(Math.round(25.9)); //26
  alert(Math.round(25.5)); //26
  alert(Math.round(25.1)); //25
</script>

(4) random()方法
Math.random()方法返回介于0到1之間一個(gè)隨機(jī)數(shù),不包括0和1珠漂。如果想大于這個(gè)范圍的話晚缩,可以套用一下公式:
值 = Math.floor(Math.random() * 總數(shù) + 第一個(gè)值)

<script>
  alert(Math.floor(Math.random() * 10 + 1)); //隨機(jī)產(chǎn)生1-10之間的任意數(shù)
</script>

(5) 其他方法

方法 說明
Math.abs(num) 返回num的絕對(duì)值
Math.exp(num) 返回Math.E的num次冪
Math.log(num) 返回num的自然對(duì)數(shù)
Math.pow(num,power) 返回num的power次冪
Math.sqrt(num) 返回num的平方根
Math.acos(x) 返回x的反余弦值
Math.asin(x) 返回x的反正弦值
Math.atan(x) 返回x的反正切值
Math.atan2(y,x) 返回y/x的反正切值
Math.cos(x) 返回x的余弦值
Math.sin(x) 返回x的正弦值
Math.tan(x) 返回x的正切值

第十二章 面向?qū)ο笈c原型

12.1 創(chuàng)建對(duì)象

12.1.1 new Object()

創(chuàng)建Object對(duì)象尾膊,然后給這個(gè)對(duì)象新建屬性和方法。

<script>
  var car = new Object();           //創(chuàng)建一個(gè)Object對(duì)象
  car.brand = "Mercedes-Benz";  //創(chuàng)建一個(gè)brand屬性并賦值
  car.model = "E260L";  
  car.color = "White";
  car.drive = function(){           //創(chuàng)建一個(gè)drive()方法并返回值
    return this.brand + " " + this.model + " " + this.color + " is driving.";
  };
  
  alert(car.drive());   
</script>

存在的問題:
這個(gè)創(chuàng)建了一個(gè)“Mercedes-Benz”的對(duì)象荞彼,如果需要在創(chuàng)建一個(gè)“BMW”的對(duì)象冈敛,則類似的代碼還要在寫一遍,如果需要再創(chuàng)建其他品牌車的對(duì)象鸣皂,那么類似的代碼就要寫許多份抓谴。
解決辦法:
使用工廠模式創(chuàng)建對(duì)象。

12.1.2 工廠模式

為了解決多個(gè)類似對(duì)象聲明的問題寞缝,我們可以使用一種叫做工廠模式的方法齐邦,這種方法就是為了解決實(shí)例化對(duì)象產(chǎn)生大量重復(fù)代碼的問題。

<script>
  function createCarObject(brand, model, color){  //集中實(shí)例化的函數(shù)
    var car = new Object();
    car.brand = brand;
    car.model = model;
    car.color = color;
    car.drive = function(){
      return this.brand + " " + this.model + " " + this.color + " is driving.";
    };
    return car;
  }
  
  var car1 = createCarObject("Mercedes-Benz", "E260L", "white");
  var car2 = createCarObject("Mercedes-Benz", "GLC260", "white");
  var car3 = createCarObject("BMW", "X5", "Red");
  alert(car1.drive());
  alert(car2.drive());
  alert(car3.drive());
</script>

存在的問題:
工廠模式解決了實(shí)例化代碼重復(fù)的問題第租,但還有一個(gè)問題,那就是識(shí)別問題我纪,因?yàn)楦緹o法搞清楚他們到底是哪個(gè)對(duì)象的實(shí)例慎宾。

<script>
  function createCarObject(brand, model, color){    //集中實(shí)例化的函數(shù)
    var car = new Object();
    car.brand = brand;
    car.model = model;
    car.color = color;
    car.drive = function(){
      return this.brand + " " + this.model + " " + this.color + " is driving.";
    };
    return car;
  }
  
  var car1 = createCarObject("Mercedes-Benz", "E260L", "white");
  var car2 = createCarObject("Mercedes-Benz", "GLC260", "white");
  var car3 = createCarObject("BMW", "X5", "Red");
  alert(typeof car1);
  alert(car1 instanceof Object);
  alert(typeof car2);
  alert(car2 instanceof Object);
  alert(typeof car3);
  alert(car3 instanceof Object);
</script>

解決辦法:
采用構(gòu)造函數(shù)可用來創(chuàng)建特定的對(duì)象

12.1.3 構(gòu)造函數(shù)

使用構(gòu)造函數(shù)的方法,即解決了實(shí)例化代碼重復(fù)的問題浅悉,又解決了對(duì)象識(shí)別的問題趟据。

<script>
  function Car(brand, model, color){    //構(gòu)造函數(shù)模式
    this.brand = brand;
    this.model = model;
    this.color = color;
    this.drive = function(){
      return this.brand + " " + this.model + " " + this.color + " is driving.";
    };
  }
  
  var car1 = new Car("Mercedes-Benz", "E260L", "white");
  alert(car1.drive());
  alert(typeof car1);
  alert(car1 instanceof Car);
  var car2 = new Car("Mercedes-Benz", "GLC260", "white");
  alert(car2.drive());
  alert(typeof car2);
  alert(car2 instanceof Car);
  var car3 = new Car("BMW", "X5", "Red");
  alert(car3.drive());
  alert(typeof car3);
  alert(car3 instanceof Car);
</script>

使用了構(gòu)造函數(shù)的方法,和使用工廠模式的方法的不同之處如下:
(1) 構(gòu)造函數(shù)方法沒有顯示的創(chuàng)建對(duì)象(new Object())术健;
(2) 直接將屬性和方法賦值給this對(duì)象汹碱;
(3) 沒有return語句。
構(gòu)造函數(shù)的方法有一些規(guī)范:
(1) 函數(shù)名和實(shí)例化構(gòu)造名相同且大寫荞估;
(2) 通過構(gòu)造函數(shù)創(chuàng)建對(duì)象咳促,必須使用new運(yùn)算符。
構(gòu)造函數(shù)和普通函數(shù)的唯一區(qū)別勘伺,就是他們調(diào)用方式不同跪腹。只不過,構(gòu)造函數(shù)也是函數(shù)飞醉,必須用new運(yùn)算符來調(diào)用冲茸,否則就是普通函數(shù)。

<script>
  function Car(brand, model, color){    //集中實(shí)例化的函數(shù)
    this.brand = brand;
    this.model = model;
    this.color = color;
    this.drive = function(){
      return this.brand + " " + this.model + " " + this.color + " is driving.";
    };
  }
  
  function sayHello(fullName){
    return "Hello " + fullName;
  }
  var car1 = new Car("Mercedes-Benz", "E260L", "white");
  alert(car1.drive());
  alert(sayHello("Johnny"));
</script>

探討構(gòu)造函數(shù)內(nèi)部的方法(或函數(shù))的問題缅帘。

<script>
  function Car(brand, model, color){    //集中實(shí)例化的函數(shù)
    this.brand = brand;
    this.model = model;
    this.color = color;
    this.drive = function(){
      return this.brand + " " + this.model + " " + this.color + " is driving.";
    };
  }
  var car1 = new Car("Mercedes-Benz", "E260L", "white");
  var car2 = new Car("Mercedes-Benz", "GLC260", "white");
  alert(car1.brand === car2.brand); //true, 類型內(nèi)容均相等
  alert(car1.model === car2.model); //false, 類型相等內(nèi)容不等
  alert(car1.color === car2.color); //true, 類型內(nèi)容均相等
  alert(car1.drive === car2.drive); //false, 引用地址不相等
</script>

12.2 原型

我們創(chuàng)建的每個(gè)函數(shù)都有一個(gè)原型屬性(prototype)轴术,這個(gè)屬性是一個(gè)對(duì)象,它的用途是包含可以由特定類型的所有實(shí)例共享的屬性和方法钦无。使用原型的好處可以讓所有對(duì)象實(shí)例共享它所包含的屬性和方法逗栽。也就是說,不必在構(gòu)造函數(shù)中定義對(duì)象信息铃诬,而是可以直接將這些信息添加到原型中祭陷。

12.2.1 使用構(gòu)造函數(shù)創(chuàng)建原型對(duì)象

<script>
  //使用聲明構(gòu)造函數(shù)的方式苍凛,在原型中添加屬性和方法
  function SaloonCar(){}
  
  SaloonCar.prototype.carType = "家用型轎車";
  SaloonCar.prototype.drive = function(){
    return "Saloon car is driving.";
  };
  
  //在構(gòu)造函數(shù)中添加屬性和方法
  function Suv(brand, model){
    this.brand = brand;
    this.model = model;
    this.drive = function(){
      return this.brand + " " + this.model + " is driving.";
    };
  }
  
  var bora = new SaloonCar();
  var mazda = new SaloonCar();
  alert(bora.drive === mazda.drive); //true
  
  var bmwX5 = new Suv("BMW", "X5");
  var benzGlc = new Suv("Benz", "GLC260");
  alert(bmwX5.drive === benzGlc.drive); //false
</script>
構(gòu)造函數(shù)方式
原型方式

在原型模式聲明中,多了一個(gè)proto屬性兵志,這個(gè)屬性都是創(chuàng)建對(duì)象時(shí)自動(dòng)生成的醇蝴。proto屬性是實(shí)例指向原型對(duì)象的指針,它的作用就是指向構(gòu)造函數(shù)的原型屬性constructor想罕。通過這個(gè)屬性悠栓,就可以訪問到原型里的屬性和方法了。
說明:IE瀏覽器在腳本訪問proto會(huì)不能識(shí)別按价,火狐和谷歌瀏覽器及其他某些瀏覽器均能識(shí)別惭适。雖然可以輸出,但無法獲取內(nèi)部信息楼镐。
原型模式的執(zhí)行流程:
Step1:先查找構(gòu)造函數(shù)實(shí)例里的屬性或方法癞志,如果有,立刻返回框产;
Step2:如果構(gòu)造函數(shù)實(shí)例里沒有凄杯,則去它的原型對(duì)象里找,如果有秉宿,就返回戒突;
通過原型添加的值類型的屬性,其值不能被重寫:

    <script>
        //使用聲明構(gòu)造函數(shù)的方式描睦,在原型中添加屬性和方法
        function SaloonCar(){}
        
        SaloonCar.prototype.carType = "家用型轎車";
        SaloonCar.prototype.drive = function(){
            return "Saloon car is driving.";
        };
        
        var bora = new SaloonCar();
        bora.carType = "商務(wù)用車";
        alert(bora.carType);
        var mazda = new SaloonCar();
        alert(mazda.carType);
    </script>

內(nèi)置方法和操作符:
isPrototypeOf()
判斷一個(gè)對(duì)象是否指向了該構(gòu)造函數(shù)的原型對(duì)象膊存。

    <script>
        //使用聲明構(gòu)造函數(shù)的方式,在原型中添加屬性和方法
        function SaloonCar(){}
        
        SaloonCar.prototype.carType = "家用型轎車";
        SaloonCar.prototype.drive = function(){
            return "Saloon car is driving.";
        };
        
        var bora = new SaloonCar();
        alert(SaloonCar.prototype.isPrototypeOf(bora));
    </script>

hasOwnProperty()
判斷一個(gè)屬性是構(gòu)造函數(shù)中的屬性而非原型中的屬性忱叭。

    <script>
        //使用聲明構(gòu)造函數(shù)的方式隔崎,在原型中添加屬性和方法
        function SaloonCar(){}
        
        SaloonCar.prototype.carType = "家用型轎車";
        SaloonCar.prototype.drive = function(){
            return "Saloon car is driving.";
        };
        
        //在構(gòu)造函數(shù)中添加屬性和方法
        function Suv(brand, model){
            this.brand = brand;
            this.model = model;
            this.drive = function(){
                return this.brand + " " + this.model + " is driving.";
            };
        }

        var bora = new SaloonCar();
        alert(bora.hasOwnProperty("carType")); //false
        
        var benzGlc = new Suv("Benz", "GLC260");
        alert(benzGlc.hasOwnProperty("brand")); //true
    </script>

in
判斷指定屬性是否在對(duì)象中,無論是構(gòu)造函數(shù)中定義的還是原型定義的屬性窑多。

    <script>
        //使用聲明構(gòu)造函數(shù)的方式仍稀,在原型中添加屬性和方法
        function SaloonCar(){}
        
        SaloonCar.prototype.carType = "家用型轎車";
        SaloonCar.prototype.drive = function(){
            return "Saloon car is driving.";
        };
        
        //在構(gòu)造函數(shù)中添加屬性和方法
        function Suv(brand, model){
            this.brand = brand;
            this.model = model;
            this.drive = function(){
                return this.brand + " " + this.model + " is driving.";
            };
        }

        var bora = new SaloonCar();
        alert("carType" in bora);//true
        
        var benzGlc = new Suv("Benz", "GLC260");
        alert("brand" in benzGlc);//true
    </script>

12.2.2 使用字面量創(chuàng)建原型對(duì)象

為了讓屬性和方法更好的體現(xiàn)封裝的效果,并且減少不必要的輸入埂息,原型的創(chuàng)建可以使用字面量的方式技潘。使用構(gòu)造函數(shù)創(chuàng)建原型對(duì)象和使用字面量創(chuàng)建原型對(duì)象在使用上基本相同,但還是有一些區(qū)別千康,字面量創(chuàng)建的方式使用constructor屬性不會(huì)指向?qū)嵗碛模鴷?huì)指向Object,構(gòu)造函數(shù)創(chuàng)建的方式則相反拾弃。

    <script>
        //使用字面量方式聲明原型屬性和方法
        function SaloonCar(){}
        SaloonCar.prototype = {
            carType: "家用型轎車",
            drive: function(){
                return "Saloon car is driving.";
            }
        };
        
        var bora = new SaloonCar();
        alert(bora instanceof SaloonCar);
        alert(bora instanceof Object);
        alert(bora.constructor === SaloonCar); //字面量方式值桩,返回false,否則豪椿,true
        alert(bora.constructor === Object); //字面量方式奔坟,返回true携栋,否則,false
    </script>

如果想讓字面量方式的constructor指向?qū)嵗龑?duì)象咳秉,那么可以這么做:

        SaloonCar.prototype = {
            constructor: SaloonCar,
            carType: "家用型轎車",
            drive: function(){
                return "Saloon car is driving.";
            }
        };

說明:使用字面量方式創(chuàng)建的原型對(duì)象為什么constructor會(huì)指向Object婉支?那是因?yàn)镾aloonCar.prototype={};這種寫法其實(shí)就是創(chuàng)建了一個(gè)新對(duì)象。而每創(chuàng)建一個(gè)對(duì)象澜建,就會(huì)同時(shí)創(chuàng)建它prototype屬性向挖,這個(gè)對(duì)象也會(huì)自動(dòng)獲取constructor屬性。所以炕舵,新對(duì)象的constructor重寫了SaloonCar原來的constructor何之,因此會(huì)指向新對(duì)象,那個(gè)新對(duì)象沒有指定構(gòu)造函數(shù)咽筋,那么就默認(rèn)為Object溶推。
原型的聲明是有先后順序的,所以奸攻,重寫的原型會(huì)切斷之前的原型悼潭,所以不要重復(fù)聲明原型。

    <script>
        //使用字面量方式聲明原型屬性和方法
        function SaloonCar(){}
        SaloonCar.prototype = {
            constructor: SaloonCar,
            carType: "家用型轎車",
            drive: function(){
                return "Saloon car is driving.";
            }
        };
        
        SaloonCar.prototype = {
            color: "White"
        };
        var bora = new SaloonCar();
        alert(bora.drive());//報(bào)錯(cuò)
    </script>

原型模式創(chuàng)建對(duì)象也有自己的缺點(diǎn)舞箍,它省略了構(gòu)造函數(shù)傳參初始化這一過程,帶來的缺點(diǎn)就是初始化的值都是一致的皆疹。而原型最大的缺點(diǎn)就是它最大的優(yōu)點(diǎn)疏橄,那就是共享。
原型中所有屬性是被很多實(shí)例共享的略就,共享對(duì)于函數(shù)非常合適捎迫,對(duì)于包含值類型的屬性也還可以。但如果屬性包含引用類型表牢,就存在一定的問題:

    <script>
        function Student(){};
        Student.prototype = {
            constructor: Student,
            family: ["父親", "母親"],
            showFamily: function(){
                return this.family;
            }
        };
        
        var s1 = new Student();
        s1.family.push("哥哥");
        alert(s1.showFamily()); //父親窄绒,母親,哥哥
        var s2 = new Student();
        alert(s2.showFamily()); //父親崔兴,母親彰导,哥哥
    </script>

為了解決構(gòu)造傳參和共享問題,可以使用構(gòu)造函數(shù)+原型模式:

    <script>
        function Student(fullName, age) { //不共享的使用構(gòu)造函數(shù)
            this.fullName = fullName;
            this.age = age;
            this.family = ['父親', '母親'];
        };
        Student.prototype = { //共享的使用原型模式
            constructor : Student,
            showFamily : function () {
                return this.fullName + " " + this.age + "歲敲茄,家庭成員:" + this.family;
            }
        };
        var s1 = new Student("佟大為", 32);
        s1.family.push("哥哥");
        alert(s1.showFamily()); //父親位谋,母親, 哥哥
        
        var s2 = new Student("馬伊琍", 20);
        alert(s2.showFamily()); //父親,母親
        
        var s3 = new Student("趙麗穎", 19);
        s3.family.push("姐姐");
        alert(s3.showFamily()); //父親堰燎,母親, 姐姐
    </script>

說明:這種構(gòu)造函數(shù)+原型的模式很好的解決了傳參和引用共享的大難題掏父。是創(chuàng)建對(duì)象比較好的方法。
原型模式秆剪,不管你是否調(diào)用了原型中的共享方法赊淑,它都會(huì)初始化原型中的方法爵政,并且在聲明一個(gè)對(duì)象時(shí),構(gòu)造函數(shù)+原型部分讓人感覺又很怪異陶缺,最好就是把構(gòu)造函數(shù)和原型封裝到一起钾挟。為了解決這個(gè)問題,我們可以使用動(dòng)態(tài)原型模式(實(shí)際項(xiàng)目中使用的模式)组哩。

    <script>
        function Student(fullName, age) { //不共享的使用構(gòu)造函數(shù)
            this.fullName = fullName;
            this.age = age;
            this.family = ['父親', '母親'];
            
            if(typeof this.showFamily != "function"){
                Student.prototype.showFamily = function(){ //共享的使用原型模式
                    return this.fullName + " " + this.age + "歲等龙,家庭成員:" + this.family;
                };
            }
        };
        
        var s1 = new Student("佟大為", 32);
        s1.family.push("哥哥");
        alert(s1.showFamily()); //父親,母親, 哥哥
        
        var s2 = new Student("馬伊琍", 20);
        alert(s2.showFamily()); //父親伶贰,母親
        
        var s3 = new Student("趙麗穎", 19);
        s3.family.push("姐姐");
        alert(s3.showFamily()); //父親蛛砰,母親, 姐姐
    </script>

說明:

  1. 當(dāng)?shù)谝淮握{(diào)用構(gòu)造函數(shù)時(shí),showFamily()方法發(fā)現(xiàn)不存在黍衙,然后初始化原型泥畅。當(dāng)?shù)诙握{(diào)用,就不會(huì)初始化琅翻,并且第二次創(chuàng)建新對(duì)象位仁,原型也不會(huì)再初始化了。這樣及得到了封裝方椎,又實(shí)現(xiàn)了原型方法共享聂抢,并且屬性都保持獨(dú)立。
  2. 不可以再使用字面量的方式重寫原型棠众,因?yàn)闀?huì)切斷實(shí)例和新原型之間的聯(lián)系琳疏。

12.2.3 繼承

繼承是面向?qū)ο笾幸粋€(gè)比較核心的概念。其他正統(tǒng)面向?qū)ο笳Z言都會(huì)用兩種方式實(shí)現(xiàn)繼承:一個(gè)是接口實(shí)現(xiàn)闸拿,一個(gè)是繼承空盼。而JavaScript只支持繼承,不支持接口實(shí)現(xiàn)新荤,而實(shí)現(xiàn)繼承的方式依靠原型鏈完成揽趾。

    <script>
        function Product(){
            this.color = "White";
        }
        
        function Cellphone(){
            this.name = "iphone"
        }
        
        Cellphone.prototype = new Product();
        
        var cellphone = new Cellphone();
        alert(cellphone.name);
        alert(cellphone.color);
    </script>

在JavaScript里,被繼承的函數(shù)稱為超類型(其他語言成為父類)苛骨,繼承的函數(shù)稱為子類型(其他語言成為派生類)篱瞎。繼承也有之前問題,比如字面量重寫原型會(huì)中斷關(guān)系痒芝,使用引用類型的原型奔缠,并且子類型還無法給超類型傳遞參數(shù)。
為了解決引用共享和超類型無法傳參的問題吼野,我們可以采用對(duì)象冒充(偽造對(duì)象校哎、經(jīng)典繼承)的方法來解決這兩種問題。

    <script>
        function Product(name){
            this.manufacturers = ["Apple", "Sumsung"];
            this.name = name;
        }
        
        function Cellphone(name, brand, model){
            Product.call(this, name)
            this.brand = brand;
            this.model = model;
        }
        
        var product1 = new Cellphone("cellphone", "letv", "1Pro");
        product1.manufacturers.push("letv");
        alert(product1.name + ": " + product1.brand + product1.model + "\n" + product1.manufacturers);
        
        var product2 = new Cellphone("cellphone", "meizu", "魅藍(lán)3");
        product2.manufacturers.push("meizu");
        alert(product2.name + ": " + product2.brand + product2.model + "\n" + product2.manufacturers);
    </script>

借用構(gòu)造函數(shù)雖然解決了剛才兩種問題,但沒有原型闷哆,復(fù)用則無從談起腰奋。所以,我們需要原型鏈+借用構(gòu)造函數(shù)的模式抱怔,這種模式成為組合繼承劣坊。

    <script>
        function Product(name){
            this.manufacturers = ["Apple", "Sumsung"];
            this.name = name;
            if(typeof this.show != "function"){
                Product.prototype.show = function(){//方法放到原型中,使其每次實(shí)例化時(shí)方法地址保持一致
                    alert("The product is:" + this.name);
                }
            }
        }
        function Cellphone(name, brand, model){
            Product.call(this, name)
            this.brand = brand;
            this.model = model;
        }
        function Pad(name, brand, model){
            Product.call(this, name);
            this.brand = brand;
            this.model = model;
        }
        Cellphone.prototype = new Product();
        Pad.prototype = new Product();
        var product1 = new Cellphone("cellphone", "iphone", "6puls");
        product1.show();
        var product2 = new Pad("pad", "ipad", "air");
        product2.show();
        alert(product1.show === product2.show);//true
    </script>

組合式繼承是JavaScript最常用的繼承模式屈留。

第十三章 匿名函數(shù)和閉包

13.1 匿名函數(shù)

匿名函數(shù)就是沒有名字的函數(shù)局冰。
(1)普通函數(shù)(有名字的函數(shù))

function showCarInfo(car){
    var carInfo = "Car brand:" + car.brand + "\n" + 
                    "Car model:" + car.model + "\n" +
                    "Car color:" + car.color;
    alert(carInfo);
}

(2)匿名函數(shù)(沒有名字的函數(shù))

function(){
    alert("hello.");
}

如何執(zhí)行匿名函數(shù):
方法1:通過表達(dá)式自我執(zhí)行

(function(){
    alert("hello.");
})();

方法2:把匿名函數(shù)賦值給變量

var show = function(){
    alert("hello.");
};

show();

方法3:函數(shù)里的匿名函數(shù)

function show(){
    return function(){
        return "hello.";
    }
}

alert(show()());

實(shí)際項(xiàng)目中使用場(chǎng)景:
場(chǎng)景一、回掉函數(shù)
場(chǎng)景二灌危、閉包

13.2 閉包

閉包是指有權(quán)訪問另一個(gè)函數(shù)作用域中的變量的函數(shù)康二,創(chuàng)建閉包的常見的方式,就是在一個(gè)函數(shù)內(nèi)部創(chuàng)建另一個(gè)函數(shù)勇蝙,通過另一個(gè)函數(shù)訪問這個(gè)函數(shù)的局部變量沫勿。
使用閉包有一個(gè)優(yōu)點(diǎn),也是它的缺點(diǎn):就是可以把局部變量駐留在內(nèi)存中味混,可以避免使用全局變量产雹。(全局變量污染導(dǎo)致應(yīng)用程序不可預(yù)測(cè)性,每個(gè)模塊都可調(diào)用必將引來災(zāi)難翁锡,所以推薦使用私有的蔓挖,封裝的局部變量)。

function show(){
    var num = 0;
    return function(){
        num++;
        return num;
    }
}

var s = show();
alert(s()); //1
alert(s()); //2
alert(s()); //3

說明:由于閉包里作用域返回的局部變量資源不會(huì)被立刻銷毀回收馆衔,所以可能會(huì)占用更多的內(nèi)存时甚。過度使用閉包會(huì)導(dǎo)致性能下降,建議在非常有必要的時(shí)候才使用閉包哈踱。

第十四章 BOM操作

BOM(Browser Object Model)也叫瀏覽器對(duì)象模型,它提供了很多對(duì)象梨熙,用于訪問瀏覽器的功能开镣。BOM缺少規(guī)范,每個(gè)瀏覽器提供商又按照自己想法去擴(kuò)展它咽扇,那么瀏覽器共有對(duì)象就成了事實(shí)的標(biāo)準(zhǔn)邪财。所以,BOM本身是沒有標(biāo)準(zhǔn)的或者還沒有哪個(gè)組織去標(biāo)準(zhǔn)它。

14.1 window對(duì)象

BOM的核心對(duì)象是window,它表示瀏覽器的一個(gè)實(shí)例竿报。window對(duì)象處于JavaScript結(jié)構(gòu)的最頂層赊豌,對(duì)于每個(gè)打開的窗口,系統(tǒng)都會(huì)自動(dòng)為其定義 window 對(duì)象映跟。

window對(duì)象

(1) window對(duì)象的屬性

屬性 含義
closed 當(dāng)窗口關(guān)閉時(shí)為真
defaultStatus 窗口底部狀態(tài)欄顯示的默認(rèn)狀態(tài)消息
document 窗口中當(dāng)前顯示的文檔對(duì)象
frames 窗口中的框架對(duì)象數(shù)組
history 保存有窗口最近加載的URL
length 窗口中的框架數(shù)
location 當(dāng)前窗口的URL
name 窗口名
offscreenBuffering 用于繪制新窗口內(nèi)容并在完成后復(fù)制已存在的內(nèi)容,控制屏幕更新
opener 打開當(dāng)前窗口的窗口
parent 指向包含另一個(gè)窗口的窗口(由框架使用)
screen 顯示屏幕相關(guān)信息尉咕,如高度绊袋、寬度(以像素為單位)
self 指示當(dāng)前窗口毕匀。
status 描述由用戶交互導(dǎo)致的狀態(tài)欄的臨時(shí)消息
top 包含特定窗口的最頂層窗口(由框架使用)
window 指示當(dāng)前窗口,與self等效

(2) window對(duì)象的方法

方法 功能
alert(text) 創(chuàng)建一個(gè)警告對(duì)話框癌别,顯示一條信息
blur() 將焦點(diǎn)從窗口移除
clearInterval(interval) 清除之前設(shè)置的定時(shí)器間隔
clearTimeOut(timer) 清除之前設(shè)置的超時(shí)
close() 關(guān)閉窗口
confirm() 創(chuàng)建一個(gè)需要用戶確認(rèn)的對(duì)話框
focus() 將焦點(diǎn)移至窗口
open(url,name,[options]) 打開一個(gè)新窗口并返回新window對(duì)象
prompt(text,defaultInput) 創(chuàng)建一個(gè)對(duì)話框要求用戶輸入信息
scroll(x,y) 在窗口中滾動(dòng)到一個(gè)像素點(diǎn)的位置
setInterval(expression,milliseconds) 經(jīng)過指定時(shí)間間隔計(jì)算一個(gè)表達(dá)式
setInterval(function,millisenconds,[arguments]) 經(jīng)過指定時(shí)間間隔后調(diào)用一個(gè)函數(shù)
setTimeout(expression,milliseconds) 在定時(shí)器超過后計(jì)算一個(gè)表達(dá)式
setTimeout(expression,milliseconds,[arguments]) 在定時(shí)器超過時(shí)后計(jì)算一個(gè)函數(shù)
print() 調(diào)出打印對(duì)話框
find() 調(diào)出查找對(duì)話框

window下的屬性和方法皂岔,可以使用window.屬性、window.方法()或者直接屬性展姐、方法()的方式調(diào)用躁垛。例如:window.alert()和alert()是一樣的。

14.2 location對(duì)象

location是BOM對(duì)象之一圾笨,它提供了與當(dāng)前窗口中加載的文檔有關(guān)的信息教馆,還提供了一些導(dǎo)航功能。事實(shí)上墅拭,location對(duì)象是window對(duì)象的屬性活玲,也是document對(duì)象的屬性;所以window.location和document.location等效谍婉。
(1) location對(duì)象的屬性

屬性 描述的URL內(nèi)容
hash 如果該部分存在舒憾,表示錨點(diǎn)部分
host 主機(jī)名:端口號(hào)
hostname 主機(jī)名
href 整個(gè)URL
pathname 路徑名
port 端口號(hào)
protocol 協(xié)議部分
search 查詢字符串

(2) location對(duì)象的方法

方法 功能
assign() 跳轉(zhuǎn)到指定頁(yè)面,與href等效
reload() 重載當(dāng)前URL
repalce() 用新的URL替換當(dāng)前頁(yè)面

14.3 history對(duì)象

history對(duì)象是window對(duì)象的屬性穗熬,它保存著用戶上網(wǎng)的記錄镀迂,從窗口被打開的那一刻算起。
(1) history對(duì)象的屬性

屬性 描述的URL內(nèi)容
length history對(duì)象中的記錄數(shù)

(2) history對(duì)象的方法

方法 功能
back() 前往瀏覽器歷史條目前一個(gè)URL唤蔗,類似后退
forward() 前往瀏覽器歷史條目下一個(gè)URL探遵,類似前進(jìn)
go(num) 瀏覽器在history對(duì)象中向前或向后

第十五章 DOM操作

DOM(Document Object Model)即文檔對(duì)象模型,針對(duì)HTML和XML文檔的API(應(yīng)用程序接口)妓柜。DOM描繪了一個(gè)層次化的節(jié)點(diǎn)樹箱季,運(yùn)行開發(fā)人員添加、移除和修改頁(yè)面的某一部分棍掐。

15.1 DOM介紹

(1) 節(jié)點(diǎn)
加載HTML頁(yè)面時(shí)藏雏,Web瀏覽器生成一個(gè)樹型結(jié)構(gòu),用來表示頁(yè)面內(nèi)部結(jié)構(gòu)作煌。DOM將這種樹型結(jié)構(gòu)理解為由節(jié)點(diǎn)組成掘殴。

DOM結(jié)構(gòu)

從上圖的樹型結(jié)構(gòu),我們理解幾個(gè)概念粟誓,html標(biāo)簽沒有父輩奏寨,沒有兄弟,所以html標(biāo)簽為根標(biāo)簽鹰服。head標(biāo)簽是html子標(biāo)簽病瞳,meta和title標(biāo)簽之間是兄弟關(guān)系揽咕。如果把每個(gè)標(biāo)簽當(dāng)作一個(gè)節(jié)點(diǎn)的話,那么這些節(jié)點(diǎn)組合成了一棵節(jié)點(diǎn)樹(后面我們經(jīng)常把標(biāo)簽稱作為元素仍源,是一個(gè)意思)心褐。
(2) 節(jié)點(diǎn)種類
節(jié)點(diǎn)種類分為三種,元素節(jié)點(diǎn)笼踩、文本節(jié)點(diǎn)逗爹、屬性節(jié)點(diǎn)。
<div title="屬性節(jié)點(diǎn)">測(cè)試div</div>

元素節(jié)點(diǎn)

DOM操作請(qǐng)參照后續(xù)jQuery課程嚎于。

第十六章 JavaScript事件

16.1 事件介紹

JavaScript事件是由訪問Web頁(yè)面的用戶引起的一系列操作掘而,例如:用戶點(diǎn)擊。當(dāng)用戶執(zhí)行某些操作的時(shí)候于购,再去執(zhí)行一系列代碼袍睡。事件一般是用于瀏覽器和用戶操作進(jìn)行交互。最早是IE和Netscape Navigator中出現(xiàn)肋僧,作為分擔(dān)服務(wù)器端運(yùn)算負(fù)載的一種手段斑胜。直到幾乎所有的瀏覽器都支持事件處理。而DOM2級(jí)規(guī)范開始嘗試以一種復(fù)合邏輯的方式標(biāo)準(zhǔn)化DOM事件嫌吠。IE9止潘、Firefox、Opera辫诅、Safari和Chrome全都已經(jīng)實(shí)現(xiàn)了“DOM2級(jí)事件”模塊的核心部分凭戴。IE8之前瀏覽器仍然使用其專有事件模型。
JavaScript有三種事件模型:內(nèi)聯(lián)模型炕矮、腳本模型和DOM2模型么夫。

16.2 內(nèi)聯(lián)模型

這種模型是傳統(tǒng)且單一的處理事件的方法。在內(nèi)聯(lián)模型中肤视,事件處理函數(shù)是HTML標(biāo)簽的一個(gè)屬性档痪,用于處理指定事件。雖然內(nèi)聯(lián)在早期使用較多邢滑,但它是和HTML混寫的腐螟,并沒有與HTML分離,現(xiàn)在已很少使用殊鞭。

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>JavaScript事件</title>
    </head>
    <script>
        function hello(n){
            alert("hello " + n);
        }
    </script>
    <body>
        <button onclick="alert('hello.')">內(nèi)聯(lián)事件(嵌入內(nèi)容)</button>
        <button onclick="hello('Johnny')">內(nèi)聯(lián)事件(調(diào)用函數(shù))</button>
    </body>
</html>

16.3 腳本模型

由于內(nèi)聯(lián)模型違反了HTML與JavaScript代碼層次分離的原則。為了解決這個(gè)問題尼桶,我們可以在JavaScript中處理事件操灿。這種處理方式就是腳本模型。

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>JavaScript事件</title>
    </head>
    <script>
        window.onload = function(){
            var btn = document.getElementById("btnOnclick");
            btn.onclick = function(){
                alert("hello.");
            };
        };
    </script>
    <body>
        <button id="btnOnclick">腳本模型</button>
    </body>
</html>

16.4 事件處理函數(shù)
JavaScript可以處理的事件類型為:鼠標(biāo)事件泵督、鍵盤事件趾盐、HTML事件。
JavaScript事件處理函數(shù)及其使用列表

事件處理函數(shù) 影響的元素 何時(shí)發(fā)生
onabort 圖像 當(dāng)圖像加載被中斷時(shí)
onblur 窗口、框架救鲤、所有表單對(duì)象 當(dāng)焦點(diǎn)從對(duì)象上移開時(shí)
onchange 輸入框久窟,選擇框和文本區(qū)域 當(dāng)改變一個(gè)元素的值且失去焦點(diǎn)時(shí)
onclick 鏈接、按鈕本缠、表單對(duì)象斥扛、圖像映射區(qū)域 當(dāng)用戶單擊對(duì)象時(shí)
ondblclick 鏈接、按鈕丹锹、表單對(duì)象 當(dāng)用戶雙擊對(duì)象時(shí)
ondragdrop 窗口 當(dāng)用戶將一個(gè)對(duì)象拖放到瀏覽器窗口時(shí)
onError 腳本 當(dāng)腳本中發(fā)生語法錯(cuò)誤時(shí)
onfocus 窗口稀颁、框架、所有表單對(duì)象 當(dāng)單擊鼠標(biāo)或者將鼠標(biāo)移動(dòng)聚焦到窗口或框架時(shí)
onkeydown 文檔楣黍、圖像匾灶、鏈接、表單 當(dāng)按鍵被按下時(shí)
onkeypress 文檔租漂、圖像阶女、鏈接、表單 當(dāng)按鍵被按下然后松開時(shí)
onkeyup 文檔哩治、圖像秃踩、鏈接、表單 當(dāng)按鍵被松開時(shí)
onload 主題锚扎、框架集吞瞪、圖像 文檔或圖像加載后
onunload 主體、框架集 文檔或框架集卸載后
onmouseout 鏈接 當(dāng)圖標(biāo)移除鏈接時(shí)
onmouseover 鏈接 當(dāng)鼠標(biāo)移到鏈接時(shí)
onmove 窗口 當(dāng)瀏覽器窗口移動(dòng)時(shí)
onreset 表單復(fù)位按鈕 單擊表單的reset按鈕
onresize 窗口 當(dāng)選擇一個(gè)表單對(duì)象時(shí)
onselect 表單元素 當(dāng)選擇一個(gè)表單對(duì)象時(shí)
onsubmit 表單 當(dāng)發(fā)送表格到服務(wù)器時(shí)

實(shí)際項(xiàng)目中一般使用jQuery來實(shí)現(xiàn)腳本模式添加事件驾孔,詳細(xì)請(qǐng)參照jQuery課程芍秆。

第十七章 表單處理

為了分擔(dān)服務(wù)器處理表單的壓力,JavaScript提供了一些解決方案翠勉,從而大大打破了處處依賴服務(wù)器的局面妖啥。
實(shí)際項(xiàng)目中一般使用jQuery來處理表單,詳細(xì)請(qǐng)參照jQuery課程对碌。

第十八章 錯(cuò)誤處理與調(diào)試

良好的錯(cuò)誤處理機(jī)制可以及時(shí)的提醒用戶荆虱,知道發(fā)生了什么事,而不會(huì)驚慌失措朽们。為此怀读,作為開發(fā)人員,我們必須理解在處理JavaScript錯(cuò)誤的時(shí)候骑脱,都有哪些手段和工具可以利用菜枷。我們可以使用try-catch語句來捕獲可能會(huì)發(fā)生的錯(cuò)誤并進(jìn)行處理。

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>原型</title>
    </head>
    <script>
        window.onload = function(){
            var btn = document.getElementById("btnOnclick");
            btn.onclick = function(){
                try{
                    var arr = new Array[-5];
                }catch(err){
                    alert(err.message);
                } 
            };
        };
    </script>
    <body>
        <input type="text" id="input-number" placeholder="請(qǐng)輸入日期" />
        <button id="btnOnclick">腳本模型</button>
    </body>
</html>

善用try-catch
在明明知道某個(gè)地方會(huì)產(chǎn)生錯(cuò)誤叁丧,可以通過修改代碼來解決的地方啤誊,是不適合用try-catch的岳瞭。或者是那種不同瀏覽器兼容性錯(cuò)誤導(dǎo)致錯(cuò)誤的也不太適合蚊锹,因?yàn)榭梢酝ㄟ^判斷瀏覽器或者判斷這款瀏覽器是否存在此屬性和方法來解決瞳筏。
常規(guī)錯(cuò)誤和這種瀏覽器兼容錯(cuò)誤,我們都不建議使用try-catch牡昆。因?yàn)槌R?guī)錯(cuò)誤可以修改代碼即可解決姚炕,瀏覽器兼容錯(cuò)誤,可以通過普通if判斷即可迁杨。并且try-catch比一般語句消耗資源更多钻心,負(fù)擔(dān)更大。所以铅协,在萬不得已捷沸,無法修改代碼,不能通過普通判斷的情況下才去使用try-catch狐史,比如后面的Ajax技術(shù)痒给。

第十九章 Cookie

19.1 Cookie介紹

隨著Web越來越復(fù)雜,開發(fā)者急切的需要能夠本地化存儲(chǔ)的腳本功能骏全。這個(gè)時(shí)候苍柏,第一個(gè)出現(xiàn)的方案:cookie誕生了。cookie的意圖是姜贡,在本地的客戶端的磁盤上以很小的文件形式保存數(shù)據(jù)试吁。
cookie也叫HTTP Cookie,最初是客戶端與服務(wù)器端進(jìn)行會(huì)話使用的楼咳。比如熄捍,會(huì)員登錄,下次回訪網(wǎng)站時(shí)無須登錄了母怜;或者是購(gòu)物車余耽,購(gòu)買的商品沒有及時(shí)付款,過兩天發(fā)現(xiàn)購(gòu)物車?yán)镞€有之前的商品列表苹熏。
HTTP Cookie要求服務(wù)器對(duì)任意HTTP請(qǐng)求發(fā)送Set-Cookie碟贾,因此,Cookie的處理原則上需要在服務(wù)器環(huán)境下進(jìn)行轨域。當(dāng)然袱耽,現(xiàn)在大部分瀏覽器在客戶端也能實(shí)現(xiàn)Cookie的生成和獲取。(目前Chrome不可以在客戶端操作干发,其他瀏覽器均可)
cookie的組成:
cookie由名/值(鍵值對(duì))形式的文本組成:name=value朱巨。完整格式為:
name=value; [expires=date]; [path=path]; [domain=somewhere.com]; [secure]
中括號(hào)是可選,name=value是必選铐然。
expires=date 失效時(shí)間蔬崩,如果沒有聲明,則為瀏覽器關(guān)閉后即失效搀暑。聲明了失效時(shí)間沥阳,那么時(shí)間到期后方能失效。
path=path 訪問路徑自点,當(dāng)設(shè)置了路徑桐罕,那么只有設(shè)置的那個(gè)路徑文件才可以訪問cookie。
domain=domain 訪問域名桂敛,用于限制只有設(shè)置的域名才可以訪問功炮,那么沒有設(shè)置,會(huì)默認(rèn)限制為創(chuàng)建cookie的域名术唬。
secure 安全設(shè)置薪伏,指明必須通過安全的通信通道來傳輸(HTTPS)才能獲取cookie。
具體Cookie的操作一般使用jQuery來實(shí)現(xiàn)粗仓,請(qǐng)參照jQuery課程嫁怀。

19.2 Cookie的局限性
Cookie雖然在持久保存客戶端用戶數(shù)據(jù)提供了方便,分擔(dān)了服務(wù)器存儲(chǔ)的負(fù)擔(dān)借浊。但是還有很多局限性的塘淑。
(1) 每個(gè)特定的域名下最多生成20個(gè)cookie(根據(jù)不同的瀏覽器有所區(qū)別)

  • IE7和之后的版本最多可以50個(gè)cookie。IE7最初也只能20個(gè)蚂斤,之后因被升級(jí)不定后增加了存捺。
  • Firefox最多50個(gè)cookie
  • Opera最多30個(gè)cookie
  • Safari和Chrome沒有做硬性限制。
    為了更好的兼容性曙蒸,所以按照最低的要求來捌治,也就是最多不得超過20個(gè)cookie。當(dāng)超過指定的 cookie時(shí)逸爵,瀏覽器會(huì)清理掉早期的cookie具滴。IE和Opera會(huì)清理近期最少使用的cookie,F(xiàn)irefox會(huì)隨機(jī)清理cookie师倔。

(2) Cookie的最大大約為4096字節(jié)(4k)构韵,為了更好的兼容性,一般不能超過4095字節(jié)即可趋艘。
(3) Cookie存儲(chǔ)在客戶端的文本文件疲恢,所以特別重要和敏感的數(shù)據(jù)是不建議保存在Cookie的。比如銀行卡號(hào)瓷胧,用戶密碼等显拳。

第二十章 XML

20.1 XML簡(jiǎn)介

XML是可擴(kuò)展標(biāo)記語言,被設(shè)計(jì)用來傳輸和存儲(chǔ)數(shù)據(jù)搓萧。XML與HTML的區(qū)別如下:

  • XML用來傳輸和存儲(chǔ)數(shù)據(jù)杂数,HTML被設(shè)計(jì)用來顯示數(shù)據(jù)宛畦。
  • XML被設(shè)計(jì)為具有自我描述性,通過XML可以發(fā)明自己的標(biāo)簽揍移。
  • XML是W3C(World Wide Web Consortium)次和,即萬維網(wǎng)聯(lián)盟的推薦標(biāo)準(zhǔn)。
  • XML是沒有任何行為的那伐,僅僅是純文本踏施。

20.2 XML用途

XML 應(yīng)用于 web 開發(fā)的許多方面,常用于簡(jiǎn)化數(shù)據(jù)的存儲(chǔ)和共享罕邀。XML主要用途如下:
(1) XML把數(shù)據(jù)從 HTML 分離
如果你需要在HTML文檔中顯示動(dòng)態(tài)數(shù)據(jù)畅形,那么每當(dāng)數(shù)據(jù)改變時(shí)將花費(fèi)大量的時(shí)間來編輯HTML。通過XML诉探,數(shù)據(jù)能夠存儲(chǔ)在獨(dú)立的XML文件中日熬。這樣你就可以專注于使用 HTML進(jìn)行布局和顯示,并確保修改底層數(shù)據(jù)不再需要對(duì) HTML 進(jìn)行任何的改變肾胯。通過使用幾行 JavaScript碍遍,你就可以讀取一個(gè)外部 XML 文件,然后更新 HTML 中的數(shù)據(jù)內(nèi)容阳液。
(2) XML簡(jiǎn)化數(shù)據(jù)共享
在真實(shí)的世界中怕敬,計(jì)算機(jī)系統(tǒng)和數(shù)據(jù)使用不兼容的格式來存儲(chǔ)數(shù)據(jù)。XML數(shù)據(jù)以純文本格式進(jìn)行存儲(chǔ)帘皿,因此提供了一種獨(dú)立于軟件和硬件的數(shù)據(jù)存儲(chǔ)方法东跪。這讓創(chuàng)建不同應(yīng)用程序可以共享的數(shù)據(jù)變得更加容易。
(3) XML簡(jiǎn)化數(shù)據(jù)傳輸
通過 XML鹰溜,可以在不兼容的系統(tǒng)之間輕松地交換數(shù)據(jù)虽填。對(duì)開發(fā)人員來說,其中一項(xiàng)最費(fèi)時(shí)的挑戰(zhàn)一直是在因特網(wǎng)上的不兼容系統(tǒng)之間交換數(shù)據(jù)曹动。由于可以通過各種不兼容的應(yīng)用程序來讀取數(shù)據(jù)斋日,以XML交換數(shù)據(jù)降低了這種復(fù)雜性。
(4) XML簡(jiǎn)化平臺(tái)的變更
升級(jí)到新的系統(tǒng)(硬件或軟件平臺(tái))墓陈,總是非常費(fèi)時(shí)的恶守。必須轉(zhuǎn)換大量的數(shù)據(jù),不兼容的數(shù)據(jù)經(jīng)常會(huì)丟失贡必。
XML 數(shù)據(jù)以文本格式存儲(chǔ)兔港。這使得 XML 在不損失數(shù)據(jù)的情況下,更容易擴(kuò)展或升級(jí)到新的操作系統(tǒng)仔拟、新應(yīng)用程序或新的瀏覽器衫樊。
(5) XML使您的數(shù)據(jù)更有用
由于XML獨(dú)立于硬件、軟件以及應(yīng)用程序,XML使數(shù)據(jù)更可用科侈,也更有用载佳。不同的應(yīng)用程序都能夠訪問您的數(shù)據(jù),不僅僅在HTML頁(yè)中臀栈,也可以從XML數(shù)據(jù)源中進(jìn)行訪問刚盈。通過XML您的數(shù)據(jù)可供各種閱讀設(shè)備使用(手持的計(jì)算機(jī)、語音設(shè)備挂脑、新聞閱讀器等),還可以供盲人或其他殘障人士使用欲侮。

20.3 XML樹形結(jié)構(gòu)

XML文檔形成了一種樹結(jié)構(gòu)崭闲,它從“根部”開始,然后擴(kuò)展到“枝葉”威蕉。

<?xml version="1.0" encoding="utf-8"?>
<student>
  <id>10001</id>
  <name>Johnny</name>
  <sex>female</sex>
  <major>Software engineering</major>
</student>

XML 文檔必須包含根元素刁俭。該元素是所有其他元素的父元素。所有元素均可擁有子元素韧涨。

<?xml version="1.0" encoding="utf-8"?>
<bookstore>
  <book category="Cooking">
    <title lang="en">Everyday Italian</title>
    <author>Giada De Laurentiis</author>
    <year>2005</year>
    <price>30.00</price>
  </book>
  <book category="Children">
    <title lang="en">Harry Potter</title>
    <author>J K. Rowling</author>
    <year>2005</year>
    <price>29.99</price>
  </book>
  <book category="Web">
    <title lang="en">Learning XML</title>
    <author>Erik T. Ray</author>
    <year>2003</year>
    <price>39.95</price>
  </book>
</bookstore>

20.4 XML語法

XML 的語法規(guī)則很簡(jiǎn)單牍戚,且很有邏輯。
(1) 所有XML元素都須有關(guān)閉標(biāo)簽

<title lang="en">Everyday Italian</title>

(2) XML 標(biāo)簽對(duì)大小寫敏感

<Message>這是錯(cuò)誤的虑粥。</message>
<message>這是正確的如孝。</message>

(3) XML 必須正確地嵌套

<b><i>This text is bold and italic</b></i> <!--錯(cuò)誤-->
<b><i>This text is bold and italic</i></b> <!--正確-->

(4) XML 文檔必須有根元素

<?xml version="1.0" encoding="utf-8"?>
<root>
  <child>
    <subchild>.....</subchild>
  </child>
</root>

(5) XML 的屬性值必須加引號(hào)

<!--錯(cuò)誤-->
<note date=08/08/2008>
  <to>George</to>
  <from>John</from>
</note>
<!--正確-->
<note date="08/08/2008">
  <to>George</to>
  <from>John</from>
</note>

(6) 實(shí)體引用
在 XML 中,一些字符擁有特殊的意義娩贷。如果你把字符 "<" 放在 XML 元素中第晰,會(huì)發(fā)生錯(cuò)誤,因?yàn)榻馕銎鲿?huì)把它當(dāng)作新元素的開始彬祖。

<message>if salary < 1000 then</message> <!--錯(cuò)誤-->

為了避免這個(gè)錯(cuò)誤茁瘦,請(qǐng)用實(shí)體引用來代替 "<" 字符:

<message>if salary &lt; 1000 then</message>

在 XML 中,有 5 個(gè)預(yù)定義的實(shí)體引用(專業(yè)字符):

轉(zhuǎn)義字符 代表字符 說明
< < 小于
> > 大于
& & and符
' ' 單引號(hào)
" " 雙引號(hào)

(7) XML中的注釋
在XML中編寫注釋的語法與 HTML 的語法很相似储笑。

<!-- 注釋內(nèi)容 -->

(8) 在XML中甜熔,空格會(huì)被保留
HTML會(huì)把多個(gè)連續(xù)的空格字符裁減(合并)為一個(gè),在XML中,文檔中的空格不會(huì)被刪節(jié)突倍。

<message>Hello   my name is David.</message>

20.5 XML元素

XML 元素指的是從(且包括)開始標(biāo)簽直到(且包括)結(jié)束標(biāo)簽的部分腔稀。元素可包含其他元素、文本或者兩者的混合物羽历。元素也可以擁有屬性烧颖。

<?xml version="1.0" encoding="utf-8"?>
<bookstore>
  <book category="Cooking">
    <title lang="en">Everyday Italian</title>
    <author>Giada De Laurentiis</author>
    <year>2005</year>
    <price>30.00</price>
  </book>
  <book category="Children">
    <title lang="en">Harry Potter</title>
    <author>J K. Rowling</author>
    <year>2005</year>
    <price>29.99</price>
  </book>
  <book category="Web">
    <title lang="en">Learning XML</title>
    <author>Erik T. Ray</author>
    <year>2003</year>
    <price>39.95</price>
  </book>
</bookstore>

在上例中,<bookstore> 和 <book> 都擁有元素內(nèi)容窄陡,因?yàn)樗鼈儼似渌亍?lt;author> 只有文本內(nèi)容炕淮,因?yàn)樗鼉H包含文本。<book> 元素?fù)碛袑傩?(category=" Children ")跳夭。
XML命名規(guī)則

  • 名稱可以含字母涂圆、數(shù)字以及其他的字符
  • 名稱不能以數(shù)字或者標(biāo)點(diǎn)符號(hào)開始
  • 名稱不能以字符“xml”(或者 XML们镜、Xml)開始
  • 名稱不能包含空格
  • 可使用任何名稱,沒有保留的字詞润歉。

20.6 XML屬性

XML元素可以在開始標(biāo)簽中包含屬性模狭,類似HTML。屬性 (Attribute) 提供關(guān)于元素的額外(附加)信息踩衩。

<?xml version="1.0" encoding="utf-8"?>
<bookstore>
  <book category="Cooking">
    <title lang="en">Everyday Italian</title>
    <author>Giada De Laurentiis</author>
    <year>2005</year>
    <price>30.00</price>
  </book>
  <book category="Children">
    <title lang="en">Harry Potter</title>
    <author>J K. Rowling</author>
    <year>2005</year>
    <price>29.99</price>
  </book>
  <book category="Web">
    <title lang="en">Learning XML</title>
    <author>Erik T. Ray</author>
    <year>2003</year>
    <price>39.95</price>
  </book>
</bookstore>

20.7 XML驗(yàn)證

XML Schema是W3C支持的基于XML的驗(yàn)證方式嚼鹉,它名為XML Schema。

<?xml version="1.0" encoding="utf-8"?>
<xs:element name="note">
  <xs:complexType>
    <xs:sequence>
      <xs:element name="to" type="xs:string"/>
      <xs:element name="from" type="xs:string"/>
      <xs:element name="heading" type="xs:string"/>
      <xs:element name="body" type="xs:string"/>
    </xs:sequence>
  </xs:complexType>
</xs:element>

第二十一章 JSON

21.1 JSON簡(jiǎn)介

盡管有許多宣傳關(guān)于 XML 如何擁有跨平臺(tái)驱富,跨語言的優(yōu)勢(shì)锚赤,然而,除非應(yīng)用于Web Services褐鸥,否則线脚,在普通的 Web 應(yīng)用中,開發(fā)者經(jīng)常為 XML 的解析傷透了腦筋叫榕,無論是服務(wù)器端生成或處理 XML浑侥,還是客戶端用JavaScript解析XML,都常常導(dǎo)致復(fù)雜的代碼晰绎,極低的開發(fā)效率寓落。實(shí)際上,對(duì)于大多數(shù)Web應(yīng)用來說荞下,他們根本不需要復(fù)雜的XML來傳輸數(shù)據(jù)零如,XML 的擴(kuò)展性很少具有優(yōu)勢(shì),許多AJAX應(yīng)用甚至直接返回HTML片段來構(gòu)建動(dòng)態(tài) Web 頁(yè)面锄弱。和返回XML并解析它相比考蕾,返回HTML片段大大降低了系統(tǒng)的復(fù)雜性,但同時(shí)缺少了一定的靈活性会宪。
現(xiàn)在肖卧,JSON為Web應(yīng)用開發(fā)者提供了另一種數(shù)據(jù)交換格式。JSON即JavaScript Object Natation掸鹅,它是一種輕量級(jí)的數(shù)據(jù)交換格式塞帐,非常適合于服務(wù)器與JavaScript的交互。

21.2 JSON語法

和XML一樣巍沙,JSON也是基于純文本的數(shù)據(jù)格式葵姥。由于JSON天生是為JavaScript準(zhǔn)備的,因此句携,JSON的數(shù)據(jù)格式非常簡(jiǎn)單榔幸,您可以用JSON傳輸一個(gè)簡(jiǎn)單的String,Number,Boolean也可以傳輸一個(gè)數(shù)組削咆,或者一個(gè)復(fù)雜的 Object 對(duì)象牍疏。
JSON語法是JavaScript對(duì)象表示法語法的子集。

  • 數(shù)據(jù)在名稱/值對(duì)中(鍵值對(duì))拨齐;
  • 數(shù)據(jù)由逗號(hào)分隔鳞陨;
  • 花括號(hào)保存對(duì)象;
  • 方括號(hào)保存數(shù)組瞻惋。

(1) JSON名稱/值對(duì)(鍵值對(duì))
JSON數(shù)據(jù)的書寫格式是:名稱/值的鍵值對(duì)對(duì)厦滤。鍵值對(duì)對(duì)包括字段名稱(在雙引號(hào)中),后面寫一個(gè)冒號(hào)歼狼,然后是值掏导。

"name": "Johnny"

(2) JSON值
JSON值可以是:

  • 數(shù)字(整數(shù)或浮點(diǎn)數(shù))
  • 字符串(在雙引號(hào)中)
  • 邏輯值(true 或 false)
  • 數(shù)組(在方括號(hào)中)
  • 對(duì)象(在花括號(hào)中)
  • null

(3) JSON對(duì)象
JSON對(duì)象在花括號(hào)中書寫,對(duì)象可以包含多個(gè)名稱/值對(duì)蹂匹。

{
    "id": 10001,
    "name": "Johnny",
    "sex": "female",
    "major": "Software engineering"
}

(4) JSON數(shù)組
JSON 數(shù)組在方括號(hào)中書寫,數(shù)組可包含多個(gè)對(duì)象凹蜈。

{
    "employees": [
        {
            "firstName":"John",
            "lastName":"Doe"
        },
        {
            "firstName":"Anna",
            "lastName":"Smith"
        },
        {
            "firstName":"Peter",
            "lastName":"Jones"
        }
    ]
}

(5) JSON使用JavaScript語法
因?yàn)镴SON使用JavaScript語法限寞,所以無需額外的軟件就能處理 JavaScript 中的 JSON。通過 JavaScript仰坦,您可以創(chuàng)建一個(gè)對(duì)象數(shù)組履植,并像這樣進(jìn)行賦值。

{
    "employees": [
        {
            "firstName":"John",
            "lastName":"Doe"
        },
        {
            "firstName":"Anna",
            "lastName":"Smith"
        },
        {
            "firstName":"Peter",
            "lastName":"Jones"
        }
    ]
}

可以像這樣訪問JavaScript對(duì)象數(shù)組中的第一項(xiàng):

employees[0].lastName;

可以像這樣修改數(shù)據(jù):

employees[0].lastName = "Jobs";

(6) JSON文件
JSON文件的文件類型是 ".json"
JSON文本的MIME類型是 "application/json"

21.3 JSON使用

JSON最常見的用法之一悄晃,是從web服務(wù)器上讀取JSON數(shù)據(jù)(作為文件或作為 HttpRequest)玫霎,將JSON數(shù)據(jù)轉(zhuǎn)換為JavaScript對(duì)象,然后在網(wǎng)頁(yè)中使用該數(shù)據(jù)妈橄。
(1) 將json字符串解析為json對(duì)象

    <script>
        var res = "{\"id\": 10001,\"name\": \"Johnny\",\"sex\": \"female\",\"major\": \"Software engineering\"}";
        var obj = JSON.parse(res);//將json字符串解析為json對(duì)象
        alert(obj.name);
    </script>

(2) 將json對(duì)象轉(zhuǎn)為json字符串

    <script>
        var obj = {
            id: 10001,
            name: "Johnny",
            sex: "female",
            major: "Software engineering"
        };
        var str = JSON.stringify(obj); //將json對(duì)象轉(zhuǎn)為json字符串
        alert(str);
    </script>

第二十二章 Ajax

Ajax庶近,是Asynchronous JavaScript + XML的簡(jiǎn)寫。這種技術(shù)能夠向服務(wù)器請(qǐng)求額外的數(shù)據(jù)而無刷新頁(yè)面眷蚓,會(huì)帶來更好的用戶體驗(yàn)鼻种。Ajax技術(shù)核心是XMLHttpRequest對(duì)象(簡(jiǎn)稱XHR),這是由微軟首先引入的一個(gè)特性沙热,其他瀏覽器提供商后來都提供了相同的實(shí)現(xiàn)叉钥。
在實(shí)際項(xiàng)目中,Ajax的實(shí)現(xiàn)是由jQuery來實(shí)現(xiàn)的篙贸,請(qǐng)參照jQuery課程投队。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市爵川,隨后出現(xiàn)的幾起案子敷鸦,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,858評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件轧膘,死亡現(xiàn)場(chǎng)離奇詭異钞螟,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)谎碍,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,372評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門鳞滨,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人蟆淀,你說我怎么就攤上這事拯啦。” “怎么了熔任?”我有些...
    開封第一講書人閱讀 165,282評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵褒链,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我疑苔,道長(zhǎng)甫匹,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,842評(píng)論 1 295
  • 正文 為了忘掉前任惦费,我火速辦了婚禮兵迅,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘薪贫。我一直安慰自己恍箭,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,857評(píng)論 6 392
  • 文/花漫 我一把揭開白布瞧省。 她就那樣靜靜地躺著扯夭,像睡著了一般。 火紅的嫁衣襯著肌膚如雪鞍匾。 梳的紋絲不亂的頭發(fā)上交洗,一...
    開封第一講書人閱讀 51,679評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音橡淑,去河邊找鬼藕筋。 笑死,一個(gè)胖子當(dāng)著我的面吹牛梳码,可吹牛的內(nèi)容都是我干的隐圾。 我是一名探鬼主播,決...
    沈念sama閱讀 40,406評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼掰茶,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼暇藏!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起濒蒋,我...
    開封第一講書人閱讀 39,311評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤盐碱,失蹤者是張志新(化名)和其女友劉穎把兔,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體瓮顽,經(jīng)...
    沈念sama閱讀 45,767評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡奉呛,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,945評(píng)論 3 336
  • 正文 我和宋清朗相戀三年藤滥,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了熬芜。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片参淫。...
    茶點(diǎn)故事閱讀 40,090評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖拣播,靈堂內(nèi)的尸體忽然破棺而出晾咪,到底是詐尸還是另有隱情,我是刑警寧澤贮配,帶...
    沈念sama閱讀 35,785評(píng)論 5 346
  • 正文 年R本政府宣布谍倦,位于F島的核電站,受9級(jí)特大地震影響泪勒,放射性物質(zhì)發(fā)生泄漏昼蛀。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,420評(píng)論 3 331
  • 文/蒙蒙 一圆存、第九天 我趴在偏房一處隱蔽的房頂上張望叼旋。 院中可真熱鬧,春花似錦辽剧、人聲如沸送淆。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,988評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至辟拷,卻和暖如春撞羽,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背衫冻。 一陣腳步聲響...
    開封第一講書人閱讀 33,101評(píng)論 1 271
  • 我被黑心中介騙來泰國(guó)打工诀紊, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人隅俘。 一個(gè)月前我還...
    沈念sama閱讀 48,298評(píng)論 3 372
  • 正文 我出身青樓邻奠,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親为居。 傳聞我的和親對(duì)象是個(gè)殘疾皇子碌宴,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,033評(píng)論 2 355

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

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn)蒙畴,斷路器贰镣,智...
    卡卡羅2017閱讀 134,659評(píng)論 18 139
  • 劇透碑隆、圖片預(yù)警恭陡,慎入! 去看了《拆彈專家》在這個(gè)熱鬧的五一檔捧了港片的場(chǎng)上煤。電影我打7分休玩。分享一下自己的觀影感受。 ...
    超懷觀道閱讀 1,388評(píng)論 3 14
  • 一年多過去了楼入,再提起你已經(jīng)沒有滿滿的恨和痛苦了哥捕。畢竟第一次那么認(rèn)真用力的去愛過一個(gè)人,那么天真的認(rèn)為一輩子可以只愛...
    懶豆閱讀 539評(píng)論 4 4
  • 到今天,我已經(jīng)堅(jiān)持每天跑步至少2公里整整30天了阐肤,這對(duì)于一個(gè)做事容易半途而廢凫佛,很難堅(jiān)持的人來說,真的是具有里程碑意...
    小草禾刀閱讀 1,673評(píng)論 9 15
  • 清晨孕惜,陽光擠進(jìn)窗簾的縫隙愧薛,輕輕的散落在地上,試圖將沉睡中的藺琳叫醒衫画,卻無濟(jì)于事毫炉,床上的人依舊睡的很香甜。突然削罩,一陣...
    余美魚閱讀 768評(píng)論 0 0