您好,登錄后才能下訂單哦!
本文實例講述了JS閉包原理與應用。分享給大家供大家參考,具體如下:
一、先來看一個例子:
function foo() { var a = 10; function bar() { a *= 2; return a; } return bar; } var baz = foo(); // baz is now a reference to function bar. console.log(baz()); // returns 20. console.log(baz()); // returns 40. console.log(baz()); // returns 80. var blat = foo(); // blat is another reference to bar. console.log(blat()); // returns 20, because a new copy of a is being used.
這里使用在線HTML/CSS/JavaScript代碼運行工具:http://tools.jb51.net/code/HtmlJsRun測試上述代碼,可得到如下運行結果:
一直以來,我都是以為只有用匿名函數才能算是閉包,但是其實不一定要用匿名函數的,就是一般的函數就可以,前提是它得被包含在另一個函數中。
在foo返回后,它的作用域被保存下來了,但只有它返回的的那個函數能夠訪問這個作用域。在前面的示例中,baz和balt各有各的作用域及a的一個副本,而且只有他們自己能對其進行修改。
其實就是說我們對foo函數的引用的調用并不會對其他引用有任何影響。
二、封裝和隱藏信息
看了上面的例子,我們可以考慮采用匿名函數來進行封裝和隱藏私有變量。
var Book = function(newIsbn, newTitle, newAuthor) { // implements Publication // Private attributes. var isbn, title, author; // Private method. function checkIsbn(isbn) { //... return true; } // Privileged methods. this.getIsbn = function() { return isbn; }; this.setIsbn = function(newIsbn) { if(!checkIsbn(newIsbn)) throw new Error('Book: Invalid ISBN.'); isbn = newIsbn; }; this.getTitle = function() { return title; }; this.setTitle = function(newTitle) { title = newTitle || 'No title specified'; }; this.getAuthor = function() { return author; }; this.setAuthor = function(newAuthor) { author = newAuthor || 'No author specified'; }; // Constructor code. this.setIsbn(newIsbn); this.setTitle(newTitle); this.setAuthor(newAuthor); }; // Public, non-privileged methods. Book.prototype = { display: function() { //... } }; var mybook=new Book("myisbtn","mytittle","myauthor"); console.log(mybook.getAuthor());
使用在線HTML/CSS/JavaScript代碼運行工具:http://tools.jb51.net/code/HtmlJsRun測試上述代碼,可得到如下運行結果:
我們通過在構造器中用var聲明了這些變量和checkIsbn函數,因此他們就變成了私有的屬性。需要訪問這些變量和函數的方法只需要在Book中聲明即可。這些方法也被陳偉特權方法。而任何不需要訪問私有屬性的方法都要在Book.prototype
中聲明。例如display。但這里也存在個問題:就是每生成一個新的對象實例都將為每一個私有方法和特權方法生成一個新的副本。這會比其他做法耗費更多內存,因此只宜用在真正需要私有成員的場合。另外,這種模式也不適合派生子類,因為派生的子類并不能訪問超類的任何私有屬性和方法。故在JavaScript中用閉包實現私有成員導致派生問題被稱為“繼承破壞封裝”。
三、改進
這里與上一種大體類似,但是也有一些重要的區別。這里私有成員和特權成員仍被聲明在構造器中,但是構造器已經變成一個內嵌函數了,并且被作為包含它的函數的返回值賦給變量Book.這就是創建了一個閉包,你可以把靜態的私有成員函數聲明在里面。
checkIsbn函數被設置為靜態方法,是因為沒必要為每個實例都生成這個方法的一個副本。此外還有靜態屬性numBooks限制了構造器總的調用次數
var Book = (function() { // Private static attributes. var numOfBooks = 0; // Private static method. function checkIsbn(isbn) { // ... return true; } // Return the constructor. return function(newIsbn, newTitle, newAuthor) { // implements Publication // Private attributes. var isbn, title, author; // Privileged methods. this.getIsbn = function() { return isbn; }; this.setIsbn = function(newIsbn) { if(!checkIsbn(newIsbn)) throw new Error('Book: Invalid ISBN.'); isbn = newIsbn; }; this.getTitle = function() { return title; }; this.setTitle = function(newTitle) { title = newTitle || 'No title specified'; }; this.getAuthor = function() { return author; }; this.setAuthor = function(newAuthor) { author = newAuthor || 'No author specified'; }; // Constructor code. numOfBooks++; // Keep track of how many Books have been instantiated // with the private static attribute. if(numOfBooks > 1) throw new Error('Book: Only 1 instances of Book can be ' + 'created.'); this.setIsbn(newIsbn); this.setTitle(newTitle); this.setAuthor(newAuthor); } })(); // Public static method. Book.convertToTitleCase = function(inputString) { //... console.log("convertToTitleCase"); }; // Public, non-privileged methods. Book.prototype = { display: function() { //... console.log("display"); } }; var mybook=new Book("myisbtn","mytittle","myauthor"); console.log(mybook.getAuthor()); //myauthor mybook.display(); //display //mybook.convertToTitleCase(); //mybook.convertToTitleCase is not a function var mybook2= new Book("my2","tittle2","myauthor2"); console.log(mybook2.getAuthor()); //Only 1 instances of Book can be created.
使用在線HTML/CSS/JavaScript代碼運行工具:http://tools.jb51.net/code/HtmlJsRun測試上述代碼,可得到如下運行結果:
更多關于JavaScript相關內容感興趣的讀者可查看本站專題:《javascript面向對象入門教程》、《JavaScript錯誤與調試技巧總結》、《JavaScript數據結構與算法技巧總結》、《JavaScript遍歷算法與技巧總結》及《JavaScript數學運算用法總結》
希望本文所述對大家JavaScript程序設計有所幫助。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。