Create by jsliang on 2019-2-21 08:42:02

Recently revised in 2019-2-23 09:44:08

Hello friends, if you think this article is good, remember to give astar, yourstarIs my motivation to learn!Making the address


Thanks to the refactoring of jsliang’s document library, some links to this article may not work, and Jsliang does not have the energy to maintain the old articles in Gold. Sorry. For those who want to get the latest posts, click on the GitHub address above and go to the document library to view the adjusted posts.


This article involves knowledge:

  • prototype
  • __proto__
  • new
  • call()/apply()/bind()
  • this

In this article, Jsliang will explain his personal understanding of the above points through his own explorations. If there are any flaws, omissions or misunderstandings, please leave your comments.

If your partner has questions about the article, you want to get a quick response. Or a friend who is interested in jsliang’s personal front end document library and wants to sort out their own front end knowledge. Welcome to add QQ group together to discuss: 798961601.

A directory

No toss of the front end, and salted fish what’s the difference

directory
A directory
The preface
Three topics
The four problem solving
Five Knowledge expansion
5.1 Troubled Youth: Journey begins
5.2 Prototype and prototype chain
5.3 What is new
5.4 What is call()
5.5 Where this points to
Six summarize
Vii references
Eight tools

The preface

Returns the directory

“Can you tell me the function of this?”

The purpose of the title:

  1. Understand this, and talk about what this does.
  2. Vue’s this. variable, this points to where Vue is. (referring to instances of Vue)
  3. Let’s say setTimeout in Vue and see that this changes (call(),apply(),= >)
  4. … Something like that…

However, I found that I had gone down a road of no return. I accidentally read Prototype!

Then I climbed a high mountain…

Three topics

Returns the directory

I believe some friends can confidently make the following questions ~

  • Title 1
var A = function() {};
A.prototype.n = 1;
var b = new A();
A.prototype = {
  n: 2.m: 3
}
var c = new A();

console.log(b.n);
console.log(b.m);

console.log(c.n);
console.log(c.m);
Copy the code

What is the output of the above program?

  • Topic 2
var F = function() {};

Object.prototype.a = function() {
  console.log('a');
};

Function.prototype.b = function() {
  console.log('b');
}

var f = new F();

f.a();
f.b();

F.a();
F.b();
Copy the code

What is the output of the above program?

  • Topic 3
function Person(name) {
    this.name = name
}
let p = new Person('Tom');
Copy the code

Question 1:1.p.__proto__ is equal to what?

Question 2: What is person. __proto__ equal to?

  • Topic 4
var foo = {},
    F = function(){};
Object.prototype.a = 'value a';
Function.prototype.b = 'value b';

console.log(foo.a);
console.log(foo.b);

console.log(F.a);
console.log(F.b);
Copy the code

What is the output of the above program?

The four problem solving

Returns the directory

  • 1.
b.n -> 1
b.m -> undefined;

c.n -> 2;
c.m -> 3;
Copy the code
  • 2.
f.a() -> a
f.b() -> f.b is not a function

F.a() - >a
F.b() - >b
Copy the code
  • Answer to question 3

答案1: Person

答案2: Function

  • Answer to question 4
foo.a => value a
foo.b => undefined
F.a => value a
F.b => value b
Copy the code

If friends look at the answer, still do not know what is going on, then, let’s expand their knowledge point, carefree to know more knowledge!

Five Knowledge expansion

Returns the directory

Archetypes and archetype chains are probably a cliche, but there are a lot of people (like Jsliang himself) who often get confused here.

First picture ancestor worship, let the storm come more violent!

5.1 Troubled Youth: Journey begins

Returns the directory

Because of love, Jsliang went on a learning journey to learn about prototypes and prototype chains.

First, jsliang goes to look at the prototype chain.

Then, I saw new on the way to understand, so BAIDU looked at the new concept of JS.

Then, when you touch new, you learn that there is also call(), and that call(), apply(), and the arrow function => are all similar things.

Finally, when we look up call(), it mentions this again, so let’s look up this “by the way.”

5.1 Prototype and prototype chain

Returns the directory

First, why do we need prototypes and prototype chains?

Let’s look at an example:

function Person(name, age) {
  this.name = name;
  this.age = age;
  this.eat = function() {
    console.log(age + "Old" + name + "Eating."); }}let p1 = new Person("jsliang".24);
let p2 = new Person("jsliang".24);

console.log(p1.eat === p2.eat); // false
Copy the code

As you can see, for the same function, each instance we generate with new will open up a new chunk of the heap, so in the above code, person 1 and Person 2 will have different meals.

It’s nice to have something of your own (a house, a car). But it has its downsides, because there’s only so much space (memory), and you build and build, and eventually you run out of space. (Out of memory)

