SoFunction
Updated on 2025-04-03

Tips for improving happiness in JS (can identify more alternative writing methods)

1. Type cast

1.1 string cast to number

Can be used*1To convert to numbers (actually, it's a call.valueOfMethod) Then useTo determine whether it isNaN, or usea !== aTo determine whether it isNaN,becauseNaN !== NaN

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

Commonly used: Can also be used+To convert strings to numbers

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

1.2 object is forced to convert to string

You can use strings+Object The way to convert the object into a string (actually a call.toString() method)

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

Of course, it can also cover the objecttoStringandvalueOfMethods customize object type conversion:

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

"Effective JavaScript" P11: When + is used to concatenate strings, when an object has both a toString method and a valueOf method, JS solves this ambiguity by blindly using the valueOf method.
Objects are cast to numbers through valueOf method and cast to string through toString method.

'' + {toString:()=>'S',valueOf:()=>'J'} // J

1.3 Filter all false values ​​in an array using Boolean

We know that there are some fake values ​​in JS:falsenull0""undefinedNaN, How to quickly filter the false values ​​in the array? You can use the Boolean constructor to perform a conversion

const compact = arr => (Boolean)
compact([0, 1, false, 2, '', 3, 'a', 'e' * 23, NaN, 's', 34]) // [ 1, 2, 3, 'a', 's', 34 ]

1.4 Double-bit operator ~~

A two-bit operator can be used instead of ( ). The advantage of the double-negative positioning operator is that it performs the same operation faster.

(4.9) === 4 //true
// Abbreviation is:~~4.9 === 4 //true

But be aware that for integers~~The calculation result and( )The operation result is the same, but not the same for negative numbers:

~~4.5 // 4
(4.5) // 4
~~-4.5 // -4
(-4.5) // -5

1.5 Short-circuit operator

We know the logic and&&with logic or||It is a short-circuit operator. The short-circuit operator means that the former meets the requirements in the operation from left to right, and the latter will no longer be executed; it can be understood as:

&& is a false operation, judge from left to right. If a false value is encountered, the false value will be returned and will not be executed in the future. Otherwise, the last true value will be returned.
||For the truth operation, judge from left to right. If a true value is encountered, the true value will be returned and will not be executed in the future. Otherwise, the last false value will be returned.

let param1 = expr1 && expr2
let param2 = expr1 || expr2
Operators Example illustrate
&& expr1&&expr2 If expr1 can be converted to false, it returns expr1, otherwise it returns expr2. Therefore, when used in Boolean environment, true when both operations are true, otherwise it returns false.
|| expr1||expr2 If expr1 can be converted to true, it returns expr1, otherwise it returns expr2. Therefore, when used in the boolean environment (in the conditional judgment of if), as long as one of the operation results is true, it returns true; if both operation results are false, it returns false.
! !expr Return false if a single expression can be converted to true, otherwise return true.

Therefore, it can be used to do many interesting things, such as assigning initial values ​​to variables:

let variable1
let variable2 = variable1 || 'foo' 

ifvariable1If it is the true value, it will be returned directly. If the short circuit is later, it will not be returned. If it is a false value, it will be returned to the followingfoo

It can also be used to make simple judgments instead of lengthyifStatement:

let variable = param && 

ifparamIf true, returnProperties, otherwise returnparamThis false value prevents it in some placesparamforundefinedWhen it is used, its attributes will cause an error.

1.6 Rounding | 0

For a number| 0It can be rounded, and negative numbers also apply.num | 0

1.3 | 0 // 1
-1.9 | 0 // -1

1.7 Judge odd and even numbers & 1

For a number& 1It can be judged that odd and even numbers are also applicable.num & 1

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

2. Function

2.1 Function default value

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

Note that the incoming parameters areundefinedOr if the default parameters are not passed in, but if thenullThe default parameters will still be overridden.

2.2 Forced parameters

By default, if no value is passed to the function parameter, JS will set the function parameter toundefined. Some other languages ​​will issue warnings or errors. To perform parameter assignment, you can useifThe statement throws an undefined error, or can be exploitedForced parameters

mandatory = ( ) => {
 throw new Error('Missing parameter!');
}
foo = (bar = mandatory( )) => { // If no parameters are passed here, the manadatory function will be executed and an error will be reported. return bar;
}

2.3 Implicit return value

The return value is the keyword we usually use to return the final result of a function. Arrow function with only one statement can implicitly return the result (the function must omit braces{ }, so as to omit the return keyword).
To return a multi-line statement (such as object text), you need to use( )Instead{ }To wrap the function body. This ensures that the code is evaluated in the form of a single statement.

function calcCircumference(diameter) {
 return  * diameter
}
// Abbreviation is:calcCircumference = diameter => (
  * diameter;
)

2.4 Lazy loading function

In a certain scenario, our function has judgment statements. This judgment basis generally does not change during the entire project operation. Therefore, it is judged that the branch will only run a specific branch during the entire project operation. Then you can consider lazy loading the function

function foo(){
 if(a !== b){
 ('aaa')
 }else{
 ('bbb')
 }
}

// After optimizationfunction foo(){
 if(a != b){
 foo = function(){
 ('aaa')
 }
 }else{
 foo = function(){
 ('bbb')
 }
 }
 return foo();
}

Then, after the first run, this method will be overwritten, and the judgment will not be performed when the next run is again. Of course, there is only one judgment now. If there are many judgments and the branches are relatively complex, then the savings are still considerable.

