JavaScript快速入門

一、概述

JavaScript是世界上最流行的腳本語言师抄,是一種運行在瀏覽器中的解釋型的編程語言,能夠?qū)崿F(xiàn)跨平臺教硫、跨瀏覽器叨吮。雖然只是十多天時間的產(chǎn)物辆布,并且有很多的缺陷和陷阱,但也造就了JavaScript的靈活和強大茶鉴。隨著Node.js的興起锋玲,JavaScript已經(jīng)從單純實現(xiàn)前端互動,發(fā)展到可以全棧實現(xiàn)整個應(yīng)用涵叮。尤其是在移動互聯(lián)網(wǎng)蓬勃發(fā)展以及應(yīng)用追求極致用戶體驗的今天惭蹂,JavaScript更是必須要重視和掌握的。

二割粮、變量

1盾碗、變量的聲明

使用var關(guān)鍵字進(jìn)行變量的聲明,聲明的同時也可以進(jìn)行賦值舀瓢。變量的聲明只能有一次廷雅,但賦值可以有多次。如果只聲明變量氢伟,但是變量沒有被賦值榜轿,此時變量的值為undefined幽歼。

var s = "Hello";

由于JavaScript屬于動態(tài)語言朵锣,所以在定義變量時,不需要指定變量的類型甸私〕闲可以把任意數(shù)據(jù)類型賦值給變量,同一個變量可以使用不同的數(shù)據(jù)類型反復(fù)賦值皇型。

2诬烹、變量的提升

根據(jù)JavaScript的規(guī)則,變量的聲明會被提升弃鸦,但是變量的初始化并不會被提升绞吁。函數(shù)外聲明的變量,會被提升到文檔頂部唬格。函數(shù)內(nèi)聲明的變量家破,會被提升到函數(shù)頂部。

function f() {
    var x = 1 + y;
    alert(x);
    var y = 2;
}
alert(x);

如果變量在函數(shù)內(nèi)沒有聲明购岗,該變量會被提升為全局變量汰聋。

function f() {
    x = 1;
}
alert(x);

3、變量的作用域

如果變量在函數(shù)內(nèi)聲明喊积,則該變量的作用域為整個函數(shù)體烹困,在函數(shù)外不可訪問,屬于局部變量乾吻。

function f() {
    var x = 1;
}
alert(x);

函數(shù)可以嵌套髓梅,內(nèi)部函數(shù)可以訪問外部函數(shù)定義的變量拟蜻,反之則不可。

function outer() {
    var x = 1;
    function inner() {
        var y = x + 1;
        alert(y);
    }
    var z = y + 1;
    alert(z);
}

如果內(nèi)部函數(shù)與外部函數(shù)定義了相同的變量枯饿,根據(jù)就近原則瞭郑,內(nèi)部函數(shù)的變量會覆蓋外部函數(shù)的變量。

function outer() {
    var x = 1;
    function inner() {
        var x = 2;
        alert(x);
    }
}

三鸭你、函數(shù)

1屈张、函數(shù)的定義

定義函數(shù)有兩種方式:聲明和表達(dá)式。

1.1函數(shù)聲明

function function_name(parameters) {
    ......
}

函數(shù)聲明后不會馬上執(zhí)行袱巨,只有被調(diào)用的時候才會執(zhí)行阁谆。

1.2函數(shù)表達(dá)式

var f = function (parameters) {
    ......    
};
f(parameters);

將函數(shù)存儲在變量中,之后可以通過變量名來調(diào)用愉老,而不需要函數(shù)名稱场绿。

2、函數(shù)的參數(shù)

函數(shù)有個內(nèi)置的對象arguments嫉入,包含了函數(shù)調(diào)用的所有參數(shù)焰盗。

參數(shù)有兩種傳遞方式:值傳遞和引用傳遞。

2.1值傳遞

函數(shù)只是獲取參數(shù)值咒林,如果修改參數(shù)的值熬拒,不會改變參數(shù)的原始值,在函數(shù)外是不可見的垫竞。

2.2引用傳遞

函數(shù)獲得的是對象的引用澎粟,在函數(shù)內(nèi)部修改對象屬性時,會改變屬性的原始值欢瞪,在函數(shù)外可見活烙。

3、函數(shù)的調(diào)用

函數(shù)可以通過四種方式進(jìn)行調(diào)用遣鼓。

3.1 自我調(diào)用

函數(shù)表達(dá)式啸盏,如果后面緊跟(),則會自動自我調(diào)用骑祟。聲明的函數(shù)不能自我調(diào)用回懦。

