JavaScript快速入門

1、概述

JavaScript是世界上最流行的腳本語言,是一種運行在瀏覽器中的解釋型的編程語言,可以實現跨平臺、跨瀏覽器。雖然只是十多天時間的產物,而且有不少的缺陷和陷阱,但也造就了JavaScript的靈活和強大。隨着Node.js的興起,JavaScript已經從單純實現前端互動,發展到能夠全棧實現整個應用。尤爲是在移動互聯網蓬勃發展以及應用追求極致用戶體驗的今天,JavaScript更是必需要重視和掌握的。javascript

2、變量

一、變量的聲明

使用var關鍵字進行變量的聲明,聲明的同時也能夠進行賦值。變量的聲明只能有一次,但賦值能夠有屢次。若是隻聲明變量,可是變量沒有被賦值,此時變量的值爲undefined。html

var s = "Hello";

因爲JavaScript屬於動態語言,因此在定義變量時,不須要指定變量的類型。能夠把任意數據類型賦值給變量,同一個變量可使用不一樣的數據類型反覆賦值。前端

二、變量的提高

根據JavaScript的規則,變量的聲明會被提高,可是變量的初始化並不會被提高。函數外聲明的變量,會被提高到文檔頂部。函數內聲明的變量,會被提高到函數頂部。java

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

若是變量在函數內沒有聲明,該變量會被提高爲全局變量。編程

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

三、變量的做用域

若是變量在函數內聲明,則該變量的做用域爲整個函數體,在函數外不可訪問,屬於局部變量。數組

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

函數能夠嵌套,內部函數能夠訪問外部函數定義的變量,反之則不可。promise

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

若是內部函數與外部函數定義了相同的變量,根據就近原則,內部函數的變量會覆蓋外部函數的變量。瀏覽器

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

3、函數

一、函數的定義

定義函數有兩種方式:聲明和表達式。cookie

1.1 函數聲明

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

函數聲明後不會立刻執行,只有被調用的時候纔會執行。閉包

1.2 函數表達式

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

將函數存儲在變量中,以後能夠經過變量名來調用,而不須要函數名稱。

二、函數的參數

函數有個內置的對象arguments,包含了函數調用的全部參數。

參數有兩種傳遞方式:值傳遞和引用傳遞。

2.1 值傳遞

函數只是獲取參數值,若是修改參數的值,不會改變參數的原始值,在函數外是不可見的。

2.2 引用傳遞

函數得到的是對象的引用,在函數內部修改對象屬性時,會改變屬性的原始值,在函數外可見。

三、函數的調用

函數能夠經過四種方式進行調用。

3.1 自我調用

函數表達式,若是後面緊跟(),則會自動自我調用。聲明的函數不能自我調用。

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

3.2 做爲函數被調用

當函數沒有被其餘對象調用時,函數默認是window全局對象的函數。此時this的值是window全局對象。

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

3.3 做爲方法被調用

能夠將函數定義爲對象的方法,該對象是函數的全部者。當使用對象調用方法時,此時的this值指向調用函數的對象。

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

3.4 做爲構造函數被調用

若是使用new關鍵字,實際是建立了一個新的對象。新對象會繼承構造函數的屬性和方法。此時this值指向新建立的對象。爲了區分普通函數和構造函數,約定構造函數的首字母爲大寫。

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

3.5 call和apply

函數是一個對象,能夠調用call或apply方法。此時this值指向方法傳遞的對象。

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

call和apply方法的惟一區別就是前者傳遞整個參數列表,然後者傳遞一個參數數組。

四、閉包

內嵌函數能夠訪問上一層函數的變量。閉包是能夠訪問上一層函數做用域裏變量的函數。若是上一層函數返回閉包函數,那麼就能夠在上一層函數的外部訪問該函數的私有變量。利用閉包,能夠實現調用公共方法,訪問私有變量。

此時返回的函數並無馬上執行,只有在調用返回函數時才真正執行。由於返回函數不會立刻執行,因此返回函數不要引用循環變量或後續會發生變化的變量。不然,在真正執行的時候,引用的變量可能已經發生改變。

