Professional JavaScript for Web Developers 3rd Edition ---讀書筆記

1. DOMContentLoaded DOM樹構建完成時觸發該事件javascript

   load 頁面加載完畢觸發html

原生js前端

document.addEventListener('DOMContentLoaded', function(){
    //code.....
}, false);

document.addEventListener('load', function(){
     //code...
}, false);

jqueryjava

//DOMContentLoaded
$(document).ready(function(){
   //code...
});

//load
$(document).load(function(){
  //code...
});

2. XHTML中的用法jquery

小於號(<)再xhtml中會被當作開始一個新標籤來解析, 做爲標籤後面不能根空格。正則表達式

不兼容xhtml算法

3. 區分大小寫express

變量名test和Test表示兩個不一樣的變量數組

4. 註釋瀏覽器

//單行註釋

/**/多行註釋

5. 嚴格模式

"use strict";

6.  ECMAScriptz中有5中簡單的數據類型  Undefined、Null、Boolean、Number、String

和    1中複雜數據類型 Object(Object其實是一組無序的名值對組成)

7. typeof操做符

typeof null 返回object, 由於特殊值null被認爲是一個空的對象引用

8. Undefined類型

該類型只有一個值, 即undefined;

使用var聲明變量但未初始化時, 這個變量的值就是undefined。var message; alert(message);//undefined alert(message == undefined);//true

若是變量未聲明, 使用會出錯,如alert(age); ReferenceError: age is not defined; typeof age //undefined 使用var聲明或沒聲明都返回undefined

9.Null類型

該類型只有一個值null

若是定義的變量在未來用於保存對象, 那麼最好將它初始化爲null。

undefined派生自null alert(null == undefined)//true, (==)相等操做符屬於比較的目的會轉換其操做數

10. Boolean類型

該類型只有兩個字面量值 true和false

要將一個值轉換爲其對應的Boolean值, 能夠調用轉型函數Boolean().

Boolean("hello world");//true 非空字符串

Boolean("");//false 空字符串

這些轉換規則對流控制語句(if)自動執行相應的Boolean轉換很是重要

var message = "hello world";

if(message){alert}

11. Number類型

11.1   8進制  在數字前面加0 如 071表示 57; 若是字面值超過了範圍, 則前導0將被忽略 如 079 表示79

          在嚴格模式下無效

16進制  在字面量0x a-f 能夠大小寫

11.2  浮點數  科學計數法 e  , e前面的數值乘以10的指數次冪 var a = 3.123e3// 3123

最小值 Number.MIN_VALUE

最大值 Number.MAX_VALUE

NaN (Not a Number) b任何數值除以0 都會返回NaN

特色: 1. NaN/10 //NaN 任何操做返回NaN

         2. NaN == NaN //false

11.3 isNan(param)函數     某些不是數值的值會被轉換爲數值,而後返回false, 如 "10"或者 true(被轉換爲1); 不能  被轉換爲數值的值返回true

11.4 數值轉換

 有3個函數能夠把非數值轉換爲數值 Number(), parseInt(), parseFloat

例子

parseInt函數在轉換字符串時,更多的是看其是否符合數值模式, 他會忽略字符串前面的空格, 直到第一個非空格字符

例子

注意

消除困惑, 提供第二個參數(轉換時使用的基數 進制)

var num1 = parseInt('AF', 16);//175

var num2 = parseInt('AF');//NaN

建議:不管在什麼狀況下都明確指明基數

parseFloat的典型示例

12. String類型

轉換爲字符串

 注意 null 和 undefined值沒有這個方法; 默認十進制, 能夠輸出其餘進制的字符串

String()函數

另外一種轉換成字符串的方式  (x + "")

13. Object類型

3.5 操做符

3.5.1 一元操做符

1. 遞增 遞減 操做符

示例

2. 有符號整數

3.5.3 布爾操做符

001 邏輯非

同時使用兩個邏輯非操做符(!!)就會模擬Boolean()轉型函數的行爲

例子

002 邏輯與(&&)

注意 : 邏輯與是一個短路操做符

003 邏輯或

 

 3.5.4 乘性操做符

001 乘法

002 除法

003 求模

3.5.5 加性操做符

001 加法

002 減法

幾個例子

3.5.6 關係操做符

大寫字母的字符編碼所有小於小寫字母的字符編碼

任何操做數與NaN比較 結果都是false

var result1 = NaN < 3; //false

var result2 = NaN >= 3; //false

 3.5.7 相等操做符

001 相等和不相等( == 和 !=)

 比較以前轉換操做數

比較時的規則

002 全等和不全等

比較以前不轉換操做數

var result1 = "55" == 55;//true

var result2 = ("55" ===55); //false

3.5.8 條件操做符

3.5.9 賦值操做符

複合賦值操做符 +=之類

3.5.10 逗號操做符

在用於賦值時, 逗號運算符老是返回最後一項

var num = (5, 1, 3, 4, 0);//0

3.6.2 do-while語句

var i=0;

do{

  i+=2;

}while(i<10);

alert(i);

3.6.4 for語句

因爲ECMAScript 中不存在塊級做用
域(第4 章將進一步討論這一點),所以在循環內部定義的變量也能夠在外部訪問到。

即便i 是
在循環內部定義的一個變量,但在循環外部仍然能夠訪問到它。

3.6.5 for-in語句

這個過程會一直持續到對象中的
全部屬性都被枚舉一遍爲止。與for 語句相似,這裏控制語句中的var 操做符也不是必需的。可是,
爲了保證使用局部變量,咱們推薦上面例子中的這種作法。
ECMAScript 對象的屬性沒有順序。所以,經過for-in 循環輸出的屬性名的順序是不可預測的。

可是,若是表示要迭代的對象的變量值爲null 或undefined,for-in 語句會拋出錯誤。
ECMAScript 5 更正了這一行爲;對這種狀況再也不拋出錯誤,而只是不執行循環體。爲了保證最大限度的

兼容性,建議在使用for-in 循環以前,先檢測確認該對象的值不是null 或undefined

3.6.6 label語句

3.6.7 break和 continue語句

outermost : for(){};

break:outermost 從outermost後開始執行

continue: outermost 從outermost開始執行

 3.7 函數

ECMAScript 中的函數在定義時沒必要指定是否返回值 實際上,任何函數在任什麼時候候均可以經過
return 語句後跟要返回的值來實現返回值

另外,return 語句也能夠不帶有任何返回值。在這種狀況下,函數在中止執行後將返回undefined
值。這種用法通常用在須要提早中止函數執行而又不須要返回值的狀況下

3.7.1理解參數

這個事實說明了ECMAScript 函數的一個重要特色:命名的參數只提供便利,但不是必需的。另
外,在命名參數方面,其餘語言可能須要事先建立一個函數簽名,而未來的調用必須與該簽名一致。但
在ECMAScript 中,沒有這些條條框框,解析器不會驗證命名參數。

雖然這個特性算不上完美的重載,但也足夠彌補ECMAScript 的這一缺憾了。