(function () {
    alert("Hello");
})();

3.2 作為函數(shù)被調(diào)用

當(dāng)函數(shù)沒有被其他對象調(diào)用時,函數(shù)默認(rèn)是window全局對象的函數(shù)曾我。此時this的值是window全局對象粉怕。

function f() {
    alert("Hello");
    return this;
};
f();

3.3 作為方法被調(diào)用

可以將函數(shù)定義為對象的方法,該對象是函數(shù)的所有者抒巢。當(dāng)使用對象調(diào)用方法時贫贝,此時的this值指向調(diào)用函數(shù)的對象。

var obj = {
    x : 1,
    y : 2,
    f : function () { return this.x + this.y;}
};
obj.f();

3.4 作為構(gòu)造函數(shù)被調(diào)用

如果使用new關(guān)鍵字,實際是創(chuàng)建了一個新的對象稚晚。新對象會繼承構(gòu)造函數(shù)的屬性和方法崇堵。此時this值指向新創(chuàng)建的對象。為了區(qū)分普通函數(shù)和構(gòu)造函數(shù)客燕,約定構(gòu)造函數(shù)的首字母為大寫鸳劳。

function F(x, y) {
    this.x = x;
    this.y = y;
};
var obj = new F(1, 2);

3.5 call和apply

函數(shù)是一個對象,可以調(diào)用call或apply方法也搓。此時this值指向方法傳遞的對象赏廓。

function f(x, y) {
    return x+y;
};
arr = [1, 2];
f.call(obj, 1, 2);
f.apply(obj, arr);

call和apply方法的唯一區(qū)別就是前者傳遞整個參數(shù)列表,而后者傳遞一個參數(shù)數(shù)組傍妒。

4幔摸、閉包

內(nèi)嵌函數(shù)可以訪問上一層函數(shù)的變量。閉包是可以訪問上一層函數(shù)作用域里變量的函數(shù)颤练。如果上一層函數(shù)返回閉包函數(shù)既忆,那么就可以在上一層函數(shù)的外部訪問該函數(shù)的私有變量。利用閉包嗦玖,可以實現(xiàn)調(diào)用公共方法患雇,訪問私有變量。

此時返回的函數(shù)并沒有立刻執(zhí)行宇挫,只有在調(diào)用返回函數(shù)時才真正執(zhí)行苛吱。因為返回函數(shù)不會馬上執(zhí)行,所以返回函數(shù)不要引用循環(huán)變量或后續(xù)會發(fā)生變化的變量捞稿。否則又谋,在真正執(zhí)行的時候拼缝,引用的變量可能已經(jīng)發(fā)生改變娱局。

如果必須引用的話,可以再創(chuàng)建一個函數(shù)咧七,用該函數(shù)的參數(shù)綁定循環(huán)變量的值衰齐。這樣,循環(huán)變量的值雖然發(fā)生了改變继阻,但綁定到參數(shù)的值不會隨之改變耻涛。

四、對象

1瘟檩、對象的定義

對象的定義有兩種方式抹缕。

由若干鍵值對組成,并將其賦值給一個變量墨辛。

var person = {
    name : "sean",
    age : "20",
    sayHello : function() {
        alert("Hello " + name);
    }
};
person.sayHello();

使用函數(shù)定義對象卓研,然后創(chuàng)建新的對象實例。

function person(name, age) {
    this.name = name;
    this.age = age;
};
var p = new person("sean", 20);

2、屬性和方法

由于JavaScript的對象是動態(tài)類型奏赘,所以可以給一個對象添加或刪除屬性寥闪。當(dāng)訪問的屬性不存在時,會返回undefined磨淌。如果要判斷一個屬性是否屬于某對象疲憋,可以使用in操作符。這里要注意的是梁只,該屬性可能是對象繼承得來的缚柳。如果要判斷一個屬性是否屬于某對象自身,可以使用hasOwnProperty方法搪锣。

3喂击、原型

雖然JavaScript可以面向?qū)ο缶幊蹋械膶ο蠖际菍嵗傧瑁粫^(qū)分類和實例的概念翰绊。要想實現(xiàn)類的概念,就需要借助原型旁壮。

首先創(chuàng)建一個相當(dāng)于類概念的對象實例监嗜。

var person = {
    name : "",
    age : "",
    sayHello : function() {
        alert("Hello " + this.name);
    }
};

然后創(chuàng)建一個新的對象實例,使其依賴這個原型抡谐。

var sean = {
    name : "sean"
};
sean.__prototype__ = person;
sean.sayHello();

