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