function bindings are probably the least bit of a concern when you start using JavaScript, but when you realize that you need a solution to solve how to keep the this context in another function, what you really need is Function.prototype.bind (), but you may still not be aware of this.
The first time you encounter this problem, you may prefer to set this to a variable so that you can continue referencing it after changing the context. Many people choose to use Self, _this or context as the variable name (and others use that). These methods are useful and of course there is no problem. But there is a better, more dedicated way.
What is the problem we really need to solve?
In the example code below, we can justifiably cache the context into a variable:
var myObj = {specialfunction: function function () {}, Getasyncdata: functio n (CB) {CB (); }, Render: function () { var that = this ; this . Getasyncdata (function Span style= "color: #000000;" > () {that.specialfunction (); That.anotherspecialfunction (); }); }}; Myobj.render ();
If we simply use This.specialfunction () to invoke the method, we will receive the following error:
Uncaught typeerror:object [Object Global] has no method ' specialfunction '
We need to keep a reference to the MYOBJ object context for the execution of the callback function. Calling That.specialfunction () allows us to maintain the scope context and execute our functions properly. However the use of Function.prototype.bind () can have a more concise and clean way:
function () { this. Getasyncdata (function ()} {This. Specialfunction (); This . Anotherspecialfunction (); }. Bind (this)); }
What did we just do?
. Bind () Creates a function that, when called, the This keyword is set to the value passed in (this refers to the parameter passed in when bind () is called). So we pass in the desired context, this (which is actually MYOBJ), into the. bind () function. Then, when the callback function is executed, this points to the MYOBJ object.
If you are interested in knowing what the Minister of Function.prototype.bind () is and how it works, here is a very simple example:
function (scope) { varthis; return function () { return fn.apply (scope);} ;}
There is also a very simple use case:
var foo = { 3varfunction() { Console.log (this //undefined var boundfunc =//3
We have created a new function, and when it is executed, its this will be set to foo--instead of the global scope as we call Bar ().
Browser support
Browser |
Version | Support
Chrome |
7 |
Firefox (Gecko) |
4.0 (2) |
Internet Explorer |
9 |
Opera |
11.60 |
Safari |
5.1.4 |
As you can see, unfortunately, Function.prototype.bind is not supported in the IE8 and below, so if you do not have a fallback option, you may run into problems.
Fortunately, the Mozilla Developer Network (a great repository) provides an absolutely reliable alternative to browsers that do not have their own implementation. Bind () Method:
if(!Function.prototype.bind) {Function.prototype.bind=function(othis) {if(typeof This!== "function") { //closest thing possible to the ECMAScript 5 internal iscallable function Throw NewTypeError ("Function.prototype.bind-what is trying to be bound are not callable"); } varAargs = Array.prototype.slice.call (arguments, 1), Ftobind= This, Fnop=function() {}, Fbound=function () { returnFtobind.apply ( This instanceofFnop && othis? This: Othis, Aargs.concat (Array.prototype.slice.call (argume (NTS))); }; Fnop.prototype= This. prototype; Fbound.prototype=NewFnop (); returnFbound; };}
Applicable mode
In learning the technical point, I found that the useful is not only to thoroughly learn and understand the concept, but also to see in the work at hand there is no place to apply it, or more close to it's things. I hope that some of the examples below will apply to your code or solve the problem you are facing.
Click Handlers (TAP processing function)
One purpose is to record a click event (or to perform an action after a click), which may require us to store some information in an object, such as:
var logger = { 0, function() { this. x + +; Console.log (this. x); }}
We may specify the click handler function in the following way, and then call the Updatecount () method in the Logger object.
function () { logger.updatecount ();});
But we have to create an extra anonymous function to make sure that the This keyword in the Updatecount () function has the correct value.
We can use the following cleaner way:
Document.queryselector (' button '). AddEventListener (' Click ', Logger.updateCount.bind (logger));
We cleverly used the convenient. Bind () function to create a new function and bind its scope to the Logger object.
SETTIMEOUT
If you have used a template engine (such as handlebars) or have used some mv* frameworks in particular (I can only talk about backbone.js from my experience), then you might be aware of the problems discussed below about accessing the new DOM node immediately after rendering the template.
Suppose we want to instantiate a jquery plugin:
var myView = {Template: '/* a < Select/> Template String */' ' #content ' function () { this . $el. Find (' SELECT ' function () { this . $el. html (this .template ()); this .afterrender (); }} myview.render ();
You may find it works-but not every time, because there are problems. This is a competition problem: only the first arrival can win. Sometimes the rendering is first, and sometimes the plugin is instantiated first. The Translator notes: If the rendering process has not been completed (DOM node has not been added to the DOM tree), then find (' select ') will not be able to find the corresponding node to perform the instantiation. 】
Now, perhaps not a lot of people know, we can use SetTimeout () based slight hack to solve the problem.
Let's rewrite our code a little bit and then safely instantiate our jquery plugin after the DOM node is loaded:
function () { this. $el. Find (' select '). Myplugin (); }, function () { this. $el. html (this. Template ()); SetTimeout (this. AfterRender, 0);
However, what we get is the function. AfterRender () cannot find the error message.
What we're going to do next is use. bind () in our code:
function ( ) { this. $el. Find (' select '). Myplugin ();}, function () { this. $el. html (this. Template ()); SetTimeout (this. Afterrender.bind (This), 0); //
Source: http://blog.jobbole.com/58032/
Reference: Https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Function/bind
In-depth understanding of Function.prototye.bind in JavaScript