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