JavaScript Advanced Content Notes: Prototype Chain, Inheritance, Execution Context, Scope Chain, Closure

Keywords: Javascript Attribute

Recently, in the system of learning JS deep content, and a little sorted out, as a memorandum and later review, here to share with you, I hope to help you. If there are any errors, please leave a message to correct them, tks.

To understand these problems, I will first look at them step by step, starting with a slightly shallow content, and then lead to these concepts.

This paper only uses examples to verify the results, and gives a brief explanation to give you some impression, because a single item needs a large space to explain.

1. Value Type-Reference Type

function show(x) {
    console.log(typeof(x)); // undefined
    console.log(typeof(10)); // number
    console.log(typeof('abc')); // string
    console.log(typeof(true)); // boolean

    console.log(typeof(function() {})); //function

    console.log(typeof([1, 'a', true])); //object
    console.log(typeof({
        a: 10,
        b: 20
    })); //object
    console.log(typeof(null)); //object
    console.log(typeof(new Number(10))); //object
}
show();

 

 

undefined, number, string, boolean are simple value types, not objects;
Functions, arrays, objects, null, and new Number(10) are all objects.
It is very simple to judge whether a variable is an object or not. The type of value type is typeof, and the type of reference type is instanceof.

2. Grammatical Sugar (Sugarcoat Grammar)

var obj = { a: 10, b: 20 };
var arr = [5, 'x', true];

Grammatical sugar is actually a "shortcut", the code above is an abbreviation, the complete writing is:

var obj = new Object();
obj.a=10;
obj.b=20;
 
var arr= new Array();
arr[0]=5;
arr[1]='x';
arr[2]=true;

  

3. Objects are created by functions, and functions are objects.

Method 1:

var fn = function() {
    alert(100);
};
fn.a = 10;
fn.b = function() {
    alert(123);
};
fn.c = {
    name: "Dian Orange Trade",
    year: 2016
};

FN is a function and a/b/c is an object created by fn.

Method 2:

var obj = { a: 10, b: 20 };
var arr = [5, 'x', true];
 
//Its essence is:
var obj = new Object();
obj.a = 10;
obj.b = 20;
 
var arr = new Array();
arr[0] = 5;
arr[1] = 'x';
arr[2] = true;
 
//and
console.log(typeof (Object)); // function
console.log(typeof (Array)); // function
 

 

4. Constructor