關於arguments 的行爲,還有一點比較有意思。那就是它的值永遠與對應命名參數的值保持同步。

,這並非說讀取這兩個值會訪問相同的內存空間;它們的內存空間是獨立的,但它們的值會同步。

另外還要記住,若是隻傳入了一個參數,那麼爲arguments[1]設置的值不會反應到
命名參數中。這是由於arguments 對象的長度是由傳入的參數個數決定的,不是由定義函數時的命名
參數的個數決定的。

4.1 基本類型和引用類型的值

基本類型值指的是簡單的數據段,而引用類型值指那些可能由多個值構成的對象。

4.1.1 動態的屬性

var person = new Object();

person.name = "zhangsan";

4.1.2 複製變量值

4.1.3 傳遞參數

 

4.1.4 檢測類型

typeof 檢測基本類型

知道某個值是什麼類型的對象 instanceof

var result = variable instanceof constructor

若是變量是給定引用類型的實例, 那麼instanceof就返回true

若是使用instanceof檢測基本類型的值, 則該操做符始終返回false, 由於基本類型不是對象

4.2 沒有塊級做用域

任何位於局部變量color 的聲明以後的代碼,若是不使用window.color 都沒法訪問全局color變量

4.3.2 引用計數

消除循環引用

myObject.element = null;

element.someObject = null;

爲了解決上述問題,IE9 把BOM 和DOM 對象都轉換成了真正的JavaScript 對象。這樣,就避免了
兩種垃圾收集算法並存致使的問題,也消除了常見的內存泄漏現象。

5.1 Object對象

建立Object對象的兩種方式:

001 new 操做符

var person = new Object();

person.name = "zhangsan";

002 對象字面量

var person = {

          name : "zhangsan",

          age : 19

};

可使用方括號來訪問對象的屬性

person["first name"]

5.2 Array類型

建立數組的基本方式有兩種

001 Array 構造函數

var color = new Array();

002 使用數組字面量

var color = ["red", "blue", "green"];

數組的項數保存在length屬性中( 0+)  經過設置這個屬性, 能夠從數組的末尾移除項 或向數組中添加新項

var colors = ["red", "blue", "green"];

colors.length = 2;

alert(colors[2]);//undefined

colors.length = 4;

alert(colors[3]);//undefined

利用這個特性能夠方便的添加新項

colors[colors.length] = "gray";

colors[colors.length] = "yellow";

5.2.1 檢測數組

5.2.2 轉換方法

全部對象都有 toLocaleString(), toString(), valueOf()方法

var colors = ["red", "blue", "green"]; // 建立一個包含3 個字符串的數組
alert(colors.toString()); // red,blue,green
alert(colors.valueOf()); // red,blue,green
alert(colors); // red,blue,green

若是使用join() 方法, 可使用不一樣的分隔符來建立這個字符串

colors.join("&");// red&blue&green

5.2.3  棧方法

push()方法能夠接收任意數量的參數,把它們逐個添加到數組末尾,並返回修改後數組的長度。而
pop()方法則從數組末尾移除最後一項,減小數組的length 值,而後返回移除的項。

var colors = new Array();

var count = colors.push("green", "blue");

alert(count);//2

var  item = colors.pop();

alert(item);//blue

5.2.4 隊列方法

所以要模擬隊列只需一個從數組前端取得項的方法。實現這一操做的數組方法就是shift(),它可以移
除數組中的第一個項並返回該項,同時將數組長度減1。結合使用shift()和push()方法,能夠像使
用隊列同樣使用數組。

var item = colors.shift();

alert(item);//green

unshift()與shift()的用途相反:
它能在數組前端添加任意個項並返回新數組的長度。所以,同時使用unshift()和pop()方法,能夠
從相反的方向來模擬隊列,即在數組的前端添加項,從數組末端移除項

5.2.5 重排序

數組中有兩個重排序方法

reverse() 反轉數組項的順序

sort() 即便數組中的每一項都是數值, sort() 方法比較的也是字符串(調用每一項的toString()方法 而後比較字符串)

var values = [0, 1, 5, 10, 15];
values.sort();
alert(values); //0,1,10,15,5

sort()方法能夠接收一個比較函數做爲參數,以便咱們指定哪一個值位於哪一個值的前面。
比較函數接收兩個參數,若是第一個參數應該位於第二個以前則返回一個負數,若是兩個參數相等
則返回0,若是第一個參數應該位於第二個以後則返回一個正數

