Javascript practical tips greatly Daquan, ECMAScript you do not know

Map introduction

grammar

array.map(callback[, thisArg])

parameter

callback

The elements in the original array return a new element after passing through this method.

currentValue

The first parameter of callback is the currently passed element in the array.

index

The second parameter of callback is the index of the currently passed element in the array.

array

The third parameter of callback, the array to call the map method on.

thisArg

The object pointed to by this when the callback function is executed.

return value

A new array consisting of the return values ​​of the callback function.

example

https://www.codewars.com/kata/double-char

Given a string, you have to return a string in which each character (case-sensitive) is repeated once.

doubleChar("String") ==> "SSttrriinngg"

doubleChar("Hello World") ==> "HHeelllloo  WWoorrlldd"

doubleChar("1234!_ ") ==> "11223344!!__  "

Good Luck!

Answer:

const doubleChar = (str) =>
  str
    .split('')
    .map((i) => i.repeat(2))
    .join('');

Introduction to Reduce

grammar

arr.reduce(callback, [initialValue]);

parameter

callback

A function to execute for each value in the array, with four parameters:

accumulator

The value returned by the last call to the callback, or the initial value provided (initialValue)

currentValue

the element in the array being processed

currentIndex

The index of the element being processed in the data, if initialValues ​​is not provided, it starts from 0 by default

array

Array on which to call reduce

initialValue

As the first argument to the first call to callback.

return value

The function accumulates the processed results.

example

https://www.codewars.com/kata/beginner-reduce-but-grow

Given and array of integers (x), return the result of multiplying the values together in order. Example:

[1, 2, 3] --> 6

For the beginner, try to use the reduce method - it comes in very handy quite a lot so is a good one to know.

Array will not be empty.

Answer:

const grow = (x) => x.reduce((r, i) => r * i, 1);

regular replacement

reference:

https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/RegExp

tool:

  • RegExp tester (Chrome plugin)

example

Write a function that accepts an array of 10 integers (between 0 and 9), that returns a string of those numbers in the form of a phone number.

Example:

createPhoneNumber([1, 2, 3, 4, 5, 6, 7, 8, 9, 0]) // => returns "(123) 456-7890"

The returned format must be correct in order to complete this challenge.
Don’t forget the space after the closing parenthese!

Topic address: https://www.codewars.com/kata/create-phone-number

Answer:

const createPhoneNumber = (n) => n.join('').replace(/(\d{3})(\d{3})(\d{3})/, '($1) $2-$3');

exception capture

Traditional approach in ES5

Assuming that the execution of the code block throws an error fail, then the way to catch the error is:

try {
    
    
  // 代码块执行,并抛出 fail 错误
  throw new Error('fail');
} catch (e) {
    
    
  console.log(e);
}

timer

Let's first rewrite the above code and add a timer.

try {
    
    
  setTimeout(() => {
    
    
    throw new Error('fail');
    // Uncaught Error: fail
  }, 1000);
} catch (e) {
    
    
  console.log(e);
}

Like this, throwing try/catch outside the timer cannot catch internal errors.

The correct approach should be:

setTimeout(() => {
    
    
  try {
    
    
    throw new Error('fail');
  } catch (e) {
    
    
    console.log(e);
  }
}, 1000);

Promise

function doSomething() {
    
    
  return new Promise((resolve, reject) => {
    
    
    // 同步代码中的 throw 可以被捕捉到
    throw new Error('fail');
  });
}

doSomething()
  .then((x) => {
    
    
    console.log('success:', x);
  })
  .catch((err) => {
    
    
    console.log('fail:', err);
  });

There is no problem with writing this way, errors can be caught. But as long as you modify it slightly, there may be problems. for example:

function doSomething() {
    
    
  return new Promise((resolve, reject) => {
    
    
    // 异步代码中的 throw 不能被 Promise 的 catch 捕捉到
    setTimeout(() => {
    
    
      throw new Error('fail');
    }, 1000);
  });
}

doSomething()
  .then((x) => {
    
    
    console.log('success:', x);
  })
  .catch((err) => {
    
    
    console.log('fail:', err);
  });

Here thrown but errors will not be caught. Therefore, in Promise, we generally throw errors through reject.

function doSomething(x) {
    
    
  return new Promise((resolve, reject) => reject(x));
}

doSomething('fail')
  .then((x) => {
    
    
    console.log('success:', x);
  })
  .catch((err) => {
    
    
    console.log('fail:', err);
  });
// fail: fail