若是必須引用的話,能夠再建立一個函數,用該函數的參數綁定循環變量的值。這樣,循環變量的值雖然發生了改變,但綁定到參數的值不會隨之改變。

4、對象

一、對象的定義

對象的定義有兩種方式。

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

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

使用函數定義對象,而後建立新的對象實例。

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

二、屬性和方法

因爲JavaScript的對象是動態類型,因此能夠給一個對象添加或刪除屬性。當訪問的屬性不存在時,會返回undefined。若是要判斷一個屬性是否屬於某對象,可使用in操做符。這裏要注意的是,該屬性多是對象繼承得來的。若是要判斷一個屬性是否屬於某對象自身,可使用hasOwnProperty方法。

三、原型

雖然JavaScript能夠面向對象編程,但全部的對象都是實例,不會區分類和實例的概念。要想實現類的概念,就須要藉助原型。

首先建立一個至關於類概念的對象實例。

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

而後建立一個新的對象實例,使其依賴這個原型。

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

也可使用Object.create()方法,傳入一個原型對象,並建立一個基於該原型的新對象。

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

四、建立對象

JavaScript對每一個建立的對象都會設置一個原型,指向該對象的原型對象。除了直接建立一個對象外,還可使用構造函數來建立對象。使用構造函數建立的對象,會從原型得到一個constructor屬性,該屬性指向構造函數自己。

五、原型鏈

當訪問一個對象的屬性時,首先在當前對象上查找該屬性。若是沒有找到,就到其原型對象上查找。若是尚未找到,就一直上溯到Object的原型對象。若是尚未找到,就返回undefined。這樣就造成了一條原型鏈。

由於函數也是對象,因此函數也擁有原型鏈。首先是函數自己,而後是Function.prototype,最後是Object.prototype。

六、繼承

繼承不只僅是對象的屬性和方法的繼承,原型鏈也要體現出繼承關係。

首先,定義新的構造函數,並在內部調用但願繼承的構造函數,實現屬性和方法的繼承。

其次,藉助中間函數,將新的構造函數的原型指向繼承的構造函數的原型,實現原型鏈繼承。

最後,將新的構造函數的constructor屬性從新指向新的構造函數。

七、瀏覽器對象

window對象不可是全局對象,還表示瀏覽器窗口。
屬性innerWidth和innerHeight分別表示瀏覽器窗口的內部寬度和高度,即用於顯示網頁的淨寬高。屬性outerWidth和outerHeight分別表示瀏覽器窗口的整個寬度和高度。

navigator對象表示瀏覽器的信息。屬性appName表示瀏覽器名稱。屬性appVersion表示瀏覽器版本。屬性language表示瀏覽器設置的語言。屬性platform表示操做系統類型。屬性userAgent表示瀏覽器設定的User-Agent字符串。

screen對象表示屏幕的信息。屬性width表示屏幕寬度,單位是像素。屬性height表示屏幕高度,單位是像素。屬性colorDepth表示顏色位數。

location對象表示當前頁面的URL信息。屬性href表示整個URL。屬性protocal表示使用的協議。屬性host表示主機名。屬性port表示端口號。屬性pathname表示訪問的路徑。屬性search表示查詢參數。方法assign加載一個新頁面。方法reload重載當前頁面。

document對象表示當前頁面。屬性title表示瀏覽器窗口的標題。屬性cookie獲取當前頁面的Cookie。方法getElementById按照元素的id獲取一個DOM節點。方法getElementByTabName按照元素的標籤名稱獲取一組DOM節點。

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

5、DOM

當頁面被加載時,瀏覽器解析HTML文檔,並會建立頁面的文檔對象模型DOM。DOM是一個樹形結構,經過操做DOM節點,能夠訪問或改變文檔的全部元素。針對DOM的操做主要有四種:查找、更新、插入、刪除。

一、查找