也可以使用Object.create()方法裁奇,傳入一個原型對象,并創(chuàng)建一個基于該原型的新對象麦撵。

var sean = Object.create(person);
sean.name = "sean";
sean.sayHello();

4刽肠、創(chuàng)建對象

JavaScript對每個創(chuàng)建的對象都會設(shè)置一個原型,指向該對象的原型對象免胃。除了直接創(chuàng)建一個對象外音五,還可以使用構(gòu)造函數(shù)來創(chuàng)建對象。使用構(gòu)造函數(shù)創(chuàng)建的對象羔沙,會從原型獲得一個constructor屬性躺涝,該屬性指向構(gòu)造函數(shù)本身。

5扼雏、原型鏈

當(dāng)訪問一個對象的屬性時坚嗜,首先在當(dāng)前對象上查找該屬性。如果沒有找到诗充,就到其原型對象上查找苍蔬。如果還沒有找到,就一直上溯到Object的原型對象蝴蜓。如果還沒有找到碟绑,就返回undefined。這樣就形成了一條原型鏈。

因為函數(shù)也是對象蜈敢,所以函數(shù)也擁有原型鏈辜荠。首先是函數(shù)本身,然后是Function.prototype抓狭,最后是Object.prototype伯病。

6、繼承

繼承不僅僅是對象的屬性和方法的繼承否过,原型鏈也要體現(xiàn)出繼承關(guān)系午笛。

首先,定義新的構(gòu)造函數(shù)苗桂,并在內(nèi)部調(diào)用希望繼承的構(gòu)造函數(shù)药磺,實現(xiàn)屬性和方法的繼承。

其次煤伟,借助中間函數(shù)癌佩,將新的構(gòu)造函數(shù)的原型指向繼承的構(gòu)造函數(shù)的原型,實現(xiàn)原型鏈繼承便锨。

最后围辙,將新的構(gòu)造函數(shù)的constructor屬性重新指向新的構(gòu)造函數(shù)。

7放案、瀏覽器對象

window對象不但是全局對象姚建,還表示瀏覽器窗口。
屬性innerWidth和innerHeight分別表示瀏覽器窗口的內(nèi)部寬度和高度吱殉,即用于顯示網(wǎng)頁的凈寬高掸冤。屬性outerWidth和outerHeight分別表示瀏覽器窗口的整個寬度和高度。

navigator對象表示瀏覽器的信息友雳。屬性appName表示瀏覽器名稱稿湿。屬性appVersion表示瀏覽器版本。屬性language表示瀏覽器設(shè)置的語言沥阱。屬性platform表示操作系統(tǒng)類型缎罢。屬性userAgent表示瀏覽器設(shè)定的User-Agent字符串。

screen對象表示屏幕的信息考杉。屬性width表示屏幕寬度,單位是像素舰始。屬性height表示屏幕高度崇棠,單位是像素。屬性colorDepth表示顏色位數(shù)丸卷。

location對象表示當(dāng)前頁面的URL信息枕稀。屬性href表示整個URL。屬性protocal表示使用的協(xié)議。屬性host表示主機名萎坷。屬性port表示端口號凹联。屬性pathname表示訪問的路徑。屬性search表示查詢參數(shù)哆档。方法assign加載一個新頁面蔽挠。方法reload重載當(dāng)前頁面。

document對象表示當(dāng)前頁面瓜浸。屬性title表示瀏覽器窗口的標(biāo)題澳淑。屬性cookie獲取當(dāng)前頁面的Cookie。方法getElementById按照元素的id獲取一個DOM節(jié)點插佛。方法getElementByTabName按照元素的標(biāo)簽名稱獲取一組DOM節(jié)點杠巡。

history對象保存瀏覽器的歷史記錄。

五雇寇、DOM

當(dāng)頁面被加載時氢拥,瀏覽器解析HTML文檔,并會創(chuàng)建頁面的文檔對象模型DOM锨侯。DOM是一個樹形結(jié)構(gòu)兄一,通過操作DOM節(jié)點,可以訪問或改變文檔的所有元素识腿。針對DOM的操作主要有四種:查找出革、更新、插入渡讼、刪除骂束。

1、查找

要想操作DOM節(jié)點成箫,首先需要找到要操作的節(jié)點展箱。

  • 通過id查找
    調(diào)用document.getElementById方法查找指定id的元素。

  • 通過標(biāo)簽名查找
    調(diào)用document.getElementByTagName方法查找指定標(biāo)簽名的所有元素蹬昌。

  • 通過類名查找
    調(diào)用document.getElementByClassName方法查找指定class的所有元素混驰。

