Javascript高級程序設(shè)計
最近想把Javascript再擼一篇,加深理解。所以在啃
Javascript高級程序設(shè)計。在這里記錄下那些易遺忘的知識點記錄下來,方便以后回顧。會一直更新。
1.瀏覽器作用
瀏覽器的主要功能就是向服務(wù)器發(fā)出請求,在瀏覽器窗口中展示您選擇的網(wǎng)絡(luò)資源。這里所說的資源一般是指 HTML 文檔,也可以是 PDF、圖片或其他的類型。資源的位置由用戶使用 URI(統(tǒng)一資源標示符)指定。
2.瀏覽器高層結(jié)構(gòu)
1. 用戶界面 - 包括地址欄、前進/后退按鈕、書簽菜單等。除了瀏覽器主窗口顯示的您請求的頁面外,其他顯示的各個部分都屬于用戶界面。
2. 瀏覽器引擎 - 在用戶界面和呈現(xiàn)引擎之間傳送指令。
3. 呈現(xiàn)引擎 - 負責顯示請求的內(nèi)容。如果請求的內(nèi)容是 HTML,它就負責解析 HTML 和 CSS 內(nèi)容,并將解析后的內(nèi)容顯示在屏幕上。
4. 網(wǎng)絡(luò) - 用于網(wǎng)絡(luò)調(diào)用,比如 HTTP請求。其接口與平臺無關(guān),并為所有平臺提供底層實現(xiàn)。
5. 用戶界面后端 - 用于繪制基本的窗口小部件,比如組合框和窗口。其公開了與平臺無關(guān)的通用接口,而在底層使用操作系統(tǒng)的用戶界面方法。
6. JavaScript 解釋器。用于解析和執(zhí)行 JavaScript 代碼。
7. 數(shù)據(jù)存儲。這是持久層。瀏覽器需要在硬盤上保存各種數(shù)據(jù),例如 Cookie。新的 HTML 規(guī)范 (HTML5) 定義了“網(wǎng)絡(luò)數(shù)據(jù)庫”,這是一個完整(但是輕便)的瀏覽器內(nèi)數(shù)據(jù)庫。
3.主流程
呈現(xiàn)引擎將開始**解析 HTML 文檔**,并將各標記逐個轉(zhuǎn)化成“內(nèi)容樹”上的 DOM 節(jié)點。同時也會解析外部 CSS 文件以及樣式元素中的樣式數(shù)據(jù)。HTML 中這些帶有視覺指令的樣式信息將用于創(chuàng)建另一個樹結(jié)構(gòu):呈現(xiàn)樹。
呈現(xiàn)樹包含多個帶有視覺屬性(如顏色和尺寸)的矩形。這些矩形的排列順序就是它們將在屏幕上顯示的順序。
呈現(xiàn)樹構(gòu)建完畢之后,進入“布局”處理階段,也就是為每個節(jié)點分配一個應(yīng)出現(xiàn)在屏幕上的確切坐標。下一個階段是繪制 - 呈現(xiàn)引擎會遍歷呈現(xiàn)樹,由**用戶界面后端層將每個節(jié)點繪制出來。
需要著重指出的是,這是一個漸進的過程。為達到更好的用戶體驗,呈現(xiàn)引擎會力求盡快將內(nèi)容顯示在屏幕上。它不必等到整個 HTML 文檔解析完畢之后,就會開始構(gòu)建呈現(xiàn)樹和設(shè)置布局。在不斷接收和處理來自網(wǎng)絡(luò)的其余內(nèi)容的同時,呈現(xiàn)引擎會將部分內(nèi)容解析并顯示出來。
4.什么是JavaScript解析引擎?
簡單地說,JavaScript解析引擎就是能夠“讀懂”JavaScript代碼,并準確地給出代碼運行結(jié)果的一段程序。比方說,當你寫了 var a = 1 + 1; 這樣一段代碼,JavaScript引擎做的事情就是看懂(解析)你這段代碼,并且將a的值變?yōu)?。
學過編譯原理的人都知道,對于靜態(tài)語言來說(如Java、C++、C),處理上述這些事情的叫編譯器(Compiler),相應(yīng)地對于JavaScript這樣的動態(tài)語言則叫解釋器(Interpreter)。這兩者的區(qū)別用一句話來概括就是:編譯器是將源代碼編譯為另外一種代碼(比如機器碼,或者字節(jié)碼),而解釋器是直接解析并將代碼運行結(jié)果輸出。比方說,firebug的console就是一個JavaScript的解釋器。
但是,現(xiàn)在很難去界定說,JavaScript引擎它到底算是個解釋器還是個編譯器,因為,比如像V8(Chrome的JS引擎),它其實為了提高JS的運行性能,在運行之前會先將JS編譯為本地的機器碼(native machine code),然后再去執(zhí)行機器碼(這樣速度就快很多),相信大家對JIT(Just In Time Compilation)一定不陌生吧。
我個人認為,不需要過分去強調(diào)JavaScript解析引擎到底是什么,了解它究竟做了什么事情我個人認為就可以了。對于編譯器或者解釋器究竟是如何看懂代碼的,翻出大學編譯課的教材就可以了。
這里還要強調(diào)的就是,JavaScript引擎本身也是程序,代碼編寫而成。比如V8就是用C/C++寫的。
5. JavaScript解析引擎與ECMAScript是什么關(guān)系?
JavaScript引擎是一段程序,我們寫的JavaScript代碼也是程序,如何讓程序去讀懂程序呢?這就需要定義規(guī)則。比如,之前提到的var a = 1 + 1;,它表示:
左邊var代表了這是申明(declaration),它申明了a這個變量
右邊的+表示要將1和1做加法
中間的等號表示了這是個賦值語句
最后的分號表示這句語句結(jié)束了
上述這些就是規(guī)則,有了它就等于有了衡量的標準,JavaScript引擎就可以根據(jù)這個標準去解析JavaScript代碼了。那么這里的ECMAScript就是定義了這些規(guī)則。其中ECMAScript 262這份文檔,就是對JavaScript這門語言定義了一整套完整的標準。其中包括:
var,if,else,break,continue等是JavaScript的關(guān)鍵詞
abstract,int,long等是JavaScript保留詞
怎么樣算是數(shù)字、怎么樣算是字符串等等
定義了操作符(+,-,>,<等)
定義了JavaScript的語法
定義了對表達式,語句等標準的處理算法,比如遇到==該如何處理
??
標準的JavaScript引擎就會根據(jù)這套文檔去實現(xiàn),注意這里強調(diào)了標準,因為也有不按照標準來實現(xiàn)的,比如IE的JS引擎。這也是為什么JavaScript會有兼容性的問題。
簡單的說,ECMAScript定義了語言的標準,JavaScript引擎根據(jù)它來實現(xiàn),這就是兩者的關(guān)系。
6.input="type='number'"會有滾輪
去除瀏覽器默認樣式
input::-webkit-outer-spin-button, //谷歌瀏覽器
input::-webkit-inner-spin-button {
-webkit-appearance: none;
}
input[type="number"] { //火狐瀏覽器
-moz-appearance: textfield;
}
7.javascirpt嚴格模式use-strict
嚴格模式為javascript定義了一種不同的解析和執(zhí)行模型。在嚴格模式下,ECMAscript3中的一些不確定的行為將得到處理,而且對某些不安全的操作也會拋出錯誤。給未經(jīng)申明的變量賦值在嚴格模式下會報ReferenceError 錯誤。
1.腳本頂部:"use strict";
2.函數(shù)體頂部:function doSomething(){
"use strict";
}
8.NaN
JS中,0除以0是NaN,正數(shù)除以0為Infinity,負數(shù)除以0為-Infinity因此不會影響其他代碼的執(zhí)行。
- [x] 任何涉及NaN的操作都將返回NaN
- [x] NaN與任何值都不相等,包括自身
console.log(NaN == NaN); //false
isNaN()函數(shù)用來判斷參數(shù)不是一個數(shù),該函數(shù)還將會把參數(shù)嘗試著轉(zhuǎn)成數(shù)值,再去判斷
alert(isNaN(NaN)); //true
alert(isNaN(10)); //false 10
alert(isNaN("10")); //false 10
alert(isNaN("blue")); //true
alert(isNaN(true)); //false 1
9.break continue
break語句會立即退出循環(huán),強制執(zhí)行循環(huán)以后的語句。
continue語句雖然也是退出循環(huán),但退出循環(huán)后,會退出循環(huán)從循環(huán)的頂部繼續(xù)執(zhí)行
//break
var num = 0;
for (var i=1; i < 10; i++) {
if (i % 5 == 0) {
break;
}
num++;
}
console.log(num); //4
//containue
var num = 0;
for (var i=1; i < 10; i++) {
if (i % 5 == 0) {
continue;
}
};
console.log(num); //8
10.基本數(shù)據(jù)類型、引用數(shù)據(jù)類型
1.在js中分為基本數(shù)據(jù)類型和引用數(shù)據(jù)類型
2.基本數(shù)據(jù)類型保存那些基本數(shù)據(jù)片段,而引用數(shù)據(jù)類型中保存著對堆內(nèi)存中對象的引用,是一個指針。與其他語言的不同是,你不可以直接訪問堆內(nèi)存空間中的位置和操作堆內(nèi)存空間。只能操作對象在棧內(nèi)存中的引用地址。
3.引用類型數(shù)據(jù)在棧內(nèi)存中保存的實際上是對象在堆內(nèi)存中的引用地址。通過這個引用地址可以快速查找到保存中堆內(nèi)存中的對象。
4.在將一個保存著基本數(shù)據(jù)類型的變量復(fù)制給另一個變量時,會將原始值的副本賦值給新變量,此后這兩個變量是完全獨立的,他們只是擁有相同的value而已。
5.在將一個保存著對象內(nèi)存地址的變量復(fù)制給另一個變量時,會把這個內(nèi)存地址賦值給新變量,也就是說這兩個變量都指向了堆內(nèi)存中的同一個對象,他們中任何一個作出的改變都會反映在另一個身上。(這里要理解的一點就是,復(fù)制對象時并不會在堆內(nèi)存中新生成一個一模一樣的對象,只是多了一個保存指向這個對象指針的變量罷了)。多了一個指針。
6.可以為引用數(shù)據(jù)類型值添加屬性和方法,不可以為基本數(shù)據(jù)類型值添加屬性和方法。
資料鏈接:[資料鏈接](http://www.cnblogs.com/cxying93/p/6106469.html)
11.typeof instanceof
`typeof`能夠辨別基本數(shù)據(jù)類型,卻無法辨別引用數(shù)據(jù)類型,只能判斷出來是對象,而無法判定是什么類型的對象。
`instanceof`可以判斷一個引用數(shù)據(jù)類型是什么類型的對象。
12.執(zhí)行環(huán)境
執(zhí)行環(huán)境定義了變量或者函數(shù)有權(quán)訪問的的其他數(shù)據(jù),每個執(zhí)行環(huán)境都有一個與之關(guān)聯(lián)的變量對象。環(huán)境中定義的的所有變量和函數(shù)都保存在這個對象中。我們編寫代碼時,無法去操控這個對象,但解析器在處理數(shù)據(jù)時,會在后臺使用他們。
全局執(zhí)行環(huán)境被認為是window對象,因為所有的全局變量和函數(shù)都是被當作屬性和方法創(chuàng)建的。
某個執(zhí)行環(huán)境中的所有代碼執(zhí)行完畢后,該環(huán)境中的所有變量和函數(shù)定義也將被銷毀。
每個函數(shù)都有自己的執(zhí)行環(huán)境,當執(zhí)行流進入一個函數(shù)時,函數(shù)的環(huán)境就被推入一個環(huán)境棧中,當函數(shù)執(zhí)行完畢之后,棧將起環(huán)境推出,把控制權(quán)返回給之前的執(zhí)行環(huán)境。ECMAscript程序的執(zhí)行流正是由這個機制控制著。
函數(shù)在處于執(zhí)行流時,會沿著作用域鏈去尋找變量,作用域鏈的前端始終是當前執(zhí)行代碼所在環(huán)境的變量對象下一個變量來自外部環(huán)境,再下一個來自下一個包含環(huán)境。一層一層往外尋找,當找到第一個符合變量時,不在繼續(xù)尋找,當沒有找到時,會報錯。
13.垃圾回收機制
javascript具有垃圾回收機制,執(zhí)行環(huán)境會管理代碼執(zhí)行過程中的內(nèi)存使用。
原理:找到那些不在繼續(xù)使用的變量,然后釋放其內(nèi)存。
方式:1.標記清除
這是javascript中最常用的垃圾回收方式。當變量進入執(zhí)行環(huán)境是,就標記這個變量為“進入環(huán)境”。從邏輯上講,永遠不能釋放進入環(huán)境的變量所占用的內(nèi)存,因為只要執(zhí)行流進入相應(yīng)的環(huán)境,就可能會用到他們。當變量離開環(huán)境時,則將其標記為“離開環(huán)境”。
垃圾收集器在運行的時候會給存儲在內(nèi)存中的所有變量都加上標記。然后,它會去掉環(huán)境中的變量以及被環(huán)境中的變量引用的標記。而在此之后再被加上標記的變量將被視為準備刪除的變量,原因是環(huán)境中的變量已經(jīng)無法訪問到這些變量了。最后。垃圾收集器完成內(nèi)存清除工作,銷毀那些帶標記的值,并回收他們所占用的內(nèi)存空間。
2.引用計數(shù)
另一種不太常見的垃圾回收策略是引用計數(shù)。引用計數(shù)的含義是跟蹤記錄每個值被引用的次數(shù)。當聲明了一個變量并將一個引用類型賦值給該變量時,則這個值的引用次數(shù)就是1。相反,如果包含對這個值引用的變量又取得了另外一個值,則這個值的引用次數(shù)就減1。當這個引用次數(shù)變成0時,則說明沒有辦法再訪問這個值了,因而就可以將其所占的內(nèi)存空間給收回來。這樣,垃圾收集器下次再運行時,它就會釋放那些引用次數(shù)為0的值所占的內(nèi)存。
14.Array.prototype
數(shù)組對象的方法,都是通過繼承構(gòu)造函數(shù)Array的原型對象方法而來的??梢栽跒g覽器查看window.Array.prototype
一:數(shù)組插入和移除數(shù)組元素
1.push()
從數(shù)組的末尾插入任意多的元素,返回值為新數(shù)組長度。
var colors = new Array();
var count = colors.push("red", "green");
console.log(count); //2
2.pop()
從數(shù)組末尾移除一項,返回值為被移除的項。
var name = ["tom","jack","tony"];
var result = name.pop();
console.log(result);//"tony"
3.shift()
移除數(shù)組的第一項,返回值為被移除的項。和pop對立!
var name = ["tom","jack","tony"];
var result = name.shift();
console.log(result);//"tom"
4.unshift()
從數(shù)組的開頭插入任意多的元素,返回值為新數(shù)組長度。和push()對立!
var colors = ["javascript","css","html"];
var count = colors.unshift("jquery", "vue");
console.log(count); //5
二:數(shù)組排序
1.sort(function)
sort排序并不會按照我們的意愿去排列數(shù)組,如果調(diào)用該方法時沒有使用參數(shù),將按字母順序?qū)?shù)組中的元素進行排序,說得更精確點,是按照字符編碼的順序進行排序。要實現(xiàn)這一點,首先應(yīng)把數(shù)組的元素都轉(zhuǎn)換成字符串toString(),以便進行比較。
要想按照我們?nèi)藶榈囊庠?對數(shù)值數(shù)組進行排序:
可使用:arrayObj.sort(function(a,b){
return a-b;
})
2.reverse()
reverse會把數(shù)組中的元素顛倒過來。
三:數(shù)組截取
1.slice(a,b)
slice為數(shù)組截取,有兩個參數(shù),即是返回項的起始和結(jié)束位置。當只有一個參數(shù)時,會從當前數(shù)組項截取到數(shù)組末尾。當兩個參數(shù)時,返回起始和結(jié)束項位置的元素,但是不包括結(jié)束位置的項。slice方法不影響原始數(shù)組。
2.splice(a,b,c)
1.刪除-用于刪除元素,兩個參數(shù),第一個參數(shù)(要刪除第一項的位置),第二個參數(shù)(要刪除的項數(shù))
2.插入-向數(shù)組指定位置插入任意項元素。三個參數(shù),第一個參數(shù)(插入位置),第二個參數(shù)(0),第三個參數(shù)(插入的項)
3.替換-向數(shù)組指定位置插入任意項元素,同時刪除任意數(shù)量的項,三個參數(shù)。第一個參數(shù)(起始位置),第二個參數(shù)(刪除的項數(shù)),第三個參數(shù)(插入任意數(shù)量的項)
四:位置方法
indexOf/lastIndexOf
分別為從數(shù)組的第一個元素和數(shù)組的最后一個元素查找特定項,返回值為查找的項在數(shù)組中的位置。
var numbers = [1,2,3,4,5,4,3,2,1];
console.log(numbers.indexOf(4)); //3
console.log(numbers.lastIndexOf(4)); //5
五:迭代方法
1、every(): 對數(shù)組中的每一項運行給定的函數(shù),如果該函數(shù)對每一項都返回true,則結(jié)果返回true。
2、filter(): 對數(shù)組中的每一項運行給定函數(shù),返回該函數(shù)會返回true的項組成的數(shù)組。
3、forEach(): 對數(shù)組中的每一項運行給定函數(shù),這個方法沒有返回值。
4、map(): 對數(shù)組中的每一項運行給定函數(shù),返回每次函數(shù)調(diào)用的結(jié)果組成的數(shù)組。
5、some(): 對數(shù)組中的每一項運行給定函數(shù),如果該函數(shù)任意一項返回true,則返回true。
var numbers = [1, 2, 3, 4, 5, 4, 3, 2, 1];
//every,每一項是否都滿足
var everyResult = numbers.every(function(item, index, array) {
return (item > 2);
});
//some,是否有一些滿足
var someResult = numbers.some(function(item) {
return (item > 2);
});
console.log(everyResult); //false
console.log(someResult); //true
//filter,找到符合條件的項
var numbers = [1, 2, 3, 4, 5, 4, 3, 2, 1];
var filterResult = numbers.filter(function(item) {
return (item > 2);
});
console.log(filterResult); \\[3, 4, 5, 4, 3]
//map,就是對數(shù)組中的每一項執(zhí)行操作,再返回數(shù)組
var numbers = [1, 2, 3, 4, 5, 4, 3, 2, 1];
var mapResult = numbers.map(function(item) {
return (item * 2);
});
console.log(mapResult); //[2, 4, 6, 8, 10, 8, 6, 4, 2]
//forEach和for循環(huán)差不多,一般是用來循環(huán)數(shù)組元素,做一些操作
var numbers = [1, 2, 3, 4, 5, 4, 3, 2, 1];
numbers.forEach(function(item, index, arr) {
//這里執(zhí)行一些操作
});
六:并歸
reduce()/reduceRight()
很多時候需要累加數(shù)組項的得到一個值(比如說求和)。之前都是用for循環(huán),會很out...
reduce()方法接收一個函數(shù)callbackfn作為累加器(accumulator),數(shù)組中的每個值(從左到右)開始合并,最終為一個值。第二個參數(shù)可選,即是人為的插入并歸起始項。
var arr = [0,1,2,3,4];
arr.reduce(function (preValue,curValue,index,array) {
return preValue + curValue;
}); //10
reduceRight()方法和reduce方法雷同,只不過從右邊并歸開始。
16.元素寬高和位置
- 頁面適口大?。次覀兛匆姷捻撁妫?/li>
var pageWidth = window.innerWidth,//頁面適口寬度
pageHeight = window.innerHeight;//頁面適口高度
if (typeof pageWidth != "number"){
if (document.compatMode == "CSS1Compat"){
pageWidth = document.documentElement.clientWidth;
pageHeight = document.documentElement.clientHeight;
} else {
pageWidth = document.body.clientWidth;
pageHeight = document.body.clientHeight;
- 窗口位置
var leftPos = (typeof window.screenLeft == "number") ?
window.screenLeft : window.screenX;//窗口距左
var topPos = (typeof window.screenTop == "number") ?
window.screenTop : window.screenY;//窗口距右
- 元素
原生js中:
offsetHeight/offsetWidth:帶邊框高/寬
clientHeight/offsetWidth:不帶邊框高/寬
offsetTop/offsetLeft:相對視窗的上邊/左邊
jQuery中:
$(".box").offset().top/.left:相對視窗的上邊/左邊(和上面原生js一樣)
$(".box").position().top/.left:相對父元素的上邊/左邊
$(".box").height(num)/width(num):獲取/設(shè)置一個元素的寬高(不包括邊框和padding)
$(".box").innerHeight()/innerWidth():獲取一個元素的寬高(包含padding)
$(".box").outerHeight()/outerWidth():獲取一個元素的寬高(包含padding和border)
- 事件對象獲取目標元素坐標值
$(".box").click(function(e){
e.pageX/pageY:指的是觸發(fā)事件距離于頁面左邊和頂端的距離
e.clientX/clientY:指的是觸發(fā)事件距離于適口左邊和頂端的距離
e.offsetX/offsetY:指的是觸發(fā)事件距離于觸發(fā)目標左邊和頂端的距離
e.screenX/screenY:指的是觸發(fā)事件距離于屏幕左邊和頂端的距離
})
11.直客通-gitlab圖片

zkt-count.gif