JavaScript的面向對象基礎知識

近年來,JavaScript 越來越受歡迎,部分原因是開發了一些庫,使那些尚未完全掌握核心語言的人更容易創建 JavaScript 應用程序/效果。

雖然在過去,人們普遍認為 javascript 是一種基礎語言,而且非常“草率”,沒有真正的基礎;但現在情況已不再如此,尤其是隨著大規模 web 應用程序和 json(javascript 對象表示法)等“適應”的引入。

JavaScript 可以擁有面向對象語言所提供的所有功能,盡管需要付出一些超出本文討論范圍的額外工作。

讓我們創建一個對象

    function myObject(){          }; 

恭喜,您剛剛創建了一個對象。創建 JavaScript 對象有兩種方法:“構造函數”和“文字表示法”。上面的函數是一個構造函數,我將很快解釋其中的區別,但在此之前,這是使用文字表示法的對象定義的樣子。

    var myObject = {          }; 

文字是名稱間距的首選選項,這樣您的 JavaScript 代碼就不會干擾(反之亦然)頁面上運行的其他腳本,并且如果您將此對象用作單個對象并且不需要多個對象對象的實例,而如果您需要在創建對象之前執行一些初始工作,或者需要對象的多個實例(其中每個實例都可以在腳本的生命周期內更改),則首選構造函數類型表示法。讓我們繼續同時構建兩個對象,以便我們可以觀察差異。

定義方法和屬性

構造函數版本:

    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);         }     } 

對于每個對象,我們創建了一個屬性“iAm”,其中包含一個字符串值,該字符串值在我們的對象方法“whatAmI”中使用,該方法會發出警報消息。

立即學習Java免費學習筆記(深入)”;

屬性是在對象內部創建的變量,方法是在對象內部創建的函數。

現在可能是解釋如何使用屬性和方法的最佳時機(盡管如果您熟悉庫,您可能已經這樣做了)。

要使用屬性,首先要輸入它所屬的對象 – 因此在本例中是 myObject – 然后要引用其內部屬性,請先加上句號,然后輸入屬性名稱,這樣它最終看起來會像 myObject .iAm(這將返回“一個對象”)。

對于方法來說,除了執行方法之外,都是一樣的,就像任何函數一樣,必須在其后面加上括號;否則,您將只返回對函數的引用,而不是函數實際返回的內容。所以它看起來像 myObject.whatAmI() (這會提醒“我是一個對象”)。

現在來看看差異:

  • 構造函數對象的屬性和方法是在其前面使用關鍵字“this”定義的,而字面版本則沒有。
  • 在構造函數對象中,屬性/方法的“值”在等號“=”之后定義,而在字面版本中,它們在冒號“:”之后定義。
  • 構造函數可以有(可選)分號“;”在每個屬性/方法聲明的末尾,而在字面版本中,如果您有多個屬性或方法,則它們必須用逗號“,”分隔,并且它們后面不能有分號,否則 JavaScript 將返回錯誤。

這兩種類型的對象聲明的使用方式也存在差異。

要使用字面上標注的對象,您只需通過引用其變量名稱來使用它,因此無論何時需要它,您都可以通過鍵入來調用它;

    myObject.whatAmI(); 

使用構造函數,您需要首先實例化(創建對象的新實例);您可以通過輸入來完成此操作;

    var myNewObject = new myObject();     myNewObject.whatAmI(); 

使用構造函數。

讓我們使用之前的構造函數并在其基礎上進行構建,以便在實例化它時執行一些基本(但動態)操作。

    function myObject(){         this.iAm = 'an object';         this.whatAmI = function(){             alert('I am ' + this.iAm);         };     }; 

就像任何 JavaScript 函數一樣,我們可以在構造函數中使用參數;

function myObject(what){ 	this.iAm = what; 	this.whatAmI = function(language){ 		alert('I am ' + this.iAm + ' of the ' + language + ' language'); 	}; }; 

現在讓我們實例化我們的對象并調用它的 WhatAmI 方法,同時填寫所需的字段。

    var myNewObject = new myObject('an object');     myNewObject.whatAmI('JavaScript'); 