Tips:要精確地定位DOM,可以先定位父節(jié)點皂贩,再逐步縮小范圍栖榨。

2、更新

定位好節(jié)點之后明刷,就可以進(jìn)行更新操作婴栽。

  • 修改innerHTML屬性
    不但可以修改一個DOM節(jié)點的文本內(nèi)容,還可以通過HTML片段修改DOM節(jié)點內(nèi)部的子樹辈末。

  • 修改innerText或textContent屬性
    可以對字符串進(jìn)行HTML編碼愚争,保證無法設(shè)置任何HTML標(biāo)簽映皆。這兩個屬性的區(qū)別是前者不返回隱藏元素的文本,而后者則返回所有文本轰枝。

  • 修改style屬性
    可以用來設(shè)置CSS樣式捅彻。如果是無效的屬性名,可以在JavaScript中使用駝峰式命名屬性鞍陨。

3步淹、插入

可以插入新的節(jié)點,從而改變DOM結(jié)構(gòu)湾戳。

  • appendChild方法
    把一個子節(jié)點添加到父節(jié)點的最后一個子節(jié)點贤旷。如果子節(jié)點已經(jīng)存在,會先從原來的位置刪除砾脑,然后再插入到新的位置幼驶。通常會新創(chuàng)建一個節(jié)點,然后插入到指定位置韧衣,實現(xiàn)動態(tài)添加節(jié)點盅藻。

  • insertBefore方法
    父節(jié)點會將新建的子節(jié)點插入到參照節(jié)點之前。

4畅铭、刪除

可以刪除節(jié)點氏淑,從而改變DOM結(jié)構(gòu)。

  • removeChild方法
    首先獲得要刪除的節(jié)點和它的父節(jié)點硕噩,然后調(diào)用父節(jié)點的方法將其刪除假残。遍歷父節(jié)點的子節(jié)點并進(jìn)行刪除操作時,父節(jié)點的children屬性會在子節(jié)點發(fā)生變化時實時更新炉擅,需要特別注意辉懒。

六、異步處理

JavaScript語言是單線程的谍失,一次只能完成一個任務(wù)眶俩。好處是實現(xiàn)簡單,壞處是如果有任務(wù)耗時很長快鱼,其他的任務(wù)就必須得排隊等待颠印,直到該任務(wù)完成。導(dǎo)致的結(jié)果就是造成瀏覽器無響應(yīng)抹竹,其他任務(wù)無法執(zhí)行线罕,體驗極差。

因此柒莉,JavaScript語言分成兩種任務(wù)執(zhí)行模式:同步和異步闻坚。所謂同步,就是指程序的執(zhí)行順序與任務(wù)的排列順序是一致的兢孝、同步的窿凤。所謂異步,是指每個任務(wù)有一個或多個回調(diào)函數(shù)跨蟹,后一個任務(wù)無需等待前一個任務(wù)完成就可執(zhí)行雳殊,當(dāng)前一個任務(wù)完成后,執(zhí)行回調(diào)函數(shù)窗轩。這樣夯秃,程序的執(zhí)行順序與任務(wù)的排列順序是不一致的、異步的痢艺。

1仓洼、回調(diào)函數(shù)

這是異步處理最常用的的方法。

兩個同步執(zhí)行的函數(shù):

f1();
f2();

兩個異步執(zhí)行的函數(shù):

function f1(callback){
    setTimeout(function () {
        // f1的任務(wù)代碼
        callback();
    }, 1000);
}

f1(f2);

回調(diào)函數(shù)的優(yōu)點是簡單堤舒、容易理解色建。缺點是不利于閱讀和維護(hù)、高耦合舌缤、流程混亂箕戳,每個任務(wù)只能指定一個回調(diào)函數(shù)。

2国撵、事件監(jiān)聽

采用事件驅(qū)動模式陵吸,由事件來決定要進(jìn)行的處理,而不是代碼的順序介牙。

為f1綁定一個事件壮虫,當(dāng)f1發(fā)生done事件,就執(zhí)行f2:

f1.on('done', f2);

執(zhí)行完成后环础,立即觸發(fā)done事件囚似,從而開始執(zhí)行f2:

function f1(){
    setTimeout(function () {
        // f1的任務(wù)代碼
        f1.trigger('done');
    }, 1000);
}

事件監(jiān)聽的優(yōu)點是容易理解,可以綁定多個事件喳整,每個事件可以指定多個回調(diào)函數(shù)谆构,低耦合。缺點是流程不夠清晰框都。

