In JavaScript, browsers, especially browsers on mobile devices allocate very limited memory, and how to save memory has become a very meaningful thing. An effective way to save memory is to reduce the number of objects.
The Flyweight mode (Flyweight) runs sharing technology to effectively support a large number of fine-grained objects, avoiding the overhead of a large number of small classes with the same content (such as memory consumption), and allowing everyone to share a class (metaclass).
The Encyclopedia pattern can avoid a large amount of overhead of very similar classes. In programming, it is sometimes necessary to produce a large number of fine-grained class instances to represent data. If you can find that these instances have basically the same overhead except for a few parameters, you can significantly reduce the number of classes that need to be instantiated. If those parameters can be moved outside the class instance and passed them in when the method is called, the number of individual instances can be greatly reduced by sharing.
There are two ways to apply the Encyclopedia mode in JavaScript. The first is to apply it on the data layer, mainly to a large number of similar objects in memory; the second is to apply it on the DOM layer, Encyclopedia can be used on the central event manager to avoid adding event handles to each child element in the parent container.
There are two important concepts in Flyweight - internal state intrinsic and external state extrinsic. Internal state is managed through internal methods in the object, and external information can be deleted or saved externally.
To put it bluntly, it is to first pinch an original model, and then produce specific models with different characteristics according to different occasions and environments. Obviously, different new objects need to be generated here, so Factory mode often appears in the Flyweight mode. The internal state of Flyweight is used to share. Flyweight factory is responsible for maintaining a Flyweight pool (mode pool) to store objects with internal state.
We can replace all objects with the same internal state with the same shared object, and to create such a shared object, a singleton factory method is required instead of a normal constructor. This can track individual objects that have been instantiated, so that a new object is created only if the internal state of the required object is different from the existing object. The external state of the object is saved in a manager object. When calling the object's method, the manager will pass these external states as parameters.
Save the data of an object in two different objects (shared object, manager object)
1. Shared object (enjoy the original object)
2. Singleton factory method (create a shared object)
3. Manager object (manage external state)
For example, a book in a library can be represented by an object, which has many attributes.
var Book = function( id, title, author, genre, pageCount, publisherID, ISBN, checkoutDate, checkoutMember, dueReturnDate, availability ){ ...//Initialization code}Book.prototype = { getTitle:function(){ return this.title; }, ... // Update the lending status method updateCheckoutStatus:function(bookID, newStatus, checkoutDate, checkoutMember, newReturnDate){...}, //Renew extendCheckoutPeriod: function(bookID, newReturnDate){...}, // Whether it expires isPastDue: function(bookID){...}}The program may be fine at the beginning, but as time goes by, books may increase in large quantities, and each type of book has different versions and quantities, you will find that the system is getting slower and slower. Thousands of book objects can be imagined in memory, and we need to use the Encyclopedia mode to optimize.
We can divide the data into two types of data. In the same book, the data related to book objects (title, author, etc.) can be attributed to internal properties, while (checkoutMember, dueReturnDate, etc.) can be attributed to external properties. In this way, the following code can share the same object in the same book, because no matter who borrows the book, as long as the book is the same book, the basic information is the same:
//Shared object var Book = function(title, author, genre, pageCount, publisherID, ISBN){ this.title = title; this.author = author; this.genre = genre; this.pageCount = pageCount; this.publisherID = publisherID; this.ISBN = ISBN;};Let's define a basic factory to check whether the object of the book was created before, return if there is, and recreate and store it so that it can continue to access later, which ensures that we only create one object for each book:
/* Book factory singleton*/var BookFactory = (function(){ var existingBooks = {}; return{ createBook: function(title, author, genre,pageCount,publisherID,ISBN){ /* Find whether to create before */ var existingBook = existingBooks[ISBN]; if(existingBook){ return existingBook; }else{ /* If not, create one and save */ var book = new Book(title, author, genre,pageCount,publisherID,ISBN); existingBooks[ISBN] = book; return book; } } }});The external state is relatively simple. Except for the book we encapsulated, everything else needs to be managed here:
/*BookRecordManager Singleton for Borrow Management*/var BookRecordManager = (function(){ var bookRecordDatabase = {}; return{ /*Add a borrowing record*/ addBookRecord: function(id, title, author, genre, pageCount, publisherID,ISBN, checkoutDate, checkoutMember, dueReturnDate, availability){ var book = bookFactory.createBook(title, author, genre, pageCount, publisherID,ISBN); bookRecordDatabase[id] ={ checkoutMember: checkoutMember, checkoutDate: checkoutDate, dueReturnDate: dueReturnDate, availability: availability, book: book; }; }, updateCheckoutStatus: function(bookID, newStatus, checkoutDate, checkoutMember, newReturnDate){ var record = bookRecordDatabase[bookID]; record.availability = newStatus; record.checkoutDate = checkoutDate; record.checkoutMember = checkoutMember; record.dueReturnDate = newReturnDate; }, extendCheckoutPeriod: function(bookID, newReturnDate){ bookRecordDatabase[bookID].dueReturnDate = newReturnDate; }, isPastDue: function(bookID){ var currentDate = new Date(); return currentDate.getTime() > Date.parse(bookRecordDatabase[bookID].dueReturnDate); } };});In this way, we have saved the same information of the same book in a bookmanager object and saved only one copy; compared with the previous code, we can find that it saves a lot of memory.
Object pool
Object pool is another performance optimization solution, which has some similarities with the Xiangyuan mode, but does not separate the internal state and the external state.
General object pool implementation:
var objectPoolFactory = function (createObjFn) { var objectPool = []; //Object Pool return { create: function () { //Retrieve var obj = objectPool.length === 0 ? createObjFn.apply(this,arguments) : objectPool.shift(); return obj; }, recover: function (obj) { //Retrieve objectPool.push(obj); } }};Now use objectPoolFactory to create an object pool that loads some iframes:
var iframeFactory = objectPoolFactory(function () { var iframe = document.createElement('iframe'); document.body.appendChild(iframe); iframe.onload = function () { iframe.onload = null; // Prevent bugs of iframe loading iframeFactory.recover(iframe); //Fill in the object pool back to the node (retrieve) }; return iframe;}); //Call var iframe1 = iframeFactory.create(); iframe1.src = 'http://www.qq.com';References: "JavaScript Pattern" "JavaScript Design Pattern and Development Practice"
The above is all the content of this article. I hope it will be helpful to everyone's learning and I hope everyone will support Wulin.com more.