Still afraid of handwritten questions, this article can help you expand and consolidate their JS foundation, by the way, 90% of the handwritten questions. In my work, I can also implement common requirements by hand, such as deep copy, anti-shake throttling, which can be directly used in future projects to improve the efficiency of project development. No more nonsense, let’s go straight to the code.

1. The realization of the call

  • When the first argument is null or undefined, this refers to the global object window, and the autowrap object with the original value, such as String, Number, or Boolean, refers to that original value
  • To avoid conflicts between function names and context attributes, use the Symbol type as the unique value
  • Execute the function as the context property passed in
  • Delete the property after the function completes
  • Return execution result
Function.prototype.myCall = function(context,... args){
    let cxt = context || window;
    // Define the currently invoked method on cxt.func (in order to bind this as an object call)
    // Create a unique Symbol variable to avoid duplication
    let func = Symbol() 
    cxt[func] = this;
    args = args ? args : []
    // Call func as an object call, where this refers to CXT, which is passed in to bind to this
    const res = args.length > 0? cxt[func](... args) : cxt[func]();// Delete this method, otherwise it will contaminate the object passed in (add this method)
    delete cxt[func];
    return res;
}
Copy the code

2. The realization of the apply

  • The previous part is the same as call
  • The second argument may not be passed, but it must be of type array or array-like
Function.prototype.myApply = function(context,args = []){
    let cxt = context || window;
    // Define the currently invoked method on cxt.func (in order to bind this as an object call)
    // Create a unique Symbol variable to avoid duplication
    let func = Symbol()
    cxt[func] = this;
    // Call func as an object call, where this refers to CXT, which is passed in to bind to this
    const res = args.length > 0? cxt[func](... args) : cxt[func]();delete cxt[func];
    return res;
}
Copy the code

3. The realization of the bind

To consider:

  • Bind () can pass multiple arguments in addition to changing the point to this;
  • A new function created by bind may pass in multiple arguments;
  • New functions may be called as constructors;
  • Functions may return values;

Implementation method:

  • The bind method does not execute immediately and returns a function to be executed. (closures)
  • Implement scoped binding (APPLY)
  • Parameter passing (array passing for apply)
  • When used as a constructor, prototype inheritance is performed

Function.prototype.myBind = function (context, ... args) {
    // Create a new variable and assign the value this to the current function
    const fn = this
    // Determine whether or not an argument has been passed, and assign a value if it is null []
    args = args ? args : []
    // Return a newFn function in which fn is called
    return function newFn(. newFnArgs) {
        if (this instanceof newFn) {
            return newfn(... args, ... newFnArgs) }return fn.apply(context, [...args,...newFnArgs])
    }
}
Copy the code
  • test
let name = 'wang',age =17;
let obj = {
    name:'zhang'.age: this.age,
    myFun: function(from,to){
        console.log(this.name + 'age' + this.age+'from'+from+'去往'+ to)
    }
}
let db = {
    name: 'DE m'.age: 99
}

