When you use new, you will:

  1. Create a new empty object.
  2. willthisBind to the object;
  3. Add a file named__proto__Property, and points to the constructor’s prototype;
  4. Returns thethisObject.


The working procedure of executing the new command is as follows:

  1. Creates an empty object as an instance of the object to be returned
  2. Point the empty object’s prototype to the constructor’sprototypeattribute
  3. Assigns this empty object to the internalthisThe keyword
  4. Start executing the code inside the constructor

If you don’t understand, let’s use examples to explain in detail. Start by defining a constructor, Student, that takes two arguments, name and age.

 function Student(name, age){
  this.name = name;
  this.age = age;
}Copy the code

Now we use new to create a new object:

  var first = new Student('John'26);Copy the code

So what happened?

  1. A new object is created, let’s call itobj;
  2. thisBound to theobj, anythisThe quote is rightobjThe reference;
  3. __proto__Property is added toobjObject.obj.__proto__Will pointStudent.prototype;
  4. theobjObject is assigned tofirstThe variable.

We can test by printing:

console.log(first.name); // John console.log(first.age); / / 26Copy the code

Let’s take a closer look at __proto__.

The Prototype (Prototype)

Every JavaScript object has a prototype. All objects inherit objects and properties from their archetypes.

Open your Browser developer Control Panel (Windows: Ctrl + Shift + J)(Mac: Cmd + Option + J) and enter the Student function you defined earlier:

  function Student(name, age) {
  this.name = name;
  this.age = age;
}Copy the code

To verify that each object has a prototype, type:

Student.prototype; // Object {... }Copy the code

You will see that an object is returned. Now let’s try to define a new object:

  var second = new Student('Jeff', 50);Copy the code

The object referred to by second has a __proto__ attribute and should refer to its parent’s prototype.

 second.__proto__ === Student.prototype
// trueCopy the code

Student. The prototype. The constructor will point to the Student constructor, we print it out and see:

  Student.prototype.constructor;
//  function Student(name, age) {
//    this.name = name;
//    this.age = age;
//  }Copy the code

As if things are getting more complicated, let’s use a picture to visualize it:

The Student constructor has a property called.prototype, which in turn has a.constructor property pointing to the Student constructor. They form a ring. When we use new to create a new object, each object has a.__proto__ property that in turn points to student.prototype.

This design is important for inheritance. Because the prototype object is shared by all objects created by the constructor. When we add functions and attributes to the prototype object, all other objects are available.

In this article we have only created two Student objects. If we had created 20,000, putting properties and functions into Prototype instead of each object would have saved a lot of storage and computing resources.

Let’s look at an example:

  Student.prototype.sayInfo = function(){
  console.log(this.name + ' is ' + this.age + ' years old');
}Copy the code

We added a new function sayInfo to the Student prototype – so any Student object created using Student can access this function.

  second.sayInfo();
// Jeff is 50 years oldCopy the code

Create a new student object and test it again:

var third = new Student(‘Tracy’, 15); // If we print third now, we can still access the sayInfo function, although we only see the age and name attributes.

var third = new Student('Tracy', 15); // If we print third now, we can still access the sayInfo function, although we only see the age and name attributes. third; // Student {name:"Tracy", age: 15}
third.sayInfo();
// Tracy is 15 years old
Copy the code

In JavaScript, you first check to see if the current object has the property; If not, see if the attribute is present in the stereotype. This rule continues until the attribute is successfully found or until the top-level global object is not found and returns a failure.

Inheritance lets you use the toString() function without having to define it. Because the toString() function is built into the Object prototype. Every Object we create ends up pointing to Object.prototype, so we can call toString(). Of course, we can also rewrite this function:

  var name = {
  toString: function(){
    console.log('Not a good idea'); }}; name.toString(); // Not a good ideaCopy the code

The created Name object first checks to see if it has toString, and if it does, it doesn’t look in the prototype.









Constructor and new command

constructor

  • The object architecture of the JavaScript language is not based on “classes”, but on constructors and prototype chains.
  • Constructor names are capitalized to distinguish them from normal functions, such as: var Person = function(){this.name = ‘kinghammer ‘; }
  • Constructor features:

    A. The function body is used internallythisKeyword, representing the object instance to be generated;

    B, when generating objects, must be usednewCommand to invoke this constructor

2, new

The constructor returns an instance object