這將警告“我是 JavaScript 語言的對象。”

實例化或不實例化

我之前提到過對象構造函數和對象文字之間的差異,當對對象文字進行更改時,它會影響整個腳本中的該對象,而當構造函數被實例化然后對其進行更改時實例,它不會影響該對象的任何其他實例。讓我們嘗試一個例子;

首先我們將創建一個對象文字;

	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 

即使您創建一個新變量并將其指向該對象,也會產生相同的效果。

	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' 

現在讓我們嘗試使用構造函數進行類似的練習。

	//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' 

正如預期的那樣,兩者都返回正確的值,但讓我們更改其中一個實例的 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' 

從這個示例中可以看出,即使我們更改了 constructorOne 的屬性,它也沒有影響 myObjectConstructor,因此也沒有影響 constructorTwo。即使在更改 constructorOne 的 myProperty 屬性之前實例化了 constructorTwo,它仍然不會影響 constructorTwo 的 myProperty 屬性,因為它是 JavaScript 內存中完全不同的對象實例。

那么您應該使用哪一個呢?好吧,這取決于情況,如果您的腳本只需要一個此類對象(正如您將在本文末尾的示例中看到的那樣),則使用對象文字,但如果您需要一個對象的多個實例,其中每個實例彼此獨立,并且根據其構造方式可以具有不同的屬性或方法,然后使用構造函數。

這個和那個

在解釋構造函數時,出現了很多“this”關鍵字,我想這是討論作用域的更好時機!

現在您可能會問“您所說的范圍是什么”? JavaScript 中的作用域是基于函數/對象的,因此這意味著如果您在函數之外,則無法使用在函數內部定義的變量(除非您使用閉包)。

然而,存在作用域鏈,這意味著另一個函數內的函數可以訪問其父函數中定義的變量。讓我們看一些示例代碼。

<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>

正如你在這個例子中看到的, var1 是在全局對象中定義的,可用于所有函數和對象, var2 是在 function1 中定義的,可用于 function1 和 function2,但是如果你嘗試引用從全局對象中獲取它會給出錯誤“var2 未定義”,var3 只能由 function2 訪問。

那么“this”指的是什么呢?在瀏覽器中,“this”引用窗口對象,因此從技術上講,窗口是我們的全局對象。如果我們在一個對象內部,“this”將引用該對象本身,但是如果您在一個函數內部,這仍然會引用窗口對象,同樣,如果您在一個對象內的方法內部,“ this’ 將引用該對象。

由于我們的作用域鏈,如果我們位于子對象(對象內的對象)內部,“this”將引用子對象而不是父對象。

作為旁注,還值得補充的是,當使用 setInterval、setTimeout 和 eval 等函數時,當您通過其中之一執行函數或方法時,“this”指的是 window 對象,因為這些是 window 的方法,所以 setInterval() 和 window.setInterval() 是相同的。

好吧,現在我們已經解決了這個問題,讓我們做一個真實的示例并創建一個表單驗證對象!

現實世界的用法:表單驗證對象

首先我必須向您介紹我們將創建的 addEvent 函數,它是 ecmascript 的(firefoxsafari 等)addEventListener() 函數和 microsoft ActiveX Script 的 AttachEvent() 函數的組合。

    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;         }	     }; 

這將創建一個具有三個參數的新函數,to 是我們將事件附加到的 dom 對象,type 是事件類型,fn 是觸發事件時運行的函數。它首先檢查是否支持 addEventListener,如果支持,它將使用它,如果不支持,它將檢查 AttachEvent,如果其他所有方法都失敗,您可能正在使用 IE5 或同樣過時的東西,因此我們將事件直接添加到其事件屬性上(注意:第三個選項將覆蓋可能已附加到事件屬性的任何現有函數,而前兩個選項會將其作為附加函數添加到其事件屬性中)。

現在讓我們設置我們的文檔,使其與您開發 jquery 內容時可能看到的類似。