Only constructors have prototype attributes.
Usually our custom functions belong to constructors, so they all have this property.
Some of the built-in functions in the JS runtime environment are not constructors, such as alert and Math.sqrt, which do not have this property.
Note: Constructors are those functions that have an internal property [[Construct], through which objects can be created by new.

5. prototype and _proto type__

Each function has a prototype, or prototype.
Each object has an _proto_, which is an implicit prototype.
Only constructors have prototype attributes.
Object _proto_ points to the prototype of the function that created it.
Function prototypes are created by Object, and at the beginning of each custom function creation, there will be a prototype (how it was created is unknown!).

For example:

function Foo(){};
var foo = new Foo();
Foo.__proto__ === Function.prototype // Any function is constructed by Function Created, so any function's__proto__All point to Function Of prototype
foo.__proto__ === Foo.prototype // Object__proto__Pointing to the function that created it prototype
Foo.prototype.__proto__ === Object.prototype // If it is a custom function, its prototype.__proto__ point Object.prototype,Because of the custom function prototype Essentially, it's grammatical sugar. var obj = {} It's the same. It's all by. Object Establish.
Object.prototype.__proto__ === null // Object.prototype It's an object, too.__proto__yes null(This is an exceptional case. Keep in mind.
 
foo.prototype == undefined //Only function has prototype Attributes, foo Is the object
Object.prototype === (new Object()).__proto__ // As mentioned above, Object It's a function.(new Object())Is the object
Function.prototype.__proto__ === Object.prototype // Function It's a function. prototype Be being Object Create, so its Prototype.__proto__Point to Creation Object.prototype
Function.__proto__ === Function.prototype //Function It's also a function. A function is an object. There are also functions.__proto__Attributes. Since it is a function, then it must be by Function Establish. So—— Function It was created by itself.
Object.__proto__ === Function.prototype //Object It's a function, it's an object, it's a function.__proto__Pointing to the function that created it prototype

Reference resources:

http://www.cnblogs.com/wangfupeng1988/p/3978131.html
http://www.cnblogs.com/wangfupeng1988/p/3979290.html

6. instanceof principle

The first variable of the Instanceof operator is an object, temporarily called A; the second variable is generally a function, temporarily called B.
Instanceof's rule of judgment is:
Follow the _proto_ line of A. If the prototype of B is on this line, return true or false.

 

Such as:

function Foo(){}
var f1 = new Foo();
console.log(f1 instanceof Foo);    // true
console.log(f1 instanceof Object); // true

Analytical methods:
Route A of _proto_ of f1:

(1) f1.__proto__ === Foo.prototype
(2) Foo.prototype.__proto__ === Object.prototype
(3) Object.prototype.__proto__ === null //To the end

Conclusion:
Foo.prototype appears in F1 instance of Foo: A line (1)
Object.prototype appears in F1 instance of Object: Line A (2)


Reference resources:

http://www.cnblogs.com/wangfupeng1988/p/3979533.html

7. Prototype Chain

When accessing the attributes of an object, first look in the basic attributes, if not, then look up along the _proto_ chain, which is the prototype chain.
For example:

function Foo(){}
var f1 = new Foo();
f1.a = 2;
f1.b = 3;
Foo.prototype.b = 6;
Foo.prototype.c = 7;
 
console.log(f1.a); // 2,a yes f1 Basic attributes, direct access is no problem
console.log(f1.c); // 7,f1 Not in the basic attributes c,Up the prototype chain, f1.__proto__yes Foo.prototype,and Foo.prototype Yes c,Accessible.
console.log(f1.b); // 3,b yes f1 Basic attributes, direct access is no problem. can Foo.prototype One more b,But it will not show that this situation is called "attribute masking".

 

To determine whether an attribute is a basic attribute (also called instance attribute) or an attribute on a prototype chain (also called prototype attribute), hasOwnProperty is used, usually for (...) in... loop. For... in... Instance and prototype attributes are output.
Attribute list reference The attributes of instance attributes vs prototype vs static attributes
Such as:

var item;
for(item in f1){
    console.log(item); // a,b,c
}
 
for(item in f1){
    f1.hasOwnProperty(item) && console.log(item); // a,b
}

 

8. Inheritance

On the basis of prototype chains, inheritance is easy to understand. For example, in the prototype chain example, f1.hasOwnProperty is inherited from Object.prototype.
The process is as follows:

  • There is no hasOwn Property in the basic attributes of f1. Look up the prototype chain: f1. proto is Foo.prototype;
  • There is no hasOwn Property in Foo.prototype, so we continue to look up the prototype chain: Foo.prototype. prototype is Object.prototype;
  • Object.prototype has hasOwnProperty, which ends the lookup and allows access to hasOwnProperty.

Since Object.prototype is found in the prototype chain of all objects, all objects have Object.prototype methods. This is called "inheritance".
In addition, each function has call, apply method, and length, arguments, caller and other attributes are inherited.

9. Execution context/execution context environment

Definition 1: js declares ahead, assigns or assigns an initial value (undefined) before executing a piece of code. So in the same code segment, you can access it first and then define it, which is the "execution context".
Definition 2: Before executing the code, take out all the variables that will be used in advance, some assign directly, some use undefined to fill in the blank first.

There are four situations:

The first case: variable, function expression - only declare in advance, not assign in advance, default assignment is undefined;

console.log(a); // undefined
var a=10;
console.log(fn1); // undefined
var fn1 = function(){};

The second case: this keyword -- declare ahead of time and assign values

console.log(this); // Window {external: Object, chrome: Object, document: document, __ctrip: Object, __SERVERDATE__: Object...}

 

The third scenario: Function Declaration -- pre-declaration and assignment

console.log(fn2); // function fn2(){}
function fn2(){};

 

Case 4: Functions create their own unique contextual environment

Each time a function is called, a new execution context is created. Because different calls may have different parameters.
In addition, when each function is defined (not called), the scope of the internal free variables in the function body has been determined.
Such as:

var a = 10;

function fn() {
    Console. log (a); / / / A is a free variable. When a function is created, the scope of a is determined.
}

function bar(f) {
    var a = 20;
    F (); / / / 10, go to the place where fn is created to find the scope of variable a, not the current scope where it is called.
}
bar(fn);

 

 

10. Execution context stack

As described in Execution Context/Execution Context Environment, there will be countless function calls and nested calls in js code, which will generate countless context environments. How can so many context environments be managed, and how can memory be freed by destruction? This requires the participation of the Execution Context Stack.

Execution context stack: When global code is executed, a global context environment is generated and pushed into the stack. Each call to a function generates an execution context environment, and pushes the function context into the stack. When the function call is completed, the function context is out of the stack, the function context and its data are eliminated, and then the global context is returned. There is only one execution context in the active state. In fact, this is a process of stacking out.

Such as:

var a = 10, // 1. Enter the global context
fn,
bar = function(x) {
    var b = 5;
    fn(x + b); // 3. Get into fn Function context environment, merged into the stack, set to active state. After the function has been executed, bar Function context out of the stack, and timely destruction, release memory
};
 
fn = function(y) {
    var c = 5;
    console.log(y + c);
}
 
bar(10); // 2. Get into bar Function context environment, merged into the stack, set to active state. After the function has been executed, bar Function context out of the stack, and timely destruction, release memory
 

 

Reference resources: http://www.cnblogs.com/wangfupeng1988/p/3989357.html

11. this

this plays a very important role in the context of execution, which should be mentioned here.

To understand this, one thing to remember is that the value of this in a function is determined when the function is actually called and executed, but not when the function is defined.

It can be roughly divided into the following four situations:

Scenario 1: Constructor, this represents the new object.

function Foo(){
    this.name = Dian Orange Trade;
    this.year = 2016;
    console.log(this); // Foo {name: `Dian Orange Trade', year: 2016}
}
var f1 = new Foo(); // The so-called constructor is the function used for the new object.

 

In addition, if you use this in the prototype chain (Foo.prototype uses this), this still represents the new object.

function Foo(){
    this.name = 'Dian Orange Trade 2016';
}
Foo.prototype.getName = function(){
    console.log(this); // Foo {name: "Dian Orange Trade 2016"}
}
var f1 = new Foo();
f1.getName();

 

Case 2: A function as an attribute of an object,And when called directly by the object, this Point to the object.

var obj = {
    name:'Dian Orange Trade',
    fn:function(){
        console.log(this); // Object {name: "Dian Orange Trade"}
        console.log(this.name); // Dian Orange Trade
    }
}
obj.fn(); // Direct call
 
// If it is not called directly, this Just point to window
var obj = {
    name: 'Dian Orange Trade',
    fn: function() {
        console.log(this); // Window {external: Object, chrome: Object, document: document, __ctrip: Object, __SERVERDATE__: Object...}
        console.log(this.name); // undefined
    }
}
var fn1 = obj.fn;
fn1();

Case 3: Functional use call perhaps apply Call, this Is the value of the incoming object

var obj ={
    name:'Dian Orange Trade'
}
var fn = function(){
    console.log(this); // Object {name: "Dian Orange Trade"}
    console.log(this.name); // Dian Orange Trade
}
fn.call(obj);
// perhaps
// fn.apply(obj);

 

Scenario 4: Global - Call ordinary functions, this is window

Overall situation:

console.log(this===window); // true
 
Call a normal function:
var name = Dian orange trade;
var fn = function() {
    console.log(this); // Window {external: Object, chrome: Object,     document: document, __ctrip: Object, __SERVERDATE__: Object...}
    console.log(this.name); / / Dian Orange Trade
}
fn();

 

Be careful:

var obj = {
    name: 'Dian Orange Trade',
    fn: function() {

        function f() {
            console.log(this); // Window {external: Object, chrome: Object,     document: document, __ctrip: Object, __SERVERDATE__: Object...}
            console.log(this.name); // undefined
        }
        f(); // function f Although in obj.fn Internally defined, but it is still a normal function. this Still pointing window. 

    }
}
obj.fn();

 

12. Scope

Knowledge Point 1: There is no block-level scope in javascript.

var i = 2;
if(i>1){
    var name ='Dian Orange Trade';
}
console.log(name);//Dian Orange Trade
The for loop {} is similar.

 

Knowledge Point 2: Except for global scope, only function can create its own scope, which is called function scope.

For example, classical questions:

<ul id = "list">
    <li> we </li>
    <li> sdf </li>
    <li> cx </li>
    <li> h </li>
    <li> z </li>
</ul>

 

var list = document.getElementById('list');
var e = list.getElementsByTagName('li');
var i = 0;

//Wrong Writing:
for (; i < e.length; i++) {
  e[i].onclick = function() {
    console.log(i);
  }
}

//Correct Writing:
for (; i < e.length; i++) {
  (function(a) {
    e[i].onclick = function() {
      console.log(a);
    }
  })(i);
}
//Equivalent to:
for (; i < 5; i++) {
  var Fn = function(a) {
    e[i].onclick = function() {
      console.log(a);
    }
  }
  Fn(i);
}

Reasons for the error:
Each cycle of e[i].onclick is assigned to onclick only, while the for loop has no block scope, so the value of I will accumulate until the maximum value is 5, so each cycle will output 5.
Correct reasons:
Since functions can create their own scopes, and each scopes will not interact with each other, each cycle Fn(i) will create a unique function scope to provide the corresponding onclick, and each variable in action will not interact with each other.

KNOWLEDGE POINT 3: The greatest use of scopes is to isolate variables. There is no conflict between variables of the same name in different scopes.

{
    var a = 1,
        b = 2;

    function fn1() {
        var a = 100,
            b = 200;

        function fn2() {
            var a = 1000,
                b = 2000;
        }
    }
} 

The "a and b" variables are declared in all three scopes, but they do not conflict. In their respective scopes, use their respective "a and b".

 

13. Free Variables and Their Valuation Rules

The variable x used in scope A is not declared in scope A (that is, in other scopes). For scope A, x is a free variable.
Such as:

var x=1;
function fn(){
    var b=2;
    console.log(x+b); // There x It's a free variable.
}

Free variable value rule: to create a free variable in the scope of the function in which the value - is [create], not [call], nor [parent scope].

Such as:

var x = 10;
function fn() {
    console.log(x); // fn Free function scope is created, so no matter where it is called, it will output 10
}
function show(f) {
    var x = 20;
    (function() {
        console.log(x); // To arrive x Find the scope of the anonymous function in which it is located x,So output 20
        f(); // To create fn Finding in the scope of a function x,So here output 10, not 20.
    })();
}
show(fn);

  

14. Scope chain

It is easier to understand scoping chains on the basis of free variables.
Use a variable A in scope Fn. If there is no definition of A in Fn, find it in scope Fm where Fn was created. If it is not found, continue to search in scope where Fm was created... By analogy, until the variable A is found or the global scope is not found, this line across multiple scopes is called "scope chain".
The code is as follows:

{
    // var A = 4; // Step 4, this is the global scope. If found, return 4. If not found here, it will be over. Error "A is not defined"

    function Fw() {
        // var A = 3; // Step 3: Find in scope Fw, return 3 if found, otherwise find in the global scope of creating Fw.

        function Fm() {
            // var A = 2; // Step 2: Find in scoped Fm, return 2 if found, or find in Fw where Fm was created.

            function Fn() {
                // var A = 1; // Step 1: Find in the current scope, return 1 if found, or find in the Fm where Fn is created.
                console.log(A);
            }
            return Fn();
        }
        return Fm();
    }
    Fw();
}

Be careful:

The scope in which Fn is created is not the scope in which Fn is invoked, nor is it the "parent scope". Refer to examples in Free Variables and Their Valuation Rules > Free Variables Valuation Rules for details.

15. Closure

To understand closures, the first three parts are the basis.
There are two forms of closure: function as return value and function as parameter.

First, the function is the return value

function fn() {
    var max = 10;
    return function bar(x) {
        if (x > max) { // max It is a free variable, the rule of value, refer to [free variable and its rule of value]
            console.log(x);
        }
    }
}
var f1 = fn();
f1(15); // 15

Second, functions are passed as parameters

var max = 10,
    fn = function(x) {
        if (x > max) { // max It is a free variable, the rule of value, refer to [free variable and its rule of value]
            console.log(x);
        }
    };
(function(f) {
    var max = 100;
    f(15); // 15
})(fn)

In addition,
In the Execution Context Stack, it is said that when each function is executed, its function context environment is destroyed and the data is emptied. But after the closure function is executed, the context will not be destroyed. Because functions in closures are returned or passed as parameters, they are used elsewhere, and once destroyed, the place where closures are called cannot be used again. So closures increase content overhead.

 

Reference resources:

  http://www.cnblogs.com/wangfupeng1988/p/3994065.html

  http://blog.csdn.net/yueguanghaidao/article/details/9568071

  http://blog.csdn.net/lmj623565791/article/details/25076713

Posted by fotofx on Tue, 09 Jul 2019 15:54:27 -0700