Reference Book: JavaScript Advanced Programming 3rd Edition

Refer to the blog: www.jianshu.com/p/f8c7c5502…

The execution environment

The execution environment is one of the most important concepts in Javascript. The execution environment defines other data that variables or functions have access to, and determines their respective behavior. Each execution environment has a variable object associated with it, and all variables and functions defined in the environment are stored in this object

The global execution environment is typically a Window object, so all global variables and functions are created as properties and methods of the Window object.

After all code in an execution environment is executed, the environment is destroyed, along with all variables and function definitions stored in it.

The global execution environment is not destroyed until the application exits —-, for example by closing a web page or browser —-.

Each function has its own execution environment. When the execution stream enters a function, the function’s environment is pushed onto an environment stack. After the function is executed, the stack pops up its environment, returning control to the previous execution environment.

The scope chain

When code is executed in an environment, a scope chain of variable objects is created. The purpose of a scope chain is to ensure orderly access to all variables and functions that the execution environment has access to, the front end of the scope chain. Is always the variable object of the environment in which the code is currently executing.

The next variable object in the scope chain comes from the containment (external object), and the next variable object comes from the next containment object, and so on, all the way to the global execution environment.

var color = "blue";

function changeColor() {
	if(color === "blue") {
		color = "red";
	} else {
		color = "blue"
	}
}

changeColor();

alert("Color is now " + color); // Color is now red
Copy the code

prototype

For reference types in ECMAScript, Prototype is the real place to hold all of their instance methods. The Prototype attribute is extremely important when creating custom reference types and implementing inheritance.

The Prototype attribute is not enumerable and therefore cannot be found with for-in.

Call () and the apply ()

Both are used to call a function in a particular scope and are actually equivalent to setting the value of the this object in the function body.

The **call()** method takes the first argument to the scope in which the function is run, which is the value of this. The rest of the arguments are passed directly to the function.

The **apply()** method takes the first argument to this value and the second argument to an instance of Array, which can also be a arguments object.

Change the four ways this points to

  1. call()

  2. apply()

  3. bind()

  4. Store this in a variable

What does the new() method do

  1. Create a new object

  2. Points the __proto__ of the new object to the protpType object of the constructor

  3. Assign the constructor’s scope to the new object (that is, this refers to the new object)

  4. Execute the code in the constructor (add attributes to this new object)

  5. Return a new object

Prototype chain

Prototype chain is one of the main methods to implement inheritance. The basic idea is to use stereotypes to make one reference type inherit the properties and methods of another.

Each constructor has a prototype object, which contains a pointer to the constructor, and each instance contains an internal pointer to the prototype object.

Only the constructor has the prototype object, prototype, which is an object

The stereotype object has a constructor property, which points to the constructor itself, and only the stereotype object has a constructor property.

All objects have a _proto_ attribute, which is also an object.

// constructor
function Student(name, age, sex){
	this.name = name;
	this.age = age;
	this.sex = sex;
	SayHi = sayHi; sayHi = sayHi; sayHi = sayHi
	this.sayHi = function() {
		console.log('Hello, I am.' + this.name); }}var s1 = new Student('lilei'.18.'male');
var s2 = new Student('hmm'.18.'woman');

s1.sayHi();
s2.sayHi();

console.log(s1.sayHi === s2.sayHi);// false Two separate sayHi methods
Copy the code
// constructor
function Student(name, age, sex){
    this.name = name;
    this.age = age;
    this.sex = sex;
}

Student.prototype.sayHi = function() {
    console.log('Hello, I am.' + this.name);
}

// Use the Student constructor to create an object that accesses a member of Student. Prototype
var s1 = new Student('lilei'.18.'male');var s2 = new Student('hmm'.18.'woman');

s1.sayHi();
s2.sayHi();