So find a way to create objects that resemble shared libraries (such as building taller buildings), so that when needed, you can call a shared library-like object (community), allowing instances to follow a clue to where they belong.

And that clue, in the front end, is the chain of prototypes.

function Person(name) {
  this.name = name;
}

// Use the constructor's Person prototype property to find the Person prototype object
Person.prototype.eat = function() {
  console.log("Eat");
}

let p1 = new Person("jsliang".24);
let p2 = new Person("Leung Jun-wing".24);

console.log(p1.eat === p2.eat); // true
Copy the code

Look! So we have the two instances pointing to the same location by sharing them (the community).

Then, at this point, we became interested in, what is prototype? How amazing!

It’s a long story without a mother. First of all, let’s start with the birth of JavaScript, but the story line is too long to put here, so here is a theatrical version of this article “the Birth of Everything in JavaScript world”, interested partners can go to learn about it. Let’s look at the picture again and return to the topic:

  • JS said, I am so lonely. Because the source of JS is empty, that is: null.
  • JS says, let there be god. So it works through magic__proto__The god No1 was created, namely:No1.__proto__ == null.
  • JS says, God, you should have your own ideas. So God came up with his own idea, based on his own prototypeprototypeI’ve created an objectObject, that is:Object.prototype == No1; No1.__proto__ == null. So we putprototypeIt’s called a prototype. It’s likeObjectThe archetype of god, the archetype of man is the same as human, at the same time__proto__It’s called the prototype chain, but there it is__proto__, object, god, JS is the connection between. At this timeObject.prototype.__proto__ == null.
  • JS said, god you have to have more ideas ah, I put the magic__proto__I borrowed it for you. So the divine basisObject, the use of__proto__I made a machine No2, which isNo2.__proto__ == No1And prescribes everything through__proto__You can connect to machines and find yourself, includingObjectStudent: Yeah, soObject becomes the prototype for all objects.Object.__proto__.__proto__ == No1And thenString,Number,Boolean,ArrayThe same is true of these species.
  • JS said, god, your machine is so powerful! Can your machine make more machines? God grinned: You created me through the magic, I created objects through my prototype. So, let me build a machine called Function,Function.prototype == No2, Function.__proto__ == No2, i.e.,Function.prototype == Function.__proto__!!!! So No2 becomes the machine that builds the machine, and it manages objects, functions, strings, numbers, Boolean, and arrays.

Finally, having said this, we should be very familiar with the picture of the beginning of ancestor worship, and a little suddenly enlightened feeling, can clearly understand the following formulas:

Object.__proto__ === Function.prototype;
Function.prototype.__proto__ === Object.prototype;
Object.prototype.__proto__ === null;
Copy the code

5.3 What is new

Returns the directory

At this point, we know what prototype and __proto__ are, so let’s return to our previous code:

function Person(name) {
  this.name = name;
}

// Use the constructor's Person prototype property to find the Person prototype object
Person.prototype.eat = function() {
  console.log("Eat");
}

let p1 = new Person("jsliang".24);
let p2 = new Person("Leung Jun-wing".24);

console.log(p1.eat === p2.eat); // true
Copy the code

So you can see that there’s a point here that we don’t know yet, which is: What is new?

First, let’s talk about functions: functions are divided into constructors and ordinary functions.

What’s going on? In the process of creating machine Function, too many machines are created. In order to distinguish these machines conveniently, No1 divides machines into two categories: Functions that create classes of objects are called constructors (usually object-oriented), and functions that create classes of actions are called normal functions (usually process-oriented). For example: function Birl() {}, function Person() {}, and so on are defined with uppercase to define a type or species. Function fly() {}, function eat() {}, and function fly() {} are called normal functions.

Notice that they’re essentially just from Function, just for the sake of distinction, so we’ll call them that

Then, we tried to make a bird that could fly:

// Define birds
function Bird(color) {
  this.color = color;
}

