This article mainly introduces some tips used in JS to improve happiness in daily Coding. It will be updated from time to time

Interested students can add the end of the wechat group, discuss together ~

1. Type casting

1.1 String to a number

You can use *1 to convert to a Number (actually calling the.valueof method) and then use number.isnan to determine whether it is a NaN, or use a! == a to see if it’s a NaN, because NaN! == NaN

'32' * 1            / / 32
'ds' * 1            // NaN
null * 1            / / 0
undefined * 1    // NaN
1  * { valueOf: (a)= >'3' }        / / 3
Copy the code

Commonly used: + can also be used to convert strings to numbers

+ '123'            / / 123
+ 'ds'               // NaN
+ ' '                    / / 0
+ null              / / 0
+ undefined    // NaN
+ { valueOf: (a)= >'3' }    / / 3
Copy the code

1.2 Force an object to a String

You can convert an Object to a string using the string +Object method (actually calling the.toString() method)

'the Math object:' + Math                // "the Math object:[object Math]"
'the JSON object:' + JSON              // "the JSON object:[object JSON]"
Copy the code

It is also possible to override the toString and valueOf methods of an object from defining the conversion of the object:

2  * { valueOf: (a)= >'3' }                / / 6
'J' + { toString: (a)= >'S' }                // "JS"
Copy the code

Effective JavaScript P11: When + is used in concatenation strings, and when an object has both toString and valueOf methods, JS resolves the ambiguity by blindly using valueOf. Objects are cast to numbers by the valueOf method and to strings by the toString method

' ' + {toString:(a)= >'S'.valueOf:(a)= >'J'}                // J
Copy the code

1.3 Use Boolean to filter all false values in an array

We know there are some false values in JS: false, null, 0, “”, undefined, NaN. How to filter the false values in an array quickly

const compact = arr= > arr.filter(Boolean)
compact([0.1.false.2.' '.3.'a'.'e' * 23.NaN.'s'.34])             // [ 1, 2, 3, 'a', 's', 34 ]
Copy the code

1.4 The two-bit operator ~~

You can use two-bit operators to replace positive math.floor () and negative math.ceil (). The advantage of the double negative bit operator is that it performs the same operation faster.

Math.floor(4.9) = = =4      //true
// short for:~ ~4.9= = =4      //true
Copy the code

Note, however, that for positive numbers ~~ yields the same result as math.floor (), and for negative numbers it yields the same result as Math.ceil() :

~ ~4.5                / / 4
Math.floor(4.5)      / / 4
Math.ceil(4.5)       / / 5~ ~4.5        		/ / - 4
Math.floor(4.5)     / / - 5
Math.ceil(4.5)      / / - 4
Copy the code

1.5 Short circuit operator

We know that logic and && and | or logical | is short-circuit operator, short-circuit operator is from left to right in the operation which meet the requirements, no longer perform the latter; It can be interpreted as:

  • &&If a false value is encountered, the false value is returned. Otherwise, the last true value is returned
  • ||If it encounters a true value, it returns the true value. Otherwise, it returns the last false value
let param1 = expr1 && expr2
let param2 = expr1 || expr2
Copy the code
The operator The sample instructions
&& expr1&&expr2 Return expr1 if expr1 can be converted to false, otherwise return expr2. Therefore, when used in a Boolean environment, return true if both operations are true, and false otherwise.
|| expr1||expr2 Return expr1 if expr1 converts to true, otherwise return expr2. Therefore, when used in a Boolean environment (in the if condition), returns true as long as either of the operations is true; Return false if both results are false.
! ! expr Return false if a single expression can be converted to true, true otherwise.

So it can be used to do a lot of interesting things, like assign an initial value to a variable:

let variable1
let variable2 = variable1  || 'foo'
Copy the code

If variable1 is true, it returns the following value and the short circuit is not returned. If variable1 is false, it returns the following value foo.

Can also be used to make simple judgments instead of lengthy if statements:

let variable = param && param.prop
Copy the code

Return the param. Prop property if param is true, or false if param is false, in some cases to prevent an error when param is undefined.

1.6 take the whole| 0

For a digital | 0 can be integer, negative number also applies, num | 0

1.3 | 0         / / 1
1.9 | 0        // -1
Copy the code

1.7 Checking odd even numbers& 1

For a number &1, it’s odd or even, and the same is true for a negative number, num &1

const num=3; !!!!! (num &1)                    // true!!!!! (num %2)                    // true
Copy the code

2. The function

2.1 Default function values

func = (l, m = 3, n = 4 ) = > (l * m * n);
func(2)             //output: 24
Copy the code

Note that the default argument is used when passed with undefined or no argument, but null will override the default argument.

2.2 Mandatory Parameters

By default, if no value is passed to a function argument, then JS sets the function argument to undefined. Other languages emit warnings or errors. To perform parameter allocation, you can use an if statement to throw an undefined error, or you can use mandatory parameters.

