Before I write this blog post, I’d like to mention something that has been on my mind today (March 28, 2019) (in the spirit of being part of the fun — awkward). On Github, the world’s largest dating site, a document titled 996.ICU appeared yesterday. The project has no code, but lists some provisions of the Labor Law and the companies that have recently identified 996 working hours. I thought it was a small complaint, but when I looked again at noon today, the star number had been more than 30K, and issues reached 5000+. In the afternoon, the project was even more overwhelming. It has been defeated six times in Github star list. Up to now, this project, which appeared less than 24 hours ago, has 63K STAR and ranks 21st. Why such a simple project will suddenly rise, with the posture of the slaughter, out of control. Perhaps it’s just touches the forced 996 work friends, as well as the endless overtime no return programmers in the heart of the most sensitive nerve, susceptible to livelihood issues, real life can only submit to humiliation, but when there is a virtual world can let you enjoy venting, pouring out of the heart of the bitter, has created the weird project. It is not that we cannot accept 996, but that the company has to pay the corresponding remuneration for the implementation of 996 working system, which makes employees feel that their efforts are rewarded. There is no corresponding remuneration and no own time, and their anger will only accumulate more and more. What can we do now: first, try not to go to 996 company, let 996 company no one can recruit; Two, improve their technical level, so that they have the dominant bargaining power, not to implement 996, can talk about the salary you can accept. Above is my personal opinion, do not like spray. (Again… The money is enough, the company is all right)

What is this?

What is this? What’s this? What is this? (Black question mark face) Today s topic (😍?) Call, apply, and bind, this one here and I think it works very well, and I’ll explain why I don’t put bind in the same category as call and apply.

This object is bound at runtime based on the function’s execution environment (without the arrow function). When a function is called as a method of an object, this equals that object. This equals the object on which the function was last called

Let’s go for example ⬇️

var name = 'Jack Sparrow';

function sayWhoAmI() {
  console.log(this.name)
}

sayWhoAmI(); // Jack Sparrow

var onePiece = {
  name: 'Monkey d. Luffy'.sayWhoAmI: function () {
    console.log(this.name)
  }
};

onePiece.sayWhoAmI(); / / Monkey d. Luffy
Copy the code

SayWhoAmI () : sayWhoAmI() : sayWhoAmI() : sayWhoAmI() : sayWhoAmI() : sayWhoAmI() : sayWhoAmI() : sayWhoAmI() : sayWhoAmI() : sayWhoAmI() ∵ “sayWhoAmI”, ∴ “sayWhoAmI”, ∴ “sayWhoAmI”, ∴ “sayWhoAmI”, ∴ “sayWhoAmI”, ∴ “sayWhoAmI”, ∴ “sayWhoAmI”, ∴ “sayWhoAmI”, So let me write it this way so you can see ⬇️

var name = 'Jack Sparrow';

function sayWhoAmI() {
  console.log(this.name)
}

- sayWhoAmI(); // Jack Sparrow
+ window.sayWhoAmI(); // Jack Sparrow
Copy the code

So is it clear ∵ in global declarations of variables or functions, is in the window or the global object ∴ statement under Windows global sayWhoAmI can be output with the window global statement under the name

Small advanced

We have understood the simple, now let’s look at the method of adding return, I think it is a little difficult, big guy please float over ⬇️

var area = 'East Ocean';

var onePiece = {
  area: 'New World'.tellMeWhereAreYou: function () {
    return function () {
      console.log(this.area); }}}; onePiece.tellMeWhereAreYou()();// East Ocean
