寫在前面:暫時只是粗略的排版,之後還會整理。也可到 http://bulabula.top/高三筆記/筆記7-9.txt 下載TXT版。。javascript
7、函數表達式
1)、定義函數的方式有兩種:函數聲明和函數表達式。
2)、函數聲明提高(function declaration hoisting),意思是在執行代碼以前會先讀取函數聲明。函數聲明能夠放在調用它的語句後面。
3)、函數表達式:建立一個匿名函數(也能夠叫拉姆達函數)並將它賦值給變量。
4)、函數聲明和函數表達式的區別:
函數聲明必須有名字,函數表達式不須要。
函數聲明會提高,函數表達式不會。
函數聲明能夠在任何位置調用,可是函數表達式必須在聲明後調用。
7.1 遞歸
1)、遞歸函數是在一個函數經過名字調用自身的狀況下構成的。
2)、arguments.callee表明函數自己。
7.2 閉包
1)、當在函數內部定義了其餘函數時,就建立了閉包。閉包有權訪問包含函數內部的全部變量,原理以下:
在後臺執行環境中,閉包的做用域鏈包含着它本身的做用域、包含函數的做用域和全局做用域。
函數的做用域及其全部變量都會在函數執行結束後被銷燬。
當函數返回了一個閉包時,這個函數的做用域將會一直在內存中保存到閉包不存在爲止。
7.2.1 閉包與變量
7.2.2 關於this對象
1)、匿名函數的執行環境具備全局性,所以其this 對象一般指向window。
7.2.3 內存泄漏
1)、閉包會引用包含函數的整個活動對象。
7.3 模仿塊級做用域
1)、語法:(function(){ //這裏是塊級做用域 })();
7.4 私有變量
1)、任何在函數中定義的變量,均可以認爲是私有變量。包括:函數的參數、局部變量和在函數內部定義的其餘函數。
2)、特權方法(privileged method):有權訪問私有變量和私有函數的公有方法。
7.4.1 靜態私有變量
7.4.2 模塊模式
7.4.3 加強的模塊模式
8、 BOM
1)、BOM即瀏覽器對象模型。
8.1 window 對象
1)、window 對象既是經過JavaScript 訪問瀏覽器窗口的一個接口,又是ECMAScript 規定的Global 對象。
8.1.1 全局做用域
1)、全局變量不能經過delete 操做符刪除,而直接在window 對象上的定義的屬性能夠。
8.1.2 窗口關係及框架
1)、每一個框架都擁有本身的window 對象,而且保存在frames 集合中。
2)、top 對象始終指向最高(最外)層的框架,也就是瀏覽器窗口。
3)、parent(父)對象始終指向當前框架的直接上層框架。
4)、self對象始終指向window;self 和window 對象能夠互換使用。
8.1.3 窗口位置
1)、跨瀏覽器取得窗口左邊和上邊的位置:
var leftPos = (typeof window.screenLeft == "number") ? window.screenLeft : window.screenX;
var topPos = (typeof window.screenTop == "number") ? window.screenTop : window.screenY;
8.1.4 窗口大小
8.1.5 導航和打開窗口
1)、window.open()方法既能夠導航到一個特定的URL,也能夠打開一個新的瀏覽器窗口。
使用方法:window.open(要加載的URL,窗口目標,一個特性字符串,表示新頁面是否取代瀏覽器歷史記錄中當前加載頁面的布爾值);
可能的值:
窗口目標:
已有窗口或框架的名稱。會在該窗口或框架中加載URL。
_self、_parent、_top 或_blank。
一個特性字符串:
設 置 值 說 明
fullscreen yes或no 表示瀏覽器窗口是否最大化。僅限IE
height 數值 表示新窗口的高度。不能小於100
left 數值 表示新窗口的左座標。不能是負值
location yes或no 表示是否在瀏覽器窗口中顯示地址欄。不一樣瀏覽器的默認值不一樣。若是設置爲no,地址欄可能會隱藏,也可能會被禁用(取決於瀏覽器)
menubar yes或no 表示是否在瀏覽器窗口中顯示菜單欄。默認值爲no
resizable yes或no 表示是否能夠經過拖動瀏覽器窗口的邊框改變其大小。默認值爲no
scrollbars yes或no 表示若是內容在視口中顯示不下,是否容許滾動。默認值爲no
status yes或no 表示是否在瀏覽器窗口中顯示狀態欄。默認值爲no
toolbar yes或no 表示是否在瀏覽器窗口中顯示工具欄。默認值爲no
top 數值 表示新窗口的上座標。不能是負值
width 數值 表示新窗口的寬度。不能小於100
2)、調用close()方法能夠(也僅能夠)關閉window.open()打開的窗口。
3)、新建立的window 對象有一個opener 屬性,其中保存着打開它的原始窗口對象。
8.1.6 間歇調用和超時調用
1)、超時調用須要使用window 對象的setTimeout()方法,它接受兩個參數:要執行的代碼和以毫秒錶示的時間(即在執行代碼前須要等待多少毫秒)。
2)、clearTimeout()方法用來取消超時調用。
栗子: //設置超時調用
var timeoutId = setTimeout(function() {
alert("Hello world!");
}, 1000);
//注意:把它取消
clearTimeout(timeoutId);
3)、超時調用的代碼都是在全局做用域中執行的,所以函數中this 的值在非嚴格模式下指向window 對象,在嚴格模式下是undefined。
4)、間歇調用的方法是setInterval(),它接受的參數與setTimeout()相同:要執行的代碼(字符串或函數)和每次執行以前須要等待的毫秒數。
5)、clearInterval()方法用來取消間歇調用。
栗子: var num = 0;
var max = 10;
var intervalId = null;
function incrementNumber() {
num++;
//若是執行次數達到了max 設定的值,則取消後續還沒有執行的調用
if (num == max) {
clearInterval(intervalId);
alert("Done");
}
}
intervalId = setInterval(incrementNumber, 500);
6)、實際開發中通常用超時調用來模擬間接調用,由於後一個間歇調用可能會在前一個間歇調用結束以前啓動。
栗子: // 倒計時
(function(k) {
var fc = arguments.callee;
setTimeout(function() {
if (k > 0) {
k--;
fc(k);
console.log("set" + k);
}
}, 1000);
})(10);
8.1.7 系統對話框
1)、瀏覽器經過alert()、confirm()和prompt()方法能夠調用系統對話框向用戶顯示消息。
栗子: a、 alert("hellow word");
b、 if(confirm("hellow word")){
alert("OK");
}else{
alert("no OK");
}
c、 var result = prompt("What is your name? ", "");
if (result !== null) {
alert("Welcome, " + result);
}
2)、window.print(); // 顯示"打印"對話框
window.find(); // 顯示"查找"對話框
8.2 location 對象
1)、location 對象提供了與當前窗口中加載的文檔有關的信息,還提供了一些導航功能。它既是window對象的屬性也是document對象的屬性,也就是window.location和document.location引用的是同一對象。
2)、location 對象的全部屬性:
屬性名 栗子 說明
hash "#contents" 返回URL中的hash(#號後跟零或多個字符),若是URL中不包含散列,則返回空字符串
host "www.wrox.com:80" 返回服務器名稱和端口號(若是有)
hostname "www.wrox.com" 返回不帶端口號的服務器名稱
href "http:/www.wrox.com" 返回當前加載頁面的完整URL。而location對象的toString()方法也返回這個值
pathname "/WileyCDA/" 返回URL中的目錄和(或)文件名
port "8080" 返回URL中指定的端口號。若是URL中不包含端口號,則 這個屬性返回空字符串
protocol "http:" 返回頁面使用的協議。一般是http:或https:
search "?q=javascript" 返回URL的查詢字符串。這個字符串以問號開頭
8.2.1 查詢字符串參數
8.2.2 位置操做
1)、assign()方法當即打開新URL 並在瀏覽器的歷史記錄中生成一條記錄。
2)、location 對象的hash、search、hostname、pathname 和port 屬性設置爲新值來也會改變URL,同時也會在歷史記錄中生成一條新記錄。
3)、replace()方法接受一個URL地址,但不會在歷史記錄中生成新記錄。
4)、reload()方法做用是從新加載當前顯示的頁面。會以最有效的方式從新加載(若頁面沒有改變則從緩存中加載),若是須要強制從服務器加載則用location.reload(true)。
8.3 navigator 對象
1)、navigator 對象已經成爲識別客戶端瀏覽器的事實標準。
2)、
8.3.1 檢測插件
8.3.2 註冊處理程序
8.4 screen 對象
1)、screen 對象基本上只用來代表客戶端的能力,其中包括瀏覽器窗口外部的顯示器的信息。
8.5 history 對象
1)、history 對象保存着用戶上網的歷史記錄,從窗口被打開的那一刻算起。
2)、go()方法能夠在用戶的歷史記錄中任意跳轉,能夠向後也能夠向前。這個方法接受一個參數,表示向後或向前跳轉的頁面數的一個整數值。
3)、back()和forward()模仿瀏覽器的「後退」和「前進」按鈕。
4)、history 對象還有一個length 屬性,保存着歷史記錄的數量。
9、 客戶端檢測
9.1 能力檢測
1)、能力檢測:在編寫代碼以前先檢測特定瀏覽器的能力。例如,腳本在調用某個函數以前,可能要先檢測該函數是否存在。這種檢測方法將開發人員從考慮具體的瀏覽器類型和版本中解放出來,讓他們把注意力集中到相應的能力是否存在上。能力檢測沒法精確地檢測特定的瀏覽器和版本。
9.2 怪癖檢測
1)、怪癖檢測(quirks detection):怪癖其實是瀏覽器實現中存在的bug,例如早期的WebKit 中就存在一個怪癖,即它會在for-in 循環中返回被隱藏的屬性。怪癖檢測一般涉及到運行一小段代碼,而後肯定瀏覽器是否存在某個怪癖。因爲怪癖檢測與能力檢測相比效率更低,所以應該只在某個怪癖會干擾腳本運行的狀況下使用。怪癖檢測沒法精確地檢測特定的瀏覽器和版本。
9.3 用戶代理檢測
1)、經過檢測用戶代理字符串來識別瀏覽器(navigator.userAgent 屬性能夠查看用戶代理字符串)。用戶代理字符串中包含大量與瀏覽器有關的信息,包括瀏覽器、平臺、操做系統及瀏覽器版本。用戶代理字符串有過一段至關長的發展歷史,在此期間,瀏覽器提供商試圖經過在用戶代理字符串中添加一些欺騙性信息,欺騙網站相信本身的瀏覽器是另一種瀏覽器。用戶代理檢測須要特殊的技巧,特別是要注意Opera會隱瞞其用戶代理字符串的狀況。即使如此,經過用戶代理字符串仍然可以檢測出瀏覽器所用的呈現引擎以及所在的平臺,包括移動設備和遊戲系統。
2)、如下爲完整的用戶代理字符串檢測腳本,包括檢測呈現引擎、平臺、Windows 操做系統、移動設備和遊戲系統。
var client = function() {
//呈現引擎
var engine = {
ie: 0,
gecko: 0,
webkit: 0,
khtml: 0,
opera: 0,
//完整的版本號
ver: null
};
//瀏覽器
var browser = {
//主要瀏覽器
ie: 0,
firefox: 0,
safari: 0,
konq: 0,
opera: 0,
chrome: 0,
//具體的版本號
ver: null
};
//平臺、設備和操做系統
var system = {
win: false,
mac: false,
x11: false,
//移動設備
iphone: false,
ipod: false,
ipad: false,
ios: false,
android: false,
nokiaN: false,
winMobile: false,
//遊戲系統
wii: false,
ps: false
};
//檢測呈現引擎和瀏覽器
var ua = navigator.userAgent;
if (window.opera) {
engine.ver = browser.ver = window.opera.version();
engine.opera = browser.opera = parseFloat(engine.ver);
} else if (/AppleWebKit\/(\S+)/.test(ua)) {
engine.ver = RegExp["$1"];
engine.webkit = parseFloat(engine.ver);
//肯定是Chrome 仍是Safari
if (/Chrome\/(\S+)/.test(ua)) {
browser.ver = RegExp["$1"];
browser.chrome = parseFloat(browser.ver);
} else if (/Version\/(\S+)/.test(ua)) {
browser.ver = RegExp["$1"];
browser.safari = parseFloat(browser.ver);
} else {
//近似地肯定版本號
var safariVersion = 1;
if (engine.webkit < 100) {
safariVersion = 1;
} else if (engine.webkit < 312) {
safariVersion = 1.2;
} else if (engine.webkit < 412) {
safariVersion = 1.3;
} else {
safariVersion = 2;
}
browser.safari = browser.ver = safariVersion;
}
} else if (/KHTML\/(\S+)/.test(ua) || /Konqueror\/([^;]+)/.test(ua)) {
engine.ver = browser.ver = RegExp["$1"];
engine.khtml = browser.konq = parseFloat(engine.ver);
} else if (/rv:([^\)]+)\) Gecko\/\d{8}/.test(ua)) {
engine.ver = RegExp["$1"];
engine.gecko = parseFloat(engine.ver);
//肯定是否是Firefox
if (/Firefox\/(\S+)/.test(ua)) {
browser.ver = RegExp["$1"];
browser.firefox = parseFloat(browser.ver);
}
} else if (/MSIE ([^;]+)/.test(ua)) {
engine.ver = browser.ver = RegExp["$1"];
engine.ie = browser.ie = parseFloat(engine.ver);
}
//檢測瀏覽器
browser.ie = engine.ie;
browser.opera = engine.opera;
//檢測平臺
var p = navigator.platform;
system.win = p.indexOf("Win") == 0;
system.mac = p.indexOf("Mac") == 0;
system.x11 = (p == "X11") || (p.indexOf("Linux") == 0);
//檢測Windows 操做系統
if (system.win) {
if (/Win(?:dows )?([^do]{2})\s?(\d+\.\d+)?/.test(ua)) {
if (RegExp["$1"] == "NT") {
switch (RegExp["$2"]) {
case "5.0":
system.win = "2000";
break;
case "5.1":
system.win = "XP";
break;
case "6.0":
system.win = "Vista";
break;
case "6.1":
system.win = "7";
break;
default:
system.win = "NT";
break;
}
} else if (RegExp["$1"] == "9x") {
system.win = "ME";
} else {
system.win = RegExp["$1"];
}
}
}
//移動設備
system.iphone = ua.indexOf("iPhone") > -1;
system.ipod = ua.indexOf("iPod") > -1;
system.ipad = ua.indexOf("iPad") > -1;
system.nokiaN = ua.indexOf("NokiaN") > -1;
//windows mobile
if (system.win == "CE") {
system.winMobile = system.win;
} else if (system.win == "Ph") {
if (/Windows Phone OS (\d+.\d+)/.test(ua)) {;
system.win = "Phone";
system.winMobile = parseFloat(RegExp["$1"]);
}
}
//檢測iOS 版本
if (system.mac && ua.indexOf("Mobile") > -1) {
if (/CPU (?:iPhone )?OS (\d+_\d+)/.test(ua)) {
system.ios = parseFloat(RegExp.$1.replace("_", "."));
} else {
system.ios = 2; //不能真正檢測出來,因此只能猜想
}
}
//檢測Android 版本
if (/Android (\d+\.\d+)/.test(ua)) {
system.android = parseFloat(RegExp.$1);
}
//遊戲系統
system.wii = ua.indexOf("Wii") > -1;
system.ps = /playstation/i.test(ua);
//返回這些對象
return {
engine: engine,
browser: browser,
system: system
};
}();
html