Home >Web Front-end >JS Tutorial >An article teaches you about the soft binding of this in JavaScript

An article teaches you about the soft binding of this in JavaScript

无忌哥哥
无忌哥哥Original
2018-07-20 09:28:111357browse

First of all, what is soft binding?

The so-called soft binding is a word corresponding to hard binding. Before explaining soft binding in detail, let’s take a look at hard binding first. In JavaScript, the binding of this is dynamic. It is bound when the function is called. What it points to depends entirely on where the function is called. The situation is more complicated. The binding rules alone include default binding and implicit binding. Defined, explicit binding, new binding, etc., and hard binding is a type of explicit binding, usually by calling a function apply(), call() Or the bind() method provided in ES5 to implement hard binding.

What are the problems with hard binding? Why do we need soft binding?

The above three methods are good. You can force this of the function to the specified object according to your own ideas ( In addition to using new binding to change hard binding), there is a problem with hard binding, which is that it will reduce the flexibility of the function, and after hard binding, you can no longer use implicit binding or explicit binding to modify this pointing.

In this case, an implementation called soft binding appears, that is, through soft binding, we hope that this will no longer point to the global object by default (non-strict mode) or undefined (strict mode), but points to an object outside the two (this has the same effect as hard binding), but at the same time retains the difference between implicit binding and explicit binding The ability pointed to by this can then be modified.

The specific implementation of soft binding

Here, I use the code implementation of soft binding in "JavaScript You Don't Know":

if(!Function.prototype.softBind){ 
    Function.prototype.softBind=function(obj){ 
        var fn=this;
        var args=Array.prototype.slice.call(arguments,1);
        var bound=function(){ 
            return fn.apply( (!this||this===(window||global))?obj:this,
            args.concat.apply(args,arguments));
            };
        bound.prototype=Object.create(fn.prototype);
        return bound;
        };
}

Let’s take a look at the effect first, and then discuss its implementation.

function foo(){
    console.log("name: "+this.name);
    }
var obj1={name:"obj1"},
obj2={name:"obj2"},
obj3={name:"obj3"};
var fooOBJ=foo.softBind(obj1);
fooOBJ();//"name: obj1" 在这里软绑定生效了,成功修改了this的指向,将this绑定到了obj1上1
obj2.foo=foo.softBind(obj1);
obj2.foo();//"name: obj2" 在这里软绑定的this指向成功被隐式绑定修改了,绑定到了obj2上
fooOBJ.call(obj3);//"name: obj3" 在这里软绑定的this指向成功被硬绑定修改了,绑定到了obj3上
setTimeout(obj2.foo,1000);//"name: obj1"18 
/*
*回调函数相当于一个隐式的传参,如果没有软绑定的话,这里将会应用默认绑定将this绑定到全局环
*境上,但有软绑定,这里this还是指向obj1
*/

You can see that the soft binding has taken effect. Let’s take a closer look at the implementation of softBind().

In the first line, first pass the judgment. If there is no softBind() method on the prototype of the function, add it, and then pass Array.prototype.slice.call( arguments,1) Get the incoming external parameters. This is actually done here for function currying, that is, it allows some parameters to be set in advance during soft binding and then passed in when calling the function. Other parameters (you can search the Internet for detailed explanations about function currying) finally return a bound function to form a closure. At this time, when the function calls softBind() After that, what you get is the bound function, such as the above var fooOBJ=foo.softBind(obj1).

In the bound function, it will first determine the calling position of the function (such as fooOBJ) after calling the soft binding, or the point of its this. If !this (this points to undefined ) or this===(window||global) (this points to the global object), then bind this of the function to the parameter obj passed in softBind. If this does not point to undefind or the global object at this time, then bind this to the function it is currently pointing to (that is, implicit binding or explicit binding). The second parameter of fn.apply is the parameters required to run foo, which is connected by the above args (external parameters) and the internal arguments (internal parameters), which is the currying mentioned above.

In fact, when I read this function for the first time, I was a little confused. I had some questions, such as the sentence var fn=this. When foo calls softBind through foo.softBind(), who does fn point to? ? Is it pointing to foo or softBind? We can write a demo test, and then we can clearly see what fn points to:

var a=2; 
function foo(){ 
}
foo.a=3;
Function.prototype.softBind=function(){ 
    var fn=this;
    return function(){
        console.log(fn.a);
    }
};
Function.prototype.a=4;
Function.prototype.softBind.a=5;
foo.softBind()();//3
Function.prototype.softBind()();//4

It can be seen that the point of fn (or this) still follows the binding rules of this Yes, softBind function is defined in Function’s prototype Function.prototype, but functions in JavaScript will never “belong” to an object (unlike definitions in classes in other languages ​​such as Java method), but this function is referenced internally in the object, so when called in the following two ways, fn (or this) is implicitly bound to foo and Function.prototype# respectively. ## , so output 3 and 4 respectively. The following fn.apply() is equivalent to foo.apply().

The above is the detailed content of An article teaches you about the soft binding of this in JavaScript. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn