近年來,JavaScript 越來越受歡迎,部分原因是開發(fā)了一些程式庫,使尚未完全掌握核心語言的人更容易創(chuàng)建 JavaScript 應(yīng)用程式/效果。
雖然在過去,人們普遍認(rèn)為JavaScript 是一種基礎(chǔ)語言,而且非?!安萋省?,沒有真正的基礎(chǔ);但現(xiàn)在情況已不再如此,尤其是隨著大規(guī)模Web 應(yīng)用程式和JSON(JavaScript 對象表示法)等「適應(yīng)」的引入。
JavaScript 可以擁有物件導(dǎo)向語言所提供的所有功能,儘管需要付出一些超出本文討論範(fàn)圍的額外工作。
讓我們建立一個(gè)物件
function myObject(){
};
恭喜,您剛剛建立了一個(gè)物件。建立 JavaScript 物件有兩種方法:「建構(gòu)函數(shù)」和「文字表示法」。上面的函數(shù)是一個(gè)建構(gòu)函數(shù),我很快就會解釋其中的區(qū)別,但在此之前,這是使用文字表示法的物件定義的樣子。
var myObject = {
};
文字是名稱間距的首選選項(xiàng),因此您的JavaScript 程式碼就不會幹?jǐn)_(反之亦然)頁面上執(zhí)行的其他腳本,並且如果您將此物件用作單個(gè)物件並且不需要多個(gè)物件物件的實(shí)例,而如果您需要在建立物件之前執(zhí)行一些初始工作,或者需要物件的多個(gè)實(shí)例(其中每個(gè)實(shí)例都可以在腳本的生命週期內(nèi)變更),則首選建構(gòu)函式類型表示法。讓我們繼續(xù)同時(shí)建構(gòu)兩個(gè)對象,以便我們可以觀察差異。
定義方法和屬性
建構(gòu)子版本:
function myObject(){
this.iAm = 'an object';
this.whatAmI = function(){
alert('I am ' + this.iAm);
};
};
文字版本:
var myObject = {
iAm : 'an object',
whatAmI : function(){
alert('I am ' + this.iAm);
}
}
對於每個(gè)對象,我們建立了一個(gè)屬性“iAm”,其中包含一個(gè)字串值,該字串值在我們的對象方法“whatAmI”中使用,該方法會發(fā)出警報(bào)訊息。
屬性是在物件內(nèi)部創(chuàng)建的變量,方法是在物件內(nèi)部創(chuàng)建的函數(shù)。
現(xiàn)在可能是解釋如何使用屬性和方法的最佳時(shí)機(jī)(儘管如果您熟悉庫,您可能已經(jīng)這樣做了)。
要使用屬性,首先要輸入它所屬的物件- 因此在本例中是myObject - 然後要引用其內(nèi)部屬性,請先加上句號,然後輸入屬性名稱,這樣它最終看起來會像myObject . iAm(這將傳回「一個(gè)物件」)。
對於方法來說,除了執(zhí)行方法之外,都是一樣的,就像任何函數(shù)一樣,必須在其後面加上括號;否則,您將只傳回對函數(shù)的引用,而不是函數(shù)實(shí)際傳回的內(nèi)容。所以它看起來像 myObject.whatAmI() (這會提醒「我是一個(gè)物件」)。
現(xiàn)在來看看差異:
- 建構(gòu)函數(shù)物件的屬性和方法是在其前面使用關(guān)鍵字「this」定義的,而字面版本則沒有。
- 在建構(gòu)函數(shù)物件中,屬性/方法的「值」在等號「=」之後定義,而在字面版本中,它們在冒號「:」之後定義。
- 建構(gòu)函數(shù)可以有(可選)分號“;”在每個(gè)屬性/方法聲明的末尾,而在字面版本中,如果您有多個(gè)屬性或方法,則它們必須用逗號“,”分隔,而且它們後面不能有分號,否則JavaScript 會回傳錯(cuò)誤。
這兩種類型的物件宣告的使用方式也存在差異。
要使用字面上標(biāo)註的對象,您只需透過引用其變數(shù)名稱來使用它,因此無論何時(shí)需要它,您都可以透過鍵入來呼叫它;
myObject.whatAmI();
使用建構(gòu)函數(shù),您需要先實(shí)例化(建立物件的新實(shí)例);您可以透過輸入來完成此操作;
var myNewObject = new myObject();
myNewObject.whatAmI();
使用建構(gòu)子。
讓我們使用先前的構(gòu)造函數(shù)並在其基礎(chǔ)上進(jìn)行構(gòu)建,以便在實(shí)例化它時(shí)執(zhí)行一些基本(但動(dòng)態(tài))操作。
function myObject(){
this.iAm = 'an object';
this.whatAmI = function(){
alert('I am ' + this.iAm);
};
};
就像任何 JavaScript 函數(shù)一樣,我們可以在建構(gòu)函式中使用參數(shù);
function myObject(what){
this.iAm = what;
this.whatAmI = function(language){
alert('I am ' + this.iAm + ' of the ' + language + ' language');
};
};
現(xiàn)在讓我們實(shí)例化我們的物件並呼叫它的 WhatAmI 方法,同時(shí)填寫所需的欄位。
var myNewObject = new myObject('an object');
myNewObject.whatAmI('JavaScript');
這將警告「我是 JavaScript 語言的物件?!?/p>
實(shí)例化或不實(shí)例化
我之前提到過對象構(gòu)造函數(shù)和對象文字之間的差異,當(dāng)對對象文字進(jìn)行更改時(shí),它會影響整個(gè)腳本中的該對象,而當(dāng)構(gòu)造函數(shù)被實(shí)例化然後對其進(jìn)行更改時(shí)實(shí)例,它不會影響該物件的任何其他實(shí)例。讓我們嘗試一個(gè)例子;
首先我們將建立一個(gè)物件文字;
var myObjectLiteral = {
myProperty : 'this is a property'
}
//alert current myProperty
alert(myObjectLiteral.myProperty); //this will alert 'this is a property'
//change myProperty
myObjectLiteral.myProperty = 'this is a new property';
//alert current myProperty
alert(myObjectLiteral.myProperty); //this will alert 'this is a new property', as expected
即使您建立新變數(shù)並將其指向該對象,也會產(chǎn)生相同的效果。
var myObjectLiteral = {
myProperty : 'this is a property'
}
//alert current myProperty
alert(myObjectLiteral.myProperty); //this will alert 'this is a property'
//define new variable with object as value
var sameObject = myObjectLiteral;
//change myProperty
myObjectLiteral.myProperty = 'this is a new property';
//alert current myProperty
alert(sameObject.myProperty); //this will still alert 'this is a new property'
現(xiàn)在讓我們嘗試使用建構(gòu)子進(jìn)行類似的練習(xí)。
//this is one other way of creating a Constructor function
var myObjectConstructor = function(){
this.myProperty = 'this is a property'
}
//instantiate our Constructor
var constructorOne = new myObjectConstructor();
//instantiate a second instance of our Constructor
var constructorTwo = new myObjectConstructor();
//alert current myProperty of constructorOne instance
alert(constructorOne.myProperty); //this will alert 'this is a property'
//alert current myProperty of constructorTwo instance
alert(constructorTwo.myProperty); //this will alert 'this is a property'
正如預(yù)期的那樣,兩者都會傳回正確的值,但讓我們更改其中一個(gè)實(shí)例的 myProperty。
//this is one other way of creating a Constructor function
var myObjectConstructor = function(){
this.myProperty = 'this is a property'
}
//instantiate our Constructor
var constructorOne = new myObjectConstructor();
//change myProperty of the first instance
constructorOne.myProperty = 'this is a new property';
//instantiate a second instance of our Constructor
var constructorTwo = new myObjectConstructor();
//alert current myProperty of constructorOne instance
alert(constructorOne.myProperty); //this will alert 'this is a new property'
//alert current myProperty of constructorTwo instance
alert(constructorTwo.myProperty); //this will still alert 'this is a property'
從這個(gè)示例中可以看出,即使我們更改了 constructorOne 的屬性,它也沒有影響 myObjectConstructor,因此也沒有影響 constructorTwo。即使在更改 constructorOne 的 myProperty 屬性之前實(shí)例化了 constructorTwo,它仍然不會影響 constructorTwo 的 myProperty 屬性,因?yàn)樗?JavaScript 內(nèi)存中完全不同的對象實(shí)例。
那么您應(yīng)該使用哪一個(gè)呢?好吧,這取決于情況,如果您的腳本只需要一個(gè)此類對象(正如您將在本文末尾的示例中看到的那樣),則使用對象文字,但如果您需要一個(gè)對象的多個(gè)實(shí)例,其中每個(gè)實(shí)例彼此獨(dú)立,并且根據(jù)其構(gòu)造方式可以具有不同的屬性或方法,然后使用構(gòu)造函數(shù)。
這個(gè)和那個(gè)
在解釋構(gòu)造函數(shù)時(shí),出現(xiàn)了很多“this”關(guān)鍵字,我想這是討論作用域的更好時(shí)機(jī)!
現(xiàn)在您可能會問“您所說的范圍是什么”? JavaScript 中的作用域是基于函數(shù)/對象的,因此這意味著如果您在函數(shù)之外,則無法使用在函數(shù)內(nèi)部定義的變量(除非您使用閉包)。
然而,存在作用域鏈,這意味著另一個(gè)函數(shù)內(nèi)的函數(shù)可以訪問其父函數(shù)中定義的變量。讓我們看一些示例代碼。
<script type="text/javascript">
var var1 = 'this is global and is available to everyone';
function function1(){
var var2 = 'this is only available inside function1 and function2';
function function2(){
var var3 = 'this is only available inside function2';
}
}
</script>
正如你在這個(gè)例子中看到的, var1
是在全局對象中定義的,可用于所有函數(shù)和對象, var2
是在 function1 中定義的,可用于 function1 和 function2,但是如果你嘗試引用從全局對象中獲取它會給出錯(cuò)誤“var2 未定義”,var3
只能由 function2 訪問。
那么“this”指的是什么呢?在瀏覽器中,“this”引用窗口對象,因此從技術(shù)上講,窗口是我們的全局對象。如果我們在一個(gè)對象內(nèi)部,“this”將引用該對象本身,但是如果您在一個(gè)函數(shù)內(nèi)部,這仍然會引用窗口對象,同樣,如果您在一個(gè)對象內(nèi)的方法內(nèi)部,“ this' 將引用該對象。
由于我們的作用域鏈,如果我們位于子對象(對象內(nèi)的對象)內(nèi)部,“this”將引用子對象而不是父對象。
作為旁注,還值得補(bǔ)充的是,當(dāng)使用 setInterval、setTimeout 和 eval 等函數(shù)時(shí),當(dāng)您通過其中之一執(zhí)行函數(shù)或方法時(shí),“this”指的是 window 對象,因?yàn)檫@些是 window 的方法,所以 setInterval() 和 window.setInterval() 是相同的。
好吧,現(xiàn)在我們已經(jīng)解決了這個(gè)問題,讓我們做一個(gè)真實(shí)的示例并創(chuàng)建一個(gè)表單驗(yàn)證對象!
現(xiàn)實(shí)世界的用法:表單驗(yàn)證對象
首先我必須向您介紹我們將創(chuàng)建的 addEvent 函數(shù),它是 ECMAScript 的(Firefox、Safari 等)addEventListener() 函數(shù)和 Microsoft ActiveX Script 的 AttachEvent() 函數(shù)的組合。
function addEvent(to, type, fn){
if(document.addEventListener){
to.addEventListener(type, fn, false);
} else if(document.attachEvent){
to.attachEvent('on'+type, fn);
} else {
to['on'+type] = fn;
}
};
這將創(chuàng)建一個(gè)具有三個(gè)參數(shù)的新函數(shù),to
是我們將事件附加到的 DOM 對象,type
是事件類型,fn
是觸發(fā)事件時(shí)運(yùn)行的函數(shù)。它首先檢查是否支持 addEventListener,如果支持,它將使用它,如果不支持,它將檢查 AttachEvent,如果其他所有方法都失敗,您可能正在使用 IE5 或同樣過時(shí)的東西,因此我們將事件直接添加到其事件屬性上(注意:第三個(gè)選項(xiàng)將覆蓋可能已附加到事件屬性的任何現(xiàn)有函數(shù),而前兩個(gè)選項(xiàng)會將其作為附加函數(shù)添加到其事件屬性中)。
現(xiàn)在讓我們設(shè)置我們的文檔,使其與您開發(fā) jQuery 內(nèi)容時(shí)可能看到的類似。
在 jQuery 中你會有;
$(document).ready(function(){
//all our code that runs after the page is ready goes here
});
使用我們的 addEvent 函數(shù);
addEvent(window, 'load', function(){
//all our code that runs after the page is ready goes here
});
現(xiàn)在我們的 Form 對象。
var Form = {
validClass : 'valid',
fname : {
minLength : 1,
maxLength : 15,
fieldName : 'First Name'
},
lname : {
minLength : 1,
maxLength : 25,
fieldName : 'Last Name'
},
validateLength : function(formEl, type){
if(formEl.value.length > type.maxLength || formEl.value.length < type.minLength ){
formEl.className = formEl.className.replace(' '+Form.validClass, '');
return false;
} else {
if(formEl.className.indexOf(' '+Form.validClass) == -1)
formEl.className += ' '+Form.validClass;
return true;
}
},
validateEmail : function(formEl){
var regEx = /^([0-9a-zA-Z]([-.\w]*[0-9a-zA-Z])*@([0-9a-zA-Z][-\w]*[0-9a-zA-Z]\.)+[a-zA-Z]{2,9})$/;
var emailTest = regEx.test(formEl.value);
if (emailTest) {
if(formEl.className.indexOf(' '+Form.validClass) == -1)
formEl.className += ' '+Form.validClass;
return true;
} else {
formEl.className = formEl.className.replace(' '+Form.validClass, '');
return false;
}
},
getSubmit : function(formID){
var inputs = document.getElementById(formID).getElementsByTagName('input');
for(var i = 0; i < inputs.length; i++){
if(inputs[i].type == 'submit'){
return inputs[i];
}
}
return false;
}
};
所以這是非?;镜模梢院苋菀椎?cái)U(kuò)展。
為了解決這個(gè)問題,我們首先創(chuàng)建一個(gè)新屬性,它只是“有效”CSS 類的字符串名稱,當(dāng)應(yīng)用于表單字段時(shí),會添加有效的效果,例如綠色邊框。我們還定義了兩個(gè)子對象,fname
和lname
,因此我們可以定義它們自己的屬性,這些屬性可以被其他地方的方法使用,這些屬性是minLength
,這是這些字段可以擁有的最小字符數(shù), maxLength
是字段可以擁有的最大字符數(shù),而 fieldName
實(shí)際上并沒有被使用,但可以用于諸如在錯(cuò)誤消息中使用用戶友好的字符串識別字段之類的事情(例如“名字字段”)是必需的。')。
接下來我們創(chuàng)建一個(gè) validateLength 方法,它接受兩個(gè)參數(shù): formEl
要驗(yàn)證的 DOM 元素和 type
,它引用要使用的子對象之一(即 fname 或 lname)。該函數(shù)檢查字段的長度是否在 minLength 和 maxLength 范圍之間,如果不是,那么我們從元素中刪除有效類(如果存在)并返回 false,否則如果是,那么我們添加有效類并返回正確。
然后我們有一個(gè) validateEmail 方法,它接受 DOM 元素作為參數(shù),然后我們根據(jù)電子郵件類型正則表達(dá)式測試這個(gè) DOM 元素值;如果通過,我們再次添加我們的類并返回 true,反之亦然。
最后我們有一個(gè) getSubmit 方法。該方法獲得表單的 id,然后循環(huán)遍歷指定表單內(nèi)的所有輸入元素,以查找哪一個(gè)具有提交類型 (type="submit")。此方法的原因是返回提交按鈕,以便我們可以禁用它,直到表單準(zhǔn)備好提交。
讓我們讓這個(gè)驗(yàn)證器對象在真實(shí)的表單上工作。首先我們需要 HTML。
<body>
<form id="ourForm">
<label>First Name</label><input type="text" /><br />
<label>Last Name</label><input type="text" /><br />
<label>Email</label><input type="text" /><br />
<input type="submit" value="submit" />
</form>
</body>
現(xiàn)在讓我們使用 JavaScript 訪問這些輸入對象,并在表單提交時(shí)驗(yàn)證它們。
addEvent(window, 'load', function(){
var ourForm = document.getElementById('ourForm');
var submit_button = Form.getSubmit('ourForm');
submit_button.disabled = 'disabled';
function checkForm(){
var inputs = ourForm.getElementsByTagName('input');
if(Form.validateLength(inputs[0], Form.fname)){
if(Form.validateLength(inputs[1], Form.lname)){
if(Form.validateEmail(inputs[2])){
submit_button.disabled = false;
return true;
}
}
}
submit_button.disabled = 'disabled';
return false;
};
checkForm();
addEvent(ourForm, 'keyup', checkForm);
addEvent(ourForm, 'submit', checkForm);
});
讓我們分解一下這段代碼。
我們將代碼包裝在 addEvent 函數(shù)中,以便在加載窗口時(shí)運(yùn)行此腳本。首先,我們使用表單 ID 獲取表單并將其放入名為 ourForm
的變量中,然后獲取提交按鈕(使用表單對象 getSubmit 方法)并將其放入名為 submit_button
的變量中,然后設(shè)置提交按鈕禁用屬性為“禁用”。
接下來我們定義一個(gè) checkForm 函數(shù)。這會將表單字段內(nèi)的所有輸入存儲為一個(gè)數(shù)組,并將其附加到一個(gè)名為..你猜對了的變量.. inputs
!然后它定義了一些嵌套的 if 語句,這些語句根據(jù)我們的 Form 方法測試輸入數(shù)組內(nèi)的每個(gè)字段。這就是我們在方法中返回 true 或 false 的原因,因此如果它返回 true,我們將傳遞該 if 語句并繼續(xù)執(zhí)行下一個(gè),但如果它返回 false,我們將退出 if 語句。
根據(jù)我們的函數(shù)定義,我們在頁面最初加載時(shí)執(zhí)行 checkForm 函數(shù),并將該函數(shù)附加到 keyup 事件和提交事件。
您可能會問,如果我們禁用了提交按鈕,為什么還要附加提交。好吧,如果您專注于輸入字段并按下 Enter 鍵,它將嘗試提交表單,我們需要對此進(jìn)行測試,因此我們的 checkForm 函數(shù)返回 true(提交表單)或 false(不提交)形式)。
結(jié)論
因此,我們學(xué)習(xí)了如何在 JavaScript 中定義不同的對象類型并在其中創(chuàng)建屬性和方法。我們還學(xué)習(xí)了一個(gè)漂亮的 addEvent 函數(shù),并在基本的現(xiàn)實(shí)示例中使用我們的對象。
這就是 JavaScript 面向?qū)ο蟮幕A(chǔ)知識。希望這可以讓您開始構(gòu)建自己的 JavaScript 庫!如果您喜歡這篇文章并對其他 JavaScript 相關(guān)主題感興趣,請將它們發(fā)布在評論中,我很樂意繼續(xù)撰寫它們。感謝您的閱讀。
為什么不看看 CodeCanyon 上的 JavaScript 項(xiàng)目范圍。您可以找到用于創(chuàng)建滑塊、倒計(jì)時(shí)、加載器和上傳器等的腳本。

以上是JavaScript的物件導(dǎo)向基礎(chǔ)知識的詳細(xì)內(nèi)容。更多資訊請關(guān)注PHP中文網(wǎng)其他相關(guān)文章!