• First published on December 02, 2020
  • Recommended reading duration: 1H
  • Recommended reading target: beginner and intermediate front-end engineers, JavaScript enthusiasts
  • The article does not coverPromiseinvolvingLess arrayRelated, the arrays topic will be updated later, as wellAsynchronous programmingFeatures, of course, there are also a lot of common you like handwriting implementation did not appear, maybe one day you come back to see the update up
  • All the interview questions you want to know are here

  • The CSS header interview questions and reference answers have been modified on December 02, 2020

  • The interview questions and reference answers were published on November 30, 2020

Update record

  • Added on 26 December 2020Encapsulation of native Ajax
  • Added on 08 December 2020Form submission

preface

This is the third official article in the series. As a front-end developer, then HTML we threw out a piece, then CSS we also shared a simple, naturally turn to Js, and then directly to look at the “so-called” handwriting implementation. In fact, in the process of sorting out and learning, I found a truth: that is why these are platitudes, or topics. It’s not hard to see that these are the very basics of being a front-end developer, not to mention that various frameworks like this and scoped chain closure inheritance are ubiquitous in our actual development or in those frameworks. Say goodbye to anxiety and don’t sell it. Ps: Case code at the end of the article

Handwritten implementationajaxrequest

 /* Encapsulate ajax functions * @param {string}opt.type HTTP connection mode, Url URL for sending requests * @param {Boolean} Opt. Async Specifies whether the request is asynchronous. True indicates that the request is asynchronous. False is the parameter sent by synchronous * @param {object}opt.data in the format of object type * @param {function}opt.success Ajax sends and receives successfully called callback function */
    ajax (opt) {
        opt = opt || {};
        opt.method = opt.method.toUpperCase() || 'POST';
        opt.url = opt.url || ' ';
        opt.async = opt.async || true;
        opt.data = opt.data || null;
        opt.success = opt.success || function () {};let xmlHttp = null;
        if (XMLHttpRequest) {
            xmlHttp = new XMLHttpRequest();
        } else {
            xmlHttp = new ActiveXObject('Microsoft.XMLHTTP');
        }
        this.XHR = xmlHttp;
        var params = [];
        for (var key in opt.data) {
            params.push(key + '=' + opt.data[key]);
        }
        var postData = params.join('&');
        if (opt.method.toUpperCase() === 'POST') {
            xmlHttp.open(opt.method, opt.url, opt.async);
            xmlHttp.setRequestHeader('Content-Type'.'application/x-www-form-urlencoded; charset=utf-8');
            xmlHttp.send(postData);
        } else if (opt.method.toUpperCase() === 'GET') {
            xmlHttp.open(opt.method, opt.url + '? ' + postData, opt.async);
            xmlHttp.send(null);
        }
        xmlHttp.onreadystatechange = function () {
            if (xmlHttp.readyState == 4 && xmlHttp.status == 200) { opt.success(xmlHttp.responseText); }}; }Copy the code

Handwritten implementationformThe form submission


function submit(){
  let xhr = new XMLHttpRequest()
  xhr.onreadystatechange = function(){
    if(xhr.readyState == 4) {if(xhr.status>=200&&xhr.status<300 || xhr.status ==304) {console.log(xhr.responseText)
      }
    }
  }
  xhr.open('post'.'https://jsonplaceholder.typicode.com/todos')
  xhr.setRequestHeader('Content-Type'.'application/x-www-form-urlencoded')
  let form = document.getElementById("user-info");
  xhr.send(serialize(form));
}
Copy the code

Handwriting implementation of anti-shake function (debounce/ anti-shake)

  • The first anti-shake function
let num =1
      const container = document.querySelector('.container')
      // Basic function content
      function commonFnCon(){
        container.innerHTML = num++
      }
      function baseShowNumber(){
        commonFnCon()
        console.log(this)  // <div>num</div>
      }
      function firstShowNumber(){
        commonFnCon()
        console.log(this) // This refers to window
      }
      
      function firstDebounce(fn,wait){
        let timerId = null;
        return function (){
          if(timerId) clearTimeout(timerId)
          // In a word: if an event is triggered, it will not be triggered again for 1s
          timerId = setTimeout(fn,wait)
        }
      }
      // container.onmousemove = baseShowNumber
      container.onmousemove = firstDebounce(firstShowNumber,1000)
