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