preface

Some time ago, I had a telephone interview, and I remember that there was a content in the interview, asking me about HTTP. I felt very happy in my heart. I read the HTTP diagram twice, and basically refined and recorded all the knowledge points. So easy?

Balabala talked a lot, from HTTP to HTTPS to HTTP2, and added a little bit of http3, and balabala talked a lot, full of confidence. Who knew? One question caught me.

Interviewer: Http2 is multiplexed. Why can’t HTTP1.x be multiplexed? Me: I said because http1.x comes in order. Interviewer: Yes, but why do HTTP1.x come in order? Me: well… I don’t know… Interviewer: HTTP/1.1 is based on text segmentation protocol, also does not have serial number, if multiplexing will result in order confusion,http2 uses frame, equal to cut into blocks, each block has a corresponding serial number, so can achieve multiplexing.

It’s not that this question is good or bad, but it makes me realize that I haven’t studied deeply enough. I should know what it is and why. Think more and sum up more questions, and then yesterday happened to see such an interview question on a little summary

The body of the

What is?

Apply,call, and bind are built-in apis that js uses to specify the execution of this and pass arguments to functions.

How does it work?

//apply 
func.apply(thisArg, [argsArray])

//call
fun.call(thisArg, arg1, arg2, ...)

//bind
const newFun = fun.bind(thisArg, arg1, arg2, ...)
newFun()
Copy the code

Apply and call pass different arguments, but both are functions that are called at the same time, while bind returns a function that is bound to this.

One other thing we need to know is what this points to.

This point

The orientation of this is determined during a function call. There are roughly five types of orientation of this.

1. Default binding

The default binding generally occurs in callback functions, which are called directly;

function test() {
    // Undefined in strict mode
    // Non-strict mode is Window
    console.log(this);
}
setTimeout(function () {
    //setTimeout is special
    // Both strict and non-strict modes are Windows
    console.log(this);
});

arr.forEach(function () {
    // Undefined in strict mode
    // Non-strict mode is Window
    console.log(this);
});
Copy the code

2. Implicit binding

This common point can be summed up in one sentence: whoever calls is to whom

    const obj = {
        name:'joy',
        getName(){
            console.log(this); //obj
            console.log(this.name); //joy}}; obj.getName();Copy the code

3. Display bind call,apply,bind

const obj1 = {
    name: 'joy',
    getName() {
        console.log(this); 
        console.log(this.name); }};const obj2 = {
    name: 'sam'
};

obj1.getName.call(obj2); //obj2 sam
obj1.getName.apply(obj2); //obj2 sam
const fn = obj1.getName.bind(obj2);
fn();//obj2 sam
Copy the code

4. The new binding

function Vehicle() {
    this.a = 2
    console.log(this);
}
new Vehicle(); // This refers to the object that comes out of Vehicle
Copy the code

5. Arrow functions in ES6

The arrow function in ES6 is special. The arrow function this is this in the parent scope, not this on the call. Remember that the first four methods are determined on call, which is dynamic, whereas the arrow function’s this pointer is static, which is determined when it’s declared. More in line with js lexical scope

window.name = 'win';
const obj = {
    name: 'joy'.age: 12.getName: (a)= > {
        console.log(this); // The parent scope of this is window, so it is window
        console.log(this.name); //win 
    },
    getAge: function () {
        // call obj.getAge, where this refers to obj
        setTimeout((a)= > {
            // So this also refers to obj so the result is 12
            console.log(this.age); }); }}; obj.getName(); obj.getAge();Copy the code

Since there are five ways to bind this, there must be a priority

Arrow functions -> New bind -> Show bind call/bind/apply -> Implicit bind -> Default bind

Here is a direct conclusion, interested partners can go to verify their own

To realize the apply

Let’s implement Apply first

  1. Extend the Function prototype with two methods and accept two parameters.
Function.prototype.myApply = function (context, args) {

}
Copy the code
  1. Because if you don’t pass the context,this will point to the window, and args will do some fault tolerance
Function.prototype.myApply = function(the context, the args) {/ / default is not on the window is here, you can also use es6 give parameters to set the default context = context | | window args = args? args : [] }Copy the code
  1. Remember that there are five ways to bind this, and now we’re going to bind this to the called function, and we’re not going to use the default binding and the new binding, so we’re going to use the implicit binding to implement the explicit binding
Function.prototype.myApply = function(the context, the args) {/ / default is not on the window is here, you can also use es6 give parameters to set the default context = context | | window args = args? Const key = Symbol() context[key] = this // Call context[key] by implicitly binding (... args) }Copy the code
  1. The last step is to return the return value of the function call, and delete the context properties so that it doesn’t matter
Function.prototype.myApply = function(the context, the args) {/ / default is not on the window is here, you can also use es6 give parameters to set the default context = context | | window args = args? args : Const key = Symbol() context[key] = this // Call the function const result = by implicitly binding context[key](... Args) // delete the added attribute delete context[key] // Returns the return value of the function callreturn result
}
Copy the code

Such a simple apply is implemented, there may be some boundary problems and misjudgments need to be improved, so I will not continue to optimize here

Now that Apply is implemented, call is also very simple, except that the parameters are passed differently

To realize the call

So let’s go straight to the code

// Pass parameters from an array to one by one instead of... Arguments can also be used instead of extension operators
Function.prototype.myCall = function (context, ... args) {
    // You can also use es6 to set default parameters for parameters
    context = context || window
    args = args ? args : []
    // Add a unique attribute to the context to avoid overwriting the original attribute
    const key = Symbol()
    context[key] = this
    // Call the function with an implicit binding
    constresult = context[key](... args)// Delete the added attribute
    delete context[key]
    // Returns the return value of the function call
    return result
}
Copy the code

To realize the bind

The difference between bind and apply is that bind returns a bound function, while apply calls directly. In fact, the implementation is very simple to think about, just return a function, which performs the above apply operation. Point, but there is a need to decide because returns the new function, want to consider to use the new call, and the new priority is higher, so you need to judge the new call, there is also a feature is the bind call can pass, after the call to generate the new function can also be spread, the effect is the same, so it will do a piece Since you’ve already implemented Apply, I’m going to borrow it, but actually not borrowing is just copying the code

Function.prototype.myBind = function(context, ... args) { const fn = this args = args ? args : []return functionnewFn(... newFnArgs) {if (this instanceof newFn) {
            returnnew fn(... args, ... newFnArgs) }return fn.apply(context, [...args,...newFnArgs])
    }
}
Copy the code

All of the above implementations could use a little more judgment, such as returning or throwing an error when calling something other than function. I won’t deal with it here

So that’s the implementation of apply, Call,bind

At the end

I have been in a daze on the road of learning, stumbling, hoping to become better and better, promoted as soon as possible. Think more, summarize more, practice more. Develop the habit of lifelong learning. Come on!