在 jQuery 中你會有;

    $(document).ready(function(){         //all our code that runs after the page is ready goes here     }); 

使用我們的 addEvent 函數;

    addEvent(window, 'load', function(){ 		//all our code that runs after the page is ready goes here 	}); 

現在我們的 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 &gt; type.maxLength || formEl.value.length   <p>所以這是非常基本的,但可以很容易地擴展。</p>  <p>為了解決這個問題,我們首先創建一個新屬性,它只是“有效”css 類的字符串名稱,當應用于表單字段時,會添加有效的效果,例如綠色邊框。我們還定義了兩個子對象,fname和lname,因此我們可以定義它們自己的屬性,這些屬性可以被其他地方的方法使用,這些屬性是minLength,這是這些字段可以擁有的最小字符數, maxLength 是字段可以擁有的最大字符數,而 fieldName 實際上并沒有被使用,但可以用于諸如在錯誤消息中使用用戶友好的字符串識別字段之類的事情(例如“名字字段”)是必需的。')。</p>  <p>接下來我們創建一個 validateLength 方法,它接受兩個參數: formEl 要驗證的 DOM 元素和 type ,它引用要使用的子對象之一(即 fname 或 lname)。該函數檢查字段的長度是否在 minLength 和 maxLength 范圍之間,如果不是,那么我們從元素中刪除有效類(如果存在)并返回 false,否則如果是,那么我們添加有效類并返回正確。</p>  <p>然后我們有一個 validateEmail 方法,它接受 DOM 元素作為參數,然后我們根據電子郵件類型正則表達式測試這個 DOM 元素值;如果通過,我們再次添加我們的類并返回 true,反之亦然。</p>  <p>最后我們有一個 getSubmit 方法。該方法獲得表單的 id,然后循環遍歷指定表單內的所有輸入元素,以查找哪一個具有提交類型 (type="submit")。此方法的原因是返回提交按鈕,以便我們可以禁用它,直到表單準備好提交。</p>  <p>讓我們讓這個驗證器對象在真實的表單上工作。首先我們需要 html。</p>  <pre class="brush:javascript;toolbal:false;">              



現在讓我們使用 JavaScript 訪問這些輸入對象,并在表單提交時驗證它們。

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 函數中,以便在加載窗口時運行此腳本。首先,我們使用表單 ID 獲取表單并將其放入名為 ourForm 的變量中,然后獲取提交按鈕(使用表單對象 getSubmit 方法)并將其放入名為 submit_button 的變量中,然后設置提交按鈕禁用屬性為“禁用”。

接下來我們定義一個 checkForm 函數。這會將表單字段內的所有輸入存儲為一個數組,并將其附加到一個名為..你猜對了的變量.. inputs!然后它定義了一些嵌套的 if 語句,這些語句根據我們的 Form 方法測試輸入數組內的每個字段。這就是我們在方法中返回 true 或 false 的原因,因此如果它返回 true,我們將傳遞該 if 語句并繼續執行下一個,但如果它返回 false,我們將退出 if 語句。

根據我們的函數定義,我們在頁面最初加載時執行 checkForm 函數,并將該函數附加到 keyup 事件和提交事件。

您可能會問,如果我們禁用了提交按鈕,為什么還要附加提交。好吧,如果您專注于輸入字段并按下 Enter 鍵,它將嘗試提交表單,我們需要對此進行測試,因此我們的 checkForm 函數返回 true(提交表單)或 false(不提交)形式)。

結論

因此,我們學習了如何在 JavaScript 中定義不同的對象類型并在其中創建屬性和方法。我們還學習了一個漂亮的 addEvent 函數,并在基本的現實示例中使用我們的對象。

這就是 JavaScript 面向對象的基礎知識。希望這可以讓您開始構建自己的 JavaScript 庫!如果您喜歡這篇文章并對其他 JavaScript 相關主題感興趣,請將它們發布在評論中,我很樂意繼續撰寫它們。感謝您的閱讀。

為什么不看看 CodeCanyon 上的 JavaScript 項目范圍。您可以找到用于創建滑塊、倒計時、加載器和上傳器等的腳本。

JavaScript的面向對象基礎知識

? 版權聲明
THE END
喜歡就支持一下吧
點贊11 分享