mandatory = ( )= > {
  throw new Error('Missing parameter! ');
}
foo = (bar = mandatory( )) = > {     // If no argument is passed, the manadatory function is executed and an error is reported
  return bar;
}
Copy the code

2.3 An implicit return value

The return value is the keyword we usually use to return the final result of a function. A one-statement arrow function that can implicitly return a result (the function must omit the curly braces {} in order to omit the return keyword).

To return multi-line statements (such as object text), use () instead of {} to wrap the body of the function. This ensures that the code is evaluated as a single statement.

function calcCircumference(diameter) {
  return Math.PI * diameter
}
// short for:
calcCircumference = diameter= > (
  Math.PI * diameter;
)
Copy the code

2.4 Lazy loading functions

In a scenario where we have a judgment statement in our function, the judgment does not change during the entire project run, so the branch will only run a particular branch during the entire project run, then we can consider lazy loading functions

function foo(){
    if(a ! == b){console.log('aaa')}else{
        console.log('bbb')}}/ / after optimization
function foo(){
    if(a ! = b){ foo =function(){
            console.log('aaa')}}else{
        foo = function(){
            console.log('bbb')}}return foo();
}
Copy the code

So the method will be overridden after the first run, and the next run will not execute the judgment. Of course, now there is only one judgment, if there are many judgments, branches are more complex, then the resources saved is considerable.

2.5 One-time function

In the same way as the lazy-loaded function above, you can overwrite the current function in the body of the function, so you can create a one-time function. The code before the reassignment is equivalent to being run only once, which is suitable for running initialization code that needs to be executed only once

var sca = function() {
    console.log('msg')
    sca = function() {
        console.log('foo')
    }
}
sca()        // msg
sca()        // foo
sca()        // foo
Copy the code

3. The string

3.1 String Comparison Time sequence

A string can be used to compare chronological order:

var a = "2014-08-08";
var b = "2014-09-09";
 
console.log(a>b, a<b); // false true
console.log("At"<"09:10");  // false
console.log("At"<"Territory");   // True time form add 0
Copy the code

Since the size of the string comparison is based on the charCode of each character in the string from left to right, pay special attention to the time format and add zeros

4. Digital

4.1 Different base representations

In ES6, there are new writing formats for different bases. Be aware of this when passing parameters in the background.

29            / / decimal
035            // Base 8 is the original way of 29
0o35            // Base 8 29 ES6 mode
0x1d            // Hexadecimal 29
0b11101            // Base 2 is 29
Copy the code

4.2 Exact to the specified decimal place

Round a number to the specified decimal place. Use math.round () and template literals to round numbers to the specified decimal place. Omit the second parameter decimals and the number will be rounded to an integer.

const round = (n, decimals = 0) = > Number(`The ${Math.round(`${n}e${decimals}`)}e-${decimals}`)
round(1.345.2)                 / / 1.35
round(1.345.1)                 / / 1.3
Copy the code

4.3 Digit complement 0 operation

Sometimes when you want to display time you need to put two digits into one digit and you need to add zero. You can use slice and string padStart to do this

const addZero1 = (num, len = 2) = > (` 0${num}`).slice(-len)
const addZero2 = (num, len = 2) = > (`${num}`).padStart( len   , '0')
addZero1(3) // 03
 
addZero2(32.4)  / / 0032
Copy the code

An array of 5.

5.1 Reduce Implements map and Filter simultaneously

Suppose you have a sequence and you want to update each of its entries (map functionality) and then filter some of them (Filter functionality). If you use map first and then filter, you need to iterate through the array twice. In the code below, we double the values in the sequence and then pick out those numbers greater than 50.

const numbers = [10.20.30.40];
const doubledOver50 = numbers.reduce((finalList, num) = > {
  num = num * 2;
  if (num > 50) {
    finalList.push(num);
  }
  returnfinalList; } []); doubledOver50;/ / [60, 80]
Copy the code

5.2 Counting the number of the same items in an array

A lot of times, you want to count the number of recurring items in an array and represent them in an object. Then you can use the reduce method to process the array.

The following code counts the number of cars of each type and represents the total as an object.

var cars = ['BMW'.'Benz'.'Benz'.'Tesla'.'BMW'.'Toyota'];
var carsObj = cars.reduce(function (obj, name) {
  obj[name] = obj[name] ? ++obj[name] : 1;
  return obj;
}, {});
carsObj; // => { BMW: 2, Benz: 2, Tesla: 1, Toyota: 1 }
Copy the code

5.3 Use deconstruction to exchange parameter values

Sometimes you put multiple values returned by a function in an array. We can use array deconstruction to get each of these values.

let param1 = 1;
let param2 = 2;
[param1, param2] = [param2, param1];
console.log(param1) / / 2
console.log(param2) / / 1
Copy the code

