See December is coming, seize the tail of this year, a good summary of the shortcomings and harvest in front. This article is the second article, I wrote design pattern project is based on summarizing and refining in the work, in the actual application will be heavily used in the scene, as to why want to write a design pattern, mainly in order to improve the team code quality and maintainability, the subsequent will continue to launch design patterns related articles, for your reference and study.
You will learn
- What the iterator pattern means
- Implement an array iterator
- Implement an object iterator
- Implement path lookup/assignment iterators
- How to solve the branch loop nesting problem with the idea of iterators
- Implement a picture player
The body of the
1. What iterators mean
The main idea behind the iterator pattern is to access the elements of an object in a certain order without exposing its internal structure.
In fact, many methods in javascript use the idea of iterators, such as forEach, every, find, some, map, entries, and so on. These operations greatly simplify our logical operations. Next, let’s take a look at its specific applications.
Implement an array iterator
We all know the forEach method for arrays in javascript, so instead of using this method, can we implement one ourselves?
// Array iterator
let eachArr = function(arr, fn) {
let i = 0,
len = arr.length;
for(; i < len; i++) {
if(fn.call(arr[i], i, arr[i]) === false) {
break; }}}/ / use
eachArr([1.2.3.4], (index, value) => { console.log(index, value) })
Copy the code
Implement an object iterator
Object iterators are similar to array iterators except that the parameters are passed differently, as follows:
// Object iterator
let eachObj = function(obj, fn) {
for(let key in obj) {
if(fn.call(obj[key], key, obj[key]) === false) {
break; }}}/ / use
eachObj({a: 11.b: 12}, (key, value) => { console.log(key, value) })
Copy the code
4. Implement path lookup/assignment iterators
Sometimes some of the qualities of the action object, we don’t know whether the server will be the property or the property of the superior property right is returned to us, this time we directly through some grammar or direct access to the [] syntax can lead to an error code, so we need to each layer operation to do security check, it will produce a large number of bloated code, such as:
let obj = {};
/ / get obj. Num. TitNum
let titNum = obj.num.titNum; / / an error
let titNum = obj && obj.num && obj.num.titNum; / / right
Copy the code
We can greatly reduce this validation with iterators and achieve a more robust code pattern:
let findObjAttr = function(obj, key){
if(! obj || ! key) {return undefined
}
let result = obj;
key = key.split('. ');
for(let i =0; len = key.length; i< len; i++) {
if(result[key[i]] ! = =undefined) {
result = result[key[i]]
}else {
return undefined}}return result
}
/ / use
let a = { b: { c: { d: 1}}}; findObjAttr(a,'a.b.c.d') / / 1
Copy the code
Isn’t this a bit like lodash’s object/array finder? In the same way, we can implement path assignment, as follows:
let setObjAttr = function(obj, key, value){
if(! obj) {return false
}
let result = obj,
key = key.split('. ');
for(let i =0, len = key.length; i< len - 1; i++){
if(result[key[i]] === undefined) {
result[key[i]] = {};
}
if(! (result[key[i]]instanceof Object)) {// If layer I does not correspond to an object, then the error is cropped
throw new Error('is not Object')
return false
}
result = result[key[i]]
}
return result[key[i]] = val
}
/ / use
setObjAttr(obj, 'a.b.c.d'.'xuxi')
Copy the code
5. How to solve the branch loop nesting problem with the idea of iterators
The problem with nested branch loops is that additional judgments need to be made in the body of the loop, which can cause serious performance overhead problems if the number of criteria is increased, as shown in the following example:
// Data grouping
function group(name, num) {
let data = [];
for(let i = 0; i < num; i++){
switch(name) {
case 'header':
data[i][0] = 0;
data[i][1] = 1;
break;
case 'content':
data[i][0] = 2;
data[i][1] = 3;
break;
case 'footer':
data[i][0] = 4;
data[i][1] = 532;
break;
default:
break; }}return data
}
Copy the code
From the above analysis, we can see that there is a lot of room for optimization in the above code, because each iteration requires a branch judgment, so if num becomes 100000, and there are 100 types of name, then we have to make 100000*100 useless branch judgments, which will undoubtedly make your code stuck under the big data. But we can optimize it in the following ways:
// Data grouping
function group(name, num) {
let data = [];
let strategy = function() {
let deal = {
'default': function(i){
return
},
'header': function(i){
data[i][0] = 0;
data[i][1] = 1;
},
'content': function(i){
data[i][0] = 2;
data[i][1] = 3;
},
/ /...
}
return function(name) {
return deal[name] || deal['default']}} ();// Iterators process data
function _each(fn) {
for(let i = 0; i < num; i++){
fn(i)
}
}
_each(strategy(name))
return data
}
Copy the code
In this way, we can avoid branch judgments, greatly improving code efficiency and performance.
6. Implement a picture player
// Picture player
let imgPlayer = function(imgData, box) {
let container = box && document.querySelector(box) || document,
img = container.querySelector('img'),
// Get the image length
len = imgData.length,
// The current index value
index = 0;
// Initialize the image
img.src = imgData[0];
var timer = null;
return {
// Get the first image
first: function() {
index = 0
img.src = imgData[index]
},
// Get the last image
last: function() {
index = len - 1
img.src = imgData[index]
},
// Switch to the previous image
pre: function() {
if(--index > 0) {
img.src = imgData[index]
}else {
index = 0
img.src = imgData[index]
}
},
// Switch to the latter image
next: function() {
if(++index < len) {
img.src = imgData[index]
}else {
index = len - 1
img.src = imgData[index]
}
},
// Autoplay the image
play: function() {
timer = setInterval((a)= > {
if(index > len - 1) {
index = 0
}
img.src = imgData[index]
index++
}, 5000)},// Stop playing the picture
stop: function() {
clearInterval(timer)
}
}
}
/ / use
let player = new imgPlayer(imgData, '#box')
Copy the code
In short, the iterator idea and the combination of other design patterns can design a wide variety of highly configured components, so learning and understanding the essence of javascript design patterns determines our altitude and attitude.
The last
If you want to learn more about webpack, node, gulp, CSS3, javascript, nodeJS, Canvas and other front-end knowledge and actual practice, welcome to join us in the public account “Interesting Talk front-end” to learn and discuss, and jointly explore the boundary of the front-end.
More recommended
- “Front-end combat summary” using CSS3 to achieve cool 3D rotation perspective
- Add a loading progress bar to your site using pace. Js
- The Application of design Pattern of “Summary of Front End Actual Combat” — Memorandum Pattern
- “Front End Combat Summary” using postMessage to achieve pluggable cross-domain chatbot
- “Front-end combat summary” of the variable promotion, function declaration promotion and variable scope detailed explanation
- “Front-end combat summary” how to change the URL without refreshing the page
- A picture shows you how to play vue-Cli3 quickly
- Vue Advanced Advanced series – Play with Vue and vuex in typescript
- Implementing a CMS full stack project from 0 to 1 based on nodeJS (Part 1)
- Implementing a CMS full stack project from 0 to 1 based on nodeJS (middle)
- Implement a CMS full stack project from 0 to 1 based on nodeJS (Part 2)
- Write a mock data server using nodeJS in 5 minutes
- With CSS3 to achieve stunning interviewers background that background animation (advanced source)
- Teach you to use 200 lines of code to write a love bean spell H5 small game (with source code)
- Cartesian product is implemented and applied in javascript