// Define the action of flying
function fly(bird) {
  console.log(bird + "It's flying!);
}
Copy the code

Next, we are going to use the bird machine to create a bird. No1 scratched his head and said, “Use new”, so:

// Define birds
function Bird(color) {
  this.color = color;
}

// Create a bird
let bird1 = new Bird('blue');

// Define the action of flying
function fly(bird) {
  console.log(bird.color + "The bird is flying!");
}

fly(bird1); // The blue bird flies!
Copy the code

Having said that, we know how to use type to create machines and motion to create machines.

Finally, if we’re interested, we can check out what No1 is doing inside new:

Let bird1 = new Bird(‘ blue ‘);

// 1. First, there is a type machine
function ClassMachine() {
  console.log("Type creation machine");
}
// 2. Then we define an object object
let thingOne = {};
// 3. The object item refers to the prototype of the type machine (i.e. No 2 beginning machine) by __proto__.
thingOne.__proto__ = ClassMachine.prototype;
// 4.
ClassMachine.call(thingOne);
// 5. Define the action of the type machine
ClassMachine.prototype.action = function(){
  console.log("Motion Creation Machine.");
}
// 6. The object object performs the action
thingOne.action();
/* * Console: * Type creation machine * Action creation machine */
Copy the code

OK, what new did, No. 1 god’s plan is clear.

So in this example, we are clear:

function Person(name){
    this.name = name
}

Person.prototype = {
  eat:function(){
    console.log('eat')},sleep:function(){
    console.log('sleep')}};let p = new Person('Leung Jun-wing'.28);

// Access the prototype object
console.log(Person.prototype);
console.log(p.__proto__); // __proto__ is only used for testing and cannot be written in formal code

The Console / * * {eat: ƒ, sleep: ƒ} * {eat: ƒ, sleep: ƒ} * /
Copy the code

So a lot of people will come up with this formula:

The instance__proto__Property (stereotype) equal to its constructorprototypeProperties.

Now understand no problem!

But, did you notice point 4 in the new process? !!!!!!!!!

5.4 What is call()

Returns the directory

In point 4, we used the call() method.

So, what is call()?

Note that the call() method exists in Funciton, function.prototype. call should be ƒ call() {[native code]}.

Then, we look at the following code:

function fn1() {
  console.log(1);
  this.num = 111;
  this.sayHey = function() {
    console.log("say hey."); }}function fn2() {
  console.log(2);
  this.num = 222;
  this.sayHello = function() {
    console.log("say hello.");
  }
}
fn1.call(fn2); / / 1

fn1(); / / 1
fn1.num; // undefined
fn1.sayHey(); // fn1.sayHey is not a function

fn2(); / / 2
fn2.num; / / 111
fn2.sayHello(); // fn2.sayHello is not a function

fn2.sayHey(); //say hey.
Copy the code

With fn1.call(fn2), we find that both Fn1 and fn2 are altered, and call() acts like a mistress, destroying the harmonious family of Fn1 and fn2.

Now, Fn1 does nothing but print its own console. Fn2 has everything except fn1 console: Num and sayHello.

Remember: here, call() changes the direction of this.

Then, we should take a look at the source code to understand how it is implemented, but jsliang is too easy to read the source code process articles on the Internet, so let’s use a few more examples to understand what call() can do

  • Example 1:
function Product(name, price) {
  this.name = name;
  this.price = price;
}

function Food(name, price) {
  Product.call(this, name, price);
  this.category = 'food';
}

let food1 = new Food('chees'.5);

food1; // Food {name: "chees", price: 5, category: "food"}
Copy the code

As you can see, by calling call() inside the Food constructor, Food successfully expands the name and price fields. So:

Rule # 1: Yescall()Method calls the parent constructor.

  • Example 2:
var animals = [
  {
    species: 'Lion'.name: 'King'
  },
  {
    species: 'Whale'.name: 'Fail'}]for(var i = 0; i < animals.length; i++) {
  (function(i) {
    this.print = function() {
      console.log(The '#' + i + ' ' + this.species + ":" + this.name);
    }
    this.print();
  }).call(animals[i], i);
}

// #0 Lion: King
// #1 Whale: Fail
Copy the code

As you can see, in the anonymous function, we successfully point this from Animals to the anonymous function through call(), thus looping out the value.

Rule two: Usecall()Method calls anonymous functions.

  • Example 3:
function greet() {
  var reply = [this.animal, 'typically sleep between'.this.sleepDuration].join(' ');
  console.log(reply);
}

var obj = {
  animal: 'cats'.sleepDuration: '12 and 16 hours'
};

greet.call(obj);  // cats typically sleep between 12 and 16 hours
Copy the code

Rule three: Usecall()Method that calls a function and specifies the contextthis.

Finally, at this point, you should know some of the uses of call().

When we talk about call(), we have to talk about apply(), which is similar to it. In fact, they are both similar, but the way apply() is called is different. For example:

function add(a, b){
  return a + b;  
}
function sub(a, b){
  return a - b;  
}

// use of apply()
var a1 = add.apply(sub, [4.2]); // sub calls the add method
var a2 = sub.apply(add, [4.2]);

a1; / / 6
a2; / / 2

// call()
var a1 = add.call(sub, 4.2);
Copy the code

Yes, apply() can only be called with two arguments: a new this object and an array argArray. Call (thisObj, [arg1, arg2]);

Above, we know that both apply() and call() exist to change the context in which a function is run (that is, to change the reference to this within the function). Then, since these two methods are called immediately, to compensate for their absence, there is a method bind() that is not called immediately:

<! DOCTYPEhtml>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="Width = device - width, initial - scale = 1.0, the maximum - scale = 1.0, user - scalable = no">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Call (), apply(), and bind()</title>
</head>
<body>
  <div id="box">I'm a box!</div>
  
  <script>
    window.onload = function() {
      var fn = {
        num: 2.fun: function() {
          document.getElementById("box").onclick = (function() {
            console.log(this.num);
          }).bind(this);
          // }).call(this);
          // }).apply(this);
        }
        /* * this is fun, so num can be accessed correctly, * if bind() is used, 2 will be printed after clicking; * If you use call() or apply(), 2 */ will be printed when the page is refreshed
      }
      fn.fun();
    }
  </script>
</body>
</html>
Copy the code

Call (), apply(), this (), and the arrow function (=>) are involved

5.5 Where this points to

Returns the directory

  • In most cases, how a function is called determinesthisThe value of the. It’s in the global execution environmentthisBoth point to global objects

Here’s an example:

// In the browser, the window object is also a global object
conosle.log(this= = =window); // true

a = 'apple';
conosle.log(window.a); // apple

this.b = "banana";
console.log(window.b); // banana
console.log(b); // banana
Copy the code

However, in daily work, most of this is called inside a function, and:

  • Inside the function,thisThe value of depends on how the function is called.
function showAge(age) {
  this.newAge = age;
  console.log(newAge);
}
showAge("24"); / / 24
Copy the code

However, there are always questions:

  • generalthisPoints to problems that occur in the callback function. So when we write the callback function, we have to be carefulthisPoint to the problem.
var obj = {
  birth: 1995.getAge: function() {
    var b = this.birth; / / 1995;
    var fn = function() {
      return this.birth; 
      // This direction has been changed!
      // Because this redefines function,
      // Suppose it has its own this1 inside,
      // Then getAge's this is this2,
      // Fn, of course, follows the proximity principle and uses its own this, i.e., this1
    };
    return fn();
  }
}

obj.getAge(); // undefined
Copy the code

So what we can see here is that this in FN is now undefined.

There are remedies, of course.

First, we use the call() mentioned above:

var obj = {
  birth: 1995.getAge: function() {
    var b = this.birth; / / 1995
    var fn = function() {
      return this.birth; 
    };
    return fn.call(obj); // call(), obj (obj), obj (obj), obj (obj)
  }
}

obj.getAge(); / / 1995
Copy the code

Then, we use “that” for “this” :

var obj = {
  birth: 1995.getAge: function() {
    var b = this.birth; / / 1995
    var that = this; // Throw this to that
    var fn = function() {
      return that.birth; // Look for that
    };
    return fn();
  }
}

obj.getAge(); / / 1995
Copy the code

We passed var that = this and successfully referenced obJ’s birth in FN.

Finally, we can also use the arrow function => :

var obj = {
  birth: 1995.getAge: function() {
    var b = this.birth; / / 1995
    var fn = () = > this.birth;
    return fn();
  }
}
obj.getAge(); / / 1995
Copy the code

At this point, let’s go back to the new piece of code that we don’t understand:

// 1. First, there is a type machine
function ClassMachine() {
  console.log("Type creation machine");
}
// 2. Then we define an object object
let thingOne = {};
// 3. The object item refers to the prototype of the type machine (i.e. No 2 beginning machine) by __proto__.
thingOne.__proto__ = ClassMachine.prototype;
// 4.
ClassMachine.call(thingOne);
// 5. Define the action of the type machine
ClassMachine.prototype.action = function(){
  console.log("Motion Creation Machine.");
}
// 6. The object object performs the action
thingOne.action();
/* * Console: * Type creation machine * Action creation machine */
Copy the code

In step 4, we changed ClassMachine’s “this” to thingOne’s “this”.

Above, is not feeling a close to death, finally successful to see the dawn!!

Six summarize

Returns the directory

At the beginning, maybe some friends, watching will be confused!

It doesn’t matter, me too!

When I follow their own ideas, step by step after knocking down, I found that they seem to get through the two pulse, some topics have their own understanding.

So, the most important thing is to toss!

After all,

Do not toss the front end, and salted fish what difference!

Vii. Reference Materials

Returns the directory

The following is a selection of references to this article, some of which are not important and scattered about 30 articles have been selected.

  • The Birth of Everything in JavaScript
  • “Xiao Shao teach you to play with JS Object-oriented”
  • What does new() do in js?
  • The MDN Function. The prototype. The call ()”
  • Call, apply, bind in JavaScript
  • Arrow Function – Liao Xuefeng

Eight tools

Returns the directory

  • Online drawing Process On



Jsliang’s document library 由 Liang JunrongusingCreative Commons Attribution – Non-commercial – Share in the same way 4.0 International licenseLicense.

Based on theGithub.com/LiangJunron…On the creation of works.

Permissions outside of this license agreement may be obtained from
Creativecommons.org/licenses/by…Obtained.