JavaScript coding specification
1 introduction
JavaScript has been widely used in Baidu, especially in browser behavior management. The goal of this document is to make the JavaScript code style consistent, easy to understand, and easy to maintain.
Although this document is designed for JavaScript, the conventions of this document should be followed when working with various JavaScript precompiled languages (such as TypeScript).
2 Code Style
2.1 file
[Suggestion] use JavaScript file noneBOM
的 UTF-8
Encoding.
Explanation:
Utf-8 encoding has wider adaptability. BOM can cause unnecessary interference when using programs or tools to process documents.
[Suggestion] Leave a blank line at the end of the file.
2.2 structure
2.2.1 the indentation
[Mandatory] Use4
A space as an indentation level is not allowed2
A blank space ortab
Characters.
[] compulsoryswitch
Under thecase
和 default
An indent level must be added.
Example:
// good
switch (variable) {
case '1':
// do...
break;
case '2':
// do...
break;
default:
// do...
}
// bad
switch (variable) {
case '1':
// do...
break;
case '2':
// do...
break;
default:
// do...
}
Copy the code
2.2.2 Spaces
Binary operators must have a space on either side. Unary operators are not allowed to have a space between the operator and the object.
Example:
vara = ! arr.length; a++; a = b + c;Copy the code
[Force] is used as an open curly brace at the beginning of a code block{
There must be a space before.
Example:
// good
if (condition) {
}
while (condition) {
}
function funcName() {}// bad
if (condition){
}
while (condition){
}
function funcName(){}Copy the code
[] compulsoryif / else / for / while / function / switch / do / try / catch / finally
The keyword must be followed by a space.
Example:
// good
if (condition) {
}
while (condition) {
}
(function () {
})();
// bad
if(condition) {
}
while(condition) {
}
(function() {
})();
Copy the code
[Force] when the object is created:
There must be a space after that,:
No Spaces were allowed before.
Example:
// good
var obj = {
a: 1.b: 2.c: 3
};
// bad
var obj = {
a : 1.b:2.c :3
};
Copy the code
Function declaration, named function expression, function call, function name and(
No Spaces are allowed between.
Example:
// good
function funcName() {}var funcName = function funcName() {}; funcName();// bad
function funcName () {}var funcName = function funcName () {}; funcName ();Copy the code
[] compulsory.
和 ;
Spaces are not allowed before. If it’s not at the end of the line,.
和 ;
Must be followed by a space.
Example:
// good
callFunc(a, b);
// bad
callFunc(a , b) ;
Copy the code
Function calls, function declarations, parenthesis expressions, attribute access,if / for / while / switch / catch
And so on,(a)
和 []
Spaces are not allowed within the brackets.
Example:
// good
callFunc(param1, param2, param3);
save(this.list[this.indexes[i]]);
needIncream && (variable += increament);
if (num > list.length) {
}
while (len--) {
}
// bad
callFunc( param1, param2, param3 );
save( this.list[ this.indexes[ i ] ] );
needIncreament && ( variable += increament );
if ( num > list.length ) {
}
while ( len-- ) {
}
Copy the code
[enforces] single-line declared arrays and objects, if containing elements,{}
和 []
Spaces are not allowed in the inner brackets.
Explanation:
Declare arrays and objects that contain elements. Write on a single line only if the internal elements are simple. If the element is complex, you should write on a new line.
Example:
// good
var arr1 = [];
var arr2 = [1.2.3];
var obj1 = {};
var obj2 = {name: 'obj'};
var obj3 = {
name: 'obj'.age: 20.sex: 1
};
// bad
var arr1 = [ ];
var arr2 = [ 1.2.3 ];
var obj1 = { };
var obj2 = { name: 'obj' };
var obj3 = {name: 'obj'.age: 20.sex: 1};
Copy the code
No extra space at the end of a line.
2.2.3 newline
[Mandatory] Line breaks must follow the end of each independent statement.
No more than one line120
A character.
Explanation:
Extremely long, indivisible code allows exceptions, such as complex regular expressions. Long strings are not an exception.
When the operator is newline, the operator must be at the beginning of the new line.
Example:
// good
if (user.isAuthenticated()
&& user.isInRole('admin')
&& user.hasAuthority('add-admin')
|| user.hasAuthority('delete-admin')) {// Code
}
var result = number1 + number2 + number3
+ number4 + number5;
// bad
if (user.isAuthenticated() &&
user.isInRole('admin') &&
user.hasAuthority('add-admin') ||
user.hasAuthority('delete-admin')) {
// Code
}
var result = number1 + number2 + number3 +
number4 + number5;
Copy the code
Function declarations, function expressions, function calls, object creation, array creation,for
Statements are not allowed in scenarios.
或 ;
Before the line break.
Example:
// good
var obj = {
a: 1.b: 2.c: 3
};
foo(
aVeryVeryLongArgument,
anotherVeryLongArgument,
callback
);
// bad
var obj = {
a: 1
, b: 2
, c: 3
};
foo(
aVeryVeryLongArgument
, anotherVeryLongArgument
, callback
);
Copy the code
[Suggestion] A set of statements with different behaviors or logic, separated by blank lines, is easier to read.
Example:
// This is only an example of logical line breaking and does not represent an optimal implementation of setStyle
function setStyle(element, property, value) {
if (element == null) {
return;
}
element.style[property] = value;
}
Copy the code
[suggestion] exceeds the line length of a statement120
, according to the logical conditions of the reasonable indentation.
Example:
// For more complex combinations of logical conditions, separate each condition on a single line, place the logical operator at the beginning of the line for separation, or separate part of the logic according to the logical combination.
// It is recommended to finally put the close parenthesis) and the left curly brace {on a separate line to ensure that the statement block within 'and' if 'can be easily visually identified.
if (user.isAuthenticated()
&& user.isInRole('admin')
&& user.hasAuthority('add-admin')
|| user.hasAuthority('delete-admin')) {// Code
}
// Truncate the string to a certain length and concatenate it using the + operator.
// Separate strings as semantically as possible, such as not breaking in the middle of a complete noun.
// In particular, HTML fragments are concatenated to keep the same structure as HTML.
var html = ' ' // An empty string is used here so that the entire HTML fragment is strictly aligned on the new line
+ '<article>'
+ '<h1>Title here</h1>'
+ '<p>This is a paragraph</p>'
+ '<footer>Complete</footer>'
+ '</article>';
// Arrays can also be used for concatenation, which is easier to adjust the indentation than '+'.
var html = [
'<article>'.'<h1>Title here</h1>'.'<p>This is a paragraph</p>'.'<footer>Complete</footer>'.'</article>'
];
html = html.join(' ');
// When there are too many arguments, write each argument on its own line, and separate the closing parenthesis) on its own line.
// All parameters must be indent.
foo(
aVeryVeryLongArgument,
anotherVeryLongArgument,
callback
);
// Arguments can also be combined logically.
// The most classic is the bidu. format function, which divides parameters into "template" and "data"
baidu.format(
dateFormatTemplate,
year, month, date, hour, minute, second
);
// When a function is called, if one or more arguments span multiple lines, each argument should have its own line.
// This usually occurs when an anonymous function or object is initialized as an argument, such as the setTimeout function.
setTimeout(
function () {
alert('hello');
},
200
);
order.data.read(
'id=' + me.model.id,
function (data) {
me.attchToModel(data.result);
callback();
},
300
);
// Use indentation for longer chain calls.
$('#items')
.find('.selected')
.highlight()
.end();
// The ternary operator is made up of three parts, so newlines should behave differently depending on the length of each part.
var result = thisIsAVeryVeryLongCondition
? resultA : resultB;
var result = condition
? thisIsAVeryVeryLongResult
: resultB;
// Mix array and object initialization, strictly following the style of each object '{' and end'} 'on a separate line.
var array = [
{
// ...
},
{
// ...}];Copy the code
[Suggestion] Forif... else...
,try... catch... finally
And other statements are recommended to be used in}
Add a line break style after the symbol to make the code hierarchy clearer and easier to read.
Example:
if (condition) {
// some statements;
}
else {
// some statements;
}
try {
// some statements;
}
catch (ex) {
// some statements;
}
Copy the code
2.2.4 statement
[Mandatory] Do not omit the semicolon at the end of a statement.
[compulsion] inif / else / for / do / while
A block must not be omitted from a statement, even if it is only one line{... }
.
Example:
// good
if (condition) {
callFunc();
}
// bad
if (condition) callFunc();
if (condition)
callFunc();
Copy the code
Semicolons are not allowed at the end of function definition.
Example:
// good
function funcName() {}// bad
function funcName() {};// In function expressions, semicolons are not allowed to be omitted.
var funcName = function () {};Copy the code
[] compulsoryIIFE
Must be added outside the function expression(
,IIFE
May not be added outside function expressions(
.
Explanation:
IIFE = Immediately-Invoked Function Expression.
Extra (allows the code to determine at the beginning of the reading whether a function is called immediately, and hence what the following code is for. Instead of dragging it all the way to the bottom.
Example:
// good
var task = (function () {
// Code
returnresult; }) ();var func = function () {};// bad
var task = function () {
// Code
returnresult; } ();var func = (function () {});Copy the code
2.3 named
[] compulsoryvariable
useCamel nomenclature
.
Example:
var loadingModules = {};
Copy the code
[] compulsoryconstant
useAll letters are capitalized and words are separated by underscores
The naming method of.
Example:
var HTML_ENTITY = {};
Copy the code
[] compulsoryfunction
useCamel nomenclature
.
Example:
function stringFormat(source) {}Copy the code
Mandatory of a functionparameter
useCamel nomenclature
.
Example:
function hear(theBells) {}Copy the code
[] compulsoryclass
usePascal nomenclature
.
Example:
function TextNode(options) {}Copy the code
Classmethods
/ attribute
useCamel nomenclature
.
Example:
function TextNode(value, engine) {
this.value = value;
this.engine = engine;
}
TextNode.prototype.clone = function () {
return this;
};
Copy the code
[] compulsoryEnumeration variable
usePascal nomenclature
.Enumerated properties
useAll letters are capitalized and words are separated by underscores
The naming method of.
Example:
var TargetState = {
READING: 1.READED: 2.APPLIED: 3.READY: 4
};
Copy the code
[] compulsoryThe namespace
useCamel nomenclature
.
Example:
equipments.heavyWeapons = {};
Copy the code
[Mandatory] A multi-word abbreviation in which the case of all letters is the same as the case of the first letter, based on the current nomenclature and the position in which it occurs.
Example:
function XMLParser() {}function insertHTML(element, html) {}var httpRequest = new HTTPRequest();
Copy the code
[] compulsoryThe name of the class
usenoun
.
Example:
function Engine(options) {}Copy the code
[suggestion]The function name
useThe svo phrases
.
Example:
function getStyle(element) {}Copy the code
[suggestion]boolean
Type variable usedis
或 has
At the beginning.
Example:
var isReady = false;
var hasMoreCommands = false;
Copy the code
[suggestion]Promise object
用 The continuous tense of verb-object phrases
Expression.
Example:
var loadingData = ajax.get('url');
loadingData.then(callback);
Copy the code
2.4 annotations
2.4.1 Single-line comments
Mandatory The row must be exclusive.//
Followed by a space, indented to match the next line of commented code.
2.4.2 Multi-line comments
[Suggestion] Avoid using/ *... * /
Such a multi-line comment. Use multiple single-line comments when you have multi-line comment content.
2.4.3 Documented comments
[Mandatory] For easy code reading and self-documentation, the following must be included with/ * *... * /
Block comments in the form.
Explanation:
- file
- namespace
- class
- A function or method.
- Class attribute
- The event
- The global variable
- constant
- AMD modules
[Mandatory] A line must be left blank before a comment.
[Suggestion] Self-documented documents say what, not how.
2.4.4 Type Definition
Type definitions are all defined as{
Began to}
The end.
Explanation:
Common types include: {string}, {number}, {Boolean}, {Object}, {Function}, {RegExp}, {Array}, {Date}.
Types are not limited to built-in types, but can also be custom types. For example, if you define a class Developer, you can use it to define the type of a parameter and return value.
[Mandatory] For basic types {string}, {number}, {Boolean}, the first letter must be lowercase.
The type definition | Syntax examples | explain |
---|---|---|
String | {string} | — |
Number | {number} | — |
Boolean | {boolean} | — |
Object | {Object} | — |
Function | {Function} | — |
RegExp | {RegExp} | — |
Array | {Array} | — |
Date | {Date} | — |
Single type set | {Array.<string>} | Array of type string |
g | {(number | Boolean)} | It can be of type number or Boolean |
Allow null | {? number} | It could be number or null |
Null is not allowed | {! Object} | Object, but not null |
The Function type | {function(number, boolean)} | Function, parameter type |
Function returns a value | {function(number, boolean):string} | Function, parameter, return value type |
Promise | Promise.<resolveType, rejectType> | Promise, data type returned on success, error type returned on failure |
Parameters can be chosen | @param {string=} name | This parameter is optional. = is the type suffix |
Variable parameter | @param {… number} args | Variable length parameter,… Is the type prefix |
Any type | {*} | Any type |
Any type is optional | @param {*=} name | This parameter is optional. The type is not limited |
Mutable arbitrary type | @param {… *} args | Variable length parameter, type is unlimited |
2.4.5 File Comments
[mandatory] The top of the file must contain file comments, using@file
Identifies the file description.
Example:
/ * * *@file Describe the file
*/
Copy the code
[Suggestion] It can be used in file comments@author
Identify developer information.
Explanation:
Developer information reflects the developer’s contribution to the document and can be directed to the maintainer by people who have problems or want to know more about it. Typically, files are created with the identity of the creator. As the project progresses and more people participate in the development of this file, new authors should be added to the @author identifier.
When @author identifies multiple people, the principle is to sort by responsibility. Usually if there’s a problem, it’s better to go to the first person than to go to the second person. For example, the author of a file for some reason, the module is handed over to someone else or another team, and later, because of new requirements, someone else should add their own name before the author when adding new code.
Names in @author are not allowed to be deleted. The fruits of any labor should be respected.
In a business project, a file may be frequently modified by multiple people, and the maintenance time of each person may not be long. Therefore, it is not recommended to add the @author identifier to a file. Better accountability management is to track changes through version control systems, identify maintenance responsibilities for modules by business logic units, and track and query through documentation and wikis.
For technical infrastructure projects that are business logic-neutral, especially open source public projects, the @author identifier should be used.
Example:
/ * * *@file Describe the file
* @author author-name(mail-name@domain.com)
* author-name2(mail-name2@domain.com)
*/
Copy the code
2.4.6 Namespace Comments
[Suggestion] Use the namespace@namespace
Logo.
Example:
/ * * *@namespace* /
var util = {};
Copy the code
2.4.7 class annotation
[Recommended] Use@class
Tag a class or constructor.
Explanation:
Constructors defined using the object constructor property can be marked with @constructor.
Example:
/** * description **@class* /
function Developer() {
// constructor body
}
Copy the code
[Recommended] Use@extends
Marks the inheritance information of the class.
Example:
/** * description **@class
* @extends Developer* /
function Fronteer() {
Developer.call(this);
// constructor body
}
util.inherits(Fronteer, Developer);
Copy the code
When a wrapper is used to extend a class member, it must pass@lends
Reroute.
Explanation:
The document that contains the members of the extended class cannot be generated for the class without the @lendings tag.
Example:
/** * class description **@class
* @extends Developer* /
function Fronteer() {
Developer.call(this);
// constructor body
}
util.extend(
Fronteer.prototype,
/ * *@lends Fronteer.prototype */{
getLevel: function () {
// TODO}});Copy the code
Member information such as attributes or methods of a class is notpublic
Should be used@protected
或 @private
Identify accessibility.
Explanation:
The generated document will be marked for accessibility, preventing users from directly using non-public properties or methods.
Example:
/** * class description **@class
* @extends Developer* /
var Fronteer = function () {
Developer.call(this);
/** * Attribute description **@type {string}
* @private* /
this.level = 'T12';
// constructor body
};
util.inherits(Fronteer, Developer);
/** * method description **@private
* @return {string} Return value description */
Fronteer.prototype.getLevel = function () {};Copy the code
2.4.8 Function/method comments
Mandatory function/method comments must contain function descriptions and must be identified by comments if they have arguments and return values.
Explanation:
When the return keyword is used only as an exit function/method, you do not need to comment on the return value.
Parameter and return value comments must contain type information, and parameter descriptions are not allowed to be omitted.
[Suggestion] You can use this function when the function is internal and cannot be accessed externally@inner
Logo.
Example:
/** * function description **@param {string} P1 Description of parameter 1 *@param {string} P2 parameter 2, the description of the long * then newline. *@param {number=} P3 (Optional) Description of Parameter 3 *@return {Object} Return value description */
function foo(p1, p2, p3) {
var p3 = p3 || 10;
return {
p1: p1,
p2: p2,
p3: p3
};
}
Copy the code
[Mandatory] Specifies the description of items in Object@param
Logo.
Example:
/** * function description **@param {Object} Option Parameter description *@param {string} Option. url Description of the option option *@param {string=} Option. method Specifies the option option. */ is optional
function foo(option) {
// TODO
}
Copy the code
[Suggestion] Should be added when overriding a parent class method@override
Logo. If the number, type, order, and return value type of the overridden parameters are not changed, you can omit them@param
,@return
, only use@override
Identification, otherwise full comments should still be made.
Explanation:
In short, a subclass can omit comments on arguments and return values when it overrides a method that uses the parent class’s method comments directly.
2.4.9 Event Comments
[Mandatory] Must be used@event
Identifies the event. The identification of the event parameters is the same as that of the method description.
Example:
/** * triggers ** when the value changes@event Select#change
* @param {Object} E e Description *@param {string} E.before before describe *@param {string} After description */
this.fire(
'change',
{
before: 'foo'.after: 'bar'});Copy the code
[force] used before functions that broadcast events@fires
Identifies the broadcast event, used before the broadcast event code@event
Identify the event.
[Suggestion] For comments on event objects, use@param
Identification for better readability when generating documents.
Example:
/** * click handle **@fires Select#change
* @private* /
Select.prototype.clickHandler = function () {
/** * triggers ** when the value changes@event Select#change
* @param {Object} E e Description *@param {string} E.before before describe *@param {string} After description */
this.fire(
'change',
{
before: 'foo'.after: 'bar'}); };Copy the code
2.4.10 Constant comments
Constant must be used@const
Tag and contain description and type information.
Example:
/** * Constant description **@const
* @type {string}* /
var REQUEST_URL = 'myurl.do';
Copy the code
2.4.11 Annotation of complex types
[Suggestion] You can use this command to annotate complex structures whose types are not defined@typedef
Identity to define.
Example:
// 'namespaceA~' can be replaced with other namepaths in order to generate the types and links defined by @typedef in the document.
/** * server **@typedef {Object} namespaceA~Server
* @property {string} The host host *@property {number} The port port * /
/** * Server list **@type {Array.<namespaceA~Server>}* /
var servers = [
{
host: '2.'.port: 8080
},
{
host: '1.2.3.5'.port: 8081}];Copy the code
2.4.12 COMMENTS on AMD Modules
[Mandatory] Used by AMD module@module
或 @exports
Logo.
Explanation:
@exports and @Module can both be used to identify modules. The difference is that @module can omit the module name. You can omit the module: prefix in namepaths if you only use @exports.
Example:
define(
function (require) {
/**
* foo description
*
* @exports Foo* /
var foo = {
// TODO
};
/**
* baz description
*
* @return {boolean} return description
*/
foo.baz = function () {
// TODO
};
returnfoo; });Copy the code
You can also use the @module flag before the exports variable:
define(
function (require) {
/**
* module description.
*
* @module foo* /
var exports = {};
/** * bar description * */
exports.bar = function () {
// TODO
};
return exports; });Copy the code
If you use the factory exports argument directly, you can also:
/**
* module description.
*
* @module* /
define(
function (require.exports) {
/** * bar description * */
exports.bar = function () {
// TODO
};
return exports; });Copy the code
[Mandatory] Used@module
Identified as a reference to an AMD module innamepaths
Must be added tomodule:
As a prefix.
Explanation:
If the Namepaths do not have the Module: prefix, the generated documents will not generate links correctly.
Example:
/** * click handle **@fires module:Select#change
* @private* /
Select.prototype.clickHandler = function () {
/** * triggers ** when the value changes@event module:Select#change
* @param {Object} E e Description *@param {string} E.before before describe *@param {string} After description */
this.fire(
'change',
{
before: 'foo'.after: 'bar'}); };Copy the code
[Suggestion] This parameter can be used for modules defined by classes@alias
Identifies the builder function.
Example:
/**
* A module representing a jacket.
* @module jacket* /
define(
function () {
/ * * *@class
* @alias module:jacket
*/
var Jacket = function () {};returnJacket; });Copy the code
[Suggestion] This parameter can be used when multiple modules are defined@exports
Identify each module.
Example:
// one module
define('html/utils'./**
* Utility functions to ease working with DOM elements.
* @exports html/utils
*/
function () {
var exports= {};return exports; });// another module
define('tag'./ * *@exports tag */
function () {
var exports= {};return exports; });Copy the code
Suggestion: This command can be used for the Object module of exports@namespace
Logo.
Explanation:
Module references can omit the module: prefix when using @namespace instead of @module or @exports.
[Suggestion] For the module whose class name is exports@class
和 @exports
Logo.
Example:
// Using @exports alone, class methods and attributes must be identified with @name Bar#methodName. Working with @exports avoids this problem and references can be made without the module: prefix.
// Also note that class names need to be defined using var.
/**
* Bar description
*
* @see foo
* @exports Bar
* @class* /
var Bar = function () {
// TODO
};
/**
* baz description
*
* @return {(string|Array)} return description
*/
Bar.prototype.baz = function () {
// TODO
};
Copy the code
2.4.13 Detailed comments
For internal implementations, difficult logic instructions, summary information, and so on, we may need to write detailed annotations.
[Suggestion] Follow the format of a single line comment. Specifies that when line breaks are required, each line is the start of a single-line comment.
Example:
function foo(p1, p2, opt_p3) {
// The internal logic is as follows
// It is too long and needs a line break
for(...). {... }}Copy the code
[Mandatory] Sometimes we use special tokens to illustrate. Special tags must be in the form of a single-line comment. Here are some common tags:
Explanation:
- TODO: Features waiting to be implemented. In this case, a brief description of the functions to be implemented is required.
- FIXME: This code runs fine, but may need to be fixed due to time constraints or other reasons. A brief explanation of how to fix it is needed.
- HACK: code that is poorly written to fix a problem or uses some weird trick. A description of the train of thought or the strange method is needed.
- XXX: There is a trap. The trap needs to be described.
3 Language Features
3.1 variable
A variable or function must be defined before it can be used.
Explanation:
Not defining variables with var will cause them to pollute the global environment.
Example:
// good
var name = 'MyName';
// bad
name = 'MyName';
Copy the code
In principle, you are not advised to use global variables. For existing global variables or those introduced by third-party frameworks, you need to identify them based on the syntax of the check tool.
Example:
/* globals jQuery */
var element = jQuery('#element-id');
Copy the code
[Force] everyvar
Only one variable can be declared.
Explanation:
A var declares multiple variables, which can lead to long lines and confusion between commas and semicolons when modified.
Example:
// good
var hangModules = [];
var missModules = [];
var visited = {};
// bad
var hangModules = [],
missModules = [],
visited = {};
Copy the code
[Mandatory] The variable mustReady-to-use declaration
You may not uniformly declare all variables at the start of a function or other code block.
Explanation:
The more distant a variable declaration is from use, the greater the span of occurrence, and the higher the cost of code reading and maintenance. Although JavaScript variables are function scoped, you should reduce the distance between variables depending on your programming intent.
Example:
// good
function kv2List(source) {
var list = [];
for (var key in source) {
if (source.hasOwnProperty(key)) {
var item = {
k: key,
v: source[key] }; list.push(item); }}return list;
}
// bad
function kv2List(source) {
var list = [];
var key;
var item;
for (key in source) {
if (source.hasOwnProperty(key)) {
item = {
k: key,
v: source[key] }; list.push(item); }}return list;
}
Copy the code
3.2 conditions
Equality Expression is strictly typed= = =
. Only when the judgenull
或 undefined
Is allowed to be used== null
.
Explanation:
Implicit type conversions in equal judgment can be avoided by using ===.
Example:
// good
if (age === 30) {
/ /...
}
// bad
if (age == 30) {
/ /...
}
Copy the code
[Suggestion] Use concise expressions whenever possible.
Example:
// The string is empty
// good
if(! name) {/ /...
}
// bad
if (name === ' ') {
/ /...
}
Copy the code
// The string is not empty
// good
if (name) {
/ /...
}
// bad
if(name ! = =' ') {
/ /...
}
Copy the code
// The array is not empty
// good
if (collection.length) {
/ /...
}
// bad
if (collection.length > 0) {
/ /...
}
Copy the code
// Boolean is not valid
// good
if(! notTrue) {/ /...
}
// bad
if (notTrue === false) {
/ /...
}
Copy the code
/ / null or undefined
// good
if (noValue == null) {
/ /...
}
// bad
if (noValue === null || typeof noValue === 'undefined') {
/ /...
}
Copy the code
[Suggestion] Arrange branches by execution frequency.
Explanation:
The benefits of ordering branches by frequency of execution are:
- Readers can easily find the most common situations, increasing readability.
- Improve execution efficiency.
[Suggestion] For multi-value conditions of the same variable or expression, useswitch
Instead ofif
.
Example:
// good
switch (typeof variable) {
case 'object':
/ /...
break;
case 'number':
case 'boolean':
case 'string':
/ /...
break;
}
// bad
var type = typeof variable;
if (type === 'object') {
/ /...
}
else if (type === 'number' || type === 'boolean' || type === 'string') {
/ /...
}
Copy the code
[Suggestion] If the function or globalelse
There are no statements after the block that can be deletedelse
.
Example:
// good
function getName() {
if (name) {
return name;
}
return 'unnamed';
}
// bad
function getName() {
if (name) {
return name;
}
else {
return 'unnamed'; }}Copy the code
3.3 cycle
Do not include function expressions in the body of the loop. Extract the functions out of the loop beforehand.
Explanation:
The function expression in the loop body will generate a number of function objects during operation.
Example:
// good
function clicker() {
/ /...
}
for (var i = 0, len = elements.length; i < len; i++) {
var element = elements[i];
addListener(element, 'click', clicker);
}
// bad
for (var i = 0, len = elements.length; i < len; i++) {
var element = elements[i];
addListener(element, 'click'.function () {});
}
Copy the code
[Suggestion] Use variable caching outside the loop for constant values that are used multiple times within the loop.
Example:
// good
var width = wrap.offsetWidth + 'px';
for (var i = 0, len = elements.length; i < len; i++) {
var element = elements[i];
element.style.width = width;
/ /...
}
// bad
for (var i = 0, len = elements.length; i < len; i++) {
var element = elements[i];
element.style.width = wrap.offsetWidth + 'px';
/ /...
}
Copy the code
[Suggestion] Perform traversal and cache on ordered collectionslength
.
Explanation:
Although modern browsers cache array lengths, for some host objects and older browser array objects, the number of elements is dynamically counted each time length is accessed. Caching length can effectively improve program performance.
Example:
for (var i = 0, len = elements.length; i < len; i++) {
var element = elements[i];
/ /...
}
Copy the code
[Suggestion] Use reverse order traversal to perform an ordinary-independent traversal of an ordered set.
Explanation:
Reverse traversal can save variables, code optimization.
Example:
var len = elements.length;
while (len--) {
var element = elements[len];
/ /...
}
Copy the code
3.4 type
3.4.1 Type detection
[Suggestion] Type check is preferredtypeof
. Object type detectioninstanceof
.null
或 undefined
Detection use of== null
.
Example:
// string
typeof variable === 'string'
// number
typeof variable === 'number'
// boolean
typeof variable === 'boolean'
// Function
typeof variable === 'function'
// Object
typeof variable === 'object'
// RegExp
variable instanceof RegExp
// Array
variable instanceof Array
// null
variable === null
// null or undefined
variable == null
// undefined
typeof variable === 'undefined'
Copy the code
3.4.2 Type Conversion
[Suggestion] Convert tostring
When using+ ' '
.
Example:
// good
num + ' ';
// bad
new String(num);
num.toString();
String(num);
Copy the code
[Suggestion] Convert tonumber
“, usually used+
.
Example:
// good
+str;
// bad
Number(str);
Copy the code
[suggestion]string
Converted tonumber
, is used when the end of the string to be converted contains non-numbers and is expected to be ignoredparseInt
.
Example:
var width = '200px';
parseInt(width, 10);
Copy the code
[Mandatory] UseparseInt
, the base must be specified.
Example:
// good
parseInt(str, 10);
// bad
parseInt(str);
Copy the code
[Suggestion] Convert toboolean
When using!!!!!
.
Example:
var num = 3.14; !!!!! num;Copy the code
[suggestion]number
Get rid of the decimal point, useMath.floor
/ Math.round
/ Math.ceil
And don’t useparseInt
.
Example:
// good
var num = 3.14;
Math.ceil(num);
// bad
var num = 3.14;
parseInt(num, 10);
Copy the code
3.5 the string
[Mandatory] Use single quotation marks at the beginning and end of a string'
.
Explanation:
- You do not need to hold down to enter single quotes
shift
To facilitate input. - In practice, strings are often used to concatenate HTML. You don’t need to escape to include double quotes in HTML.
Example:
var str = 'I'm a string';
var html = '
Concatenate HTML without double quotes to escape
';
Copy the code
[Recommended] UseAn array of
或 +
Concatenate string.
Explanation:
- use
+
Concatenated strings. If the concatenated string is all StringLiteral, the compression tool can optimize it for automatic merging. Therefore, static strings are recommended+
Joining together. - In modern browsers, use
+
Concatenate strings, which performs better than arrays. - If you need to accommodate older browsers, use array concatenation strings.
Example:
// Concatenate strings with arrays
var str = [
// It is recommended to start with a line break and indent the first string to align the code for easy reading.
'<ul>'.' first term '.' second term '.'</ul>'
].join(' ');
// Concatenate strings with '+'
var str2 = ' ' // It is recommended that the first string be an empty string and the second line start with indentation to align the code for easy reading
+ '<ul>',
+ ' first term ',
+ ' second term ',
+ '</ul>';
Copy the code
[Suggestion] Use string concatenation to generate HTML. Escape the HTML properly according to the context.
Explanation:
Concatenated strings in JavaScript that will eventually be output to a page need to be properly escaped to prevent security vulnerabilities. The following example code is a scenario description and cannot be run directly.
Example:
/ / HTML escaped
var str = '<p>' + htmlEncode(content) + '</p>';
/ / HTML escaped
var str = '<input type="text" value="' + htmlEncode(value) + '" >';
/ / URL escaped
var str = ' + htmlEncode(urlEncode(value)) + '">link</a>';
// JavaScript string escape + HTML escape
var str = '<button onclick="check(\'' + htmlEncode(strLiteral(name)) + '\') "> submit < / button > ';
Copy the code
[Suggestion] Choose a template engine for complex data to view string conversion process.
Explanation:
Using a template engine has the following benefits:
- Focus on data in the development process and maintain the process of view generation by another layer, making the logical structure of the program clearer.
- A good templating engine can achieve better performance than manual concatenation of strings through template compilation techniques and high-quality compilation products.
- The template engine can conveniently escape dynamic data. Some template engines escape HTML by default, which is safer.
- ArtTemplate: Small size, high performance in all environments, flexible syntax.
- Dot.js: small size, high performance in modern browsers, flexible syntax.
- Etpl: Small size, high performance in all environments, high template reuse, flexible syntax.
- Handlebars: Large size, high performance and scalability in all environments.
- Hogon: Small size, high performance in modern browsers.
- Nunjucks: Large size, average performance, high template reuse.
3.6 object
Enforce the use of object literals{}
Create a newObject
.
Example:
// good
var obj = {};
// bad
var obj = new Object(a);Copy the code
[Suggestion] When an object is created, if all of an objectattribute
You are advised not to add quotation marksattribute
No quotes are added.
Example:
var info = {
name: 'someone'.age: 28
};
Copy the code
[Suggestion] Object creation if anyattribute
If quotation marks are required, allattribute
Suggest to add'
.
Explanation:
If attributes do not conform to the form of Identifier and NumberLiteral, they need to be supplied as StringLiteral.
Example:
// good
var info = {
'name': 'someone'.'age': 28.'more-info': '... '
};
// bad
var info = {
name: 'someone'.age: 28.'more-info': '... '
};
Copy the code
It is not allowed to modify or extend any of the native and host object stereotypes.
Example:
// The following behavior is strictly prohibited
String.prototype.trim = function () {};Copy the code
[Suggestion] Use this parameter when accessing properties.
.
Explanation:
Attribute names that meet the Identifier requirement can be accessed through., otherwise only through [expr].
For objects declared in JavaScript, attribute naming is done using Camel nomenclature, using. To make access clear and concise. Some special attributes, such as JSON from the back end, may be named in an unusual way and can be accessed through [expr].
Example:
info.age;
info['more-info'];
Copy the code
[suggestion]for in
Is used when traversing an objecthasOwnProperty
Filter out attributes in the stereotype.
Example:
var newInfo = {};
for (var key in info) {
if(info.hasOwnProperty(key)) { newInfo[key] = info[key]; }}Copy the code
3.7 an array
Use array literals[]
Creates a new array, unless you want to create an array of the specified length.
Example:
// good
var arr = [];
// bad
var arr = new Array(a);Copy the code
[Mandatory] The traversal number group is not usedfor in
.
Explanation:
Array objects may have attributes other than numbers, in which case for in will not get the correct result.
Example:
var arr = ['a'.'b'.'c'];
// This is for demonstration only. In practice, the Object type should be used
arr.other = 'other things';
// The correct way to traverse
for (var i = 0, len = arr.length; i < len; i++) {
console.log(i);
}
// Error traversal
for (var i in arr) {
console.log(i);
}
Copy the code
[Suggestion] Do not implement the array sorting function for performance reasons, and try to use arrayssort
Methods.
Explanation:
The conventional sort algorithm implemented by ourselves is no better than the default sort method for arrays in terms of performance. There are two scenarios where you can sort by yourself:
- Stable sorting algorithm is needed to achieve strictly consistent sorting results.
- Distinctive data characteristics, suitable for the use of bucket row.
[Suggestion] Empty the array.length = 0
.
3.8 the function
3.8.1 Function length
[Suggestion] The length of a function should be controlled in50
Line within.
Explanation:
Mixing too many lUs into one large function is difficult to maintain. A clear and understandable function should complete a single logical unit. Complex operations should be further abstracted to represent the flow through function calls.
Indivisible logic such as specific algorithms allows exceptions.
Example:
function syncViewStateOnUserAction() {
if (x.checked) {
y.checked = true;
z.value = ' ';
}
else {
y.checked = false;
}
if (a.value) {
warning.innerText = ' ';
submitButton.disabled = false;
}
else {
warning.innerText = 'Please enter it';
submitButton.disabled = true; }}// Reading this function directly makes it difficult to understand the main line logic, so here is a more reasonable way to express it:
function syncViewStateOnUserAction() {
syncXStateToView();
checkAAvailability();
}
function syncXStateToView() {
y.checked = x.checked;
if (x.checked) {
z.value = ' '; }}function checkAAvailability() {
if (a.value) {
clearWarnignForA();
}
else{ displayWarningForAMissing(); }}Copy the code
3.8.2 Parameter design
[Suggestion] control the parameters of a function in6
A less than.
Explanation:
In addition to variable length parameters, you are advised to limit the number of parameters with different logical meanings to six. Too many parameters increase maintenance difficulty.
In some cases, such as using THE AMD Loader require to load multiple modules, the callback may have many parameters, so the number of function parameters is not mandatory.
[Recommendation] Passedoptions
Parameters pass non-data input parameters.
Explanation:
Some function parameters are not used as input to the algorithm, but are used to determine some branch conditions of the algorithm. It is recommended that such parameters be passed through an options parameter.
The following function:
/** ** Removes an element **@param {Node} Element The element to be removed@param {boolean} Whether removeEventListeners remove all events registered to the element at the same time */
function removeElement(element, removeEventListeners) {
element.parent.removeChild(element);
if(removeEventListeners) { element.clearEventListeners(); }}Copy the code
Can be converted to the following signature:
/** ** Removes an element **@param {Node} Element The element to be removed@param {Object} Options Logical configuration *@param {boolean} Options. Whether removeEventListeners also removes all registered on the element events * /
function removeElement(element, options) {
element.parent.removeChild(element);
if(options.removeEventListeners) { element.clearEventListeners(); }}Copy the code
This model has several significant advantages:
boolean
Type configuration items have names, which make it easier to understand the logical meaning of their expression from the calling code.- If the number of configuration items increases, you do not need to endlessly increase the number of parameters
removeElement(element, true, false, false, 3)
Such unintelligible call code. - When some configuration parameters are optional, the multiple parameter form is very difficult to handle overloaded logic, and using an options object only needs to determine whether the property exists, simplifying the implementation.
3.8.3 closure
[Suggestion] Set large objects inside closures to when appropriatenull
.
Explanation:
In JavaScript, closures can be used without special keywords, and a function can arbitrarily access variables outside its defined scope. It is important to note that the scope of a function is static, that is, determined at definition time and has nothing to do with when or how it is called.
Closures prevent garbage collection of some variables and, for older JavaScript engines, may result in all external variables not being collected.
First, a relatively clear conclusion is that the following will affect the collection of variables inside closures:
- Whether the variable is used in a nested function.
- Is there a direct call to eval in the nested function?
- Whether the with expression is used.
Chakra, V8, and SpiderMonkey will have different and similar recycling strategies due to these factors, while jscript.dll and Carakan are not optimized at all. All variable bindings in the entire LexicalEnvironment are retained completely, causing some memory consumption.
Since Chakra, V8, and SpiderMonkey engines that have a recycling optimization strategy for variables inside closures behave similarly, it can be summarized as follows when a function fn is returned:
- iffn 的
[[Scope]]
ObjectEnvironment (with expression generates ObjectEnvironment, function and catch expression generates DeclarativeEnvironment),- If you have a V8 engine, exit the whole process.
- If it is SpiderMonkey, the ObjectEnvironment’s outer LexicalEnvironment is processed.
- Get all objects of type Function in the current LexicalEnvironment. For each Function object, analyze its FunctionBody:
- If the FunctionBody contains a direct call to eval, exit the process.
- Otherwise you get all the identifiers.
- For each Identifier, set it to name and look for a binding named name from the LexicalEnvironment according to the rules for finding variable references.
- The binding to addnotSwapProperty, whose value is
true
.
- Check each variable binding in the current LexicalEnvironment, if it has onenotSwapProperty and the value is
true
, then:- If the engine is V8, delete the binding.
- If it is SpiderMonkey, set the value of this binding to
undefined
, will be deletednotSwapProperties.
For the Chakra engine, it is not clear whether it will be in V8 mode or SpiderMonkey mode.
If you have very large objects that are expected to be executed in an older engine, be careful when using closures to make empty references to objects that are not needed by the closure.
[Recommended] UseIIFE
avoidLift effect
.
Explanation:
When referring to an external variable of a function whose value is determined at runtime rather than defined, the most typical scenario is as follows:
var tasks = [];
for (var i = 0; i < 5; i++) {
tasks[tasks.length] = function () {
console.log('Current cursor is at ' + i);
};
}
var len = tasks.length;
while (len--) {
tasks[len]();
}
Copy the code
All of the above code executing the functions in tasks would print Current Cursor is at 5, which is often not as expected.
This phenomenon is called the Lift effect. The solution is to unbind variables by adding an extra layer of closure functions that pass the required external variables as arguments:
var tasks = [];
for (var i = 0; i < 5; i++) {
// Notice that there is an extra layer of closures
tasks[tasks.length] = (function (i) {
return function () {
console.log('Current cursor is at ' + i);
};
})(i);
}
var len = tasks.length;
while (len--) {
tasks[len]();
}
Copy the code
3.8.4 empty function
[Suggestion] Do not use empty functionsnew Function()
In the form.
Example:
var emptyFunction = function () {};
Copy the code
[Suggestion] For scenarios with high performance requirements, it is recommended to have an empty function constant for multiple use and sharing.
Example:
var EMPTY_FUNCTION = function () {};
function MyClass() {
}
MyClass.prototype.abstractMethod = EMPTY_FUNCTION;
MyClass.prototype.hooks.before = EMPTY_FUNCTION;
MyClass.prototype.hooks.after = EMPTY_FUNCTION;
Copy the code
3.9 Object-oriented
Class inheritance scheme that needs to be fixed when implementedconstructor
.
Explanation:
Class inheritance schemes using other libraries typically do constructor corrections. If you implement your own class inheritance scheme, you need to make a constructor correction.
Example:
/** * Build inheritance relationships between classes **@param {Function} SubClass subClass function *@param {Function} SuperClass superClass function */
function inherits(subClass, superClass) {
var F = new Function(a); F.prototype = superClass.prototype; subClass.prototype =new F();
subClass.prototype.constructor = subClass;
}
Copy the code
[Suggestion] Ensure that the class is declaredconstructor
Is correct.
Example:
function Animal(name) {
this.name = name;
}
Constructor needs to be fixed when direct prototype equals the object
Animal.prototype = {
constructor: Animal,
jump: function () {
alert('animal ' + this.name + ' jump'); }};// Extend prototype this way without bothering with constructor
Animal.prototype.jump = function () {
alert('animal ' + this.name + ' jump');
};
Copy the code
[Suggestion] Properties are declared in constructors and methods are declared in stereotypes.
Explanation:
Members of the prototype object are shared by all instances, saving memory. So when coding, we should follow the principle that prototype objects contain members that the program will not modify, such as method functions or configuration items.
function TextNode(value, engine) {
this.value = value;
this.engine = engine;
}
TextNode.prototype.clone = function () {
return this;
};
Copy the code
[Mandatory] User-defined eventThe event name
It must be all lowercase.
Explanation:
In browser environments where JavaScript is widely used, most DOM event names are all lowercase. To follow the custom of most JavaScript developers, the event name should also be all lowercase when designing custom events.
Only one custom event can be configuredevent
Parameters. If an event needs to convey a lot of information, the event object should be carefully designed.
Explanation:
The benefits of an event object are:
- Order independence prevents event listeners from having to remember the order of arguments.
- Each event information can be provided or not provided as required, more freely.
- The extension is convenient, and in the future, when adding event information, there is no need to worry about breaking the listener parameter form and not being backward compatible.
[Suggestion] Disable the default behavior when designing custom events.
Explanation:
There are two common ways to disable default behavior:
- Event listener function
return false
. - The event object contains methods that disable the default behavior, such as
preventDefault
.
3.10 Dynamic Characteristics
3.10.1 eval
Avoid using directeval
Function.
Explanation:
Direct eval refers to a call method that calls eval functionally. The scope of the code executing the direct EVAL call is local and should be avoided.
If direct EVAL is needed in special cases, detailed comments should be made in the Code to explain why direct EVAL must be used. Other methods of dynamic Code execution should not be used, and Code Review should be conducted by other senior engineers.
[Suggestion] Avoid using iteval
Function.
3.10.2 Dynamic code execution
[Recommended] Usenew Function
Execute dynamic code.
Explanation:
The scope of the Function generated by new Function is global and does not affect the current local scope. If dynamic code execution is required, new Function is recommended.
Example:
var handler = new Function('x'.'y'.'return x + y; ');
var result = handler($('#x').val(), $('#y').val());
Copy the code
3.10.3 with
[Suggestion] Do not use itwith
.
Explanation:
Using with may increase code complexity and make it difficult to read and manage. It also has an impact on performance. Most scenarios that use with can be better served by other alternatives. So, try not to use with.
3.10.4 delete
[Suggest] reducedelete
The use of.
Explanation:
If there are no specific requirements, reduce or avoid the use of DELETE. The use of DELETE can break some of the performance optimizations of JavaScript engines.
[Suggestion] Handledelete
Possible exceptions.
Explanation:
For objects that need to be traversed and whose value is NULL is considered to have business logical meaning, the DELETE operation must be used to remove an attribute.
When delete is used in strict mode or IE, exceptions are thrown for attributes that cannot be deleted, so it is recommended to add a try-catch block when you are unsure whether an attribute can be deleted.
Example:
try {
delete o.x;
}
catch (deleteError) {
o.x = null;
}
Copy the code
3.10.5 Object Properties
Suggestion: Do not modify external objects.
Explanation:
JavaScript can add, delete, and modify attributes when an object is not sealed or freeze due to the dynamic nature of the scripting language.
But arbitrarily making changes to objects you don’t control can easily cause code to break in unexpected circumstances. Therefore, well-designed components and functions should avoid modifications to objects passed in from outside.
The selectNode method of the following code modifies the datasource object passed in from the outside. If the datasource is used in another context (such as another Tree instance), it will cause state confusion.
function Tree(datasource) {
this.datasource = datasource;
}
Tree.prototype.selectNode = function (id) {
// Find the node object from the datasource
var node = this.findNode(id);
if (node) {
node.selected = true;
this.flushView(); }};Copy the code
For this type of scenario, you need to use additional objects to maintain the selected state of the node, using a selectedNodeIndex object that is controlled by itself and does not interact with the outside world.
function Tree(datasource) {
this.datasource = datasource;
this.selectedNodeIndex = {};
}
Tree.prototype.selectNode = function (id) {
// Find the node object from the datasource
var node = this.findNode(id);
if (node) {
this.selectedNodeIndex[id] = true;
this.flushView(); }};Copy the code
In addition, deepClone and other methods can be used to separate self-maintained objects from external incoming objects, ensuring that they do not affect each other.
[Suggestion] Design with strong type.
Explanation:
- If a property is designed to be
boolean
Type, do not use it1
或0
As its value. Identifying attributes, such as strict code size requirements, can be designed from the outsetnumber
Type and will0
As a negative value. - The value fetched from the DOM is usually
string
Type if there is an object or function whose receive type isnumber
Type, rather than expecting an object or function to handle multiple types of values.
4 Browser Environment
4.1 modular
4.1.1 AMD
[Mandatory] UseAMD
As a module definition.
Explanation:
AMD is a community-approved form of module definition that offers multiple overloads and flexible usage, and most good libraries support AMD as a suitable specification.
At present, the more mature AMD Loader has:
- The official implementation requirejs
- Baidu’s own esl implementation
[Mandatory] Moduleid
Must meet standards.
Explanation:
The module ID must meet the following constraints:
- The type is string and is specified by
/
Split a series of terms. Such as:this/is/a/module
. - Term should comply with the [A-ZA-Z0-9_ -]+ rule.
- There should be no.js suffix.
- Keep it the same as the file path.
4.1.2 define
[Suggestion] Do not specify when defining modulesid
和 dependencies
.
Explanation:
In AMD’s design philosophy, module names are associated with the path, and anonymous modules are better for encapsulation and migration. Module dependencies should be referenced within the module definition via local require.
Therefore, it is recommended to define modules in the form of define(Factory).
Example:
define(
function (require) {});Copy the code
[Recommended] Usereturn
To return the module definition.
Explanation:
Using return reduces the number of arguments that factory accepts (no exports and Modules needed) and makes it easier to simply fake a Loader without AMD loaders.
Example:
define(
function (require) {
var exports = {};
// ...
return exports; });Copy the code
4.1.3 the require
[Force] In the global runtime environment,require
Have to beasync require
Formal invocation.
Explanation:
Modules are loaded asynchronously, and synchronous calls do not guarantee correct results.
Example:
// good
require(['foo'].function (foo) {});// bad
var foo = require('foo');
Copy the code
Only allowed in the module definitionlocal require
, not allowed to useglobal require
.
Explanation:
- Used in module definitions
global require
, is a kind of destruction of encapsulation. - In AMD,
global require
It can be renamed. And Loader doesn’t even have globalrequire
Instead, use the Loader nameglobal require
. Module definitions should not depend on the Loader being used.
[mandatory] Package when implemented, the internal modulerequire
You must use therelative id
.
Explanation:
The name defined by the developer does not represent the name used by the consumer for any third-party library, framework, or package that may be reused in a publish-import format. So don’t make any assumptions about names. In the implementation source code, require other modules of its own use relative ID.
Example:
define(
function (require) {
var util = require('./util'); });Copy the code
[Suggestion] dependency modules that will not be called infactory
Unity at the beginningrequire
.
Explanation:
Some modules are dependent modules that are not called directly in a module implementation, most typically external content introduced by plugins such as CSS/JS/TPL. This kind of content is recommended to be referenced uniformly at the beginning of the module definition.
Example:
define(
function (require) {
require('css! foo.css');
require('tpl! bar.tpl.html');
// ...});Copy the code
4.2 the DOM
4.2.1 Element Acquisition
[Suggestion] For a single element, use it whenever possibledocument.getElementById
Get, avoid usingdocument.all
.
[Suggestion] For a collection of multiple elements, use it if possiblecontext.getElementsByTagName
To obtain. Among themcontext
Can I do fordocument
Or other elements. The specifiedtagName
Parameters for*
You can get all the children.
[Suggestion] Cache the set length as much as possible when traversing the set of elements. If you need to manipulate the same collection more than once, you should turn the collection into an array.
Explanation:
The result of a natively fetched set of elements does not refer directly to a DOM element, but rather reads from the index, so changes to the DOM structure are reflected in the result in real time.
Example:
<div></div>
<span></span>
<script>
var elements = document.getElementsByTagName(The '*');
// display as DIV
alert(elements[0].tagName);
var div = elements[0];
var p = document.createElement('p');
docpment.body.insertBefore(p, div);
// display P
alert(elements[0].tagName);
</script>
Copy the code
Suggestion: Obtain the direct child elements of an elementchildren
. Avoid the use ofchildNodes
Unless you expect nodes that need to contain text, comments, and attribute types.
4.2.2 Style Acquisition
[Suggestion] Use this parameter when obtaining the actual style information of an elementgetComputedStyle
或 currentStyle
.
Explanation:
With style you can only get styles defined inline or set directly through JavaScript. Element styles set by CSS class cannot be obtained directly by style.
4.2.3 Style Settings
If possible, change the style of an element by adding a predefined className to the element, avoiding direct manipulation of the style setting.
[Force] When styling an element with a style object, it is not allowed to omit units for attributes with non-zero unit values.
Explanation:
With the exception of Internet Explorer, standard browsers ignore non-standard attribute values, leading to compatibility issues.
4.2.4 DOM manipulation
[Suggestion] OperationDOM
Minimize the number of pagesreflow
.
Explanation:
Page reflow is a time-consuming activity that can easily lead to performance bottlenecks. The following scenarios trigger reflow in the browser:
- Add, modify (content), and delete DOM elements.
- Apply new styles or modify any attributes that affect the layout of elements.
- Resize browser window and scroll page.
- Read the elements of certain attributes (offsetLeft and offsetTop, offsetHeight, offsetWidth, scrollTop/Left/Width/Height, clientTop/Left/Width/Height, getCompu TedStyle (), currentStyle(in IE)).
[Recommendation] minimizeDOM
Operation.
Explanation:
DOM manipulation is also a time-consuming operation, and reducing DOM manipulation can help improve performance. As a simple example, build a list. We can do this in two ways:
- CreateElement in the body of the loop and append to the parent element.
- Concatenate the HTML string in the body of the loop, and write the innerHTML of the parent element after the loop ends.
The first approach looks standard, but the DOM is manipulated every time the loop is used, and performance is extremely low. The second approach is recommended here.
4.2.5 DOM events
[Suggestion] Preferentially useaddEventListener / attachEvent
Bind events to avoid directly in HTML attributes or DOMexpando
Property binding event handling.
Explanation:
The expando attribute binds events to easily overwrite each other.
[Recommended] UseaddEventListener
Is used for the third parameterfalse
.
Explanation:
The addEventListener in standard browsers can specify two time-triggered models with a third parameter: bubbling and capturing. IE attachEvent supports only bubbling events. So for consistency, the third argument to addEventListener is usually false.
[Recommendation] Without the support of an automatic event management framework, you should hold a reference to the listener function and remove the added listener when appropriate (element release, page unload, etc.).
Reference: Javascript coding specification