1. 程式人生 > >Javascript高階程式設計重讀

Javascript高階程式設計重讀

Javascript高階程式設計重讀

基本概念

typeof null // object

特殊值null被認為是一個空的物件引用

if(car != null){
	// 對car進行某些操作
}

如果定義的變數準備在將來用於儲存物件,最好將該變數初始化為null

null === undefined // false
null == undefined // true
資料型別 轉換為true的值 轉換為false的值
Boolean true false
String 任何非空字串 “”
Number 任何非零數字 0和NaN
Object 任何物件 null
Undefined n/a undefined
NaN == NaN // false

NaN與任何值都不相等,包括自己。可以使用isNaN()來判斷是否“不是數值”

String(null) // 'null'
null.toString() // cannot read property 'toString' of null
String(undefined) // 'undefined' undefined.toString() // cannot read property 'toString' of null

null與undefined沒有toString方法,但是可以用String轉型函式來實現轉型

var num = 20
--num // 19
num + 20 // 39

前置遞增(遞減)時,變數會在複製之前就被改變,相應的:

var num = 20
num-- + 20 // 40
num + 20 // 39

typeof可以確定一個變數是字串、數值、布林值還是undefined的最佳工具。但是當判斷null和物件時都會返回’object’

typeof null // 'object'
typeof {} // 'object'
var a = {};
a instanceof Object // true

可以用instanceof來判斷到底是物件還是null

var color = 'blue'
function getColor(){
	var color = 'red';
	return color;
}
color // 'blue'
getColor() // 'red'
color //’blue'

搜尋過程從作用域鏈的前端開始,向上逐級查詢與給定名字匹配的識別符號。如果在區域性環境中找到 了該識別符號,搜尋過程停止,變數就緒。如果在區域性環境中沒有找到該變數名,則繼續沿作用域鏈向上 搜尋。搜尋過程將一直追溯到全域性環境的變數物件。

var colors = ['black', 'red', 'blue']
colors instanceof Array // true
Array.isArray(colors) // true

但是如果有兩個框架意味著兩個全域性空間和兩個Array建構函式,所以有另外一個方法Array.isArray(value)來判斷是否為陣列

colors.push('white') // 4
colors // ['red', 'blue', 'black', 'white']
colors.pop() // 'white'

陣列模擬棧(後進先出),有push和pop方法,可以完成陣列的推入和彈出。push可以推入多個引數,按左到右的順序進行增加,pop則彈出最後一個引數。

colors.push('white', 'green')
colors.shift() // ['blue', 'black', 'white', 'green']
colors.unshift('red', 'brown') // ['red', 'brown', 'blue', 'black', 'white', 'green']

模擬佇列(先進先出),有shift方法,實現在陣列的第一個位置刪除引數。使用unshift方法可以在陣列的前端增加n個引數

console.log(sum(10, 10)) // 20
function sum(num1, num2){
	return num1 + num2
}

解析器會優先讀取函式宣告,使其在任何其他程式碼可用之前可用,如上例,函式定義在後,但是依然可以獲取結果。(函式宣告提升)

function fibonacci(n) {
    if(n==0 || n == 1)
        return n;
    return fibonacci(n-1) + fibonacci(n-2);
}

斐波那契數列優化:

function fibonacci(n){
	if(n == 0 || n == 1){
		return n;
	}
	return arguments.callee(n-1) + arguments.callee(n - 2)
}

Function中有一個arguments內部有callee,實際上可以呼叫當前函式,這樣fibonacci執行完畢後會等待垃圾回收銷燬,不會一直佔用記憶體。

call與apply方法的區別在於接受引數的方式不同,call()需要在使用時將傳遞的引數全部列出來:

function sum(num1, num2){
	return num1 + num2
}
function callSum1(num1, num2){
	return sum.call(this, num1, num2)
}
function callSum2(num1, num2){
	return sum.apply(this, [num1, num2]);
}
function callSum3(num1, num2){
	return sum.apply(this, arguments);
}

如上,apply方法則接受arguments或者一個數組。也就是說apply方法最多接受兩個引數,而call方法則可以接受多個引數。

var bar = function(){
	console.log(this.x);
}
var foo = {
	x:3
}
bar(); // undefined
var func = bar.bind(foo);
func(); // 3