/ / the result
obj.myFun.myCall(db,'chengdu'.'Shanghai');// Dema is 99 years old. She comes from Chengdu and is going to Shanghai
obj.myFun.myApply(db,['chengdu'.'Shanghai']);      // Dema is 99 years old. She comes from Chengdu and is going to Shanghai
obj.myFun.myBind(db,'chengdu'.'Shanghai') ();// Dema is 99 years old. She comes from Chengdu and is going to Shanghai
obj.myFun.myBind(db,['chengdu'.'Shanghai') ();// Dema is 99 years old. She comes from Chengdu and goes to Undefined from Shanghai
Copy the code

Parasitic combination inheritance

function Person(obj) {
    this.name = obj.name
    this.age = obj.age
}
Person.prototype.add = function(value){
    console.log(value)
}
var p1 = new Person({name:"Tomato".age: 18})

function Person1(obj) {
    Person.call(this, obj)
    this.sex = obj.sex
}
// This step is the key to inheritance
Person1.prototype = Object.create(Person.prototype);
Person1.prototype.constructor = Person1;

Person1.prototype.play = function(value){
    console.log(value)
}
var p2 = new Person1({name:"Eggs".age: 118.sex: "Male"})
Copy the code

5. ES6 inheritance

// Class is equivalent to the es5 constructor
// When you define a method in a class, do not add function before or after it. Define all methods in the protopyte attribute of the class
// All methods defined in class are not enumerable
// Only methods can be defined in a class, not objects, variables, etc
// Strict mode is the default for both class and method
// Constructor is an implicit property in ES5
class People{
  constructor(name='wang',age='27'){
    this.name = name;
    this.age = age;
  }
  eat(){
    console.log(`The ${this.name} The ${this.age} eat food`)}}// Inherit from the parent class
class Woman extends People{ 
   constructor(name = 'ren',age = '27'){ 
     // Inherit the properties of the parent class
     super(name, age); 
   } 
    eat(){ 
     // Inherit the superclass method
      super.eat() 
    } 
} 
let wonmanObj=new Woman('xiaoxiami'); 
wonmanObj.eat();

// Es5 inheritance creates the instance object of the subclass, and then adds the method of the Parent class to this (parent-.apply (this)).
// Es6 inheritance is to create an instance object of the parent class using the keyword super, and then modify this in the subclass class.
Copy the code

6. The new implementation

  • A new object inherited from foo. prototype is created.
  • Calls the constructor Foo with the specified arguments and binds this to the newly created object. New Foo is the same as new Foo(), that is, when no argument list is specified and Foo is called with no arguments.
  • The object returned by the constructor is the result of the new expression. If the constructor does not explicitly return an object, the object created in Step 1 is used.
  • Normally, constructors do not return values, but users can choose to actively return objects to override the normal object creation steps
function Ctor(){... }function myNew(ctor,... args){
    if(typeofctor ! = ='function') {throw 'myNew function the first param must be a function';
    }
    var newObj = Object.create(ctor.prototype); // Create a new object inherited from ctor.prototype
    var ctorReturnResult = ctor.apply(newObj, args); // Bind constructor ctor's this to newObj
    var isObject = typeof ctorReturnResult === 'object'&& ctorReturnResult ! = =null;
    var isFunction = typeof ctorReturnResult === 'function';
    if(isObject || isFunction){
        return ctorReturnResult;
    }
    return newObj;
}

let c = myNew(Ctor);

Copy the code

7. Instanceof implementation

  • Instanceof is used to determine whether A is an instanceof b. the expression is: A instanceof B, return true if A is an instanceof B, false otherwise.
  • The instanceof operator tests whether an object has a constructor’s prototype property in its prototype chain.
  • Cannot detect the basic data type, the results on the prototype chain may not be accurate, cannot detect null,undefined
  • Implementation: iterates through the left-hand variable’s prototype chain until it finds the right-hand variable’s prototype, returning false if none is found
function myInstanceOf(a,b){
    let left = a.__proto__;
    let right = b.prototype;
    while(true) {if(left == null) {return false
        }
        if(left == right){
            return true
        }
        left = left.__proto__
    }
}

// The instanceof operator is used to determine whether the constructor's prototype property appears anywhere in the object's prototype chain.
function myInstanceof(left, right) {
    let proto = Object.getPrototypeOf(left), // Get the prototype of the object
    prototype = right.prototype; // Get the constructor's prototype object
    // Determine whether the constructor's prototype object is on the prototype chain of the object
    while (true) {
        if(! proto)return false;
        if (proto === prototype) return true;
        proto = Object.getPrototypeOf(proto); }}Copy the code

8. The Object. The create () implementation

  • MDN document
  • Object.create() takes the argument Object as a prototype for a newly created empty Object and returns the empty Object
/ / a brief version
function myCreate(obj){
    // Declare a function
    function C(){};
    // Point the function prototype to obj
    C.prototype = obj;
    // Return the functionalized object
    return new C()
}
// Official Polyfill
if (typeof Object.create ! = ="function") {
    Object.create = function (proto, propertiesObject) {
        if (typeofproto ! = ='object' && typeofproto ! = ='function') {
            throw new TypeError('Object prototype may only be an Object: ' + proto);
        } else if (proto === null) {
            throw new Error("This browser's implementation of Object.create is a shim and doesn't support 'null' as the first argument.");
        }

        if (typeofpropertiesObject ! = ='undefined') throw new Error("This browser's implementation of Object.create is a shim and doesn't support a second argument.");

        function F() {}
        F.prototype = proto;

        return new F();
    };
}
Copy the code

9. The achieve Object. Assign

Object.assign2 = function(target, ... source) {
    if (target == null) {
        throw new TypeError('Cannot convert undefined or null to object')}let ret = Object(target) 
    source.forEach(function(obj) {
        if(obj ! =null) {
            for (let key in obj) {
                if (obj.hasOwnProperty(key)) {
                    ret[key] = obj[key]
                }
            }
        }
    })
    return ret
}
Copy the code

10. The realization of the Promise

Implementing A Promise requires A thorough understanding of the Promise A+ specification, but there are A few points to consider in terms of the overall implementation:

  • A Promise is a state machine and can only be in the following three states: This is very depressing. The change of the state is one-way. The change of the state can only be changed from Pending -> Fulfilled or Pending -> Rejected
  • Then needs to support chained calls
class Promise {
    callbacks = [];
    state = 'pending';// Add the state
    value = null;// Save the result
    constructor(fn) {
        fn(this._resolve.bind(this), this._reject.bind(this));
    }
    then(onFulfilled, onRejected) {
        return new Promise((resolve, reject) = > {
            this._handle({
                onFulfilled: onFulfilled || null.onRejected: onRejected || null.resolve: resolve,
                reject: reject
            });
        });
    }
    _handle(callback) {
        if (this.state === 'pending') {
            this.callbacks.push(callback);
            return;
        }
 
        let cb = this.state === 'fulfilled' ? callback.onFulfilled : callback.onRejected;
 
        if(! cb) {// If nothing is passed in the then
            cb = this.state === 'fulfilled' ? callback.resolve : callback.reject;
            cb(this.value);
            return;
        }
 
        let ret = cb(this.value);
        cb = this.state === 'fulfilled' ? callback.resolve : callback.reject;
        cb(ret);
    }
    _resolve(value) {
 
        if (value && (typeof value === 'object' || typeof value === 'function')) {
            var then = value.then;
            if (typeof then === 'function') {
                then.call(value, this._resolve.bind(this), this._reject.bind(this));
                return; }}this.state = 'fulfilled';// Change the state
        this.value = value;// Save the result
        this.callbacks.forEach(callback= > this._handle(callback));
    }
    _reject(error) {
        this.state = 'rejected';
        this.value = error;
        this.callbacks.forEach(callback= > this._handle(callback)); }}Copy the code

Promise.resolve

  • Promsie.resolve(value) can turn any value to a value whose state is value, but if the value passed in is itself a Promise it will be returned as is.
Promise.resolve(value) {
  if (value && value instanceof Promise) {
    return value;
  } else if (value && typeof value === 'object' && typeof value.then === 'function') {
    let then = value.then;
    return new Promise(resolve= > {
      then(resolve);
    });
  } else if (value) {
    return new Promise(resolve= > resolve(value));
  } else {
    return new Promise(resolve= >resolve()); }}Copy the code

Promise.reject

  • Like promise.resolve (), promise.reject () instantiates a Promise in the rejected state. But unlike promise.resolve (), if you pass a Promise object to Promise.reject(), that object becomes the value of the new Promise.
Promise.reject = function(reason) {
    return new Promise((resolve, reject) = > reject(reason))
}
Copy the code

Promise.all

  • This will be fulfilled if all Promsie passed in are fulfilled, and the new Promise consisting of their values is returned.
  • As long as any Promise is rejected, a new Promsie in the rejected state is returned, and its value is the value of the first Promise rejected;
  • As long as any Promise is pending, a new Promise in the pending state is returned.
Promise.all = function(promiseArr) {
    let index = 0, result = []
    return new Promise((resolve, reject) = > {
        promiseArr.forEach((p, i) = > {
            Promise.resolve(p).then(val= > {
                index++
                result[i] = val
                if (index === promiseArr.length) {
                    resolve(result)
                }
            }, err= > {
                reject(err)
            })
        })
    })
}
Copy the code

Promise.race

  • Promises. Race returns a new instance wrapped by the first instance of all the iterable instances fulfilled or rejected.
Promise.race = function(promiseArr) {
    return new Promise((resolve, reject) = > {
        promiseArr.forEach(p= > {
            Promise.resolve(p).then(val= > {
                resolve(val)
            }, err= > {
                rejecte(err)
            })
        })
    })
}
Copy the code

11. The realization of Ajax

function ajax(url,method,body,headers){
    return new Promise((resolve,reject) = >{
        let req = new XMLHttpRequest();
        req.open(methods,url);
        for(let key in headers){
            req.setRequestHeader(key,headers[key])
        }
        req.onreadystatechange(() = >{
            if(req.readystate == 4) {if(req.status >= '200' && req.status <= 300){
                    resolve(req.responeText)
                }else{
                    reject(req)
                }
            }
        })
        req.send(body)
    })
}
Copy the code

12. Implement anti-skid function (debounce)

  • Successive trigger on last execution method, scenario: input box match
let debounce = (fn,time = 1000) = > {
    let timeLock = null

    return function (. args){
        clearTimeout(timeLock)
        timeLock = setTimeout(() = >{ fn(... args) },time) } }Copy the code

13. Implement throttling functions

  • Triggers only once in a certain period of time, scenario: long list scrolling throttling
let throttle = (fn,time = 1000) = > {
    let flag = true;

    return function (. args){
        if(flag){
            flag = false;
            setTimeout(() = >{
                flag = true; fn(... args) },time) } } }Copy the code

14. Deepclone

  • Determine the type, re, and date and return the new object directly
  • Null or non-object type, return the original value
  • Consider circular references and determine if the hash contains the value directly returned from the hash
  • Create a corresponding new obj.constructor to add the hash
  • Iterating over object recursion (normal key and key are symbol cases)
function deepClone(obj,hash = new WeakMap(a)){
    if(obj instanceof RegExp) return new RegExp(obj);
    if(obj instanceof Date) return new Date(obj);
    if(obj === null || typeofobj ! = ='object') return obj;
    // The case of circular references
    if(hash.has(obj)){
        return hash.get(obj)
    }
    //new a corresponding object
    //obj为Array,相当于new Array()
    //obj = new Object();
    let constr = new obj.constructor();
    hash.set(obj,constr);
    for(let key in obj){
        if(obj.hasOwnProperty(key)){
            constr[key] = deepClone(obj[key],hash)
        }
    }
    // Consider the symbol case
    let symbolObj = Object.getOwnPropertySymbols(obj)
    for(let i=0; i<symbolObj.length; i++){if(obj.hasOwnProperty(symbolObj[i])){
            constr[symbolObj[i]] = deepClone(obj[symbolObj[i]],hash)
        }
    }
    return constr
}
Copy the code

15. Implementation of array flat

let arr = [1.2[3.4[5[6]]]]
console.log(arr.flat(Infinity))// The flat argument specifies the structure depth to extract the nested array. The default value is 1
Copy the code
// Reduce
function fn(arr){
   return arr.reduce((prev,cur) = >{
      return prev.concat(Array.isArray(cur)? fn(cur):cur) },[]) }Copy the code

16. Function currying

function sumFn(a,b,c){return a+ b + c};
let sum = curry(sumFn);
sum(2) (3) (5)/ / 10
sum(2.3) (5)/ / 10
Copy the code
function curry(fn,... args){
  let fnLen = fn.length,
      argsLen = args.length;
  // Compare the parameters of the function to the parameters currently passed
  // Return curry recursively if there are not enough parameters
  // If there are enough arguments, call the function to return the corresponding value
  if(fnLen > argsLen){
    return function(. arg2s){
      returncurry(fn,... args,... arg2s) } }else{
    returnfn(... args) } }Copy the code

17. Print 1,2,3,4 every second using closures

for (var i=1; i<=5; i++) {
  (function (i) {
    setTimeout(() = > console.log(i), 1000*i)
  })(i)
}
Copy the code

18. Write a jSONP by hand

const jsonp = function (url, data) {
    return new Promise((resolve, reject) = > {
        // Initialize the URL
        let dataString = url.indexOf('? ') = = = -1 ? '? ' : ' '
        let callbackName = `jsonpCB_The ${Date.now()}`
        url += `${dataString}callback=${callbackName}`
        if (data) {
            // Have the request parameters, which are added to the URL in turn
            for (let k in data) {
                url += `${k}=${data[k]}`}}let jsNode = document.createElement('script')
        jsNode.src = url
        // Trigger the callback, which removes the js tag and the callback bound to the window
        window[callbackName] = result= > {
            delete window[callbackName]
            document.body.removeChild(jsNode)
            if (result) {
                resolve(result)
            } else {
                reject('No data returned')}}// js load exception
        jsNode.addEventListener('error'.() = > {
            delete window[callbackName]
            document.body.removeChild(jsNode)
            reject('JavaScript resource failed to load ')},false)
        // When the js node is added to the document, the request begins
        document.body.appendChild(jsNode)
    })
}
jsonp('http://192.168.0.103:8081/jsonp', {
    a: 1.b: 'heiheihei'
})
.then(result= > {
    console.log(result)
})
.catch(err= > {
    console.error(err)
})
Copy the code

19. Hand write an observer pattern

class Subject{
  constructor(name){
    this.name = name
    this.observers = []
    this.state = 'XXXX'
  }
  // The observed should provide a method for receiving the observer
  attach(observer){
    this.observers.push(observer)
  }

  // Change the state of being observed
  setState(newState){
    this.state = newState
    this.observers.forEach(o= >{
      o.update(newState)
    })
  }
}

class Observer{
  constructor(name){
    this.name = name
  }

  update(newState){
    console.log(`The ${this.name}say:${newState}`)}}// The observed lamp
let sub = new Subject('light')
let mm = new Observer('Ming')
let jj = new Observer('kin')
 
// Subscribe to the observer
sub.attach(mm)
sub.attach(jj)
 
sub.setState('The light is on, the power is on.')
Copy the code

20.EventEmitter implementation

class EventEmitter {
    constructor() {
        this.events = {};
    }
    on(event, callback) {
        let callbacks = this.events[event] || [];
        callbacks.push(callback);
        this.events[event] = callbacks;
        return this;
    }
    off(event, callback) {
        let callbacks = this.events[event];
        this.events[event] = callbacks && callbacks.filter(fn= >fn ! == callback);return this;
    }
    emit(event, ... args) {
        let callbacks = this.events[event];
        callbacks.forEach(fn= >{ fn(... args); });return this;
    }
    once(event, callback) {
        let wrapFun = function (. args) { callback(... args);this.off(event, wrapFun);
        };
        this.on(event, wrapFun);
        return this; }}Copy the code

21.Various ways to generate random numbers?

function getRandom(min, max) {
  return Math.floor(Math.random() * (max - min)) + min   
}
Copy the code

22. How to implement random array sort?

let arr = [2.3.454.34.324.32]
arr.sort(randomSort)
function randomSort(a, b) {
  return Math.random() > 0.5 ? -1 : 1;
}
Copy the code

23. Write a generic event listener function.

const EventUtils = {
  / / sight, respectively dom0 | | dom2 | | IE way to bind the event
  // Add events
  addEvent: function(element, type, handler) {
    if (element.addEventListener) {
      element.addEventListener(type, handler, false);
    } else if (element.attachEvent) {
      element.attachEvent("on" + type, handler);
    } else {
      element["on"+ type] = handler; }},// Remove events
  removeEvent: function(element, type, handler) {
    if (element.removeEventListener) {
      element.removeEventListener(type, handler, false);
    } else if (element.detachEvent) {
      element.detachEvent("on" + type, handler);
    } else {
      element["on" + type] = null; }},// Get the event target
  getTarget: function(event) {
    return event.target || event.srcElement;
  },
  // Get a reference to the event object, fetching all the information about the event, ensuring that the event can be used at any time
  getEvent: function(event) {
    return event || window.event;
  },
 // Prevent events (mainly event bubble, because IE does not support event capture)
  stopPropagation: function(event) {
    if (event.stopPropagation) {
      event.stopPropagation();
    } else {
      event.cancelBubble = true; }},// Cancel the default behavior of the event
  preventDefault: function(event) {
    if (event.preventDefault) {
      event.preventDefault();
    } else {
      event.returnValue = false; }}};Copy the code

24. Implement the flatten function iteratively.

var arr = [1.2.3[4.5], [6[7[8]]]]
Ret * returns a recursive function **/
function wrap() {
    var ret = [];
    return function flat(a) {
        for (var item of
            a) {
                if (item.constructor === Array) {
                    ret.concat(flat(item))
                } else {
                    ret.push(item)
                }
        }
        return ret
    }
} 
console.log(wrap()(arr));
Copy the code

25.How to implement a sleep

  • The sleep function tells the thread to sleep until it is reawakened at the specified time.
function sleep(delay) {
  var start = (new Date()).getTime();
  while ((new Date()).getTime() - start < delay) {
    continue; }}function test() {
  console.log('111');
  sleep(2000);
  console.log('222');
}

test()
Copy the code

26.Achieve regular thousandths (10000 => 10000)

// No decimal point
let num1 = '1321434322222'
num1.replace(/(\d)(? =(\d{3})+$)/g.'$1')
// There is a decimal point
let num2 = '342243242322.3432423'
num2.replace(/(\d)(? =(\d{3})+\.) /g.'$1')
Copy the code

27.Object array deduplicate

Input: [{2, a: 1, b: c: 3}, {2, b: c: 3, a: 1}, {2, d: c: 2}] output: [{2, a: 1, b: c: 3}, {d: 2, c: 2}]Copy the code
  • First write a function to sort the key in the object, and then turn it into a string
  • The traversal group uses the Set to de-iterate the objects that have been converted to strings
function objSort(obj){
    let newObj = {}
    // Iterate over the object and sort the keys
    Object.keys(obj).sort().map(key= > {
        newObj[key] = obj[key]
    })
    // Turn the sorted array into a string
    return JSON.stringify(newObj)
}

function unique(arr){
    let set = new Set(a);for(let i=0; i<arr.length; i++){let str = objSort(arr[i])
        set.add(str)
    }
    // Turn the string from the array back to the object
    arr = [...set].map(item= > {
        return JSON.parse(item)
    })
    return arr
}
Copy the code

28. Parse URL Params as objects

let url = 'http://www.domain.com/?user=anonymous&id=123&id=456&city=%E5%8C%97%E4%BA%AC&enabled'; {user: 'name ', id: [123, 456]; // select * from' name 'where' name '=' name 'and' name '=' name '; 'Beijing ', // Chinese must be decoded enabled: true, // not specified value key convention to true} */Copy the code
function parseParam(url) {
  const paramsStr = /. + \? (. +) $/.exec(url)[1]; / / will be? I'm going to take the strings that follow
  const paramsArr = paramsStr.split('&'); // Store the string in an array, split by &
  let paramsObj = {};
  // Save params to an object
  paramsArr.forEach(param= > {
    if (/ = /.test(param)) { // Process parameters with value
      let [key, val] = param.split('='); // Separate key and value
      val = decodeURIComponent(val); / / decoding
      val = /^\d+$/.test(val) ? parseFloat(val) : val; // Determine whether to convert to a number

      if (paramsObj.hasOwnProperty(key)) { // Add a value if the object has a key
        paramsObj[key] = [].concat(paramsObj[key], val);
      } else { // If the object does not have this key, create the key and set the valueparamsObj[key] = val; }}else { // Process parameters without value
      paramsObj[param] = true; }})return paramsObj;
}
Copy the code

29. Template engine implementation

Let template = 'I'm {{name}}, age {{age}}, sex {{sex}}'; Let data = {name: 'name ', age: 18} render(template, data); // My name is name, age 18, gender undefinedCopy the code
function render(template, data) {
  const reg = /\{\{(\w+)\}\}/; // The template string is regular
  if (reg.test(template)) { // Check whether there is a template string in the template
    const name = reg.exec(template)[1]; // Find the field of the first string in the current template
    template = template.replace(reg, data[name]); // Render the first template string
    return render(template, data); // Render recursively and return the rendered structure
  }
  return template; // If the template does not have a template string, return it directly
}
Copy the code

30. Convert to hump naming

Var s1 = "get-element-by-id" // Convert to getElementByIdCopy the code
var f = function(s) {
    return s.replace(/-\w/g.function(x) {
        return x.slice(1).toUpperCase(); })}Copy the code

31. Find the character and number that appear most in the string

  • Example: abbcccDDDDD -> the most common character is d, which occurs 5 times
let str = "abcabcabcbbccccc";
let num = 0;
let char = ' ';

 // Arrange them in a certain order
str = str.split(' ').sort().join(' ');
// "aaabbbbbcccccccc"

// Define the regular expression
let re = /(\w)\1+/g;
str.replace(re,($0, $1) = > {
    if(num < $0.length){
        num = $0.length;
        char = $1; }});console.log(The most 'characters are${char}Appeared,${num}Time `);
Copy the code

32. Images are loading lazily

let imgList = [...document.querySelectorAll('img')]
let length = imgList.length

const imgLazyLoad = function() {
    let count = 0
    return (function() {
        let deleteIndexList = []
        imgList.forEach((img, index) = > {
            let rect = img.getBoundingClientRect()
            if (rect.top < window.innerHeight) {
                img.src = img.dataset.src
                deleteIndexList.push(index)
                count++
                if (count === length) {
                    document.removeEventListener('scroll', imgLazyLoad)
                }
            }
        })
        imgList = imgList.filter((img, index) = >! deleteIndexList.includes(index)) })() }// It is better to add anti-shake treatment here
document.addEventListener('scroll', imgLazyLoad)
Copy the code

The resources

  • High-frequency JavaScript handwriting
  • Early, intermediate front-end should be to master the handwritten code implementation
  • 22 high-frequency JavaScript handwriting
  • Dead knock 36 JS handwritten problem (understand, promote really big)