Copy the code
  • The second stabilization function resolves the orientation of this
let num =1
      const container = document.querySelector('.container')
      // Basic function content
      function commonFnCon(){
        container.innerHTML = num++
      }
      function baseShowNumber(){
        commonFnCon()
        console.log(this)  // <div>num</div>
      }
      function secShowNumber(){
        commonFnCon()
        console.log('sec'.this) // This refers to window
      }
      
      function secDebounce(fn,wait){
        let timerId = null;
        return function (){
          let ctx = this 
          console.log('ctx',ctx) BaseShowNumber 
      
num
if(timerId) clearTimeout(timerId) // In a word: if an event is triggered, it will not be triggered again for 1s timerId = setTimeout(() = >{ // Bind the this of the current environment to the event function (baseShowNumber) // Execute the event function fn.apply(ctx) },wait) } } // container.onmousemove = baseShowNumber container.onmousemove = secDebounce(secShowNumber,1000) Copy the code
  • The third anti – shake function fixes the event object being undefined
let num =1
      const container = document.querySelector('.container')
      // Basic function content
      function commonFnCon(){
        container.innerHTML = num++
      }
      function baseShowNumber(e){
        commonFnCon()
        console.log(e) // MouseEvent
        console.log(this)  // <div>num</div>
      }
      function thirdShowNumber(e){
        commonFnCon()
      }
      
      function thirdDebounce(fn,wait){
        let timerId = null;
        return function (){
          let ctx = this
          let args =  arguments
          console.log('ctx',ctx) BaseShowNumber 
      
num
console.log('args'.arguments) // Arguments happens to be a pseudo-array containing event objects if(timerId) clearTimeout(timerId) // In a word: if an event is triggered, it will not be triggered again for 1s timerId = setTimeout(() = >{ // Bind the this of the current environment to the event function (baseShowNumber) // Execute the event function fn.apply(ctx,args) },wait) } } // container.onmousemove = baseShowNumber container.onmousemove = thirdDebounce(thirdShowNumber,1000) Copy the code
  • summary

The above implementation is still not complete, so let’s explore it by ourselves and paste the anti-shake function in our enterprise project

const debounce = (fn, delay, isImmediate) = > {
    var timer = null;
    return function() {
        var that = this;
        var args = [].slice.call(arguments);
        varcallNow = ! timer && isImmediate;if(timer) clearTimeout(timer);

        // Not immediately executed
        timer = setTimeout(function() {
            timer = null;
            if(! isImmediate) fn.apply(that, args); }, delay);// Execute immediately
        if(callNow) fn.apply(that, args); }};export {
     debounce
 }
Copy the code
  • The business scenario
    • Click the button to refresh to prevent frequent refresh
    • There is also the validation of forms (validation scenario for asynchronous call interfaces)

Implementing throttle functions by hand

  • Know the throttle

Throttling is every once in a while, only one event is performed, and shaking is one thing that is triggered and no longer triggers this event within 1s

  function throttle(func, wait) {
      let timerId = null
      let now = 0
      return function(){
       let context = this;
        let  args = arguments;
        if(! timerId){ timerId =setTimeout(() = >{
            timerId = null
            func.apply(context,args)
          },wait)
        }
      }
    }
Copy the code

Handwriting depth copy (depth clone)

background

Dark copy is the star topic of the interview

Just to be clear, we’re going to be talking about reference types, and we’re going to be copying more complex data types like array objects

If your brother changes the layout of your house, you and your brother will come home with the same keys. They will look the same. So you are family.

How do you cut off the data, by making a new copy of it a shallow copy of it a superficial copy of it a deep copy of it an infinite copy of it

Shallow copy

Shallow copy: create a new object with the original property values of the old object (primitive type, copied primitive type; Reference type (memory address) an exact copy of an object whose address changes and affects each other

let obj1 = {
  name: "Zhang".age: 18};let obj2 = obj1;
obj2.name = "Bill";

console.log(obj1.name); // The name attribute of the first object is changed
Copy the code

And what we found is that we did this with a simple assignment and can we do it with a simple function, which is theta

const shallow = (target) = > {
  let obj = {};
  for (let prop intarget) { obj[prop] = target[prop]; }};Copy the code

If you look at the array

let targetArr = [{name:'oldName'},"1"."1".1.1.true.true.undefined.undefined.null.null,]

let resultArr = targetArr.concat()
resultArr[0] ['name'] = 'newName'

console.log('old',targetArr) // The name of the first element in the targetArr is also changed
console.log('new',resultArr)
Copy the code

The specific implementation


function firstShallowClone(target){
    if(typeoftarget ! = ='object') return
    let result = Array.isArray(target) ? [] : {}for(let k in target){
        if(target.hasOwnProperty(k)){
            result[k] = target[k]
        }
    }
    return result
}
Copy the code

Deep copy

The core idea of deep copy is copy plus recursion which means that when a property of an object is still an object, we need to copy it further, copy it in full from memory, reopen the interval in the heap, and the address of the object doesn’t change

First deep copy: passJSONTwo of the API

  • The json.parse () method parses JSON strings to construct JavaScript values or objects described by the strings
  • The json.stringify () method converts a JavaScript value (object or array) to a JSON string

There’s a really neat way to implement deep copy in JavaScript — json.stringify,

let obj = {
  name: "yayxs".fav: [{type: "play"}].friend: {
    name: "wanghuahua"}};const objStr = JSON.stringify(obj) // deepClone.js:16 {"name":"yayxs","fav":[{"type":"play"}],"friend":{"name":"wanghuahua"}}
const objCopy = JSON.parse(objStr)



objCopy.fav.splice(0.1)

console.log(obj['fav']) / / ({})
console.log(objCopy['fav']) / / []
Copy the code

But if the individual elements are functions, let’s try it


let fnArr = [

    () = >{
        console.log(1)},() = >{
        console.log(2)}]console.log(JSON.parse(JSON.stringify(fnArr))); // [null, null]
Copy the code

Second deep copy: recursive copy

Determine the type of the property value, when the current property value type is an object, and then recursively clone,

function firstDeepClone(target){
  // If it is a value type or null, return directly
  if(typeoftarget ! = ='object' ||target===null ) {
    return target
  }
  // Result object
  let res = target instanceof Array ? [] : {};
  for(let key in res){
    if(obj.hasOwnProperty(key)){
      // Check whether the attribute value corresponding to the current key is a reference type
      if(typeof obj[key] === 'object'){
        res[key] = firstDeepClone(obj[key])
      }else{
        res[key] = obj[key]
      }
    }
  }
}
Copy the code

Implement the New operator in JavaScript by hand

Extended interview questions

Do you have a lot of question marks

  • Question1: What did New do after that?
  • Can I write the principle of the new operator?
  • Q3: What is the difference between creating objects with new and creating objects with literals

MDN description of the new operator keyword

  1. Create an empty simple JavaScript object (i.e{});
  2. Link this object (that is, set its constructor) to another object;
  3. Take the object created in Step 1 as the objectthisContext;
  4. Returns if the function does not return an objectthis.

The above four articles are about the new operator (or keyword) on MDN. It is a simple experience to use the constructor to new an object

function Person(name, age) {
  console.log("this".this);
  this.name = name;
  this.age = age;
}
// Then add the prototype method ** to the ** constructor
Person.prototype.height = 180;
Person.prototype.sayName = function() {
  console.log(this.name);
};
let p = new Person("yayxs".20);
console.log(p.name); // yayxs
console.log(p.age);
20;
p.sayName(); // yayxs
console.log(p.__proto__ === Person.prototype); // The stereotype property of object P (instance) points to the stereotype of the constructor,
Copy the code

Now that we’re customizing it, we’ll use it in much the same way as new.

// ------ when using new

const p = myNew Person('yayxs'.20) // The result is an object

// ---------
Copy the code

The first version of myNew

The idea is to declare an object, take the current constructor and its parameters, have the new object’s prototype attribute point to the constructor’s prototype, and then call the constructor, passing in the object’s parameters

function myNew() {
  let obj = new Object(),constructor.args] = [...arguments];
  obj.__proto__ = constructor.prototype;

  constructor.apply(obj, args);
  return obj;
}
Copy the code

The second edition of myNew

As can be seen from the simple case mentioned above,

  • New A constructor returns an object whose stereotype property (that is, ** proto **) is congruent with the constructor’s stereotype

  • The instance created by new through the constructor Persion has access to properties in the constructor, like this

    console.log(xiaoMing.name); / / xiao Ming
    Copy the code
  • To the point: Instance objects from new are linked by a prototype chain and a constructor

A constructor is basically a function, and a function can have a return value

function Person(name) {
  this.name = name;
  // return 1; // Returns the internally created object
  // return "1"; // Returns the internally created object
  // return null; // Returns the internally created object
  // return undefined; // Returns the internally created object
  // return {}; // {} // returns directly
  return function() {}; // Return directly
  return [1]; // [1] // Returns directly
}
let p = new Person("Bill");
console.log(p);
Copy the code

Given the worthwhile idea of returning a constructor, test it out with different data types

  • Different data types return different effects, like the number 1 string “1”, which still returns an internally created object
  • So if you return an object ({}) or an array ([]), it will be returned directly

summary

That is, constructors generally do not need a return

  • Return a generic datatype. It doesn’t work
  • So let’s return an object. What’s the point of new

function myNew(){
  let obj = new Object(),constructor.args] =  [...arguments]
   obj.__proto__ = constructor.prototype;

  let res =  constructor.apply(obj,args)
  return =  typeof res= = = 'object'?res : obj;
}

Copy the code

Write your own myNew summary

If you implement a new yourself, you must first satisfy several of its effects

  1. A constructor that returns an object should have an object in it

    let obj = {};
    Copy the code
  2. And points its __proto__ attribute to the constructor’s Prototype attribute

    obj.__proto__ = constructor.prototype;
    Copy the code
  3. Call the constructor to bind this

    constructor.apply(obj, args);
    Copy the code
  4. The original value should be ignored, and the returned object should be processed normally

    res instanceof Object ? res : obj;
    Copy the code

Arrow function usingnew

var Foo = () = > {};
var foo = new Foo(); // TypeError: Foo is not a constructor
Copy the code
  • Cannot be used as constructors, that is, not usednewCommand, otherwise an error will be thrown

thisPointing is fixed, not because there is a binding inside the arrow functionthisThe actual reason for this is that arrow functions don’t have their ownthisLead to internalthisThat’s the outer code blockthis. Precisely because it doesn’tthis, so it cannot be used as a constructor.

Handwriting implementation of call and apply

preface

Functions can be passed, used as objects, etc. Let’s look at a bit of code. The function passes the call to the original method, but the context this is missing, which leads to our call() method. Call is just a built-in function method. The method used is add.call(), and the add function automatically executes output 3

// The context parameter specifies the this value
// arg1 argument one
// arg2 argument two
func.call(context, arg1, arg2, ...)
Copy the code
function add(a, b) {
  console.log("Add this".this);
  console.log(a + b);
}
add(1.2); // This points to window
add.call({ name: "yayxs" }, 1.2); // this points to {name:'yayxs'}
Copy the code

Implement the first version of Call

At this point we pull out the incoming object

let o = {
  name: "yayxs"};function sayName() {
  console.log(this.name);
}

sayName.call(o); // yayxs
Copy the code

Function.prototype.myCall = function(ctx) {
    console.log(this) // This is the sayName function
    console.log(ctx) // {name: "yayxs"}
    ctx.tempFunc = this
    ctx.tempFunc()
    delete ctx.tempFunc
};

sayName.myCall(o,'Parameter one'.'Parameter two') // Theoretically output yayxs
Copy the code

Implement call version 2

Parameters 1 and 2 in myCall are not participatory

Function.prototype.myCall = function(ctx) {
    console.log(this) // This is the sayName function
    console.log(ctx) // {name: "yayxs"}
    console.log('arguments'.arguments)
    let tempArgs = [];// Use it to store parameters
    for(let i=1,len=arguments.length; i<len; i++){console.log(arguments[i]) // First loop body output parameter 1 second loop body parameter 2
        tempArgs.push('arguments[' + i + '] ');
    }
    console.log(tempArgs);
    ctx.tempFunc = this
    // ctx.tempFunc()
    let evalScript = 'ctx.tempFunc(' + tempArgs +') '
    eval(evalScript);
    delete ctx.tempFunc
};
Copy the code

Implement Apply manually


// ---------------- implement myApply
Function.prototype.myApply = function(ctx,arr){
  ctx.tempFunc = this
  let result
  if(! arr){ result = ctx.tempFunc()// Execute directly
  }else{
    let args = []
    for (let i = 0, len = arr.length; i < len; i++) {
      args.push('arr[' + i + '] ');
  }
    result = eval('ctx.tempFunc(' + args + ') ')}delete ctx.tempFunc
  return result 
}
Copy the code

conclusion

In general, the call Apply function is used to change the direction of this. At present, js still exists the phenomenon of callback function, especially in the framework of some asynchronous callback is also very common, it is inevitable that this will get lost both different and similar, if their own handwritten code to implement call and apply

  1. Gets the bound function
  2. The bound function appends to the hijacked replacement object
  3. The bound function appends to the hijacked replacement object
The method name role Automatic execution The list of parameters
call Change the direction of this Autoexecute function General list
apply Change the direction of this Autoexecute function An array

Implement bind by hand

Before we implement bind by hand, let’s remind ourselves of how bind works. Let’s say that in the React framework,

class App extends React.Component {
  constructor() {
    super(a);this.state = {
      num: 0}; }// 1 synthesizes the setState in the event
  handleClick() {
    console.log(this.state);

    this.setState({ num: this.state.num + 1 }); // State is not updated after the synthesis event is completed, resulting in the so-called asynchronous try block
    console.log(this.state);
  }
  componentDidUpdate() {
    console.log(this.state.num);
  }
  render() {
    return (
      <>{this.state.num} // You can see that we use the bind function to bind this<button onClick={this.handleClick.bind(this)}>button</button>
      </>); }}export default App;
Copy the code

The bind() method creates a new function. When bind() is called, this of the new function is specified as the first argument to bind(), and the remaining arguments are used as arguments to the new function. But we need to mention in advance that bind needs Polyfill. Because most browsers implement the built-in function.prototype. bind implementation, some don’t

const user = {
    name:'yayxs',}function showYourself(){
    console.log(this.name)
}

const result = showYourself.bind(user)

Copy the code

The first bind

const user = {
  name: "yayxs"};function showYourself(sex) {
  console.log(this.name);
  console.log(sex)
}

let resultFn;
resultFn = showYourself.bind(user);

// console.log(resultFn)

Function.prototype.myFirstBind = function(ctx) {
  console.log(ctx); // user {name:'yayxs'}
  let _this = this;

  // The first step returns a function
  return function() {
    // _this is the showYourself function
    return _this.apply(ctx);
  };
};

resultFn = showYourself.myFirstBind(user);

// console.log(resultFn)

Copy the code

The second bind

Function.prototype.secBind = function() {
  let self = this.// Save the original function
    context = [].shift.call(arguments); // The context of this to bind
  args = [].slice.call(arguments); // The remaining parameters are converted to arrays
  return function() {
    // Return a new function
    // It's going to execute the new function using the previously passed context as the this in the new function. It's going to combine the UN parameters twice as its parameters
    return self.apply(context, [].concat.call(args, [].slice.call(arguments)));
  };
};

Copy the code

Handwriting implementation of string.prototpye.trim () method

ECMAScript provides the trim() method on all strings. This method creates a copy of the string, removes all preceding and following Spaces, and returns the result. Since trim() returns a copy of the string, the original string is unaffected, meaning that the original pre-and post-whitespace characters are preserved.

To simplify substring substitution, ECMAScript provides the replace() method. This method takes two arguments. The first argument can be a RegExp object or a string (which is not converted to a regular expression), and the second argument can be a string or a function. If the first argument is a string, only the first substring is replaced. To replace all substrings, the first argument must be a regular expression with a global tag,

The method of clearing Spaces on both sides of a string with replace and the re preserves the Spaces on both sides and clears the Spaces inside

String.prototype.trim
if (!String.prototype.trim) {
    String.prototype.trim = function () {
        return this.replace(/^\s+|\s+$/gm.' '); }}Copy the code

Handwriting implementation of EventBus/EventEmitter

/ / eventBus. Js file
import Vue from "vue";
const EventBus = new Vue(); // Is essentially a Vue instance
export default EventBus;
Copy the code
// main.js
import EventBus from "eventBus.js";

Vue.prototype.EventBus = EventBus;
Copy the code
// Send events
this.$EventBus.$emit("sendVal"."Event issuing");
// Listen on events
this.$EventBus.$on("sendVal".(val) = > {
  console.log(val);
});
Copy the code
class EventEmitter {
  constructor() {
    this.handles = new Map(a);// Store the relationship between practice callbacks
  }

  on(evtName, cb) {
    if (!this.handles.has(evtName)) {
      this.handles.set(evtName, []);
    }

    this.handles[evtName].push(cb);
  }

  emit(evtName, ... args) {
    if (this.handles.has(evtName)) {
      for (let i = 0, len = this.handles[evtName].length; i < len; i++) {
        this.handles[evtName][cb](... args); }}}off(evtName, cb) {
    const cbs = this.handles[evtName];
    const idx = cbs.indexOf(cb);
    if(idx ! = = -1) {
      cbs.splice(idx, 1); }}once(evtName, cb) {
    const warp = (. args) = >{ cb(... args);this.off(evtName, warp);
    };
    this.on(evtName, warp); }}Copy the code

Handwritten array to achieve the method of heavy

So the first thing you have to do to figure out how to do this is, what is a repeating element

/** * When it comes to array de-duplication, the first thing to do is to have an array */
// First step
console.log(1= = =1); // true
console.log("1"= = ="1"); // true
console.log("true"= = ="true"); // true
console.log(false= = =false); // true
console.log(undefined= = =undefined); // true
console.log(null= = =null); // true

console.log(NaN= = =NaN); // false
console.log({} === {}); // false
console.log([] === []); // false
Copy the code

Next step: Prepare the target array with repeating elements

let targetArr = ["1"."1".1.1.true.true.undefined.undefined.null.null];

console.log(targetArr);
Copy the code

Step 3: Write out the method, this is the time to write the method

/** * desc */
function unique1(arr) {
  let result = []; // Result array
  for (let i = 0, len = arr.length; i < len; i++) {
    for (var j = 0, resLen = result.length; j < resLen; j++) {
      if (arr[i] === result[j]) {
        break; }}if(j === result.length) { result.push(arr[i]); }}return result;
}
Copy the code
/** * desc indexOf */

const unique2 = (arr) = > {
  let result = [];
  for (let i = 0, len = arr.length; i < len; i++) {
    if (result.indexOf(arr[i]) === -1) {
      // No element was found in the result arrayresult.push(arr[i]); }}return result;
};
Copy the code
/** * sort */

const unique3 = (target) = > {
  target.sort();
  let result = [target[0]].// Fetch the first element

  for (let i = 1; i < target.length; i++) { target[i] ! == target[i -1] && result.push(target[i]); // The current item is added to the result array if it differs from its predecessor
  }
  return result;
};
Copy the code
/** * desc The fourth option uses the filter function in conjunction with indexof */

const unique4 = (target) = > {
  return target.filter((item, index) = > {
    return target.indexOf(item) === index; // The index of the array is the same as the index of the retrieval
  });
};
Copy the code
/** * desc the fifth method uses the key-value pair of the object combined with obj.hasownProperty () */

const unique5 = (target) = > {
  let obj = {}; // Initialize an empty object
  let result = new Array(a); result = target.filter((item, index) = >
    // typeof item + item mainly considers that the key value 1 of the object is changed to '1'.
    obj.hasOwnProperty(typeof item + item)
      ? false
      : (obj[typeof item + item] = true));return result;
};
Copy the code
/** * desc The sixth option uses ES6's new syntax Set ** /
const unique6 = (target) = > {
  The Set object allows you to store a unique value of any type, either a primitive value or an object reference.
  let x = new Set(target); // Set { '1', 1, true, null }

  return [...x]; // Convert to an array
};
Copy the code
/** * select * from ** /
const unique7 = (target) = > {
  The Set object allows you to store a unique value of any type, either a primitive value or an object reference.
  let x = new Set(target); // Set { '1', 1, true, null }

  return Array.from(x); // Convert to an array
};
Copy the code
/** * desc ** /

const unique8 = (target) = > {
  let result = []; // Result array
  let hash = {};
  for (let ele of target) {
    if(! hash[ele]) {// Hash has no elements in the array
      result.push(ele); // Put the element in
      hash[ele] = true; // The hash is already marked true so that the next loop will not continue to put the same element in the result array}}return result;
};
Copy the code
Desc / * * * 9 * faults hash scheme using the Map types exist in the same key is not to find, but the '1' and 1 is different elements * please test it on its own haha ~ * /

const unique9 = (target) = > {
  let map = new Map(a);// Initialize the map
  let result = new Array(a);// Initialize the array
  for (let i = 0; i < target.length; i++) {
    if (map.has(target[i])) {
      map.set(target[i], true);
    } else {
      map.set(target[i], false); result.push(target[i]); }}return result;
};
Copy the code
/** * desc 10 double-layer for loop variant ** */

const unique10 = (target) = > {
  // let result = [];

  for (let i = 0; i < target.length; i++) {
    for (let j = i + 1; j < target.length; j++) {
      if (target[i] === target[j]) {
        // If two elements are the same, one is removed from the target element
        target.splice(j, 1);
        // Splice will change the array, so the relevant length should be subtracted by onei--; j--; }}}return target;
};
Copy the code
/** * desc Includes ** */

const unique11 = (target) = > {
  let result = [];
  for (let ele of target) {
    // where ele is each element of each target element! result.includes(ele) && result.push(ele);// If there is no ele in the result array, add it
  }
  return result;
};
Copy the code
/** * desc reduce ** */

const unique12 = (target) = > {
  return target.reduce((previousValue, currentValue, currentIndex) = > {
    returnpreviousValue.includes(currentValue) ? previousValue : [...previousValue, currentValue]; } []); };Copy the code
console.log(unique1(targetArr)); // ["1", 1, true, undefined, null]
console.log(unique2(targetArr)); // ["1", 1, true, undefined, null]
console.log(unique3(targetArr)); // ["1", 1, null, true, undefined]
console.log(unique4(targetArr)); // ["1", 1, null, true, undefined]
console.log(unique5(targetArr)); // ["1", 1, null, true, undefined]
Copy the code

Handwritten implementation outputs triangles made up of * signs


 / * * * * * * * 1-1-2 * * * * 3-3 * * * * * * / 4-4
      for (let row = 0; row < 4; row++) { / / the number of rows
        for (let num = 0; num < row; num++) {
          document.write("*");
        }
        document.write("<br />");
      }

      for(let row = 4; row>0; row--){for(let num=0; num<row; num++){document.write("*");
          }
          document.write("<br />");
      }
Copy the code
  • Author: Yang Xiaoyang
  • The code examples above can be found in… /demos/written
  • Alternate browsing address…… debounce.html
  • reference
    • Hu Yu’s blog
    • JavaScript Design Patterns and Development Practices
  • Thank you for your thumbs up and comments if it helps. What topics would you like to share in the future?