3搬素、發(fā)布/訂閱

與事件監(jiān)聽類似。某個任務(wù)執(zhí)行完成之后魏保,會發(fā)布一個信號熬尺,其他任務(wù)可以訂閱這個信號,從而知道什么時候可以開始執(zhí)行谓罗。又稱為觀察者模式粱哼。

訂閱信號:

jQuery.subscribe("done", f2);

發(fā)布信號:

function f1(){
    setTimeout(function () {
        // f1的任務(wù)代碼
        jQuery.publish("done");
    }, 1000);
}

取消訂閱:

jQuery.unsubscribe("done", f2);

可以了解存在多少信號、每個信號有多少訂閱者檩咱,從而監(jiān)聽程序的運行揭措。

4蹬铺、Promises對象

該對象是CommonJS提出的一種規(guī)范,旨在為異步編程提供統(tǒng)一接口恕刘。

每一個異步任務(wù)返回一個Promises對象:

function f1(){
    var dfd = $.Deferred();
    setTimeout(function () {
        // f1的任務(wù)代碼
        dfd.resolve();
    }, 500);
    return dfd.promise;
}

該對象有一個then方法屈尼,可以指定回調(diào)函數(shù):

f1().then(f2);  

優(yōu)點是回調(diào)函數(shù)可以使用鏈?zhǔn)綄懛ǎ鞒糖逦洌⑶胰绻粋€任務(wù)已經(jīng)完成逃顶,再添加回調(diào)函數(shù),該回調(diào)函數(shù)會立刻執(zhí)行充甚。缺點是編寫和理解比較困難以政。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市伴找,隨后出現(xiàn)的幾起案子盈蛮,更是在濱河造成了極大的恐慌,老刑警劉巖疆瑰,帶你破解...
    沈念sama閱讀 218,451評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件眉反,死亡現(xiàn)場離奇詭異,居然都是意外死亡穆役,警方通過查閱死者的電腦和手機寸五,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,172評論 3 394
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來耿币,“玉大人梳杏,你說我怎么就攤上這事⊙徒樱” “怎么了十性?”我有些...
    開封第一講書人閱讀 164,782評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長塑悼。 經(jīng)常有香客問我劲适,道長,這世上最難降的妖魔是什么厢蒜? 我笑而不...
    開封第一講書人閱讀 58,709評論 1 294
  • 正文 為了忘掉前任霞势,我火速辦了婚禮,結(jié)果婚禮上斑鸦,老公的妹妹穿的比我還像新娘愕贡。我一直安慰自己,他們只是感情好巷屿,可當(dāng)我...
    茶點故事閱讀 67,733評論 6 392
  • 文/花漫 我一把揭開白布固以。 她就那樣靜靜地躺著,像睡著了一般嘱巾。 火紅的嫁衣襯著肌膚如雪憨琳。 梳的紋絲不亂的頭發(fā)上诫钓,一...
    開封第一講書人閱讀 51,578評論 1 305
  • 那天,我揣著相機與錄音栽渴,去河邊找鬼尖坤。 笑死稳懒,一個胖子當(dāng)著我的面吹牛闲擦,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播场梆,決...
    沈念sama閱讀 40,320評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼墅冷,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了或油?” 一聲冷哼從身側(cè)響起寞忿,我...
    開封第一講書人閱讀 39,241評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎顶岸,沒想到半個月后腔彰,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,686評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡辖佣,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,878評論 3 336
  • 正文 我和宋清朗相戀三年霹抛,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片卷谈。...
    茶點故事閱讀 39,992評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡杯拐,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出世蔗,到底是詐尸還是另有隱情端逼,我是刑警寧澤,帶...
    沈念sama閱讀 35,715評論 5 346
  • 正文 年R本政府宣布污淋,位于F島的核電站顶滩,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏寸爆。R本人自食惡果不足惜礁鲁,卻給世界環(huán)境...
    茶點故事閱讀 41,336評論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望而昨。 院中可真熱鬧救氯,春花似錦、人聲如沸歌憨。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,912評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽务嫡。三九已至甲抖,卻和暖如春漆改,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背准谚。 一陣腳步聲響...
    開封第一講書人閱讀 33,040評論 1 270
  • 我被黑心中介騙來泰國打工挫剑, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人柱衔。 一個月前我還...
    沈念sama閱讀 48,173評論 3 370
  • 正文 我出身青樓樊破,卻偏偏與公主長得像,于是被迫代替她去往敵國和親唆铐。 傳聞我的和親對象是個殘疾皇子哲戚,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,947評論 2 355

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