// If you don't understand why this is executed twice, or you don't understand why the output of global variables
// I'll introduce an intermediate variable to make the process more readable by one step
var grandLine = onePiece.tellMeWhereAreYou();
Function () {console.log(this.area); // grandLine = function() {console.log(this.area); }, equal to onePiece. TellMeWhereAreYou (); Function returned
// Since grandLine is a global variable, this.area returns East Ocean
grandLine(); // East Ocean
Copy the code

I thought I explained the problem in a very concise way, because it involves the knowledge of closures, and the active object of functions. If you don’t understand this, you can read my other blog post “JavaScript: Closures”. For a more in-depth look, check out the two diagrams in section 7.2 of JavaScript Advanced Programming, which includes closing packages.

How do I get this function to print the area inside my object: ‘New World’ ⬇️

var area = 'East Ocean';

var onePiece = {
  area: 'New World'.tellMeWhereAreYou: function () {
    var that = this;
    // We declare a variable to hold the object to which this refers, and then use it in the closure, the function returned
    // A typical closure structure is complete
    return function () {
      console.log(that.area); }}}; onePiece.tellMeWhereAreYou()();// New World
Copy the code

You might have used intermediate variables to save this in your previous work, and I don’t think it’s hard, so I’m going to skip it.

We should now have a general idea of what this refers to. But we are abnormal, we are sick, we finally understand the direction of this problem, then we now want to change the direction of this, 😜 life is difficult everywhere

That’s where we need to use the titlecallandapply

Apply nothing and just call me

The call() method does the same thing as the apply() method; the only difference is how the parameters are received. ———————— JavaScript Advanced Programming

It’s very clear in the book that they do the same thing, just the way they receive parameters, so what’s the difference? Listen to me

Crazy play call

The call() method can specify a value of this (the first argument) and pass in each argument.

The call() method is used to change the direction of this. ⬇ ️

var first = 'Big Black Knife night',
    second = 'Ghost Of the Second Generation',
    third = "The Original Ghost.",
    fourth = 'rain';

var zoro = {
  first: 'And tao one word'.second: 'Three Generations of Ghosts'.third: 'snow go'.fourth: 'stop'
};

function sayYourWeapon(num, num2) {
  console.log(` this is me${num}Get the knife."The ${this[num]}"`)
  console.log(` this is me${num2}Get the knife."The ${this[num2]}"`)
}

sayYourWeapon('first'.'third'); // This is my first dao "Big black Dao · night"; This is my third's dao, "The First Ghost."
sayYourWeapon.call(zoro, 'first'.'fourth'); // This is my first dao "He Dao yi wen"; This is my dao "Qiushui" that Fourth got.
Copy the code

If I call sayYourWeapon(), it will output the first and third global variables. SayYourWeapon. Call (zoro, ‘first’, ‘fourth’); call(sayYourWeapon. Call (zoro, ‘first’, ‘fourth’); The ‘this’ value is changed from the global object to the’ zoro ‘object. The following outputs are the ‘first’, ‘fourth’ values in the zoro object

Apply all configurations

The apply() method can specify a value of this (the first argument) and pass in an array of arguments (the arguments need to be in an array or an array of classes)

Now that we know how to use the call() method, we should be more familiar with the apply() method. We can change the above example to ⬇️

var first = 'Big Black Knife night',
  second = 'Ghost Of the Second Generation',
  third = "The Original Ghost.",
  fourth = 'rain';

var zoro = {
  first: 'And tao one word'.second: 'Three Generations of Ghosts'.third: 'snow go'.fourth: 'stop'
};

function sayYourWeapon(num, num2) {
  console.log(` this is me${num}Get the knife."The ${this[num]}"`)
  console.log(` this is me${num2}Get the knife."The ${this[num2]}"`)
}

sayYourWeapon('first'.'third'); // This is my first dao "Big black Dao · night"; This is my third's dao, "The First Ghost."
- sayYourWeapon.call(zoro, 'first'.'fourth'); // This is my first dao "He Dao yi wen"; This is my dao "Qiushui" that Fourth got.
+ sayYourWeapon.apply(zoro, ['first'.'fourth']); // This is my first dao "He Dao yi wen"; This is my dao "Qiushui" that Fourth got.
Copy the code

As you can see, all I did was change call to apply and change the parameters passed in ‘first’, ‘fourth’ to [‘first’, ‘fourth’] as an array. If we use arguments in a function, we can also use the array-like object ⬇️

var first = 'Big Black Knife night',
    second = 'Ghost Of the Second Generation',
    third = "The Original Ghost.",
    fourth = 'rain';

  var zoro = {
    first: 'And tao one word'.second: 'Three Generations of Ghosts'.third: 'snow go'.fourth: 'stop'
  };

  function sayYourWeapon(num, num2) {
    console.log(` this is me${num}Get the knife."The ${this[num]}"`)
    console.log(` this is me${num2}Get the knife."The ${this[num2]}"`)}function mySayYourWeapon(num, num2) {
    sayYourWeapon.apply(zoro, arguments) // We declare a function and call arguments inside it, so we just pass in arguments instead of calling it one by one
  }

  sayYourWeapon('first'.'fourth'); // This is my first dao "Big black Dao · night"; This is my sword "Shi Yu" that Fourth got.
  mySayYourWeapon('first'.'fourth'); // This is my first dao "He Dao yi wen"; This is my dao "Qiushui" that Fourth got.
Copy the code

Where the bind secret

At the beginning of this article, I said the following sentence: ⬇️

Call, apply and bind, this one here and I think it works well

Now let’s talk about the meaning of ‘and’. Why do I say ‘and’? Bind is slightly different from call and apply. Call () or apply(), which executes immediately and gets the value if the function returns a value. Bind (), however, does not execute the target function immediately. Instead, bind() returns a copy of the original function with the specified this value and the original function. We uploaded it ourselves, of course.

What is a copy of the original function, so let’s look at ⬇️

function a() {}

console.log(typeof a.bind() === 'function'); A.bind () is a function
console.log(a.bind()); Function a() {} function a() {
console.log(a.bind() == a); // false
console.log(a.bind() === a); // false either === or == is false, proving that the function is copied instead of the original one
Copy the code

Bind () = bind(); bind() = bind()

“Printing preparation

The bind() method takes the same arguments as call. The first argument is the object to bind to, followed by the arguments required by the function, as shown in ⬇️

var name = 'Jack Sparrow';

var onePiece = {
  name: 'Monkey d. Luffy'
};

function sayWhoAmI() {
  console.log(this.name)
}

var mySayWhoAmI = sayWhoAmI.bind(onePiece)

sayWhoAmI(); // Jack Sparrow
mySayWhoAmI(); / / Monkey d. Luffy
Copy the code

Bind nodeMonkey·D·Luffy onePiece nodeMonkey·D·Luffy onePiece

That we need to transfer the time how to do ⬇️

var first = 'Big Black Knife night',
  second = 'Ghost Of the Second Generation',
  third = "The Original Ghost.",
  fourth = 'rain';

var zoro = {
  first: 'And tao one word'.second: 'Three Generations of Ghosts'.third: 'snow go'.fourth: 'stop'
};

function sayYourWeapon(num, num2) {
  console.log(` this is me${num}Get the knife."The ${this[num]}"`)
  console.log(` this is me${num2}Get the knife."The ${this[num2]}"`)}// Now that we know that bind returns a function, it's easier to declare a variable to take that function
var mySayYourWeapon = sayYourWeapon.bind(zoro, 'first'.'fourth'); // Pass in the initial argument
var hisSayYourWeapon = sayYourWeapon.bind(zoro); // Only the target object is passed in

sayYourWeapon('first'.'third');
mySayYourWeapon(); // Since we already passed in the zoro object and the specified parameters when we bind the binding function, there is no need to pass in the parameters
hisSayYourWeapon( 'first'.'fourth'); // We can pass in the parameters when we call the bind function
Copy the code

For mySayYourWeapon and hisSayYourWeapon, one of the initial parameters is passed in, and the other is not passed in, but can be passed in later calls

If it is an initial parameter, you can set it to —————— and pass it a partial Function (function.prototype.bind)

We’re done. It’s time to move

Shadow mimicry

By default, you already know how to use bind, so the challenge is to write a bind method by hand, which will help you understand how bind works, Bind: function.prototype.bind: function.prototype.bind: function.prototype.bind: function.prototype.bind: function.prototype.bind: function.prototype.bind: function.prototype.bind: function.prototype.bind: function.prototype.bind: function.prototype.bind: function.prototype.bind: function.prototype.bind: function.prototype.bind: function.prototype.bind: function.prototype.bind

// Determine if the prototype of the Function object in the current environment has a bind method, if not, we can add one ourselves
if (!Function.prototype.bind) {
  /** * Add bind method * @param oThis target object * @returns {function(): *} return copy function */
  Function.prototype.bind = function(oThis) {
    if (typeof this! = ='function') {
      // closest thing possible to the ECMAScript 5
      // The closest implementation of ECMAScript 5
      // internal IsCallable function
      // Internal IsCallable function (🙄 what the heck)
      // If this object is not function, throw an error, because only function needs to implement bind... It's a return function, after all
      throw new TypeError('Function.prototype.bind - what is trying to be bound is not callable');
    }
    // Declare the variable aArgs to hold an array of arguments other than the first argument in arguments, because the first argument is not the argument the function needs, but the target object to bind to
    // Arguments is an Array object. There is no slice method, so only one call from Array can be used
    var aArgs = Array.prototype.slice.call(arguments.1);
    // Save the original this object. If no target object is passed in when bind is called, use the original this object
    var fToBind = this;
    // Declare an empty function, which can be used in the following prototype
    var fNOP = function() {};
    // Copy the body of the function that needs to be put back, as we know from the last return, and the last return is the fBound method
    var fBound  = function() {
        // when this instanceof fBound === true, the returned fBound is called as a constructor for new
        Bind initializes the parameters, or passes the parameters when bind is called later
        return fToBind.apply(
          // Determine if the original this object is an instance of fBound, or if the prototype chain of this has fBound
          this instanceof fBound
            // If so, use the original this
          ? this
            // If not, use the current passed this object
          : oThis,
          // Get the arguments to the call (fBound). This is how the function inputs returned by bind are usually passed
          // This step ensures that the parameters passed to bind will work if no arguments are passed
          aArgs.concat(Array.prototype.slice.call(arguments)));
      };

    // Maintain prototype relationships
    // Check if there is a prototype on the original this object
    if (this.prototype) {
      // Function.prototype doesn't have a prototype property
      // If there is a prototype on this object, change fNOP's prototype to this.prototype, then fNOP inherits from this
      fNOP.prototype = this.prototype;
    }
    // The descending code makes fbound. prototype an instance of fNOP, so
    // Return fBound as the constructor of new, and pass the new object as this. The __proto__ of the new object is an instance of fNOP
    // Since fNOP inherits from the original this object, the step here is to make the copy function have the original this object's prototype, inheriting from the same place and drawing from the same source
    fBound.prototype = new fNOP();
    // Returns the function that was copied
    return fBound;
  };
}
Copy the code

The code above I add annotations, convenient we can better understand, to understand the code above, the bind method is to know about, on other implementation principle May be a bit more code comments above, looking at very laborious, post without annotation code below, help you copy and paste the debugging

if (!Function.prototype.bind) {
  Function.prototype.bind = function(oThis) {
    if (typeof this! = ='function') {
      throw new TypeError('Function.prototype.bind - what is trying to be bound is not callable');
    }
    var aArgs = Array.prototype.slice.call(arguments.1);
    var fToBind = this;
    var fNOP = function() {};
    var fBound  = function() {
        return fToBind.apply(this instanceof fBound ? this : oThis, aArgs.concat(Array.prototype.slice.call(arguments)));
    };
    if (this.prototype) {
      fNOP.prototype = this.prototype;
    }
    fBound.prototype = new fNOP();
    return fBound;
  };
}
Copy the code

So it doesn’t take much code to implement bind

People’s dreams, they never end, do they?

Maybe 996.ICU does not play an essential role, but it lets us know that there are a group of lovely people who are struggling to make a living just like us. It lets us know that our circle is not small, but when we are not united, it is not bad to dare to do something about it.

Blogging while sick…

Ps: Blog can share technology, but also when the record of life, when I see it in the future, maybe I will say “is not stupid at that time”, but now I feel perfect


I’m a front end warrior, a front end elementary school.