Bind is especially important because of the presence of this in JS. It can explicitly and strongly bind this to a particular environment. Those who have used React should know how often bind occurs in code. Bind: bind bind: bind bind: bind bind: Bind bind: Bind bind: Bind bind: Bind bind: Bind bind: Bind bind: Bind bind: Bind bind: Bind bind: Bind

Bind = bind

Bind (bind)

The bind() method creates a new function, and when bind() is called, this of the new function is specified as the first argument to bind(), and the remaining arguments will be used as arguments to the new function.

Grammar:

function.bind(thisArg[, arg1[, arg2[, ...]]])
Copy the code

Parameter Description:

thisArg

  • The value passed to the target function as the this parameter when the binding function is called.
  • If the new operator is used to construct the binding function, this value is ignored.
  • When using bind to create a function in setTimeout (provided as a callback), any raw values passed as thisArg are converted to Object.
  • If bind’s argument list is empty, or thisArg is null or undefined, this executing the scope will be treated as thisArg for the new function.

arg1, arg2, …

  • Arguments that are preset into the argument list of the binding function when the target function is called

Here’s an example:

var value = 2;

var foo = { value: 1 };

function bar(name, age) { return { value: this.value, name: name, age: age } };

bar.call(foo, "Jack", 20); {value: 1, name: "Jack", age: 20}

var bindFoo1 = bar.bind(foo, "Jack", 20); // Return a function bindFoo1(); // {value: 1, name: "Jack", age: 20}

Copy the code

var bindFoo2 = bar.bind(foo, "Jack"); // Return a function bindFoo2(20); // {value: 1, name: "Jack", age: 20}

Call and apply also bind to this, but call and aplly execute directly. Bind returns a new function in which this is the context you specify. For example, the bar function above specifies a context in which this is foo, which is equivalent to a method specifying bar as foo.

Bind has the following features, which we can implement one by one:

  • You can specify this for the function execution
  • Returns a new function
  • You can pass in parameters
  • Implement creefaction

I think it is necessary to mention the above mentioned Currization, because the students who are not familiar with currization will close this page and go angrily when they see such a mouthful of words. In fact, Currization is a bluffing name, you call him parameter simplification, ah, to let you understand the simplification first

Currie,

The function of currization is to return a function from a function, call it by passing some arguments to it, and then return a function to process the remaining arguments

Let’s start with this chestnut:

Var add = function(x) {return function(y) {return x + y; // The final result is the amount of the argument passed twice}; };Copy the code

var increment = add(1); var addTen = add(10); increment(2); // 3 increment(6); // 7 addTen(2); // 12 add(1)(2); // 3 Call once

Here we define an add function that takes an argument and returns a new function. After you call Add, the returned function remembers the first argument to add in the form of a closure

There are scenarios where we need to call a function frequently if the function takes many arguments such as:

function add(x1,x2,x3,x4, Y1, y2) {return x1 + x2 + x3, x5 + y1, y2} / / call the add,2,3,4,45,90 (1) add,2,3,4,3453,50 (1) add,2,3,4,535,3450 (1)Copy the code

Have you noticed that the first four parameters are basically the same, except for the last two parameters that change constantly? There is no need to pass in the parameters again and again. Using the idea of Currization, we can write it like this:

function add(x1,x2,x3,x4) { return function(y1, Y2) {return x1+x2+x3+x5+y1+y2}} const add_ = add(1,2,3,4) add_(45,90) add_(345,50) add_(55,3450)Copy the code

If you are smart enough to know the benefits of currization, you can write less code and make your code more structured.

I’m going to bind it for you. Don’t worry, you see, the original function of bind is that I can pass in a couple of parameters when I bind, for example

Var bindFoo1 = bar.bind(foo,12,45) bindFoo1(5,88,5Copy the code

So the final parameters are 2,45,5,88,5. Is that familiar? That’s right, bind is also currified

The bind to realize

Well, that said, it’s pretty easy to get started, and it’s pretty refreshing to implement our function points:

  • You can specify this for the function execution
  • Returns a new function
  • You can pass in parameters
  • Implement creefaction

First of all:

For the first two function points, I can write with my eyes closed:

Function. Prototype. Bind_ = Function (CTX) {const self = this () {return self. Specify that the function executes this}}Copy the code

This is the simple version, which implements the first two features and continues to improve

Prototype. Bind_ = Function (CTX) {const self = this Array. The prototype. Slice. Call (1) the arguments, / / as a result of the bind parameter first is this object, the second start is the real parameters, So from a position 1 return to dividing up parameter function () {const args_2 = Array. The prototype. Slice. The call (the arguments) / / this is the bind returns the new function of input parameters, Return self.apply(CTX, args_1.concat(args_2))}} return self.apply(CTX, args_1.Copy the code

Verify:

var foo ={quota:45}

function calculate(x,y) { console.log(this.quota + x + y) }

var objCal = calculate.bind_(foo,20)

objCal(30)

Copy the code

// Output 95

This may seem like a good idea, but if you look closely, the document also reads:

Binding functions are automatically adapted to use the new operator to construct a new instance created by the target function. When a binding function is used to build a value, the supplied this is ignored. However, the supplied argument list is still inserted before the argument list at the time of the constructor call.

The function that bind returns could be used to create a new instance, ignoring the “this” information, but the argument is still useful.

Take the example above:

var foo ={quota:45}
function calculate(x,y) {
    console.log(this.quota + x + y)
}

foo.protype.name = 'foo---la' var objCal = calculate.bind_(foo,20)

Var newObjCal = new calculate(30) This. Quota = undefined, undefined + 20 + 30 NaN

Copy the code

NewObjCal. Name/foo/output - la

If you use the function that bind returns as a constructor, ignore this and just use it as a normal constructor.

Now that the requirements are clear, let’s complete the bind function we implemented in the simulation

Prototype. Bind_ = Function (CTX) {const self = this Array.prototype.slice.call(arguments,1) function newBind() { const args_2 = Array.prototype.slice.call(arguments) const reallyCtx = this instanceof newBind ? this : CTX // this is the function that you want to specify. If newBind is on the prototype chain of this, then this is the function returned by new bind. Return self. Apply (reallyCtx,args_1.concat(args_2))} newBind. Prototype =this.prototype Return newBind} return newBind}Copy the code

Verify:

var foo = {name:122} function bar() { console.log(this.name) this.age = 678 } var objBind = Hi.bind(foo) objBind()// Var newObj = new() // undefined newobj.age // 678Copy the code

Prototype =this.prototype. If I change the prototype of newBind, the new instance of newObj will change too. Bar.prototype. sex = 123 // newobj. sex = 123

  • One is throughObject.assign(this.prototype)Is assigned to the prototype of the return function, but this, like bind, is an ES5 feature and not supported in IE9 below
  • The second is to create a new constructor as a mediatorthis.prototypeAssign to the prototype of the new constructor and then assign the instantiated mediation instance to the prototype of the return function
Prototype. Bind_ = Function (CTX) {const self = this Array.prototype.slice.call(arguments,1) const newFun = function() {} function newBind() { const args_2 = Array.prototype.slice.call(arguments) const reallyCtx = this instanceof newFun ? this : Return self. Apply (reallyCtx,args_1.concat(args_2))} newfun.prototype = this.prototype NewBind. Prototype = new newBind (); newBind (); newBind (); Subsequent changes to the prototype of the function that calls bind do not affect the instance return newBindCopy the code

The final version:

Prototype. Bind_ = Function (CTX) {const self = this Array.prototype.slice.call(arguments,1) const newFun = function() {} function newBind() { const args_2 = Array.prototype.slice.call(arguments) const reallyCtx = this instanceof newFun ? this : ctx return self.apply(reallyCtx,args_1.concat(args_2)) } newFun.prototype = this.prototype newBind.prototype = new newFun() return newBindCopy the code

Wonderful!

conclusion

After this detailed analysis and step by step implementation, let us have a clear understanding of bind’s own functions and implementation. This is also the first time I’ve really started to look at bind in a comprehensive way. I’m really familiar with bind. I’ve been using bind for a long time and I don’t know why it works

reference

  • Muyiy. Cn/blog / 3/3.4….
  • MDN-Function.prototype.bind()

This article is formatted using MDNICE