如果bind有多個引數,那麼第一個引數作為要被繫結的物件,之後的引數作為被呼叫的方法的引數使用

fucntion test(){
	return console.log.bind(console, ...arguments)()
}
test(1, 2, 3) // 1 2 3

當多次呼叫bind時,僅第一次有效

var bar = function(){
    console.log(this.x);
}
var foo = {
    x:3
}
var sed = {
    x:4
}
var func = bar.bind(foo).bind(sed);
func(); //?
 
var fiv = {
    x:5
}
var func = bar.bind(foo).bind(sed).bind(fiv);
func(); //?

apply,call,bind的區別

var obj = {
    x: 81,
};
 
var foo = {
    getX: function() {
        return this.x;
    }
}
 
console.log(foo.getX.bind(obj)());  //81
console.log(foo.getX.call(obj));    //81
console.log(foo.getX.apply(obj));   //81

都可以繫結this,call和apply是立即執行的,而bind需要在後邊加圓括號來執行函式。bind可以應用在回撥函式上。

var a = '123456789'
var b = a.substring(1, 4) // 234
var c = a.substr(1, 4) // 2345
var d = a.slice(1,4) // 234

substring和slice第二個引數是擷取的終點,擷取到的內容是終點前一個字元,substr方法第二個引數是擷取的字串的長度。

Math.floor()執行向下舍入;Math.round()四捨五入;Math.ceil()執行向上舍入

var name = 'window';
var obj = {
	name: 'obj',
	getName: function(){
		return function(){
			return this.name
		}	
   }
}
console.log(obj.getName()()) // window

在全域性函式中,this指向的是window,當函式被作為某個物件的方法來呼叫時,this指向的是當前物件,匿名函式的執行環境具有全域性性,因此有時候指向的是window。

事件

點選某個div標籤會先發生時間捕獲,然後到達目標接收事件,最後是事件冒泡。這裡寫圖片描述

DOM0級事件處理程式

例如onclick事件:

var btn = document.getElementById("myBtn");
btn.onclick = function(){
	alert(this.id)
}

DOM0級事件處理的優點是簡單、跨瀏覽器,但是缺點是這些程式碼執行以前不會指定事件處理程式,因此如果這些程式碼位於某個按鈕後面,就有可能在一段時間內怎麼點選都沒有反應。
以此種方式新增的事件會在事件流的冒泡階段被處理,也可以:

btn.onclick = null

通過以上方式刪除事件處理程式

DOM2級事件處理程式

兩分方法,處理指定和刪除事件處理程式:addEventListener()和removeEventListener()。兩個方法均接受三個引數:要處理的事件名,作為事件處理程式的函式和一個布林值,最後的布林值為false時,表示冒泡階段呼叫該事件,為true時表示捕獲階段呼叫事件。

var btn = document.getElementById('myBtn')
btn.addEventListener('click', function(){
	alert(this.id);
}, false)
btn.addEventListener('click', function(){
	alert('hello world')
}, false)

如上程式碼可以在同一個按鈕上新增多個事件,事件會按順序執行。但使用以上方法書寫程式碼時會造成無法移除事件的問題,由於移除時傳入的引數與新增時使用的引數要一致,所以使用匿名函式時會造成無法移除事件。

var btn = document.getElementById('myBtn');
var handle= function(){
	alert(this.id)
}
btn.addEventListener('click', handle, false);
btn.removeEventListener('click', handle, false);

使用以上程式碼則可以解決無法移除監聽click事件的問題。大多數情況是將處理程式新增到冒泡階段,即第三個引數為false,只有需要在事件到達目標之前截獲它的時候才設為true。

IE事件處理程式

IE實現了與DOM中類似的兩個方法:attackEvent()和detachEvent()。IE8及更早版本只支援冒泡,所以此方式新增的事件處理程式都會被新增到冒泡階段。

var btn = document.getElementById('myBtn');
var handle= function(){
	alert(this.id) // 此時this指向window
}
btn.attackEvent('onclick', handle, false);
btn.detachEvent('onclick', handle, false);