console.log(s1.sayHi === s2.sayHi); // true
Copy the code
alert(s1.__proto__ === Student.prototype) // true
alert(Student.prototype.__proto__ === Object.prototype) // true
alert(Object.prototype.__proto__ === null) // true
alert(Student.prototype.constructor === Student) // true
Copy the code

closure

A closure is a function that has access to variables and arguments in the scope of another function, even after its outer function has been returned (end-of-life). A common way to create closures is to create another function inside one function.

Advantages of closures

Variables can be reused without contaminating them.

Global variables can be reused, but can easily pollute variables. Local variables can only be valid in the local scope, can not be used repeatedly, will not cause variable pollution. Closure results combine the best of global and local variables.

Can be used to define private properties and private methods.

function creFunc() {
    var result = new Array(a);for(var i=0; i<10; i++){ result[i] =function() {
            return i;
        };
    }
    return result;
}
Copy the code
function creFuncs() {
	var result = new Array(a);for(var i=0; i<10; i++){ result[i]=function(num){
            return function(){
                return num;
            }
        }(i);
    }
    return result;
}
Copy the code

Disadvantages of closures

It takes up more memory than normal functions and results in poorer web page performance. If a closure holds an HTML element in its scope chain, that means that element cannot be destroyed.

function asHand() {
    var element = document.getElementById("someElement");
    element.onclick = function() {
        alert(element.id)
    };
}
Copy the code

The above code creates a closure that acts as an Element event handler, which in turn creates a circular reference. The anonymous function holds a reference to asHand’s live object, thus making it impossible to reduce the number of element references. As long as anonymous functions exist, Element has at least one reference, so its memory is never reclaimed.

function asHand() {
    var element = document.getElementById("someElement");
    var id = element.id;
    
    element.onclick = function(){
        alert(id);
    };
    element = null;
}
Copy the code

Eliminate circular references by storing a copy of element.id in a variable and referencing that variable in a closure. In addition, closures raise the entire live object that contains the function, including Element in the code above. Even if the closure does not reference Element directly, a reference is still stored in the live object that contains the function. Therefore, you need to set the Element variable to NULL so that the DOM object can be dereferenced, reducing the number of references to the DOM object, and ensuring that its memory is properly reclaimed.

Closure usage scenarios

1. Replace global variables with small scope

2. Privileged methods to access private variables

3. SetTimeout () calls the function

4. The timer clear itself

Closure common interview analysis

for (var i=0; i<3; i++){ setTimeout(function(){
        console.log(i);
    },0);
    console.log(i);
}
Copy the code
0, 1, 2, 3, 3, 3Copy the code
for (var i=0; i<3; i++){ setTimeout(function(){
        console.log(i++);
    },0);
    console.log(i);
}
Copy the code
0, 1, 2, 3, 4, 5Copy the code
for (var i=0; i<3; i++){ setTimeout((function(){
        return function(){
            console.log(i++);
        };
    })(i),0);
    console.log(i);
}
Copy the code
0, 1, 2, 3, 4, 5Copy the code
console.log('start');
setTimeout((function(){
	console.log('Execute immediately');
	return function(){
		console.log('setTimeout'); }; }) (),0);
console.log('end');
Copy the code
Start Executes end immediatelysetTimeout
Copy the code

this

The function this points to whoever the event triggers in the event calling environment

Global: Window Node environment: module.exports

Function of the internal

  1. This ultimately refers to the object on which it was called

    (1) Ordinary function direct call and window call

    (2) Object function call directly and window call

  2. Functions are contained by multiple layers of objects, and if a function is called by the outermost object, this refers only to the object at the level above it

    (1) The this pointer to a function in a multi-layer object

    (2) Object this points to

  3. If the constructor has a return, if the return is an object, this refers to the returned object, and if it is not, this refers to the same rule. In this case, null is special and keeps the same rule.

The arrow function this points to

The arrow function itself does not have this and arguments. In the arrow function this actually calls the upper scope defined by this, which is upper scope, since objects cannot form independent scopes.