在JavaScript 中,並沒有對抽象類別和介面的支援。 JavaScript 本身也是一門弱型別語言。在封裝類型方面,JavaScript 沒有能力,也沒有必要做得更多。對於JavaScript 的設計模式實作來說,不區分型別是一種失色,也可以說是一種解脫。
從設計模式的角度出發,封裝在更重要的層面體現為封裝變化。
透過封裝變化的方式,把系統中穩定不變的部分和容易變化的部分隔離開來,在系統的演變過程中,我們只需要替換那些容易變化的部分,如果這些部分是已經封裝好的,替換起來也相對容易。這可以最大程度地保證程式的穩定性和可擴展性。
javascript封裝的的基本模式有3種:
1、使用約定優先的原則,將所有的私有變數以_開頭
<script type="text/javascript"> /** * 使用约定优先的原则,把所有的私有变量都使用_开头 */ var Person = function (no, name, age) { this.setNo(no); this.setName(name); this.setAge(age); } Person.prototype = { constructor: Person, checkNo: function (no) { if (!no.constructor == "string" || no.length != 4) throw new Error("学号必须为4位"); }, setNo: function (no) { this.checkNo(no); this._no = no; }, getNo: function () { return this._no; setName: function (name) { this._name = name; }, getName: function () { return this._name; }, setAge: function (age) { this._age = age; }, getAge: function () { return this._age; }, toString: function () { return "no = " + this._no + " , name = " + this._name + " , age = " + this._age; } }; var p1 = new Person("0001", "小平果", "22"); console.log(p1.toString()); //no = 0001 , name = 小平果 , age = 22 p1.setNo("0003"); console.log(p1.toString()); //no = 0003 , name = 小平果 , age = 22 p1.no = "0004"; p1._no = "0004"; console.log(p1.toString()); //no = 0004 , name =小平果 , age = 22 </script>
看完程式碼,是不是有種被坑的感覺,僅僅把所有的變數以_開頭,其實還是可以直接存取的,這能叫封裝麼,當然了,說了是約定優先嘛。
下劃線的這種用法這一個眾所周知的命名規範,它表明一個屬性僅供對象內部使用,直接訪問它或設置它可能會導致意想不到的後果。這有助於防止程式設計師對它的無意使用,卻不能防止對它的有意使用。
這種方式還是不錯的,最起碼成員變數的getter,setter方法都是prototype中,並非存在物件中,整體來說還是個不錯的選擇。如果你覺得,這不行,必須嚴格實現封裝,那麼看第二種方式。
2、嚴格實現封裝
<script type="text/javascript"> /** * 使用这种方式虽然可以严格实现封装,但是带来的问题是get和set方法都不能存储在prototype中,都是存储在对象中的 * 这样无形中就增加了开销 */ var Person = function (no, name, age) { var _no , _name, _age ; var checkNo = function (no) { if (!no.constructor == "string" || no.length != 4) throw new Error("学号必须为4位"); }; this.setNo = function (no) { checkNo(no); _no = no; }; this.getNo = function () { return _no; } this.setName = function (name) { _name = name; } this.getName = function () { return _name; } this.setAge = function (age) { _age = age; } this. getAge = function () { return _age; } this.setNo(no); this.setName(name); this.setAge(age); } Person.prototype = { constructor: Person, toString: function () { return "no = " + this.getNo() + " , name = " + this.getName() + " , age = " + this.getAge(); } } ; var p1 = new Person("0001", "小平果", "22"); console.log(p1.toString()); //no = 0001 , name =小平果 , age = 22 p1.setNo("0003"); console.log(p1.toString()); //no = 0003 , name = 小平果 , age = 22 p1.no = "0004"; console.log(p1.toString()); //no = 0003 , name = 小平果 , age = 22 </script>
那麼這與我們先前講過的其他創建對象的模式有什麼不同呢,在上面的例子中,我們在創建和引用對象的屬性時總是要使用this關鍵字。而在本例中,我們用var宣告這些變數。這意味著它們只存在於Person構造器中。 checkno函數也是用同樣的方式宣告的,因此成了一個私用方法。
需要存取這些變數和函數的方法只需要聲明在Person中即可。這些方法被稱為特權方法,因為它們是公用方法,但卻能夠存取私人屬性和方法。為了在物件外部能存取這些特權函數,它們的前面被加上了關鍵字this。因為這些方法定義於Person建構器的作用域,所以它們能存取到私用屬性。引用這些屬性時並沒有使用this關鍵字,因為它們不是公開的。所有取值器和賦值器方法都改為不加this地直接引用這些屬性。
任何不需要直接存取的私人屬性的方法都可以像原來那樣在Person.prototype中聲明。像toString()方法。只有那些需要直接存取私人成員的方法才應該被設計為特權方法。但特權方法太多又會佔用過多的內存,因為每個物件實例都包含所有特權方法的新副本。
看上面的程式碼,去掉了this.屬性名,嚴格的實作了封裝,只能透過getter,setter存取成員變數了,但是存在一個問題,所有的方法都存在物件中,增加了記憶體的開銷。
3、以閉包的方式封裝
<script type="text/javascript"> var Person = (function () { //静态方法(共享方法) var checkNo = function (no) { if (!no.constructor == "string" || no.length != 4) throw new Error("学号必须为4位"); }; //静态变量(共享变量) var times = 0; //return the constructor. return function (no, name, age) { console.log(times++); // 0 ,1 , 2 var no , name , age; //私有变量 this.setNo = function (no) //私有方法 { checkNo(no); this._no = no; }; this.getNo = function () { return this._no; } this.setName = function (name) { this._name = name; } this.getName = function () { return this._name; } this.setAge = function (age) { this._age = age; } this.getAge = function () { return this._age; } this.setNo(no); this.setName(name); this.setAge(age); } })(); Person.prototype = { constructor: Person, toString: function () { return "no = " + this._no + " , name = " + this._name + " , age = " + this._age; } }; var p1 = new Person("0001", "小平果", "22"); var p2 = new Person("0002", "abc", "23"); var p3 = new Person("0003", "aobama", "24"); console.log(p1.toString()); //no = 0001 , name = 小平果 , age = 22 console.log(p2.toString()); //no = 0002 , name = abc , age = 23 console.log(p3.toString()); //no = 0003 , name = aobama , age = 24 </script>
上述程式碼,js引擎載入完後,會直接執行Person = 立即執行函數,然後此函數傳回了一個子函數,這個子函數才是new Person所呼叫的建構函數,又因為子函數中保持了對立即執行函數中checkNo(no) ,times的引用,(很明顯的閉包)所以對於checkNo和times,是所有Person對象所共有的,創建3個對象後,times分別為0,1,2 。這種方式的好處是,可以使Person中需要重複使用的方法和屬性做到私有且物件間共用。
這裡的私人成員和特權成員仍然被聲明在構造器中。但那個建構器卻從原來的普通函數變成了一個內嵌函數,並且被當作包含它的函數的回傳值給變數Person。這就創建了一個閉包,你可以把靜態的私人成員聲明在裡面。位於外層函數宣告之後的一對空括號很重要,其作用是程式碼一載入就會立即執行這個函數。這個函數的回傳值是另一個函數,它被賦給Person變量,Person因此成了一個建構函數。在實例華Person時,所呼叫的這個內層函數。外層那個函數只是用來建立一個可以用來儲存靜態成員的閉包。
在本例中,checkno被設計成為靜態方法,原因是為Person的每個實例都產生這個方法的一個新副本毫無道理。另外還有靜態屬性times,其作用在於追蹤Person建構器的總呼叫次數。
以上就是本文的全部內容,希望對大家的學習有所幫助,大家可以更深入的學習了解封裝的意義。

去掉重复并排序的方法:1、使用“Array.from(new Set(arr))”或者“[…new Set(arr)]”语句,去掉数组中的重复元素,返回去重后的新数组;2、利用sort()对去重数组进行排序,语法“去重数组.sort()”。

本篇文章给大家带来了关于JavaScript的相关知识,其中主要介绍了关于Symbol类型、隐藏属性及全局注册表的相关问题,包括了Symbol类型的描述、Symbol不会隐式转字符串等问题,下面一起来看一下,希望对大家有帮助。

怎么制作文字轮播与图片轮播?大家第一想到的是不是利用js,其实利用纯CSS也能实现文字轮播与图片轮播,下面来看看实现方法,希望对大家有所帮助!

本篇文章给大家带来了关于JavaScript的相关知识,其中主要介绍了关于对象的构造函数和new操作符,构造函数是所有对象的成员方法中,最早被调用的那个,下面一起来看一下吧,希望对大家有帮助。

本篇文章给大家带来了关于JavaScript的相关知识,其中主要介绍了关于面向对象的相关问题,包括了属性描述符、数据描述符、存取描述符等等内容,下面一起来看一下,希望对大家有帮助。

方法:1、利用“点击元素对象.unbind("click");”方法,该方法可以移除被选元素的事件处理程序;2、利用“点击元素对象.off("click");”方法,该方法可以移除通过on()方法添加的事件处理程序。

本篇文章给大家带来了关于JavaScript的相关知识,其中主要介绍了关于BOM操作的相关问题,包括了window对象的常见事件、JavaScript执行机制等等相关内容,下面一起来看一下,希望对大家有帮助。

foreach不是es6的方法。foreach是es3中一个遍历数组的方法,可以调用数组的每个元素,并将元素传给回调函数进行处理,语法“array.forEach(function(当前元素,索引,数组){...})”;该方法不处理空数组。


熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

AI Hentai Generator
免費產生 AI 無盡。

熱門文章

熱工具

Dreamweaver Mac版
視覺化網頁開發工具

Safe Exam Browser
Safe Exam Browser是一個安全的瀏覽器環境,安全地進行線上考試。該軟體將任何電腦變成一個安全的工作站。它控制對任何實用工具的訪問,並防止學生使用未經授權的資源。

禪工作室 13.0.1
強大的PHP整合開發環境

SAP NetWeaver Server Adapter for Eclipse
將Eclipse與SAP NetWeaver應用伺服器整合。

SublimeText3 英文版
推薦:為Win版本,支援程式碼提示!