在IE中使用attachEvent()與使用DOM0級方法的主要區別在於事件處理程式的作用域。在使用DOM0級方法的情況下,事件處理程式會在其所屬元素作用域內執行;在使用attachEvent()方法時,事件處理程式會在全域性作用域中執行。
當新增多個事件處理程式時,與DOM方法不同的是,這些事件處理程式的執行程式是從後往前的。與DOM事件類似,detachEvent生效需要傳入相同的引數。還有一點不同就是“onclick”而不是“click”

跨瀏覽器的事件處理程式

var EventUtil = {
	addHandler: function(element, type, handler){
		if(element.addEventListener){
			element.addEventListener(type, handler, false);
		} else if(element.attachEvent){
			ement.attachEvent("on" + type, handler);
		} else {
			element['on' + type] = handler;
		}
	},
	removeHandler: function(element, type, handler){
		if(element.removeEventListener){
			element.removeEventListener(type, handler, false);
		} else if (element.detachEvent){
			element.detachEvent('on' + type, handler);
		} else {
			element['on' + type] = null
		}
	}
}

preventDefault()和stopPropagation()

要阻止特定事件的預設行為,可以使用preventDefault()。例如,連線的預設行為是在被單擊時導航到其href指定的url,如果想阻止導航這一預設行為,可以使用該方法取消它:

var link = document.getElementById('myLink');
link.onclick = function(event){
	event.preventDefault()
}

想立即停止事件在DOM層次中傳播,即取消進一步的時間捕獲或冒泡。使用stopPropagation()。例如:

var btn = document.getElementById('myBtn')
btn.onclick = function(event){
	alert("clicked");
	event.stopPropagation();
}
document.body.onclick = function(event){
	alert("body clicked")
}

以上程式碼如果沒有event.stopPropagation()則會依次彈出兩個alert。

跨瀏覽器的事件物件

var EventUtil = {
	addHandler: function(element, type, handler){
		if(element.addEventListener){
			element.addEventListener(type, handler, false);
		} else if(element.attachEvent){
			ement.attachEvent("on" + type, handler);
		} else {
			element['on' + type] = handler;
		}
	},
	getEvent: function(event){
		return event ? event : window.event
	},
	getTarget: function(event){
		return event.target || event.srcElement
	},
	preventDefault: function(event){
		if(event.preventDeafult){
			event.preventDefault();
		} else {
			event.returnValue = false;
		}
	},
	removeHandler: function(element, type, handler){
		if(element.removeEventListener){
			element.removeEventListener(type, handler, false);
		} else if (element.detachEvent){
			element.detachEvent('on' + type, handler);
		} else {
			element['on' + type] = null
		}
	},
	stopPropagation: function(event){
		if(event.stopPropagation){
			event.stopPropagation();
		} else {
			event.cancelBubble = true;
		}
	}
}

事件委託

<ul id="myLinks">
        <li id="goSomewhere">Go somewhere</li>
        <li id="doSomething">Do something</li>
        <li id="sayHi">Say Hi</li>
</ul>
document.getElementById('myLinks').addEventListener('click', function (event) {
    switch(event.target.id){
        case "doSomething":
            console.log('doSomething');
            break;
        case "goSomewhere":
            console.log("goSomewhere");
            break;
        case "sayHi":
            console.log("sayHi")
            break;
    }
})

由於所有項都是這個元素的子節點,所以最後事件冒泡會冒泡到myLinks上,所以可以通過檢測id來判斷當前點選的li。

如果可行的話可以考慮為document物件新增一個事件處理程式,優點如下:

  • document物件很快就可以訪問,而且可以在生命週期的任何時間點新增處理程式
  • 在頁面中設定事件處理程式所需時間更少
  • 整個頁面佔用的記憶體空間更少,能提升整體效能

模擬事件

可以在document上使用createEvent()方法建立event物件。這個方法接受一個引數,即表示要建立的事件型別的字串。例如模擬滑鼠事件:

