Table of contents
-
- Map introduction
- Introduction to Reduce
- regular replacement
- exception capture
- event delegation
- Deep Clone
- Scroll Debounce
- Traversing with Map or For
- Trigger react onchange event and assign value
- Pipeline Operator (Proposal)
- Async (ES 7)
- Proxy (ES 6)
- ES6 scope
- Function creates functions
- Swap values in ES6
- Fetch API AJAX
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 for
is the most reliable.
foreach
About the same as for ... of
.
map
Lowest 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* () {
// ...
});
}
await
For 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, getFoo
and getBar
are two independent asynchronous operations (that is, independent of each other), written as a secondary relationship. This is time-consuming, because it getFoo
will only be executed after completion, getBar
and 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, getFoo
and getBar
are 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
credentials
credential 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
- Interface documentation: https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API
- Introduction: https://github.com/camsong/blog/issues/2