In addition, there is another interesting detail, adding .then after the catch will continue to execute.

function doSomething(x) {
    
    
  return new Promise((resolve, reject) => reject(x));
}

doSomething('fail')
  .then((x) => {
    
    
    console.log('success:', x);
  })
  .catch((err) => {
    
    
    console.log('fail:', err);
    // 这里可以写 return 给下面的方法继续执行
  })
  .then((x) => {
    
    
    console.log('continue:', x);
  });
// fail: fail
// continue: undefined

Async/Await

Essentially, Async/Await is implemented through Promise, so it is basically the same as what Promise said above.

You can nest try/catch outside the await method, like this:

function doSomething(x) {
    
    
  return new Promise((resolve, reject) => reject(x));
}

(async () => {
    
    
  try {
    
    
    const result = await doSomething('fail');
    console.log('success:', result);
    // return 返回
  } catch (err) {
    
    
    console.log('fail:', err);
    // return 返回
  }
})();
// fail: fail

But there is a problem here. For example, if the function needs to return, then the return statement needs to be written twice. It is normal but returns the result when it is normal, and returns one throw new Error()or the other when it is wrong. There is a little trick, you can write like this:

function doSomething(x) {
    
    
  return new Promise((resolve, reject) => reject(x));
}

(async () => {
    
    
  const result = await doSomething('fail').catch((err) => {
    
    
    console.log('fail:', err);
    return 0; // 默认值
  });
  console.log('success:', result);
})();
// fail: fail
// success: 0

After the error is caught, reassign a default value and let the code continue to run.

event delegation

For example, event binding is performed on the button in the result returned by the AJAX request click:

var handleClick = function (e) {
    
    
  if (e.target && e.target.nodeName.toLowerCase() === 'button') {
    
    
    // Codes Here
  }
};

parentNode.addEventListener('click', handleClick);

Deep Clone

Problem phenomenon:

var obj1 = {
    
    
  key1: 'value1',
  key2: 'value2',
  children: {
    
    
    key3: 'value3',
    key4: 'value4'
  }
};
var obj2 = Object.assign({
    
    }, obj1);
obj2.children.key3 = 'test';
console.log(obj1.children);
// { key3: 'test', key4: 'value4' }

Quick solution:

const obj2 = JSON.parse(JSON.stringify(obj1));

Scroll Debounce

It is used to solve the problem that the trigger frequency of front-end scrolling listening events is too high.

Core code:

function debounce(func, wait = 20, immediate = true) {
    
    
  var timeout;
  return function () {
    
    
    var context = this,
      args = arguments;
    var later = function () {
    
    
      timeout = null;
      if (!immediate) func.apply(context, args);
    };
    var callNow = immediate && !timeout;
    clearTimeout(timeout);
    timeout = setTimeout(later, wait);
    if (callNow) func.apply(context, args);
  };
}

Sample code:

function testFunc(e) {
    
    
  console.count(e);
}

window.addEventListener('scroll', () => console.count('bounce'));
window.addEventListener('scroll', debounce(testFunc));

Test in browser.

Traversing with Map or For

The same traversal, but actually very different.

Compared

map

change yourself.

[1, 2, 3, 4, 5].map((x) => x + 1);
// [ 2, 3, 4, 5, 6 ]

for

Just loop.

Benchmark test

benchmark script:

suite('iterator', function () {
    
    
  bench('for', function () {
    
    
    const a = [1, 2, 3, 4, 5];
    for (let i = 0; i < a.length; i++) {
    
    
      // nothing
    }
  });
  bench('foreach', function () {
    
    
    const a = [1, 2, 3, 4, 5];
    a.forEach(function (d) {
    
    
      // nothing
    });
  });
  bench('for of', function () {
    
    
    const a = [1, 2, 3, 4, 5];
    for (let i of a) {
    
    
      // nothing
    }
  });
  bench('map', function () {
    
    
    const a = [1, 2, 3, 4, 5];
    a.map((x) => x);
  });
});

Test Results:

                      iterator
      50,038,931 op/s » for
       8,980,276 op/s » foreach
       8,990,758 op/s » for of
       1,713,807 op/s » map


  Suites:  1
  Benches: 4
  Elapsed: 5,710.33 ms

in conclusion

Loop alone foris the most reliable.

foreachAbout the same as for ... of.

mapLowest performance.

Trigger react onchange event and assign value