var btn = document.getElementById('myBtn');
var event = document.createEvent('MouseEvents');
event.initMouseEvent('click', true, true, document.defaultView, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
btn.dispatchEvent(event);

AJAX

為支援IE7早期版本,需要如下程式碼:

function createXHR(){
	if(typeof XMLHttpRequest != "undefined"){
		return new XMLHttpRequest();
	} else if (typeof ActiveXObject != "undefined"){
		if(typeof arguments.callee.activeXString != "string"){
			var versions = ["MSXML2 .XMLHttp.6.0"6.0", "MSXML2.XMLHttp.3.0",
"MSXML2.XMLHttp"], i, len;
			for (i=0, len = versions.length; i< len; i++){
				try{
					new ActiveXObject(versions[i]);
					arguments.callee.activeXString = versions[i];
					break;
				} catch (ex){
					// jump
				}
			}
			return new ActiveXObject(arguments.callee.activeXString);
		}
	} else {
		throw new Error("No XHR object available.")
	}
}
var xhr = createXHR()
var xhr = createXHR();
xhr.onreadystatechange = function(){
	if(xhr.readyState == 4){
		if((chr.status >= 200 && chr.status < 300) || chr.status == 304){
			alert(xhr.responseText);
		} else {
			alert("Request was unsuccessful: " + xhr.status)
		}
	}
}
xhr.open("get", "example.txt"
            
           

相關推薦

Javascript高階程式設計重讀

Javascript高階程式設計重讀 基本概念 typeof null // object 特殊值null被認為是一個空的物件引用 if(car != null){ // 對car進行某些操作 } 如果定義的變數準備在將來用於儲存物件,最好將該變數初始化為null

javascript高階程式設計之---繼承

物件的繼承  1.繼承的思想:關鍵是將一個建構函式A的原型指向給另一個建構函式B的例項本身,那麼A例項將擁有(繼承)B例項的所有的屬性和方法(繼承在原型);   2.原理:將一個建構函式A的原型指向給另一個建構函式B的例項本身,也就意味著A原型將繼承B例項本身擁有的所

javascript高階程式設計之--自執行函式

什麼是自執行函式? 顧名思義.就是不用呼叫,自己自動就會執行的函式; 為什麼要用自執行函式? 自執行函式內部是一個獨立的作用域,這樣就保持了一個相對獨立的名稱空間,避免汙染全域性作用域 怎麼建立自執行函式? 寫法一:(function(param){…})(re—param)

javascript高階程式設計--單體內建物件

global:單體內建物件; encodeURL(url):對url進行編碼,事實上只會對url中的空格進行編碼(%20),其他的都不會變,與之對應的是decodeURL(),換句話說只能反解析%20; encodeURLComponent(url):也是對url進行編碼,與encod

JavaScript高階程式設計之客戶端檢測

瀏覽器檢測,是個很讓人頭痛但又必須要考慮的一個問題。畢竟市面上的瀏覽器廠商眾多,雖然有些標準化的東西約束著他們,但是有些東西,他們還是各自按自己的意願來。這其中以IE瀏覽器最為突出,它幾乎可以被稱之為萬惡之源。 瀏覽器檢測的方法有很多,這裡介紹的可能並不是全部,但基本上都是比較常用的方法。下邊我就來詳細介紹

JavaScript高階程式設計之事件

當用戶按下某個按鈕是,就會觸發對應事件,事件在執行註冊事件時,繫結的程式,實現一次成功的瀏覽器與JS之間的互動。其中事件基於設計模式中的觀察者模式原理實現,但又有些不同,事件它還擁有著一些屬於自己的特點。 事件流   事件冒泡是IE的產物,它的流向,是自下向上,從繫結事件的具體元素開始,一直流到具體元素的

JavaScript高階程式設計》筆記第一部分(ECMA5)

JavaScript分三部分: ECMAScript BOM DOM 瀏覽器組成: shell 核心 主流瀏覽器: IE trident Chrome webkit/blink firefox Gecko Opera presto Safari we

小白讀《JavaScript高階程式設計》DOM拓展部分

DOM拓展 DOM兩個主要的拓展是Selectors API和HTML5。 選擇符API jQuery核心:通過CSS選擇符查詢DOM文件取得元素的引用,從而拋開了getElementById()和getElementByTagName()。 SelectorsAPI Lecel

小白讀《JavaScript高階程式設計》DOM基礎部分

DOM DOM(文件物件模型)是針對HTML和XML文件 的一個API(應用程式程式設計介面)。 節點層次 DOM可以將任何HTML或XML文件描繪成一個由多層節點構成的結構。 每個文件只能有一個文件元素,在HTML頁面中,文件元素始終都是<html>元素。 總共有1

小白讀《JavaScript高階程式設計》BOM部分筆記

BOM 如果要在Web中使用JavaScript,那麼BOM(瀏覽器物件模型)是真正的核心。 BOM提供了很多物件,用於訪問瀏覽器的功能,這些功能與任何網頁內容無關。 window物件 BOM的核心物件是window,它表示瀏覽器的一個例項。 window物件的雙重身份:

JavaScript高階程式設計》——JS基本概念之資料型別

ECMAScript 中有五種簡單資料型別(基本資料型別):Undefined、Null、Boolean、Number 和 String。還有一種複雜資料模型:Object。 資料型別 1 typeof 操作符 typeof 用來檢測給定變數的資料型別。對一個值使用 typeof

JavaScript高階程式設計(第3版)》高清中文版.pdf

書籍簡介: 《JavaScript高階程式設計(第3版)》是JavaScript超級暢銷書的最新版。ECMAScript5和HTML5在標準之爭中雙雙勝出,使大量專有實現和客戶端擴充套件正式進入規範,同時也為JavaScript增添了很多適應未來發展的新特性。 《JavaScript高階程

JavaScript高階程式設計》事件及最佳實踐簡記

5種類型:undefined, boolean, string, number, object 使用typeof結果新增:null, function ECMAScript5中為陣列提供五種迭代方法 every(), filt

JavaScript高階程式設計學習筆記之事件

1、事件流 事件流描述的是從頁面中接收事件的順序。 事件冒泡 IE的事件流叫做事件冒泡(event bubbling),即事件開始時由最具體的元素(文件中巢狀層次最深的那個節點)接收,然後逐級向上傳播到較為不具體的節點(文件)。(DOM樹向上傳播)(通俗解釋(個人理解: 當一個元素上的事件被觸發的時候,比如

JavaScript高階程式設計讀書筆記之JSON

JSON(JavaScript Object Notation)JavaScript物件表示法。JSON是JavaScript的一個嚴格的子集,利用了JavaScript中的一些模式來表示結構化資料。關於JSON,最重要的是理解它是一種資料格式,不是一種程式語言。雖然具有相同的語法形式,但JSON並不從屬於J

JavaScript高階程式設計(讀書筆記)之函式表示式

定義函式的方式有兩種:一種是函式宣告,另一種就是函式表示式。 函式宣告的一個重要特徵就是函式宣告提升(function declaration hoisting),意思是在執行程式碼前會先讀取函式宣告。 這個例子不會報錯,因為程式碼在執行前會先讀取函式宣告。理解函式提升的關鍵就是區別函式宣告和函式表示式之

JavaScript高階程式設計(讀書筆記)之BOM

BOM(Browser Object Model)提供了很多物件用於訪問瀏覽器的功能,這些功能與任何網頁內容無關。 8.1 window物件 BOM的核心物件是window,它表示一個瀏覽器例項。在瀏覽器中,window物件有雙重角色,window物件既是JavaScript訪問瀏覽器視窗的一個介面,又是E

JavaScript高階程式設計第三版學習筆記(一)之資料型別區分詳談

  null、NaN、undefined三者的區別是什麼?   在初次接觸到JavaScript的時候,傻傻的分不清null、NaN、undefined三者到底區別何在,在實際的專案開發中也因為這個問題而困惑久矣。針對這個問題,我特意查找了多方資料,在筆記本上做了詳細的分析記錄,但是由於紙質資料不便於攜帶、

Javascript高階程式設計學習筆記(三)—— JS中的資料型別(1)

 前一段時間由於事情比較多,所以筆記耽擱了一段時間,從這一篇開始我會盡快寫完這個系列。 文章中有什麼不足之處,還望各位大佬指出。 JS中的資料型別 上一篇中我寫了有關JS引入的Script標籤相關的東西。 那麼這一篇,我們可以正式進入JS的世界了,emmm 前面的東西應該比較基礎,大佬們不

javascript 高階程式設計》 筆記2 8~章

chapter 8 BOM(瀏覽器物件模型) window物件   表示瀏覽器的一個例項。      直接在window物件上定義的屬性可以通過delete操作符刪除,而全域性變數不可以。  視窗關係及框架 位置操作   setTimeout(function