var Person = function(name, age){
    this.name = name;
    this.age = age;
    this.email = '[email protected]';
    this.eat = function(){
        console.log(this.name + ' is eating noodles');
    }
}

var per = new Person(King's Sledgehammer, 18);
console.log(per.name + ', ' + per.age + ', '+ per.email); // Wang Daqiao, 18, [email protected] per.eat(); // I'd like noodlesCopy the code

The working procedure of executing the new command is as follows:

  1. Creates an empty object as an instance of the object to be returned
  2. Point the empty object’s prototype to the constructor’sprototypeattribute
  3. Assigns this empty object to the internalthisThe keyword
  4. Start executing the code inside the constructor

Note: When a constructor contains the return keyword, if it returns a non-object, the new command ignores the information returned and returns the constructed this object. If return returns a new object unrelated to this, the new command eventually returns the new object, not this. Sample code:

console.log('---- return string start ----');
var Person = function(){
    this.name = King's Sledgehammer;
    return Luo Xiaohu;
}

var per = new Person();
for (var item in per){
    console.log( item + ':'+ per[item] ); } / / - returns a string start - / / name: wang hammer the console. The log ('----- return object start ----');
var PersonTwo = function(){
    this.name = 'Sword of Heaven';
    return {nickname: 'Dragon slayer', price: 9999 };
}
var per2 = new PersonTwo();
for (var item in per2){
    console.log(item + ':'+ per2[item]); } / / -- -- -- -- -- return objects start - / / nickname: knife / / price: 9999Copy the code

If we forget to use the new keyword when we call the constructor, this will be the global object window, and the property will be the global property.

The variable assigned by the constructor is no longer an object, but an undefined variable. Js does not allow adding attributes to undefined, so calling the attribute of undefined will result in an error.

Example:

var Person = function(){ 
    console.log( this == window );  //true
    this.price = 5188; 
}
var per = Person();
console.log(price); //5188
console.log(per);  //undefined
console.log('... _ _ '-); / /... _-_ console.log(per.price); //Uncaught TypeError: Cannotread property 'helloPrice' of undefinedCopy the code

One way to avoid forgetting the new keyword is to add: ‘use strict’ on the first line inside the function;

This indicates that the function is in strict mode. This inside the function cannot refer to the global object window, which is undefined by default

var Person = function() {'use strict';
    console.log( this );  //undefined
    this.price = 5188; //Uncaught TypeError: Cannot set property 'helloPrice' of undefined
}

var per = Person(); Copy the code

Another way around this is to manually add the new command inside the function:

var Person = function(){// Check if this is an instance of Personif(! (this instanceof Person)){returnnew Person(); } console.log( this ); //Person {} this.price = 5188; } var per = Person(); console.log(per.price); / / 5188Copy the code

Second, this keyword

var Person = function(){
    console.log('1111'); 
    console.log(this); 
    this.name = King's Sledgehammer;
    this.age = 18;

    this.run = function(){
        console.log('This is an instance object of Person:'+ (this instanceof Person) ); console.log(this); } } var per = new Person(); per.run(); 1111 Person {} This is an instance of Person:true
Person {name: "Hammer king", age: 18, run: function}
*/

console.log('-- -- -- -- -- -- -- -- -- -- -- -- -- -- --');

var Employ = {
    email: '[email protected]',
    name: 'Zhao Ritian',
    eat: function(){
        console.log(this);
    }
}

console.log(Employ.email + ', '+ Employ.name); Employ.eat(); / * print log: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- [email protected], Zhao Ri day Object {email:"[email protected]", name: "Zhao Ritian", eat: function} * /Copy the code

1. This always returns an object, the object on which the property or method is currently located, as in the example above

2. An attribute of an object can be assigned to another object, that is, the current object of the attribute can be changed, and the reference of this can be changed

var A = { 
    name: King's Sledgehammer, 
    getInfo: function() {return 'Name:' + this.name;
    } 
}

var B = { name: 'Zhao Ritian'}; B.getInfo = A.getInfo; console.log( B.getInfo() ); GetInfo = b. geinfo = b. geinfo = b. name = b. nameCopy the code

3. Due to the variability of this reference, use this carefully in functions with many levels. In general, when this is needed in a multi-level function, set a variable to fix the value of this, and then set the variable in the inner function.

Example 1: This in layers

Var o = {f1: 1;function(){ console.log(this); // This refers to the o object var f2 =function(){ console.log(this); } (); // Since it is written as (function(){})(), this in F2 refers to the top-level object Window}} o.f1(); /* Print log: Object {f1:function}

Window {stop: function, open: function, alert: function, confirm: function, prompt: function... }} */ / var temp =function(){
    console.log(this);
}
var o = {
    f1: function(){ console.log(this); // This refers to the o object var f2 = temp(); // This in temp() refers to the top-level object window}} o.f1(); /* Print log Object {f1:function}

Window {stop: function, open: function, alert: function, confirm: function, prompt: function... } // this is the same as this; // This is the same as this; // This is the same as this;function(){ console.log(this); Var that = this; var f2 =function(){ console.log(that); // That points to the o object}(); } } o.f1(); /* Print log: Object {f1:function}
Object {f1: function} * /Copy the code

Example 2: This in array traversal

Var obj = {email:'a sledgehammer @ sina.com, 
    arr: ['aaa'.'bbb'.'333'],
    fun: function(){// The first this refers to the obj object this.arr.foreach (function(item){// This refers to the top-level object window, which has no email variable, undefined console.log(this.email +)':'+ item); }); } } obj.fun(); /* Undefined: aaa - undefined: BBB - undefined: 333 */ / var obj = {email:'a sledgehammer @ sina.com, 
    arr: ['aaa'.'bbb'.'333'],
    fun: functionVar that = this; // Fix this with a variable this.arr. ForEach (function(item){// That refers to the object obj console.log(that.email +':'+ item); }); } } obj.fun(); // call /* Print log: sledgehammer @sina.com: aaa sledgehammer @sina.com: BBB sledgehammer @sina.com: 333 */forVar obj = {email:'a sledgehammer @ sina.com, 
    arr: ['aaa'.'bbb'.'333'],
    fun: function(){// The first this refers to the obj object this.arr.foreach (function(item){// This comes from the parameter this and points to the obj object console.log(this.email +)':'+ item); }, this); } } obj.fun(); // call /* Print log: hammer @sina.com: AAA hammer @sina.com: BBB hammer @sina.com: 333 */ /4. Arrow function var obj = {email:'a sledgehammer @ sina.com, 
    arr: ['aaa'.'bbb'.'333'],
    fun: functionForEach ((item)=>{this.arr.foreach ((item)=>{// This comes from this and points to console.log(this.email +)':'+ item); }); } } obj.fun(); // call vm83:8 hammer @sina.com: aaa vm83:8 hammer @sina.com: BBB vm83:8 hammer @sina.com: 333 usebind

var obj = {
    email: 'a sledgehammer @ sina.com, 
    arr: ['aaa'.'bbb'.'333'],
    fun: function(){// The first this refers to the obj object this.arr.foreach (function(item){// This comes from the parameter this and points to the obj object console.log(this.email +)':'+ item); }.bind(this)); } } obj.fun(); // call vm122:8 @sina.com: aaa vm122:8 @sina.com: BBB vm122:8 @sina.com: 333 undefinedCopy the code

4. How to fix and toggle this with the call, apply, and bind methods provided by JS

Function.prototype.call () : call(); function.prototype.call() : call(); If call(args) is null, undefined, or window, the global top-level object window is passed in by default. If the argument in call is passed to the custom object obj, then this inside the function points to the custom object obj and runs the function in the obj scope

var obj = {};
var f = function(){
    console.log(this);
    return this;
}

console.log('... start..... ');
f();
f.call();
f.call(null);
f.call(undefined);
f.call(window);
console.log('**** call method if the arguments are null, null, or undefined, the global level window is passed by default; If the call method passes in the custom object obj, function f runs ****' in the scope of the object obj.);
f.call(obj);
console.log('.....end.....'); /* Prints logs:.... start..... Window {stop:function, open: function, alert: function, confirm: function, prompt: function... } Window {stop:function, open: function, alert: function, confirm: function, prompt: function... } Window {stop:function, open: function, alert: function, confirm: function, prompt: function... } Window {stop:function, open: function, alert: function, confirm: function, prompt: function... } Window {stop:function, open: function, alert: function, confirm: function, prompt: function... } **** call method if the arguments are null, null, or undefined, the global level window is passed by default; If the call method passes in the custom Object obj, function f runs **** Object {}..... in the scope of the Object obj end..... * /Copy the code