2022 latest front end specification
[1] Necessary
1, Quote
- Use const to define all your references; Avoid using var.
Why does this ensure that you can't re assign your reference, otherwise it may lead to errors or incomprehensible code
// bad var a = 1; // good const a = 1;
- If you have to re assign your reference, use let instead of var.
Why let is a block scope, unlike var is a function scope
// bad var count = 1; if (true) { count += 1; } // good, use the let. let count = 1; if (true) { count += 1; }
2, Object
- Use literal syntax to create objects
Why? More concise and efficient
// bad const item = new Object(); // good const item = {};
- Group abbreviated attributes when declaring objects
Why is it easier to determine which attributes use abbreviations.
const anakinSkywalker = 'Anakin Skywalker'; const lukeSkywalker = 'Luke Skywalker'; // bad const obj = { episodeOne: 1, twoJediWalkIntoACantina: 2, lukeSkywalker, episodeThree: 3, anakinSkywalker, }; // good const obj = { lukeSkywalker, anakinSkywalker, episodeOne: 1, twoJediWalkIntoACantina: 2, episodeThree: 3, };
- Use quotation marks only for attributes with invalid identifiers
Why, in general, we think it's easier to read. It improves syntax highlighting and is easier to optimize through many JS engines.
// bad const bad = { 'foo': 3, 'data-blah': 5, }; // good const good = { foo: 3, 'data-blah': 5, };
- You cannot call object directly Prototype methods, such as hasOwnProperty, propertyIsEnumerable and isPrototypeOf.
Why?
1)
const obj = Object.create(null)
const text1 = obj.hasOwnProperty('a')
const text2 = Object.prototype.hasOwnProperty.call(obj, 'a')
console.log(text1) / / an error is reported
console.log(text2) // false
2)
May lead to unexpected behavior or service security vulnerabilities. For example, it is not safe for a web client to parse JSON input from a remote server and call hasOwnProperty directly on the result object, because a malicious server may send a JSON value, such as {"hasOwnProperty": 1}, disrupting business and security.
// bad console.log(object.hasOwnProperty(key)); // good console.log(Object.prototype.hasOwnProperty.call(object, key)); // best const has = Object.prototype.hasOwnProperty; // Find once in the module wide cache // ... console.log(has.call(object, key));
3, Array
- Create an array using literal syntax
Why? More concise and efficient
// bad const items = new Array(); // good const items = [];
-
Use the array expansion method... To copy the array
// bad
const len = items.length;
const itemsCopy = [];
let i;for (i = 0; i < len; i += 1) {
itemsCopy[i] = items[i];
}// good
const itemsCopy = [...items];
4, Character
-
Use single quotation mark '' to define string
// bad
const name = "Capt. Janeway";//bad - template text should contain interpolation or line breaks.
const name = Capt. Janeway;// good
const name = 'Capt. Janeway'; -
When building strings in programming mode, string templates are used instead of string splicing
Why does the string template provide you with a readable and concise syntax with correct line feed and string interpolation.
// bad function sayHi(name) { return 'How are you, ' + name + '?'; } // bad function sayHi(name) { return ['How are you, ', name, '?'].join(); } // bad function sayHi(name) { return `How are you, ${ name }?`; } // good function sayHi(name) { return `How are you, ${name}?`; }
- Do not use eval() on strings, which opens up too many vulnerabilities
- Never define a parameter as arguments
Why? Because arguments is the implicit parameter of each function
// bad function foo(name, options, arguments) { // ... } // good function foo(name, options, args) { // ... }
5. Instead of using arguments, choose to use rest Syntax... Instead
Why Specify what parameters you want to pull. What's more, the rest parameter is a real array, not just the arguments of the class array.
// bad function concatenateAll() { const args = Array.prototype.slice.call(arguments); return args.join(''); } // good function concatenateAll(...args) { return args.join(''); }
-
Use the default parameter syntax instead of changing function parameters.
// really bad
function handleThings(opts) {
// No! We shouldn't mutate function arguments.
// Double bad: if opts is falsy it'll be set to an object which may
// be what you want but it can introduce subtle bugs.
opts = opts || {};
// ...
}// still bad
function handleThings(opts) {
if (opts === void 0) {
opts = {};
}
// ...
}// good
function handleThings(opts = {}) {
// ...
} -
Always put default parameters last.
// bad
function handleThings(opts = {}, name) {
// ...
}// good
function handleThings(name, opts = {}) {
// ...
} -
Never use a function constructor to create a new function.
Why creating a function in this way will evaluate a string similar to eval(), which will open the vulnerability.
// bad var add = new Function('a', 'b', 'return a + b'); // still bad var subtract = Function('a', 'b', 'return a - b');
- Do not assign the existing parameters of the function.
Why reassigning parameters can lead to unexpected behavior, especially when accessing the arguments object. It can also lead to performance optimization problems, especially in V8.
// bad function f1(a) { a = 1; // ... } function f2(a) { if (!a) { a = 1; } // ... } // good function f3(a) { const b = a || 1; // ... } function f4(a = 1) { // ... }
5, Attributes
-
When accessing attributes, use the dot symbol, and when using variables to access attributes, use the [] notation.
const luke = {
jedi: true,
age: 28,
};// bad
const isJedi = luke['jedi'];// good
const isJedi = luke.jedi;
6, Variable
- Use const or let to declare each variable, and put the declared const and let together.
Why?
1) This makes it easier to add new variable declarations, and you don't have to worry about using them; Or use, or introduce punctuation differences. Instead of skipping all declarations immediately, you can step through each declaration through debugger.
2) This is useful when the latter needs to specify a variable according to the assigned variable of the former.
// bad let i, len, dragonball, items = getItems(), goSportsTeam = true; // bad let i; const items = getItems(); let dragonball; const goSportsTeam = true; let len; // good const goSportsTeam = true; const items = getItems(); let dragonball; let i; let length;
- Do not assign chained variables.
Why do chained variable assignments create implicit global variables.
// bad (function example() { // JavaScript interprets it as // let a = ( b = ( c = 1 ) ); // Keyword let is only applicable to variable a; Variables b and c become global variables. let a = b = c = 1; }()); console.log(a); // throws ReferenceError console.log(b); // 1 console.log(c); // 1 // good (function example() { let a = 1; let b = a; let c = a; }()); console.log(a); // throws ReferenceError console.log(b); // throws ReferenceError console.log(c); // throws ReferenceError // The same is true for 'const'
7, Comparison operator and equal sign
-
Use = = = and== Not = = and=
-
Use abbreviations for Boolean values, but make explicit comparisons between strings and numbers.
// bad
if (isValid === true) {
// ...
}// good
if (isValid) {
// ...
}// bad
if (name) {
// ...
}// good
if (name !== '') {
// ...
}// bad
if (collection.length) {
// ...
}// good
if (collection.length > 0) {
// ...
} -
In the case and default clauses, if there are declarations (such as. let, const, function, and class), curly braces are used to create blocks.
Why is the syntax declaration visible in the whole switch block, but it will be initialized only when the assignment is made, which will happen only when the case condition is met. This can cause problems when multiple case statements define the same thing.
// bad switch (foo) { case 1: let x = 1; break; case 2: const y = 2; break; case 3: function f() { // ... } break; default: class C {} } // good switch (foo) { case 1: { let x = 1; break; } case 2: { const y = 2; break; } case 3: { function f() { // ... } break; } case 4: bar(); break; default: { class C {} } }
-
Ternary expressions should not be nested, usually single line expressions. Too many should be separated.
[remarks: js code]// bad
const foo = maybe1 > maybe2
? "bar"
: value1 > value2 ? "baz" : null;//Separate into two trinomial expressions
const maybeNull = value1 > value2 ? 'baz' : null;// better
const foo = maybe1 > maybe2
? 'bar'
: maybeNull;// best
const foo = maybe1 > maybe2 ? 'bar' : maybeNull; -
Use parentheses when using this mixed operator. The only exception is the standard arithmetic operators (+,,, *, & /) because their precedence is widely understood.
Why does this improve readability and indicate the developer's intention.
8, Notes
-
When writing code comments, use / * *... * / for multiline comments instead of / /.
-
Use / / to make single line comments. Place a single line comment above the line you want to comment on. Place an empty line before the comment unless it is on the first line of the block. Start all comments with a space to make it easier to read.
// bad
const active = true; //is current tab// good
// is current tab
const active = true;// bad
function getType() {
console.log('fetching type...');
// set the default type to 'no type'
const type = this.type || 'no type';return type;
}// good
function getType() {
console.log('fetching type...');// set the default type to 'no type'
const type = this.type || 'no type';return type;
}// also good
function getType() {
// set the default type to 'no type'
const type = this.type || 'no type';return type;
}
9, Type conversion and cast
- Convert to string, with String() as the first choice
Why? Other methods have their own problems, or there may be execution errors;
let reviewScore = 9; // bad const totalScore = new String(reviewScore); // typeof totalScore is "object" not "string" // bad const totalScore = reviewScore + ''; // Symbol('123 ') +' 'error reporting // bad const totalScore = reviewScore.toString(); // If the value is null or undefined, an error will be reported // good const totalScore = String(reviewScore);
-
Convert to Number type, first Number or parseInt, and specify 10 as cardinality.
const inputValue = '4';
// bad
const val = new Number(inputValue);// bad
const val = +inputValue;// bad
const val = inputValue >> 0;// bad
const val = parseInt(inputValue);// good
const val = Number(inputValue);// good
const val = parseInt(inputValue, 10); -
If you want to use bit operations and this is the best case, please write down a comment on why you did it and what you did.
-
Convert to boolean type
const age = 0;
// bad
const hasAge = new Boolean(age);// good
const hasAge = Boolean(age);// best
const hasAge = !!age;
10, Naming conventions
-
Use camel case when naming objects, functions, and instances And avoid single letter or Pinyin naming. Use your name to describe the function.
// bad
const OBJEcttsssss = {};
const this_is_my_object = {};
function c() {}// good
const thisIsMyObject = {};
function thisIsMyFunction() {} -
The file name should exactly match the name of the default export. That is, the naming conventions of export/import/filename should be the same. PascalCase is PascalCase, camelCase is camelCase.
-
Abbreviations and abbreviations must be all uppercase or all lowercase.
Why is the name for readability, not for computer algorithms.
// bad import SmsContainer from './containers/SmsContainer'; // bad const HttpRequests = [ // ... ]; // good import SMSContainer from './containers/SMSContainer'; // good const HTTPRequests = [ // ... ]; // also good const httpRequests = [ // ... ];
11, VUE related specifications
-
The component should be named with multiple words, and the format is Pascal case, such as' TodoItem '.
-
The naming of basic components (that is, components that show classes, no logic or no state) should all start with a specific prefix, such as Base, App or V.
components/
|- BaseButton.vue
|- BaseTable.vue
|- BaseIcon.vue -
Single column components (only once per page) should be named with The prefix to show their uniqueness.
components/
|- TheHeading.vue
|- TheSidebar.vue -
Tightly coupled components (parent and child components), where the child components should be named with the parent component name as the prefix,
-
The word order of component names should start with table attribute nouns and end with descriptive modifiers.
components/
|- SearchButtonClear.vue
|- SearchButtonRun.vue
|- SearchInputQuery.vue
|- SearchInputExcludeGlob.vue
|- SettingsCheckboxTerms.vue
|- SettingsCheckboxLaunchOnStartup.vue -
There can be no self closing and label components in the DOM template.
Why? HTML does not support self closing custom elements
- The component name in the DOM template should be in kebab case format;
Why? HTML is case insensitive, and kebab case must still be used in DOM templates.
<!-- stay DOM In template --> <my-component></my-component>
-
The definition of prop should be detailed. In the submitted code, the definition of prop should be as detailed as possible, and at least its type needs to be specified.
Counterexample
//This is only acceptable when developing a prototype system
props: ['status'] -
Set the scope for the general page and component style you write, or the package of project name + component name;
Why? Styles in components and layout components can be global
<template> <button class="button button-close">X</button> </template> <!-- use `scoped` attribute --> <style scoped> .button-close { background-color: red; } </style>
- If you need to use the value of an external variable inside the function, you need to pass the variable into the function as a parameter, so that the external parameter can be used as an internal parameter of the function.
Why? It will make the logical context of data clearer and easier to track.
<button @click="onSendOut(params, info.orderId)">deliver goods</button>
- Method name in methods:
1) Hump writing;
2) The method name is English words, and Pinyin is disabled;
3) If it is an event, you need to add on before it;
4) The format to be obtained is XXdata;
5) The processing data needs to be in handleXXXData format
For example: onSubmitForm() / getListData() / handleListData()
[2] Recommend
1, Deconstruction
- Use object deconstruction when accessing and using multiple attributes of an object.
Why deconstruction can avoid creating temporary references to these attributes.
// bad function getFullName(user) { const firstName = user.firstName; const lastName = user.lastName; return `${firstName} ${lastName}`; } // good function getFullName(user) { const { firstName, lastName } = user; return `${firstName} ${lastName}`; } // best function getFullName({ firstName, lastName }) { return `${firstName} ${lastName}`; }
-
Use array deconstruction
const arr = [1, 2, 3, 4];
// bad
const first = arr[0];
const second = arr[1];// good
const [first, second] = arr; -
Use object deconstruction instead of array deconstruction for multiple return values.
Why can you add new attributes or change the order of attributes at any time without modifying the caller.
// bad function processInput(input) { // Processing code return [left, right, top, bottom]; } // The caller needs to consider the order in which the data is returned. const [left, __, top] = processInput(input); // good function processInput(input) { // Processing code return { left, right, top, bottom }; } // Callers only select the data they need. const { left, top } = processInput(input);
2, Loop (iterator)
- You should use JavaScript's higher-order functions instead of for in or for of.
Use map() / every() / filter() / find() / findIndex() / reduce() / some() /... To traverse the array, and use object keys() / Object. values() / Object. Entries () iterates over your object to generate an array.
Because they return pure why functions.
const numbers = [1, 2, 3, 4, 5]; // bad let sum = 0; for (let num of numbers) { sum += num; } sum === 15; // good let sum = 0; numbers.forEach((num) => { sum += num; }); sum === 15; // best (use the functional force) const sum = numbers.reduce((total, num) => total + num, 0); sum === 15; // bad const increasedByOne = []; for (let i = 0; i < numbers.length; i++) { increasedByOne.push(numbers[i] + 1); } // good const increasedByOne = []; numbers.forEach((num) => { increasedByOne.push(num + 1); }); // best (keeping it functional) const increasedByOne = numbers.map(num => num + 1);
3, Control statement
- If your control statement (if, while, etc.) is too long or exceeds the maximum length limit of a line, you can put each condition (or group) into a new line. Logical operators should be at the beginning of the line.
Why do you require operators to remain aligned at the beginning of a line and follow a similar pattern of convergence. This improves readability and makes more complex logic easier to understand intuitively.
// bad if ((foo === 123 || bar === 'abc') && doesItLookGoodWhenItBecomesThatLong() && isThisReallyHappening()) { thing1(); } // bad if (foo === 123 && bar === 'abc') { thing1(); } // bad if (foo === 123 && bar === 'abc') { thing1(); } // bad if ( foo === 123 && bar === 'abc' ) { thing1(); } // good if ( foo === 123 && bar === 'abc' ) { thing1(); } // good if ( (foo === 123 || bar === 'abc') && doesItLookGoodWhenItBecomesThatLong() && isThisReallyHappening() ) { thing1(); }
- Avoid nesting
When multiple nested codes are needed due to multiple conditional judgments, you can use if + return, which is more concise and easy to read
// bad function func(a, b, c, d){ if(a !== null){ if (b !== 2){ if (c !== "OK"){ // code } } } } // good function func(a, b, c, d){ if(a === null) return if (b === 2) return if (c === "OK") return // code }
4, Object
-
We prefer to use object extension operators instead of object Assign shallow copy an object. Use the object's rest operator to get a new object with some properties.
// very bad
const original = { a: 1, b: 2 };
const copy = Object.assign(original, { c: 3 }); // Original of variation?
delete copy.a; // This// bad
const original = { a: 1, b: 2 };
const copy = Object.assign({}, original, { c: 3 }); // copy => { a: 1, b: 2, c: 3 }// good
const original = { a: 1, b: 2 };
const copy = { ...original, c: 3 }; // copy => { a: 1, b: 2, c: 3 }const { a, ...noA } = copy; // noA => { b: 2, c: 3 }