Source of learning

High Performance JavaScript- Chinese Version (for learning only)

Data access

Data location

One of the classic problems in computer science is to obtain the best read and write performance by changing where data is stored. The location of data is related to the speed of data retrieval during code execution. In JavaScript, this problem is relatively simple because there are only a few storage schemes to choose from. However, as with other programming languages, where the data is stored greatly affects how fast it can be read. There are four basic data access locations in JavaScript.

  1. Literals literals represent themselves and are not stored in a specific location. Literals in JavaScript are: strings, numbers, booleans, objects, arrays, functions, regular expressions, and the special null and undefined values.
  2. Local variable developers define data storage units using the keyword var.
  3. Array elements are stored inside JavaScript array objects, indexed by numbers.
  4. Object members are stored inside JavaScript objects, indexed by strings.

The amount of time it takes to access data in different storage locations varies from browser to browser. Reading literals and local variables takes the least time and the highest performance, as shown in the figure below.

Identifier resolution

Identifier resolution comes at a cost, and virtually no computer operation can be performed without a performance overhead. The deeper an identifier is in the scope chain of the execution environment, the slower it reads and writes. Thus, reading and writing local variables in a function is always the fastest, while reading and writing global variables is usually the slowest (optimizing the JavaScript engine can improve in some cases).

The global variable always exists at the end of the execution environment scope chain, so it is also farthest.


Objects in JavaScript are based on prototypes, which are the basis for other objects

  • Literals and local variables are the fastest to access, whereas array elements and object members are relatively slow to access. Because local variables exist at the start of the scope chain, accessing local variables is faster than accessing cross-scope variables. The deeper a variable is in the scope chain, the longer it takes to access. Since global variables are always at the end of the scope chain, they are also the slowest to access.
  • Avoid using the with statement because it changes the execution environment scope chain. Similarly, the catch clause in a try-catch statement has the same effect and should be used with care.
  • Nested object members can significantly affect performance, so use them sparingly.
  • The deeper a property or method is in the prototype chain, the slower it is to access it.
  • In general, you can improve JavaScript performance by storing common object members, array elements, and cross-domain variables in local variables, which are faster to access.

A collection of objects

Accessing a collection is less efficient than accessing an array. Consider turning a collection into an array

function toArray() {
	var len = coll.length, a = [];
	for (var i = 0; i < len; i++) {
		a[i] = coll[i]
	}
}
Copy the code

The prototype

  • JavaScript objects are prototype-based

  • Stereotypes are the basis for other objects

Objects can have two types of member:

Instance member (also known as own member) 2. Prototype memberCopy the code

Example:

var book = {
   title: 'hello',
   na: 'world'
}
Copy the code

Book is an object in which book.title and book.tostring () exist.

  • Book. title belongs to the instance object
  • Book.tostring () belongs to the inherited prototype object

Object member resolution will look for the instance object first, if not found, will look for the inherited prototype object

The hasOwnProperty() method determines whether an object contains a specific instance object

book.hasOwnProperty('title')   // true
book.hasOwnProperty('toString')   //false
Copy the code

If you want to determine whether an object contains a specific attribute, you can use the IN operator, which searches for both instances and stereotypes:

console.log('title' in book)  // true
console.log('toString' in book)  // true
Copy the code

Prototype chain

By default, all objects are instances of Object

Instanceof: The instanceof operator is used to check whether the constructor’s prototype property appears on the prototype chain of an instance object

Example:

function books(title, na){
    this.title = title;
    this.na = na;
}
books.prototype.say = function() {
    console.info(this.title, this.na)
}
var b1 = new books('111111', '22');
console.log(b1 instanceof books)  // true
console.log(b1.__proto__)
console.log(books.prototype)
Copy the code

B1’s __proto__ is the same as books’ prototype

Members of the nested

Since object members may contain other members, nested members cause the JavaScript engine to search for all object members every time it encounters a dot operator, such as book.title

The deeper the object members are nested, the slower the read

Performs the location. The href than window. The location. The href window. The faster the location. The href than window. The location. The href. ToString ()

Caches object member values

Because all similar performance problems are related to object members, they should be avoided whenever possible.

There is no need to read more than one object member in the same function

You can save values in local variables to reduce lookups

Example:

function hasEitherClass(element, className1, className2) {
      for(var i = 0; i < 1000; i++) {
           var k = element.className;
      }
      return element.className == className1 || element.className == className2;
} 
Copy the code
function hasEitherClass2(element, className1, className2) {
        var currentClassName = element.className;
        for(var i = 0; i < 1000; i++) {
            var k = currentClassName;
        }                                
        return currentClassName == className1 || currentClassName == className2;
}
Copy the code

Using console.time, hasEitherClass2 ran faster than hasEitherClass


section

Can be optimized when writing code at ordinary times ① :

Document is a global object. The process of searching for this variable must traverse the entire scope chain until it is finally found in the global variable object.

The performance impact can be reduced by:

  • Start by storing a reference to a global variable in a local variable
  • This local variable is then used instead of the global variable. This reduces the number of times global variables are accessed because local variables are accessed faster.
  • Example:var doc = document; var bd = doc.body; var a = doc.getElementById("a");

Points that can be optimized when writing code at ordinary times ② :

You can use location.href instead of window.location.href