An understanding of prototype chains

Let’s start with a code problem:

function Foo() { getName = function () { alert (1); }; return this; } Foo.getName = function () { alert (2); }; Foo.prototype.getName = function () { alert (3); }; var getName = function () { alert (4); }; function getName() { alert (5); } // Write the following output: foo.getName (); getName(); Foo().getName(); getName(); new Foo.getName(); new Foo().getName(); new new Foo().getName();Copy the code

Let’s look at the results: 2, 4, 1, 1, 2, 3, 3

Think: What does each line do?

function Foo() {
 getName = function () { alert (1); };
 return this;
}
Copy the code

We first define a constructor for Foo

Foo.getName = function () { alert (2); };Copy the code

The static property getName is created for the constructor to store an anonymous function

Foo.prototype.getName = function () { alert (3); };Copy the code

A new anonymous function called getName is created for Foo’s prototype object

var getName = function () { alert (4); };Copy the code

A function getName is created using a function variable expression

function getName() { alert (5); }Copy the code

A function getName is created through the function declaration

The results of the analysis

Foo.getName();
Copy the code

Foo.getName naturally accesses the static property //2 stored on the Foo function

getName();
Copy the code

Call getName directly. This is a direct call to a function called getName that is currently in the above scope. There are two functions called getName in the stem. The function expression and the function declaration are promoted, so the function declaration is also advanced:

var getName = function () { alert (4); }; function getName() { alert (5); } // function precompiled var getName; function getName() { alert (5); } getName = function () { alert (4); };Copy the code

Var getName = function () {alert (4); }; Overrides the function declaration again, so the final output is //4

Foo().getName()
Copy the code

Foo is executed, then Foo’s return value, this, refers to the window, and getName is called. GetName = function () {alert (1); GetName = function () {alert (4); } function(){alert(1)} //1

getName()
Copy the code

Call getName directly, equivalent to window.getName(), because the variable has been modified by Foo //1

new Foo.getName()
Copy the code

Note: we are looking at the priority of the JS operator.

According to the priority code becomes below:

new (Foo.getName) ();
Copy the code

So you’re actually calling the getName function //2 in the Foo constructor

new Foo().getName()
Copy the code

For the same reason:

(new Foo()).getName();
Copy the code

Instantiate Foo, which points to itself and has no getName property in its constructor, and look for getName in its prototype object,//3

new new Foo().getName()
Copy the code

Convert to the following:

new ((new Foo()).getName)();
Copy the code

Initialize Foo’s instantiation object, and then new again,//3, with getName function on its prototype as constructor

Conclusion:

The key is to analyze the JS operations at each step