function compare(value1, value2) {//升序
if (value1 < value2) {
return -1;//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

5.2.6 操做方法

001  concat()方法

002 slice() 方法

003 splice()方法

splice()方法始終都會返回一個數組,該數組中包含從原始數組中刪除的項(若是沒有刪除任何
項,則返回一個空數組)

5.2.7 位置方法

indexOf()

lastIndexOf()  

var numbers = [1,2,3,4,5,4,3,2,1];
alert(numbers.indexOf(4,4));
alert(numbers.lastIndexOf(4, 4));

5.2.8 迭代方法

var numbers = [1,2,3,4,5,4,3,2,1];
var everyResult = numbers.every(function(item, index, array){
return (item > 2);
});
alert(everyResult); //false
var someResult = numbers.some(function(item, index, array){
return (item > 2);
});
alert(someResult); //true

var filterResult = numbers.filter(function(item, index, array){
return (item > 2);
});
alert(filterResult); //[3,4,5,4,3]

var mapResult = numbers.map(function(item, index, array){
return item * 2;
});

alert(mapResult); //[2,4,6,8,10,8,6,4,2]

最後一個方法是forEach(),它只是對數組中的每一項運行傳入的函數。這個方法沒有返回值,
本質上與使用for 循環迭代數組同樣。來看一個例子。
var numbers = [1,2,3,4,5,4,3,2,1];
numbers.forEach(function(item, index, array){
//執行某些操做
});

5.2.9 歸併方法

reduce()和reduceRight()。這兩個方法都會迭代數組的全部項,而後構建一個最終返回的值。

其中,reduce()方法從數組的第一項開始,逐個遍歷到最後。

而reduceRight()則從數組的最後一項開始,向前遍歷到第一項

給reduce()和reduceRight()的函數接收4 個參數:前一個值、當前值、項的索引和數組對象。這
個函數返回的任何值都會做爲第一個參數自動傳給下一項。第一次迭代發生在數組的第二項上,所以第
一個參數是數組的第一項,第二個參數就是數組的第二項

var values = [1,2,3,4,5];
var sum = values.reduce(function(prev, cur, index, array){
return prev + cur;
});
alert(sum); //15

reduceRight()的做用相似,只不過方向相反而已

5.3 Date類型

var now = new Date();不傳遞參數的狀況下,新建立的對象自動得到當前日期和時間

001 Date.parse()方法接收一個表示日期的字符串參數,而後嘗試根據這個字符串返回相應日期的毫秒數。

若是直接將表示日期的字符串傳遞給Date 構造函數,也會在後臺調用Date.parse()

var someDate = new Date(Date.parse("May 25, 2004"));等價於

var someDate = new Date("May 25, 2004");

 

002 Date.UTC()  日期和時間都基於本地時區而非GMT 來建立

// GMT 時間2005 年5 月5 日下午5:55:55
var allFives = new Date(Date.UTC(2005, 4, 5, 17, 55, 55));

// 本地時間2005 年5 月5 日下午5:55:55
var allFives = new Date(2005, 4, 5, 17, 55, 55);

003 Data.now()

//取得開始時間
var start = Date.now();

使用+操做符把Data 對象轉換成字符串,也能夠達到一樣的目的。

//取得開始時間
var start = +new Date();

5.3.1 繼承的方法

Date 類型也重寫了toLocaleString()、toString()和valueOf()方法;

5.3.3 日期/時間組件方法  p120

5.4 RegExp類型

建立正則表達式 var expression = /pattern/flags;

其中的模式(pattern)部分能夠是任何簡單或複雜的正則表達式,能夠包含字符類、限定符、分組、向前查找以及反向引用

正則表達式的匹配模式支持下列3 個標誌。
 g:表示全局(global)模式,即模式將被應用於全部字符串,而非在發現第一個匹配項時當即
中止;
 i:表示不區分大小寫(case-insensitive)模式,即在肯定匹配項時忽略模式與字符串的大小寫;
 m:表示多行(multiline)模式,即在到達一行文本末尾時還會繼續查找下一行中是否存在與模
式匹配的項。

所以,一個正則表達式就是一個模式與上述3 個標誌的組合體。不一樣組合產生不一樣結果

001 以字面量形式來定義的正則表達式

/*
* 匹配全部".at",不區分大小寫
*/
var pattern4 = /\.at/gi;

002 RegExp 構造函數建立正則表達式

/*
* 與pattern1 相同,只不過是使用構造函數建立的
*/
var pattern2 = new RegExp("[bc]at", "i");

ECMAScript 5 明確規定,使用正則表達式字面量必須像直接調用RegExp 構造函數同樣,每次都創
建新的RegExp 實例。

5.5 Function類型

函數其實是對象

每一個函數實際上都是Function類型的實例

函數名實際上也是一個指向函數對象的指針

5.5.3 做爲值的函數

function callSomeFunction(someFunction, someArgument){

    return someFunction(someArgument);

}

例子

function createComparisonFunction(propertyName){

  return function(object1, object2){

       var value1 = object1[propertyName];

          var value2 = object2[propertyName];

           if(value1 < value2){

                 return -1;

           }else if( value1 > value2){

          return 1;

         }else{

       return 0;

    }

      }

}

var data = [{name : "zhangsan", age : 15},{name : "lisi", age : 18}];

data.sort(createComparisonFunction('name'));

alert(data[0].name);//lisi

data.sort(createComparisonFunction('age'));

alert(data[0].name);//zhangsan

5.5.4 函數內部屬性

001 arguments對象還有一個名叫callee 的屬性,該屬性是一個指針,指向擁有這個arguments 對象的函數

消除緊密耦合的現象

function factorial(num){
if (num <=1) {
return 1;
} else {
return num * arguments.callee(num-1);
}
}

002 this 對象

window.color = "red";

var o = {color : "blue"};

function sayColor(){

  alert(this.color);

}

sayColor();//red

o.sayColor = sayColor;

o.sayColor();//blue

003 函數對象的屬性 caller

function outer(){
inner();
}
function inner(){
alert(arguments.callee.caller);
}
outer();

5.5.5 函數屬性和方法

001 length屬性

length 屬性表示函數但願接收的命名參數的個數

002 prototype屬性

引用類型而言,prototype 是保存它們全部實例方法的真正所在

 prototype 屬性是不可枚舉的,所以使用for-in 沒法發現

003 apply() 和 call() 非繼承而來的方法 每一個函數都包含

function sum(num1, num2){
return num1 + num2;
}
function callSum1(num1, num2){
return sum.apply(this, arguments); // 傳入arguments 對象
}
function callSum2(num1, num2){
return sum.apply(this, [num1, num2]); // 傳入數組
}
alert(callSum1(10,10)); //20
alert(callSum2(10,10)); //20

在使用call()方法時,傳遞給函數的參數必須逐個列舉出來

function callSum(num1, num2){
return sum.call(this, num1, num2);
}
alert(callSum(10,10)); //20

這兩個方法真正強大的地方是可以擴充函數賴以運行的做用域。

window.color = "red";
var o = { color: "blue" };
function sayColor(){
alert(this.color);
}
sayColor(); //red
sayColor.call(this); //red
sayColor.call(window); //red
sayColor.call(o); //blue

使用call()(或apply())來擴充做用域的最大好處,就是對象不須要與方法有任何耦合關係。

004 bind()

這個方法會建立一個函數的實例 其this 值會被綁定到傳給bind()函數的值。例如:

window.color = "red";
var o = { color: "blue" };
function sayColor(){
alert(this.color);
}
var objectSayColor = sayColor.bind(o);
objectSayColor(); //blue

5.6 基本包裝類型

var s1 = "some text";
var s2 = s1.substring(2);

當第二行代碼訪問s1 時,訪問過程處於一種讀取模式,也就是要從內存中讀取這個字符串的值。

而在讀取模式中訪問字符串時,後臺都會自動完成下列處理

(1) 建立String 類型的一個實例;
(2) 在實例上調用指定的方法;
(3) 銷燬這個實例。

 引用類型與基本包裝類型的主要區別就是對象的生存期。使用new 操做符建立的引用類型的實例,
在執行流離開當前做用域以前都一直保存在內存中。而自動建立的基本包裝類型的對象,則只存在於一
行代碼的執行瞬間,而後當即被銷燬

Object 構造函數也會像工廠方法同樣,根據傳入值的類型返回相應基本包裝類型的實例。例如:
var obj = new Object("some text");
alert(obj instanceof String); //true

5.6.1 Boolean類型

var falseObject = new Boolean(false);
var result = falseObject && true;
alert(result); //true
var falseValue = false;
result = falseValue && true;
alert(result); //false

布爾表達式中的全部對象都會被轉換爲true,所以falseObject 對象在布爾表達式中表明的是true。

基本類型與引用類型的布爾值還有兩個區別。首先,typeof 操做符對基本類型返回"boolean",
而對引用類型返回"object"。其次,因爲Boolean 對象是Boolean 類型的實例,因此使用instanceof
操做符測試Boolean 對象會返回true,而測試基本類型的布爾值則返回false。例如:
alert(typeof falseObject); //object
alert(typeof falseValue); //boolean
alert(falseObject instanceof Boolean); //true
alert(falseValue instanceof Boolean); //false

5.6.2 Number類型

var num = 10;
alert(num.toFixed(2)); //"10.00"

5.6.3 String類型

001 字符方法

charAt()  charCodeAt()

var stringValue = "hello world";
alert(stringValue.charAt(1)); //"e"

var stringValue = "hello world";
alert(stringValue.charCodeAt(1)); //輸出"101"

002 字符串操做方法

concat()用於將一或多個字符串拼接起來,返回拼接獲得的新字符串。

var stringValue = "hello ";
var result = stringValue.concat("world");
alert(result); //"hello world"
alert(stringValue); //"hello"

slice()、substr()和substring()。
這三個方法都會返回被操做字符串的一個子字符串,並且也都接受一或兩個參數

slice()和
substring()的第二個參數指定的是子字符串最後一個字符後面的位置。而substr()的第二個參數指

定的則是返回的字符個數。若是沒有給這些方法傳遞第二個參數,則將字符串的長度做爲結束位置

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"

003 字符串位置方法

indexOf() lastIndexOf()

var stringValue = "hello world";
alert(stringValue.indexOf("o")); //4
alert(stringValue.lastIndexOf("o")); //7

var stringValue = "hello world";
alert(stringValue.indexOf("o", 6)); //7
alert(stringValue.lastIndexOf("o", 6)); //4

004 trim()方法

這個方法會建立一個字符串的副本,刪除前置及後綴的全部空格,而後返回結果。

005 大小寫轉換

toLowerCase()、toLocaleLowerCase()、toUpperCase()和toLocaleUpperCase()

006 字符串模式匹配方法

006-1 match() 只接受一個參數,要麼是一個正則表達式,要麼是一個RegExp 對象 .  本質上與調用RegExp 的exec()方法相同

var text = "cat, bat,  sat, fat";

var pattern = /.at/;

//與pattern.exec(text);相同

var matches = text.match(pattern);

alert(matches.index);//0

alert(matches[0]);//cat

alert(pattern.lastIndex);//0

 006-2 search()

search()方法返回字符串中第一個匹配項的索引;若是沒有找到匹配項,則返回-1。

var pos = text.search(/.at/);

alert(pos);//1

006-3 replace()

這個方法接受兩個參數:第一個參數能夠是一個RegExp 對象或者一個字符串(這個字符串不會被轉換成正則表達式),

第二個參數能夠是一個字符串或者一個函數。

若是第一個參數是字符串,那麼只會替換第一個子字符串。要想替換全部子字符串,惟一的辦法就是提供一個正則表達式,並且要指定全局(g)標誌

var result = text.replace("at", "rocky");

alert(text);//"crocky, bat, sat, fat"

result = text.replace(/at/g, "rocky");

alert(text);//"crocky brocky, srocky, frocky"

replace() 第二個參數也能夠是一個函數 這個函數傳遞3 個參數:模式的匹配項、模式匹配項在字符串中的位置和原始字符串

    function htmlEscape(text){
        return text.replace(/[<>"&]/g, function(match, pos, originalText){
            switch(match){
                case "<" :
                    return "&lt;";
                case ">" :
                    return "&gt;";
                case "&" :
                    return "&amp;";
                case "\"" :
                    return "&quot;";
            
            }
        })
    
    }
    alert(htmlEscape("<p class=\"greeting\">Hello world!</p>"));

006-4 split()

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(/[^\,]+/); //["", ",", ",", ",", ""]

 

007 localeCompare()方法

var stringValue = "yellow";
alert(stringValue.localeCompare("brick")); //1
alert(stringValue.localeCompare("yellow")); //0
alert(stringValue.localeCompare("zoo")); //-1

008 fromCharCode()方法

與實例方法charCodeAt()執行的是相反的操做

alert(String.fromCharCode(104, 101, 108, 108, 111)); //"hello"

5.7 單體內置對象

5.7.1 Global對象 不屬於任何其餘對象的屬性和方法,最終都是它的屬性和方法

沒有全局變量或全局函數;全部在全局做用域中定義的屬性和函數,都是Global 對象的屬性。

001 URI編碼方法

Global 對象的encodeURI()和encodeURIComponent()方法能夠對URI(Uniform ResourceIdentifiers,通用資源標識符)進行編碼

它們的主要區別在於,encodeURI()不會對自己屬於URI 的特殊字符進行編碼,例如冒號、正斜槓、
問號和井字號;而encodeURIComponent()則會對它發現的任何非標準字符進行編碼。

var uri = "http://www.wrox.com/illegal value.htm#start";
//"http://www.wrox.com/illegal%20value.htm#start"
alert(encodeURI(uri));
//"http%3A%2F%2Fwww.wrox.com%2Fillegal%20value.htm%23start"
alert(encodeURIComponent(uri));

decodeURI()只能對使用encodeURI()替換的字符進行解碼

decodeURIComponent()可以解碼使用encodeURIComponent()

002 eval()方法

eval("function sayHi() { alert('hi'); }");
sayHi();

在eval()中建立的任何變量或函數都不會被提高,由於在解析代碼的時候,它們被包含在一個字
符串中;它們只在eval()執行的時候建立。

003 Global對象的屬性

004 window對象

在全局做用域中聲明的全部變量和函數,就都成爲了window對象的屬性。

JavaScript中的window 對象除了扮演ECMAScript規定的Global 對象的角色外,還承擔了不少別的任務

另外一種取得Global 對象的方法是使用如下代碼:
var global = function(){
return this;
}();

5.7.2 Math對象

002 min() max()

var max = Math.max(3, 54, 32, 16);
alert(max); //54
var min = Math.min(3, 54, 32, 16);
alert(min); //3

var values = [1, 2, 3, 4, 5, 6, 7, 8];
var max = Math.max.apply(Math, values);

003 舍入方法

 Math.ceil()執行向上舍入,即它老是將數值向上舍入爲最接近的整數;
 Math.floor()執行向下舍入,即它老是將數值向下舍入爲最接近的整數;
 Math.round()執行標準舍入,即它老是將數值四捨五入爲最接近的整數(這也是咱們在數學課
上學到的舍入規則)。

004 random() 方法

Math.random()方法返回大於等於0 小於1 的一個隨機數。

var num = Math.floor(Math.random() * 10 + 1);// 1.....10

var num = Math.floor(Math.random() * 9 + 2);// 2... 10

值 = Math.floor(Math.random() * 可能值的總數 + 第一個可能的值)

function selectFrom(lowerValue, upperValue){

  var choices = upperValue - lowerValue + 1;

  return Math.floor(Math.random() * choices + lowerValue);

}

var num = selectFrom(2, 10);// 2 || 3..||10

var colors = ["green", "red", "blue", "black", "white"];

var color = colors[selectFrom(0, colors.length-1)];

6 面向對象的程序設計

6.1 理解對象

對象字面量

var person = {

  name : "Zhang san",

  age : 18,

  job : "Software Engineer",

     sayName : function(){

    alert(this.name);

  }

6.1.1屬性類型

001 數據屬性

[[Configurable]]:表示可否經過delete 刪除屬性從而從新定義屬性,可否修改屬性的特
性,或者可否把屬性修改成訪問器屬性。像前面例子中那樣直接在對象上定義的屬性,它們的
這個特性默認值爲true。
 [[Enumerable]]:表示可否經過for-in 循環返回屬性。像前面例子中那樣直接在對象上定
義的屬性,它們的這個特性默認值爲true。
 [[Writable]]:表示可否修改屬性的值。像前面例子中那樣直接在對象上定義的屬性,它們的
這個特性默認值爲true。
 [[Value]]:包含這個屬性的數據值。讀取屬性值的時候,從這個位置讀;寫入屬性值的時候,
把新值保存在這個位置。這個特性的默認值爲undefined。

要修改屬性默認的特性,必須使用ECMAScript 5 的Object.defineProperty()方法。這個方法
接收三個參數:屬性所在的對象、屬性的名字和一個描述符對象。其中,描述符(descriptor)對象的屬
性必須是:configurable、enumerable、writable 和value。設置其中的一或多個值,能夠修改
對應的特性值。例如:

var person = {};

Object.defineProperty(person, name , {

  writable : false,

     value : "zhang san"

});

alert(person.name);//zhangsan

person.name = "lisi";

alert(person.name);//zhangsan

Object.defineProperty(person, name, {

  configurable : false,

   value : "zhangsan"

});

delete person.name;

alert(person.name);//zhangsan

一旦把屬性定義爲不可配置的,就不能再把它變回可配置了

//拋出錯誤
Object.defineProperty(person, "name", {
configurable: true,
value: "Nicholas"
});

002 訪問器屬性

[[Configurable]]:表示可否經過delete 刪除屬性從而從新定義屬性,可否修改屬性的特
性,或者可否把屬性修改成數據屬性。對於直接在對象上定義的屬性,這個特性的默認值爲
true。
 [[Enumerable]]:表示可否經過for-in 循環返回屬性。對於直接在對象上定義的屬性,這
個特性的默認值爲true。
 [[Get]]:在讀取屬性時調用的函數。默認值爲undefined。
 [[Set]]:在寫入屬性時調用的函數。默認值爲undefined。

訪問器屬性不能直接定義,必須使用Object.defineProperty()來定義

    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);

_year 前面的下劃線是一種經常使用的記號,用於表示只能經過對象方法訪問的屬性。

而訪問器屬性year 則包含一個
getter 函數和一個setter 函數。getter 函數返回_year 的值,setter 函數經過計算來肯定正確的版本。所以,
把year 屬性修改成2005 會致使_year 變成 2005,而edition 變爲2。這是使用訪問器屬性的常見方
式,即設置一個屬性的值會致使其餘屬性發生變化。

6.1.2 定義多個屬性

Object.dedineProperties()

利用這個方法能夠經過描述符一次定義多個屬性。這個方法接收兩個對象參數:

第一個對象是要添加和修改其屬性的對象,第二個對象的屬性與第一個對象中要添加或修改的屬性一一對應。

var book = {};

Object.defineProperties(book, {

  _year: {

    value: 2014

  },

   edition: {

    value: 1

  },

  year: {

    get: function(){

      return this._year;

    },

    set: function(newValue){

      if(newValue>2004){

        this._year = newValue;

        this.edition +=  newValue-2004;

      }

     }

  }

});

6.1.3讀取屬性的特性

Object.getOwnPropertyDescriptor(book, "year");

6.2 建立對象

6.2.1 工廠模式

開發人員就發明了一種函數,用函數來封裝以特定接口建立對象的細節

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("zhangsan", 18, "engineer");

var person2 = createPerson("lisi", 16, "doctor");

6.2.2 構造函數模式

function Person(name, age, job){'

  this.name = name;

  this.age = age;

  this.job = job;

  this.sayName = function(){

    alert(this.name);

  }

}

var person3 = new Person("wangwu", 20, "farmer");

alert(person3.constructor == Person);//true

alert(person3 instanceof  Person);//true

alert(person3 instanceof Object);//true

001 將構造函數做爲函數

// 看成構造函數使用
var person = new Person("Nicholas", 29, "Software Engineer");
person.sayName(); //"Nicholas"
// 做爲普通函數調用
Person("Greg", 27, "Doctor"); // 添加到window
window.sayName(); //"Greg"
// 在另外一個對象的做用域中調用

var o = new Object();

Person.call(o, "zhaolui", 22, "worker");

o.sayName();//zhaolui

6.2.3 原型模式

咱們建立的每一個函數都有一個prototype(原型)屬性,這個屬性是一個指針,指向一個對象,
而這個對象的用途是包含能夠由特定類型的全部實例共享的屬性和方法。若是按照字面意思來理解,那
麼prototype 就是經過調用構造函數而建立的那個對象實例的原型對象。使用原型對象的好處是能夠
讓全部對象實例共享它所包含的屬性和方法。換句話說,沒必要在構造函數中定義對象實例的信息,而是
能夠將這些信息直接添加到原型對象中

001 理解原型對象

Person.prototype.constructor指向Person

Person.prototype.isPrototypeOf(person1);//true

Object.getPrototypeOf(person1) == Person.prototype;//true

Object.getPrototypeOf(person1).name ;//"zhangsan"

雖然能夠經過對象實例訪問保存在原型中的值,但卻不能經過對象實例重寫原型中的值。若是咱們
在實例中添加了一個屬性,而該屬性與實例原型中的一個屬性同名,那咱們就在實例中建立該屬性,該
屬性將會屏蔽原型中的那個屬性。

function Person(){}

Person.prototype.name = "zhangsan";

Person.prototype.age = 18;

Person.prototype.sayName = function(){

  alert(this.name);

}

var person1 = new Person();

var person2 = new Person();

person1.name = "lisi";

alert(person1.name);//lisi 來自實例

alert(person2.name);//zhangsan 來自原型

delete person1.name;

alert(person1.name);//zhangsan 來自原型

 

hasOwnProperty()

alert(person1.hasOwnProperty("class"));//false

person1.class = "001";

alert(person1.hasOwnProperty("class"));//true

002 原型與in操做符

alert("name" in person1);//true

 

同時使用hasOwnProperty()方法和in 操做符,就能夠肯定該屬性究竟是存在於對象中,仍是存在於原型中

function hasPrototypeProperty(object, name){

    return !object.hasOwnProperty(name) && (name in object);

}

在使用for-in 循環時,返回的是全部可以經過對象訪問的、可枚舉的(enumerated)屬性,其中
既包括存在於實例中的屬性,也包括存在於原型中的屬性。屏蔽了原型中不可枚舉屬性(即將
[[Enumerable]]標記爲false 的屬性)的實例屬性也會在for-in 循環中返回,由於根據規定,所
有開發人員定義的屬性都是可枚舉的——只有在IE8 及更早版本中例外

取得對象上的全部可枚舉屬性 Object.keys() 這個的方法接受一個對象做爲參數 返回一個包含全部可枚舉屬性的字符串數組

var keys = Object.keys(Person.prototype);

alert(keys);//"name,age, job, sayName"

var p1 = new Person();

p1.name = "zhangsan";

p1.age = 31;

var p1keys = Object.keys(p1);

alert(p1keys);//"name, age"

003 更簡單的原型語法

function Person(){
}
Person.prototype = {
constructor : Person,
name : "Nicholas",
age : 29,
job: "Software Engineer",
sayName : function () {
alert(this.name);
}
};

以這種方式重設constructor 屬性會致使它的[[Enumerable]]特性被設置爲true

//重設構造函數,只適用於ECMAScript 5 兼容的瀏覽器

Object.defineProperty(Person.prototype, "constructor", {

   enumerable: false,

   value: Person

});

004 原型的動態性

005 原生對象的原型

全部原生引用類型(Object、Array、String,等等)都在其構造函數的原型上定義了方法。

6.2.4 組合使用構造函數模式和原型模式

function Person(name, age, job){
    this.name = name;
    this.age = age;
    this.job = job;
    this.friends = ["zhangsan", "lisi"];
}

Person.prototype = {
    constructor: Person,
    sayName: function(){
        alert(this.name);
    }
};

var person1 = new Person("wangwu", 22, "worker");
var person2 = new Person("zhaoliu", 23, "doctor");
person1.friends.push("qianqi");

alert(person1.friends);
alert(person2.friends);
alert(person1.friends == person2.friends);
alert(person2.sayName == person2.sayName);

6.2.5 動態原型模式

function Person(name, age, job){
    this.name = name;
    this.age = age;
    this.job = job;
    if(typeof this.sayName != 'function'){
        Person.prototype.sayName =  function(){
            alert(this.name);
        }
    }
}

var person1 = new Person("wangwu", 22, "worker");
person1.sayName(); 

6.2.6 寄生構造函數模式

    function Person(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 = new Person("zhangwan", 11, "doctor");
    person1.sayName();

6.2.7 穩妥構造函數模式

所謂穩妥對象,指的是沒有公共屬性,並且其方法也不引用this 的對象。

穩妥構造函數遵循與寄生構造函數相似的模式,但有兩點不一樣:一是新建立對象的實例方法不引用this;二是不使用new 操做符調用構造函數。

    function Person(name, age, job){
        var o = new Object();
        o.sayName = function(){
            alert(name);
        }
        return o;
    }
    var person1 = Person("zhangsan", 18, "doctor");
    person1.sayName(); 

6.3 繼承

ECMAScript 只支持實現繼承,並且其實現繼承主要是依靠原型鏈來實現的。

6.3.1原型鏈

    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();
    alert(instance.getSuperValue());
    alert(instance.getSubValue());

 001 別忘記默認的原型Object

002 肯定原型和實例的關係

instance instanceof object//true

object.isProprotypeof(instance)//true

003 謹慎的定義方法 字面量

004 原型鏈的問題

問題一 包含引用類型值的原型屬性會被全部實例共享

問題二 應該說是沒有辦法在不影響全部對象實例的狀況下,給超類型的構造函數傳遞參數

6.3.2 借用構造函數(constructor stealing)

這種技術的基本思想至關簡單,即在子類型構造函數的內部調用超類型構造函數

經過使用apply()和call()方法也能夠在(未來)新建立的對象上執行構造函數,

    function SuperType(){
        this.colors = ["red", "green", "blue"];
    }
    
    
    function SubType(){
        SuperType.call(this);
    }
    
    var instance1 = new SubType();
    instance1.colors.push("black");
    alert(instance1.colors);
    
    var instance2 = new SubType();
    alert(instance2.colors);

001 傳遞參數

      function SuperType(name){
        this.name = name;
    }
    
    
    function SubType(){
        SuperType.call(this, "zhangsan");
        this.age = 12;
    }
    
    var instance1 = new SubType();
    alert(instance1.name);
    alert(instance1.age);

6.3.3 組合繼承(combination inheritance)

     function SuperType(name){
        this.name = name;
        this.colors = ["red", "green", "blue"];
    }
    
    SuperType.prototype.sayName = function(){
        alert(this.name);
    }
    
    function SubType(name, age){
        //繼承屬性
        SuperType.call(this, name);
        this.age = age;
    }
    //繼承方法
    SubType.prototype = new SuperType();
    SubType.prototype.costructor = SubType;
    SubType.prototype.sayAge = function(){
        alert(this.age);
    }
    
    var instance1 = new SubType("zhangsan", 11);
    instance1.colors.push("black");
    instance1.sayName();
    alert(instance1.colors);
    instance1.sayAge();
    
    var instance2 = new SubType("lisi", 22);
    instance2.sayName();
    alert(instance2.colors);
    instance2.sayAge();

6.3.4 原型式繼承(Prototypal inheritance in JavaScript)

道格拉斯·克羅克服 他的想法是藉助原型能夠基於已有的對象建立新對象,同時還沒必要所以建立自定義類型

function object(o){

  function F(){};

  F.prototype = o;

      return new F();

}

在object()函數內部,先建立了一個臨時性的構造函數,而後將傳入的對象做爲這個構造函數的
原型,最後返回了這個臨時類型的一個新實例。從本質上講,object()對傳入其中的對象執行了一次淺複製

    function object(o){
        function F(){}
        F.prototype = o;
        return new F();
    }
    var person = {
        name : "zhangsan",
        friends : ["lisi", "wangwu", "zhaoliu"]
    };
    var anotherPerson = object(person);
    anotherPerson.name = "zhangsan2";
    anotherPerson.friends.push("zhangxiong");
    alert(anotherPerson.name);
    alert(anotherPerson.friends);
    
    var yetAnotherPerson = object(person);
    yetAnotherPerson.name = "zhangsan3";
    yetAnotherPerson.friends.push("zhangwei");
    alert(yetAnotherPerson.name);
    alert(yetAnotherPerson.friends);

ECMAScript 5 經過新增Object.create()方法規範化了原型式繼承。這個方法接收兩個參數:一
個用做新對象原型的對象和(可選的)一個爲新對象定義額外屬性的對象

  var person = {
        name : "zhangsan",
        friends : ["lisi", "wangwu", "zhaoliu"]
    };
    var anotherPerson = Object.create(person, {
        name: {
            value: "zhangsan11"
        }
    });
    alert(anotherPerson.name);

6.3.5 寄生式繼承(parasitic)

    function object(o){
        function F(){}
        F.prototype = o;
        return new F();
    }
    function createAnother(original){
        var clone = object(original);
        clone.sayHi = function(){
            alert("hi");
        }
        return clone;
    }
    var person = {
        name: "zhangsan",
        friends: ["lisi", "wangwu", "qianqi"]
    };
    var anotherPerson = createAnother(person);
    anotherPerson.sayHi();

6.3.6 寄生組合式繼承

所謂寄生組合式繼承,即經過借用構造函數來繼承屬性,經過原型鏈的混成形式來繼承方法。其背
後的基本思路是:沒必要爲了指定子類型的原型而調用超類型的構造函數,咱們所須要的無非就是超類型
原型的一個副本而已。本質上,就是使用寄生式繼承來繼承超類型的原型,而後再將結果指定給子類型
的原型。寄生組合式繼承的基本模式以下所示

    function object(o){
        function F(){}
        F.prototype = o;
        return new F();
    }
    function inheritPrototype(subType, superType){
        var protoobj = object(superType.prototype);//建立對象
        protoobj.constructor = subType;                //加強對象
        subType.prototype = protoobj;                //指定對象
    }
    
    function SuperType(name){
        this.name = name;
        this.colors = ["red", "green", "blue"];
    }
    
    SuperType.prototype.sayName = function(){
        alert(this.name);
    }
    
    function SubType(name, age){
        SuperType.call(this, name);
        this.age = age;
    }
    inheritPrototype(SubType, SuperType);
    SubType.prototype.sayAge = function(){
        alert(this.age);
    }

7 函數表達式

7.1 遞歸

arguments.callee是一個指向正在執行的函數的指針,用它來實現對函數的遞歸調用

//嚴格模式禁用
        function factorial(num){
            if(num<=1){
                return 1;
            }else{
                return num * arguments.callee(num-1);
            }
        }
        alert(factorial(5));

 //能夠用命名函數表達式達到一樣的效果

    var factorial = (function f(num){
            if(num <= 1){
                return 1;
            }else{
                return num * f(num - 1);
            }
    });
    var result = factorial(6);
    alert(result);

7.2 閉包

閉包是指有權訪問另外一個函數做用域中的變量的函數。建立閉包的常見方式,就是在一個函數內部建立另外一個函數

做用域鏈???

7.2.1 閉包與變量

閉包只能取得包含函數中任何變量的最後一個值。別忘了閉包所保存的是整個變量對象,而不是某個特殊的變量

    function createFunctions(){
        var result = new Array();
        for(var i=0; i<10; i++){
            result[i] = function(){
                return i;
            }
        }
        return result;
    }
    var r = createFunctions();
    alert(r[0]());//10 ,10...

創建匿名函數強制讓閉包的行爲符合預期

    function createFunctions(){
        var result = new Array();
        for(var i=0; i<10; i++){
            result[i] = function(num){
                return function(){
                    return num;
                };
            }(i);
        }
        return result;
    }
    var r = createFunctions();
    for(var j=0; j<r.length; j++){
        alert(r[j]());    
    }//0 1 2 ..

7.2.2 關於this對象

匿名函數的執行環境具備全局性, 所以其this對象一般指向window

  var name = "hello window";
  var object = {
    name : "my object",
    getNameFunc : function(){
        return function(){
            return this.name;
        };
    }
  };
  alert(object.getNameFunc()());//hello window

 每一個函數在被調用時都會自動取得兩個特殊變量, this和arguments.

內部函數在搜索這兩個變量時, 只會搜索到其活動對象爲止,所以不可能直接訪問到外部函數中的這兩個變量

不過將外部函數中的this對象保存到閉包可以訪問到的變量裏,就可讓閉包訪問到該對象了 

  var name = "hello window";
  var object = {
    name : "my object",
    getNameFunc : function(){
        var that = this;
        return function(){
            return that.name;
        };
    }
  };
  alert(object.getNameFunc()());//my object

this的值可能會意外的改變

  var name = "hello window";
  var object = {
    name : "my object",
    getNameFunc : function(){
        return this.name;
    }
  };
  alert((object.getNameFunc = object.getNameFunc)());//

7.2.3內存泄漏

  <div id="myid">fffffff</div>
  <script>
window.onload = function(){
    function assignHandler(){
        var element = document.getElementById("myid");
        element.onclick = function(){
            alert(element.id);
        };
    }
    assignHandler();
}
  </script>     

因爲匿名函數保存了一個對assignHandler()活動對象的引用,所以就會致使沒法減小element的引用數  

     function assignHandler(){
        var element = document.getElementById("myid");
        var id = element.id;
        element.onclick = function(){
            alert(id + new Date());
        };
        element = null;
    }
    assignHandler();  

7.3 模仿塊級做用域

用做塊級做用域(一般稱爲私有做用域)的匿名函數的語法以下所示。
(function(){
//這裏是塊級做用域
})();

不管在什麼地方,只要臨時須要一些變量,就可使用私有做用域  

    (function(){
        for(var i=0; i<10; i++){
        
        }
    })();
    
    alert(i);//i is not defined

經過建立私有做用域,每一個開發人員既可使用本身的變量,又沒必要擔憂搞亂全局做用域。

    (function(){
            var now = new Date();
            if(now.getMonth() ==0 && now.getDate() == 8){
                alert("good day 08/01");
            }
    })();

7.4 私有變量

任何在函數中定義的變量,均可以認爲是私有變量,由於不能在函數的外部訪問這些變量

function MyObject(){
//私有變量和私有函數
var privateVariable = 10;
function privateFunction(){
return false;
}
//特權方法
this.publicMethod = function (){
privateVariable++;
return privateFunction();
};
}

7.4.1 靜態私有變量

(function(){
//私有變量和私有函數
var privateVariable = 10;
function privateFunction(){
return false;
}
//構造函數
MyObject = function(){
};
//公有/特權方法
MyObject.prototype.publicMethod = function(){
privateVariable++;
return privateFunction();
};
})();

MyObject 沒使用var 是一個全局的變量

7.4.2 模塊模式

,若是必須建立一個對象並以某些數據對其進行初始化,同時還要公開一些可以訪問這些私有
數據的方法,那麼就可使用模塊模式。

    var application = function(){
        var components = new Array();
         components.push("aaa");
         return {
            getComponentCount : function(){
                return components.length;
            },
            registerComponent : function(component){
                if(typeof component == "object"){
                    components.push(component);
                }
                
            }
         }
        
    }();
    alert(application.getComponentCount());
 7.4.3 加強的模塊模式

    var application = function(){
        var components = new Array();
         components.push(new BaseComponent());
         var app = new BaseComponent();
         app.getComponentCount = function(){
            return components.length;
         };
         app.registerComponent = function(component){
            if(typeof component == "object"){
                components.push(component);
            }
         };
         return app;
        
        
    }();

  8. BOM

8.1 window對象

8.1.2 窗口關係及框架

001 top 對象始終指向最高(最外)層的框架,也就是瀏覽器窗口

       top.frames["topFrame"]

002 與top 相對的另外一個window 對象是parent。顧名思義,parent(父)對象始終指向當前框架的
      直接上層框架。在某些狀況下,parent 有可能等於top;但在沒有框架的狀況下,parent 必定等於
      top(此時它們都等於window)。

003 與框架有關的最後一個對象是self,它始終指向window

8.1.3窗口位置

var leftPos = (typeof window.screenLeft == "number")?(window.screenLeft):(window.screenX);
    var topPos = (typeof windwo.scrreenTop == "number")?(window.screenTop):(windwo.screenY);

使用moveTo()和moveBy()方法卻是有可能將窗口精確地移動到一個新位置。這兩個方法都接收兩個參數,其中

moveTo()接收的是新位置的x 和y 座標值,而moveBy()接收的是在水平和垂直方向上移動的像素數

8.1.4 窗口大小

window.resizeTo(100, 100);//調整到(100, 100)

window.resizeBy(100, 50);//調整到(100+100, 100+50)

8.1.5 導航和打開窗口

001 使用window.open()方法既能夠導航到一個特定的URL,也能夠打開一個新的瀏覽器窗口

接收4 個參數:要加載的URL、窗口目標、一個特性字符串以及一個表示新頁面是否取代瀏覽器歷史記錄中當前加載頁面的布爾值

第二個參數也能夠是下列任何一個特殊的窗口名稱:_self、_parent、_top 或_blank。

    var wroxWin = window.open("http://www.baidu.com", "wroxWindow", "width=400, height=400, top=10, left=10, resizable=true");
    wroxWin.resizeTo(500, 500);
    wroxWin.moveTo(100, 100);
    wroxWin.close();

8.1.6 超時調用和間歇調用

超時調用 window對象的setTimeout()方法, 他接受連個參數 1, 要執行的代碼 2,毫秒錶示的時間

該方法會返回一個數值ID,表示超時調用這個超時調用. ID 是計劃執
行代碼的惟一標識符,能夠經過它來取消超時調用。要取消還沒有執行的超時調用計劃,能夠調用
clearTimeout()方法並將相應的超時調用ID 做爲參數傳遞給它,    

    var num = 0;
    var max = 10;
    var intervalId = null;
    function incrementNumber(){
        num++;
        if(num == max){
            clearInterval(intervalId);
            alert("Done");
        }
    }
    intervalId = setInterval(incrementNumber, 1000);

使用超時調用來模擬間歇調用的是一種最佳模式

8.1.7 系統對話框

alert()、confirm()和prompt()方法能夠調用系統對話框向用戶顯示消息

經過這幾個方法打開的對話框都是同步和模態的。也就是說,顯示這
些對話框的時候代碼會中止執行,而關掉這些對話框後代碼又會恢復執行  

var result = prompt("What's your name?", "");
if(result !== null){
    alert("Welcome "+ result);
}  

8.2 location對象

location 對象是很特別的一個對象,由於它既是window 對象的屬性,也是
document 對象的屬性;換句話說,window.location 和document.location 引用的是同一個對象  

8.2.1 查詢字符串參數

function getQueryStringArguments(){
    //取得查詢字符串並去掉問號
    var qs = (window.location.search.length > 0 ? (window.location.search.substring(1)):""),
        //保存數據的對象
        args,
        //取得每一項
        items = qs.length ? qs.split('&') : [],
        item = null,
        name = null,
        value = null,
        //在for循環中使用
        i = 0,
        len = items.length;
        //逐個將每一項添加到args對象中
        for(i=0; i<len; i++){
            item = items[i].split('=');
            name = decodeURIComponent(item[0]);
            value = decodeURIComponent(item[1]);
            if(name.length){
                args[name] = value;
            }
        }
        return args;
}

8.2.2 位置操做

location.assign("http://www.wrox.com");

//假設初始URL 爲http://www.wrox.com/WileyCDA/
//將URL 修改成"http://www.wrox.com/WileyCDA/#section1"
location.hash = "#section1";
//將URL 修改成"http://www.wrox.com/WileyCDA/?q=javascript"
location.search = "?q=javascript";
//將URL 修改成"http://www.yahoo.com/WileyCDA/"
location.hostname = "www.yahoo.com";
//將URL 修改成"http://www.yahoo.com/mydir/"
location.pathname = "mydir";
//將URL 修改成"http://www.yahoo.com:8080/WileyCDA/"
location.port = 8080;
每次修改location 的屬性(hash 除外),頁面都會以新URL 從新加載。  

location.reload(); //從新加載(有可能從緩存中加載)
location.reload(true); //從新加載(從服務器從新加載)

8.3 navigator對象

 8.3.1 檢測插件

    function hasPlugin(name){
        name = name.toLowerCase();
        for(var i=0; i < navigator.plugins.length; i++){
            if(navigator.plugins[i].name.indexOf(name) > -1){
                return true;
            }
        }
        return false;
    }
    alert(hasPlugin("Flash"));
    alert(hasPlugin("QuickTime"));

IE 是以COM對象的方式實現插
件的,而COM對象使用惟一標識符來標識。所以,要想檢查特定的插件,就必須知道其COM標識符

    function hasIEPlugin(name){
        try{
            new ActiveXObject(name);
            return true;
        }catch(ex){
            return false;
        }
    }
    alert(hasIEPlugin("ShockwaveFlash.ShockwaveFlash"));
    alert(hasIEPlugin("QuickTime.QuickTime")); 

結合

function hasFlash(){
    var result = hasPlugin("Flash");
    if(!result){
        result = hasIEPlugin("ShockwaveFlash.ShockwaveFlash");
    }
    return result;
}

 8.4 screen對象

window.resizeTo(screen.availWidth, screen.availHeight);

8.5 history對象

由於history 是window對象的屬性,所以每一個瀏覽器窗口、每一個標籤頁乃至每一個框架,都有本身的history 對象與特定的
window 對象關聯。

使用go()方法能夠在用戶的歷史記錄中任意跳轉

history.go(-1);//後退一頁

history.go(1);//前進一頁

history.go(2);//前進兩頁

也能夠給go()方法傳遞一個字符串參數

//跳到最近的wrox.com

history.go("wrox.com");

back() forward()替代go()

 

history的length屬性

if(history.length == 0){

  //這應該是用戶打開窗口後的第一個頁面

}

當頁面的URL 改變時,就會生成一條歷史記錄。,這裏所說的改變包括URL 中hash 的變
化(所以,設置location.hash 會在這些瀏覽器中生成一條新的歷史記錄)。

9  客戶端檢測

9.1 能力檢測

function getElement(id){

  if(document.getElementById){

    return document.getElementById(id);

  }else if(document.all){

    return document.all[id];

  }else{

    throw new Error("No way to retrieve element");

  }

}

第一個概念就是先檢測達成目的的最經常使用的特性。

第二個重要的概念就是必須測試實際要用到的特性

9.1.1 更可靠的能力檢測

檢測對象是否支持排序

function isSortable(object){

  return typeof object.sort == "function";

}

ActiveX對象和其餘對象相差很大

function isHostMethod(object, property){
    var t = typeof object[property];
    return t=='function' || (t=='object' && object[property]) || t=='unknown';
}
var xhr = new ActiveXObject("Microsoft.XMLHttp");
alert(isHostMethod(xhr, 'open'));
alert(isHostMethod(xhr, "foo"));

9.1.2 能力檢測不是瀏覽器檢測

var hasNSPlugins = (!!(navigator.plugins && navigator.plugins.length)) ;

var hasDOM1 = (!!(document.getElementById && document.createElement && document.getElementsByTagName)); 

p238

相關文章
相關標籤/搜索