Of course we have a number of other ways to exchange values:

var temp = a; a = b; b = temp            
b = [a, a = b][0]                     
a = a + b; b = a - b; a = a - b        
Copy the code

5.4 Multiple results returned by a receiving function

In the code below, we get a post from /post and a related comment from /comments. Since we are using async/await, the function puts the return value in an array. We can use array destruct to assign the return value directly to the corresponding variable.

async function getFullPost(){
  return await Promise.all([
     fetch('/post'),
     fetch('/comments')]); }const [post, comments] = getFullPost();
Copy the code

5.5 Tiling the array to the specified depth

Using recursion, decrease depth by 1 for each depth level. Use array.reduce () and array.concat () to merge elements or arrays. In the base case, depth is equal to 1 to stop the recursion. Omit the second argument, depth can only be tiled to a depth of 1 (single-layer tiling).

const flatten = (arr, depth = 1) = >depth ! =1
    ? arr.reduce((a, v) = > a.concat(Array.isArray(v) ? flatten(v, depth - 1) : v), [])
    : arr.reduce((a, v) = > a.concat(v), []);
flatten([1[2].3.4]);                             // [1, 2, 3, 4]
flatten([1[2[3[4.5].6].7].8].2);           // [1, 2, 3, [4, 5], 6, 7, 8]
Copy the code

5.6 Object deconstruction of arrays

Arrays can also be object destructed, which makes it easy to retrieve the NTH value of an array

const csvFileLine = '1997,John Doe,US,[email protected],New York';
const { 2: country, 4: state } = csvFileLine.split(', ');
 
country            // US
state            // New Yourk
Copy the code

Object of 6.

6.1 Use deconstruction to remove unnecessary attributes

Sometimes you don’t want to keep certain object properties because they contain sensitive information or are just too big. You might enumerate the whole object and then delete it, but you can simply assign the useless attributes to the variables and keep the useful ones as the rest of the arguments.

In the code below, we want to remove the _internal and tooBig parameters. We can assign them to the internal and tooBig variables and then store the remaining properties in cleanObject for later use.

let{_internal, tooBig, ... cleanObject} = {el1: '1'._internal:"secret".tooBig: {},el2: '2'.el3: '3'};
 
console.log(cleanObject);                         // {el1: '1', el2: '2', el3: '3'}
Copy the code

6.2 Deconstructing nested objects in function arguments

In the following code, engine is an object nested within the object CAR. If we are interested in the VIN property of the engine, we can easily get it using destructive assignment.

var car = {
  model: 'bmw 2018'.engine: {
    v6: true.turbo: true.vin: 12345}}const modelAndVIN = ({model, engine: {vin}}) = > {
  console.log(`model: ${model} vin: ${vin}`);
}
modelAndVIN(car); // => model: bmw 2018 vin: 12345
Copy the code

7. Code reuse

7.1 the Object [key]

While it is common practice to write foo.bar as foo [‘bar’], it forms the basis for writing reusable code. Many frameworks use this approach, such as Element’s form validation.

Consider the following simplified example of a validation function:

function validate(values) {
  if(! values.first)return false;
  if(! values.last)return false;
  return true;
}
console.log(validate({first:'Bruce'.last:'Wayne'})); // true
Copy the code

The above function does the job perfectly. But when you have many forms, you need to apply validation, which has different fields and rules. If you can build a generic validation function that can be configured at run time, that would be a good choice.

// object validation rules
const schema = {
  first: {
    required:true
  },
  last: {
    required:true}}// universal validation function
const validate = (schema, values) = > {
  for(field in schema) {
    if(schema[field].required) {
      if(! values[field]) {return false; }}}return true;
}
console.log(validate(schema, {first:'Bruce'})); // false
console.log(validate(schema, {first:'Bruce'.last:'Wayne'})); // true
Copy the code

Now that we have this validation function, we can reuse it across all forms without having to write a custom validation function for each form.


  1. Added the numeric complement 0 operation provided by @jserwang@vczhan
  2. Add 3.1, string comparison time sequence
  3. Thanks to @pandaaa for reminding us,~ ~And in negative numbersMath.ceil( )The same

Most of the online posts are different in depth, and even some inconsistent, the following article is a summary of the learning process, if you find mistakes, welcome to leave a message to point out ~

Reference:

  1. Shorthand tips that JavaScript developers need to know
  2. The Effective Javascript
  3. Must know ES6 tips
  4. Some special applications of js operators
  5. JS Advanced Tips (Simple version)
  6. Js string comparison size

Recommended reading: ES6 demo small website

PS: Welcome everyone to pay attention to my public number [front afternoon tea], refueling together ~

In addition, you can join the wechat group of “front end afternoon tea Communication Group”. Long press to identify the qr code below to add my friend, note to add group, I pull you into the group ~