JavaScript是一種屬于網(wǎng)絡(luò)的腳本語言,已經(jīng)被廣泛用于Web應(yīng)用開發(fā),常用來為網(wǎng)頁添加各式各樣的動(dòng)態(tài)功能,為用戶提供更流暢美觀的瀏覽效果。通常JavaScript腳本是通過嵌入在HTML中來實(shí)現(xiàn)自身的功能的。
JavaScript腳本語言具有以下特點(diǎn):
(1)腳本語言。JavaScript是一種解釋型的腳本語言,C、C++等語言先編譯后執(zhí)行,而JavaScript是在程序的運(yùn)行過程中逐行進(jìn)行解釋。
?。?)基于對象。JavaScript是一種基于對象的腳本語言,它不僅可以創(chuàng)建對象,也能使用現(xiàn)有的對象。
?。?)簡單。JavaScript語言中采用的是弱類型的變量類型,對使用的數(shù)據(jù)類型未做出嚴(yán)格的要求,是基于Java基本語句和控制的腳本語言,其設(shè)計(jì)簡單緊湊。
?。?)動(dòng)態(tài)性。JavaScript是一種采用事件驅(qū)動(dòng)的腳本語言,它不需要經(jīng)過Web服務(wù)器就可以對用戶的輸入做出響應(yīng)。在訪問一個(gè)網(wǎng)頁時(shí),鼠標(biāo)在網(wǎng)頁中進(jìn)行鼠標(biāo)點(diǎn)擊或上下移、窗口移動(dòng)等操作JavaScript都可直接對這些事件給出相應(yīng)的響應(yīng)。
(5)跨平臺(tái)性。JavaScript腳本語言不依賴于操作系統(tǒng),僅需要瀏覽器的支持。因此一個(gè)JavaScript腳本在編寫后可以帶到任意機(jī)器上使用,前提上機(jī)器上的瀏覽器支 持JavaScript腳本語言,目前JavaScript已被大多數(shù)的瀏覽器所支持。
不同于服務(wù)器端腳本語言,例如PHP與ASP,JavaScript主要被作為客戶端腳本語言在用戶的瀏覽器上運(yùn)行,不需要服務(wù)器的支持。所以在早期程序員比較青睞于JavaScript以減少對服務(wù)器的負(fù)擔(dān),而與此同時(shí)也帶來另一個(gè)問題:安全性。
而隨著服務(wù)器的強(qiáng)壯,雖然程序員更喜歡運(yùn)行于服務(wù)端的腳本以保證安全,但JavaScript仍然以其跨平臺(tái)、容易上手等優(yōu)勢大行其道。同時(shí),有些特殊功能(如AJAX)必須依賴Javascript在客戶端進(jìn)行支持。隨著引擎如V8和框架如Node.js的發(fā)展,及其事件驅(qū)動(dòng)及異步IO等特性,JavaScript逐漸被用來編寫服務(wù)器端程序。
JavaScript中創(chuàng)建命名空間的幾種寫法
在JavaScript中全局變量經(jīng)常會(huì)引起命名沖突,甚至有時(shí)侯重寫變量也不是按照你想像中的順序來的,可以看看下面的例子:
var sayHello = function() {
return ‘Hello var’;
};
function sayHello(name) {
return ‘Hello function’;
};
sayHello();
最終的輸出為
》 “Hello var”
為什么會(huì)這樣,根據(jù) StackOverFlow 的解釋,實(shí)際上JavaScript的是按如下順序解析的。
function sayHello(name) {
return ‘Hello function’;
};
var sayHello = function() {
return ‘Hello var’;
};
sayHello();
不帶var的function聲明被提前解析了,因此現(xiàn)代的JS寫法建議你始終使用前置var聲明所有變量;
避免全局變量名沖突的最好辦法還是創(chuàng)建命名空間,下面是在JS中合建命名空間的幾種常用方法。
通過函數(shù)(function)創(chuàng)建
這是一種比較常見的寫法,通過聲明一個(gè)function實(shí)現(xiàn),函數(shù)里設(shè)置初始變量,公共方法寫入prototype,如:
var NameSpace = window.NameSpace || {};
/*
Function
*/
NameSpace.Hello = function() {
this.name = ‘world’;
};
NameSpace.Hello.prototype.sayHello = function(_name) {
return ‘Hello ’ + (_name || this.name);
};
var hello = new NameSpace.Hello();
hello.sayHello();
這種寫法比較冗長,不利于壓縮代碼(jQuery使用fn代替prototype),而且調(diào)用前需要先實(shí)例化(new)。使用Object寫成JSON形式可以寫得緊湊些:
通過JSON對象創(chuàng)建Object
/*
Object
*/
var NameSpace = window.NameSpace || {};
NameSpace.Hello = {
name: ‘world’
, sayHello: function(_name) {
return ‘Hello ’ + (_name || this.name);
}
};
調(diào)用
NameSpace.Hello.sayHello(‘JS’);
》 Hello JS;
這種寫法比較緊湊,缺點(diǎn)是所有變量都必須聲明為公有(public)的,導(dǎo)致所有對這些變量的引用都需要加this指示作用域,寫法也略有冗余。
通過閉包(Closure)和Object實(shí)現(xiàn)
在閉包中聲明好所有變量和方法,并通過一個(gè)JSON Object返回公有接口:
var NameSpace = window.NameSpace || {};
NameSpace.Hello = (function() {
//待返回的公有對象
var self = {};
//私有變量或方法
var name = ‘world’;
//公有方法或變量
self.sayHello = function(_name) {
return ‘Hello ’ + (_name || name);
};
//返回的公有對象
return self;
}());
Object和閉包的改進(jìn)型寫法
上個(gè)例子在內(nèi)部對公有方法的調(diào)用也需要添加self,如:self.sayHello(); 這里可以最后再返回所有公有接口(方法/變量)的JSON對象。
var NameSpace = window.NameSpace || {};
NameSpace.Hello = (function() {
var name = ‘world’;
var sayHello = function(_name) {
return ‘Hello ’ + (_name || name);
};
return {
sayHello: sayHello
};
}());
Function的簡潔寫法
這是一種比較簡潔的實(shí)現(xiàn),結(jié)構(gòu)緊湊,通過function實(shí)例,且調(diào)用時(shí)無需實(shí)例化(new),方案來自stackoverflow:
var NameSpace = window.NameSpace || {};
NameSpace.Hello = new function() {
var self = this;
var name = ‘world’;
self.sayHello = function(_name) {
return ‘Hello ’ + (_name || name);
};
};
調(diào)用
NameSpace.Hello.sayHello();
javascript模塊與命名空間的介紹
模塊化的目標(biāo)是支持大規(guī)模的程序開發(fā),處理分散源中代碼的組裝,并且能讓代碼正確運(yùn)行,哪怕包含了不需要的模塊代碼,也可以正確執(zhí)行代碼。
理想狀態(tài)下,所有模塊都不應(yīng)當(dāng)定義超過一個(gè)全局標(biāo)識(shí)。
模塊函數(shù)
通過把模塊定義在某個(gè)函數(shù)的內(nèi)部來實(shí)現(xiàn),定義的變量和函數(shù)都屬于該函數(shù)的局部變量,在函數(shù)外不可見。實(shí)際上,可以將這個(gè)函數(shù)作用域用做模塊的命名空間(模塊函數(shù))
一旦將模塊代碼封裝進(jìn)一個(gè)函數(shù)中,就需要一些方法導(dǎo)出公用API,以便在模塊函數(shù)外部調(diào)用它們。下面有幾種方式導(dǎo)出公用API:
首先創(chuàng)建一個(gè)命名空間
代碼如下:
// 創(chuàng)建一個(gè)全局變量用來存放與學(xué)校相關(guān)的模塊
var school; // 創(chuàng)建school命名空間
if(!school) school = {};
1. 利用構(gòu)造函數(shù)
代碼如下:
// 返回Student構(gòu)造函數(shù)來導(dǎo)出公共API
school.Student = (function() {
function Student() {
}
// 。。。。。。 定義Student的原型對象和私有屬性和方法 。。。。。。。。
return Student; // 返回Student構(gòu)造方法導(dǎo)出公共API
})();
2. 返回命名空間對象
如果模塊API包括多個(gè)單元,則它可以返回命名空間對象
代碼如下:
// 為school添加students模塊
school.students = (function() {
// 這里定義了很多類如課程類/成績類, 使用局部變量和函數(shù)
function Subject() { /* 。。。 */ }
function Grade() { /* 。。。 */ }
// 通過返回命名空間對象將API導(dǎo)出
return {
Subject: Subject,
Grade: Grade
};
})();
3. 通過關(guān)鍵字new調(diào)用
另外一種類似類似技術(shù):把模塊函數(shù)當(dāng)做構(gòu)造函數(shù),通過new來調(diào)用。把它們(公共API)賦值給this屬性來將其導(dǎo)出
代碼如下:
school.students = (new function() {
// 。。。。。 這里省略了代碼 。。。。。。
// 將API導(dǎo)到this對象中
this.Subject = Subject;
this.Grade = Grade;
// 注意,這里沒有返回值
}()); // 括號(hào)寫在里面。這里是創(chuàng)建新實(shí)例,new后面應(yīng)緊跟構(gòu)造函數(shù)的調(diào)用而不是表達(dá)式
4. 已定義命名空間對象
作為一種替代方案,如果已經(jīng)定義了全局命名空間對象,通過模塊函數(shù)可以直接設(shè)置那個(gè)對象的屬性。
代碼如下:
// 如果已經(jīng)定義了命名空間對象
var school; // 創(chuàng)建school命名空間
if(!school) school = {};
school.students = {}; // student命名空間已經(jīng)定義
?。╢unction(students) {
// 。。。。。 這里省略了代碼 。。。。。。
// 將公共API導(dǎo)到上面定義的命名空間中
students.Subject = Subject;
students.Grade = Grade;
// 這里也不需要返回值
})(school.students);
評論