要想操做DOM節點,首先須要找到要操做的節點。

  • 經過id查找

    調用document.getElementById方法查找指定id的元素。

  • 經過標籤名查找

    調用document.getElementByTagName方法查找指定標籤名的全部元素。

  • 經過類名查找

    調用document.getElementByClassName方法查找指定class的全部元素。

Tips:要精確地定位DOM,能夠先定位父節點,再逐步縮小範圍。

二、更新

定位好節點以後,就能夠進行更新操做。

  • 修改innerHTML屬性

    不但能夠修改一個DOM節點的文本內容,還能夠經過HTML片斷修改DOM節點內部的子樹。

  • 修改innerText或textContent屬性

    能夠對字符串進行HTML編碼,保證沒法設置任何HTML標籤。這兩個屬性的區別是前者不返回隱藏元素的文本,然後者則返回全部文本。

  • 修改style屬性

    能夠用來設置CSS樣式。若是是無效的屬性名,能夠在JavaScript中使用駝峯式命名屬性。

三、插入

能夠插入新的節點,從而改變DOM結構。

  • appendChild方法

    把一個子節點添加到父節點的最後一個子節點。若是子節點已經存在,會先從原來的位置刪除,而後再插入到新的位置。一般會新建立一個節點,而後插入到指定位置,實現動態添加節點。

  • insertBefore方法

    父節點會將新建的子節點插入到參照節點以前。

四、刪除

能夠刪除節點,從而改變DOM結構。

  • removeChild方法

    首先得到要刪除的節點和它的父節點,而後調用父節點的方法將其刪除。遍歷父節點的子節點並進行刪除操做時,父節點的children屬性會在子節點發生變化時實時更新,須要特別注意。

6、異步處理

JavaScript語言是單線程的,一次只能完成一個任務。好處是實現簡單,壞處是若是有任務耗時很長,其餘的任務就必須得排隊等待,直到該任務完成。致使的結果就是形成瀏覽器無響應,其餘任務沒法執行,體驗極差。

所以,JavaScript語言分紅兩種任務執行模式:同步和異步。所謂同步,就是指程序的執行順序與任務的排列順序是一致的、同步的。所謂異步,是指每一個任務有一個或多個回調函數,後一個任務無需等待前一個任務完成就可執行,當前一個任務完成後,執行回調函數。這樣,程序的執行順序與任務的排列順序是不一致的、異步的。

一、回調函數

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

兩個同步執行的函數:

f1();
f2();

兩個異步執行的函數:

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

f1(f2);

回調函數的優勢是簡單、容易理解。缺點是不利於閱讀和維護、高耦合、流程混亂,每一個任務只能指定一個回調函數。

二、事件監聽

採用事件驅動模式,由事件來決定要進行的處理,而不是代碼的順序。

爲f1綁定一個事件,當f1發生done事件,就執行f2:

f1.on('done', f2);

執行完成後,當即觸發done事件,從而開始執行f2:

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

事件監聽的優勢是容易理解,能夠綁定多個事件,每一個事件能夠指定多個回調函數,低耦合。缺點是流程不夠清晰。

三、發佈/訂閱

與事件監聽相似。某個任務執行完成以後,會發佈一個信號,其餘任務能夠訂閱這個信號,從而知道何時能夠開始執行。又稱爲觀察者模式。

訂閱信號:

jQuery.subscribe("done", f2);

發佈信號:

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

取消訂閱:

jQuery.unsubscribe("done", f2);

能夠了解存在多少信號、每一個信號有多少訂閱者,從而監聽程序的運行。

四、Promises對象

該對象是CommonJS提出的一種規範,旨在爲異步編程提供統一接口。

每個異步任務返回一個Promises對象:

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

該對象有一個then方法,能夠指定回調函數:

f1().then(f2);

優勢是回調函數可使用鏈式寫法,流程清晰,而且若是一個任務已經完成,再添加回調函數,該回調函數會馬上執行。缺點是編寫和理解比較困難。


參考資料:

w3cschool

廖雪峯的JavaScript教程

阮一峯:Javascript異步編程的4種方法

相關文章
相關標籤/搜索