var setValue = function (element, value) {
    
    
  element.value = value;
  if ('createEvent' in document) {
    
    
    var event = new Event('input', {
    
     bubbles: true });
    element.dispatchEvent(event);
  } else {
    
    
    element.fireEvent('onchange');
  }
};

Pipeline Operator (Proposal)

Currently in draft stage: https://github.com/tc39/proposal-pipeline-operator

function doubleSay(str) {
    
    
  return `${
      
      str}, ${
      
      str}`;
}
function capitalize(str) {
    
    
  return str[0].toUpperCase() + str.substring(1);
}
function exclaim(str) {
    
    
  return `${
      
      str}!`;
}

let result = 'hello' |> doubleSay |> capitalize |> exclaim;

result |> console.log;
//=> "Hello, hello!"

Project template: https://github.com/willin/esnext-pipeline-biolerplate

Async (ES 7)

async function fn(args) {
    
    
  // ...
}

// 等同于

function fn(args) {
    
    
  return spawn(function* () {
    
    
    // ...
  });
}

awaitFor asynchronous operations following multiple commands, if there is no successor relationship, it is best to let them trigger at the same time.

let foo = await getFoo();
let bar = await getBar();

In the above code, getFooand getBarare two independent asynchronous operations (that is, independent of each other), written as a secondary relationship. This is time-consuming, because it getFoowill only be executed after completion, getBarand they can be triggered at the same time.

// 写法一
let [foo, bar] = await Promise.all([getFoo(), getBar()]);

// 写法二
let fooPromise = getFoo();
let barPromise = getBar();
let foo = await fooPromise;
let bar = await barPromise;

The above two writing methods, getFooand getBarare triggered at the same time, which will shorten the execution time of the program.

Proxy (ES 6)

Versions after Node v6.1.0 have been tested and integrated.

Sample code:

const proxy = new Proxy(
  {
    
    },
  {
    
    
    get: (target, property) => [target, property]
  }
);

console.log(proxy.func); // [ {}, 'func' ]
console.log(proxy.func('123')); // TypeError: proxy.func is not a function
const proxy = new Proxy(
  {
    
    },
  {
    
    
    get: (target, property) => (test) => [target, property, test]
  }
);

console.log(proxy.func); // [Function]
console.log(proxy.func('123')); // [ {}, 'func', '123' ]

ES6 scope

Take the For loop as an example:

var funcs = [];

for (var i = 0; i < 10; i += 1) {
    
    
  funcs.push(function () {
    
    
    console.log(i);
  });
}

funcs.forEach((func) => func());
// 输出 10 十次

Closure:

var funcs = [];

for (var i = 0; i < 10; i += 1) {
    
    
  funcs.push((function(value){
    
     console.log(value); }(i));
}

funcs.forEach(func => func());
// 0 到 9 依次输出

In ES6 it can be simplified to:

const funcs = [];

for (let i = 0; i < 10; i += 1) {
    
    
  funcs.push(() => console.log(i));
}

funcs.forEach((func) => func());
// 0 到 9 依次输出

Function creates functions

var add = new Function('first', 'second = first', 'return first + second');
console.log(add(1, 1)); // 2
console.log(add(1)); // 2
var pickFirst = new Function('..args', 'return args[0]');
console.log(pickFirst(1, 2)); // 1

Swap values ​​in ES6

let a = 1;
let b = 2;

[a, b] = [b, a];

console.log(a, b); // 2 1

Fetch API AJAX

browser compatibility

[External link picture transfer failed, the source site may have an anti-leeching mechanism, it is recommended to save the picture and upload it directly (img-3HRKmB2K-1690025164220)(/basic/js/fetch.png)]

support check

if (typeof fetch === 'function' && typeof window.fetch === 'function') {
    
    
  // 支持
}

if (typeof fetch !== 'function' || typeof window.fetch !== 'function') {
    
    
  // 不支持
}

sample code

var req = new Request('/data.json', {
    
     method: 'POST', cache: 'reload' });
fetch(req)
  .then(function (res) {
    
    
    return res.json();
  })
  .then(function (data) {
    
    
    console.log(data);
  });

Cross-domain cookie settings

credentialscredential parameter

fetch('a.com/api', {
    
     credentials: 'include' }).then(function (res) {
    
    
  // ...
});

or

var req = new Request('/data.json', {
    
     method: 'POST', cache: 'reload', credentials: 'include' });
fetch(req)
  .then(function (res) {
    
    
    return res.json();
  })
  .then(function (data) {
    
    
    console.log(data);
  });

References

Guess you like

Origin blog.csdn.net/jslygwx/article/details/131871715