2.5 One-time function

Similar to the lazy loading function above, you can overwrite the current function in the function body, so you can create a one-time function. The code before reassigning the value is equivalent to running only once, which is suitable for running some initialization codes that only need to be executed once.

var sca = function() {
 ('msg')
 sca = function() {
 ('foo')
 }
}
sca() // msg
sca() // foo
sca() // foo

3. Code reuse

3.1 Object [key]

Although Writtenfoo ['bar'] is a common practice, but this practice forms the basis for writing reusable code. Many frameworks use this method, such as element'sForm Verification

Consider the following simplified example of the verification function:

function validate(values) {
 if(!)
 return false;
 if(!)
 return false;
 return true;
}
(validate({first:'Bruce',last:'Wayne'})); // true

The above function perfectly completes the verification work. But when there are many forms, verification needs to be applied, and there will be different fields and rules at this time. It would be a good choice if you could build a universal verification function configured at runtime.

// 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;
}
(validate(schema, {first:'Bruce'})); // false
(validate(schema, {first:'Bruce',last:'Wayne'})); // true

Now that we have this verification function, we can reuse it in all forms without writing a custom verification function for each form.

4. Numbers

4.1 Differential notation

ES6 has added writing formats with different digits, so you should pay attention to this when transferring parameters in the background.

29 // Decimal035 // Eight 29 original way0o35 // Eight 29 ES6 way0x1d // Hexadecimal 290b11101 // 29

4.2 Decimals accurate to the specified number of digits

Round the number to the specified number of decimal places. use() and template literals round the number to the specified number of decimal places. Omit the second parameterdecimals, the number will be rounded to an integer.

const round = (n, decimals = 0) => Number(`${(`${n}e${decimals}`)}e-${decimals}`)
round(1.345, 2) 				// 1.35
round(1.345, 1) 				// 1.3

4.3 Number supplement 0 operation

Thanks to netizens @JserWang @vczhan for providing this tip

Sometimes, for example, when displaying time, sometimes one number needs to be displayed in two digits. At this time, you need to add 0 operation, which can be used.sliceandstringofpadStartmethod

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

5. Array

5.1 Reduce method implements map and filter at the same time

Suppose there is now a sequence that you want to update each item of it (the function of map) and then filter out a portion (the function of filter). If used firstmapThenfilterIf so, 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 = ((finalList, num) => {
 num = num * 2;
 if (num > 50) {
 (num);
 }
 return finalList;
}, []);
doubledOver50; // [60, 80]

5.2 Statistics the number of the same items in the array

Many times, you want to count the number of repeated items in the array and then represent them with an object. Then you can usereduceMethods handle this array.

The following code will count the number of each type of car and then represent the total number as an object.

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

5.3 Use deconstruction to exchange parameter values

Sometimes you will put multiple values ​​returned by the function in an array. We can use array deconstruction to get each of them.

let param1 = 1;
let param2 = 2;
[param1, param2] = [param2, param1];
(param1) // 2
(param2) // 1

Of course, we have many 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

5.4 Receive multiple results returned by the function

In the following code, we/postGet a post in/commentsGet relevant comments in . Since we are usingasync/await, the function puts the return value in an array. After deconstructing the array, we can assign the return value directly to the corresponding variable.

async function getFullPost(){
 return await ([
 fetch('/post'),
 fetch('/comments')
 ]);
}
const [post, comments] = getFullPost();

5.5 Tile the array to a specified depth

Use recursion for each depth leveldepthDecrement by 1. use() and() to merge elements or arrays. Under basic circumstances,depthEqual to 1 Stop recursion. The second parameter is omitted.depthTile only to a depth of 1 (single-layer tiling).

const flatten = (arr, depth = 1) =>
 depth != 1
 ? ((a, v) => ((v) ? flatten(v, depth - 1) : v), [])
 : ((a, v) => (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]

5.6 Object destruction of arrays

Arrays can also be deconstructed in objects, which can easily obtain the nth value of the array.

const csvFileLine = '1997,John Doe,US,john@,New York';
const { 2: country, 4: state } = (',');

country			// US
state			// New Yourk

6. Object

6.1 Use deconstruction to delete unnecessary attributes

Sometimes you don't want to retain certain object properties, maybe because they contain sensitive information or are just too big. You might enumerate the entire object and delete them, but you actually just need to simply assign these useless properties to the variable and then take the useful parts you want to keep as the remaining parameters.
In the following code, we want to delete the _internal and tooBig parameters. We can assign them to internal and tooBig variables, and then store the remaining properties in the cleanObject for later use.

let {_internal, tooBig, ...cleanObject} = {el1: '1', _internal:"secret", tooBig:{}, el2: '2', el3: '3'};

(cleanObject);  // {el1: '1', el2: '2', el3: '3'}

6.2 Deconstructing nested objects in function parameters

In the following code, engine is an object nested in the object car. If we are interested in the vin property of engine, it is easy to get it using deconstructed assignment.

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

Add the number supplement 0 operation provided by @JserWang @vczhan

Most of the posts on the Internet are different in depth, and even some are inconsistent. The articles below are summary during the learning process. If you find any errors, please leave a message to point them out~

refer to:

JavaScript abbreviation tips that developers need to know

Effective Javascript
The ES6 tips that you have to know
Some special applications of js operator
Advanced JS Tips (Simplified Version)

Recommended reading: ES6 demo website