Here I have copied code snippet from MDN :
function LateBloomer() {
this.petalCount = Math.ceil(Math.random() * 12) + 1;
}
// Declare bloom after a delay of 1 second
LateBloomer.prototype.bloom = function() {
window.setTimeout(this.declare.bind(this), 1000);
};
LateBloomer.prototype.declare = function() {
console.log('I am a beautiful flower with ' +
this.petalCount + ' petals!');
};
var flower = new LateBloomer();
flower.bloom();
// after 1 second, triggers the 'declare' method
The most confusing part is : window.setTimeout(this.declare.bind(this), 1000);
I understand how this
works and this
inside settimeout is always bound to global object.I know there can be var self or var that inside bloom function.
There are two this
in that line but which this
refers to what and how that works is totally confusing.
How works?
Here I have copied code snippet from MDN : https://developer.mozilla/en/docs/Web/JavaScript/Reference/Global_objects/Function/bind
function LateBloomer() {
this.petalCount = Math.ceil(Math.random() * 12) + 1;
}
// Declare bloom after a delay of 1 second
LateBloomer.prototype.bloom = function() {
window.setTimeout(this.declare.bind(this), 1000);
};
LateBloomer.prototype.declare = function() {
console.log('I am a beautiful flower with ' +
this.petalCount + ' petals!');
};
var flower = new LateBloomer();
flower.bloom();
// after 1 second, triggers the 'declare' method
The most confusing part is : window.setTimeout(this.declare.bind(this), 1000);
I understand how this
works and this
inside settimeout is always bound to global object.I know there can be var self or var that inside bloom function.
There are two this
in that line but which this
refers to what and how that works is totally confusing.
How works?
Share Improve this question asked Aug 3, 2016 at 7:18 SiddharthSiddharth 5232 gold badges5 silver badges10 bronze badges 1-
Both
this
's are the same object.Bind
returns the function with the context orthis
explicitly set. so whensetTimeout
eventually runs it can't overridethis
to global so it remains set to thethis
of thebloom
method. – ste2425 Commented Aug 3, 2016 at 7:38
3 Answers
Reset to default 8First of all read this article, which offers a very nice explanation about how this
works.
.bind(this, args)
just helps you to pass your this
context inside your function (because inside it in your example by default this
is undefined
or refers to window
).
Also bind
is a nice alternative to this:
// Declare bloom after a delay of 1 second
LateBloomer.prototype.bloom = function() {
var self = this;
window.setTimeout(self.declare, 1000);
};
And as the last point in es6
you can do it in this way:
window.setTimeout(() => {
//do some stuff
}, 1000);
instead of
window.setTimeout(function () {
//do some stuff
}.bind(this), 1000);
this allow you to not think about this
.
MSDN defines Function.prototype.bind()
as,
The bind() method creates a new function that, when called, has its this keyword set to the provided value, with a given sequence of arguments preceding any provided when the new function is called.
By using .bind(this)
we are passing this
to the function declare
See this snippet.
function LateBloomer() {
console.log(this.constructor);
this.petalCount = Math.ceil(Math.random() * 12) + 1;
}
// Declare bloom after a delay of 1 second
LateBloomer.prototype.bloom = function() {
window.setTimeout(this.declare.bind(this), 1000);
};
LateBloomer.prototype.undefinedbloom = function() {
window.setTimeout(this.declare, 1000);
};
LateBloomer.prototype.declare = function() {
console.log(this.constructor);
console.log('I am a beautiful flower with ' +
this.petalCount + ' petals!');
};
var flower = new LateBloomer();
flower.bloom();
flower.undefinedbloom();
In the function undefinedbloom
we are just calling the declare function. So the object will be the window
object. It doesn't have property petalCount
so its undefined.
In the function bloom
we are binding the this
of LateBloomer
to the declare function by which we will have access to the LateBloomer
's object petalCount
.
this
in JavaScript is a very difficult to fathom at first.
MDN Link: https://developer.mozilla/en/docs/Web/JavaScript/Reference/Operators/this
function LateBloomer() {
this.name = 'triven'; //simplified property
}
// Some thoughts we discuss main requirement.
LateBloomer.prototype.bloom = function() {
window.setTimeout(function() {console.log(this);}, 1000); //Logs window: We all know that keyword this INSIDE CALLBACK
//function refers to Window [Comment 1]
//window.setTimeout(console.log(this), 1000); /Attentions: Here it is very easy to MISUNDERSTAND
//that keyword this is inside setTimeout and it should refer to window.
//Please note that here keyword this is not INSIDE CALLBACK function so here
//keyword this will refer to object on which its wrapper function is
//executed(in our case flower). [Comment 2]
};
//The requirement: We need to call .bloom and it should log name after 1 second.
LateBloomer.prototype.bloom = function() {
//here keyword this refers to object
//window.setTimeout(function() {console.log(this);}, 1000); //But inside callback keyword this refers to window.
};
//We need some way to access object inside call back function so that its name can be accessed after 1 sec.
//step 1; Taking out anonymous function and adding it as a prototype property
LateBloomer.prototype.bloom = function() {
//window.setTimeout(this.callback, 1000); //Note: Keyword this is not inside callback so
//it is referring to object (not window). We can access newly
//defined function on the object. Also keyword this placed inside callback
//function(below) will still refer to window.
};
LateBloomer.prototype.callback = function() {console.log(this.name);}
//step 2; bringing .bind into picture.
//Definition of .bind as per MDN : The bind() method creates a new function
//that, when called, has its this keyword set to the provided value
LateBloomer.prototype.bloom = function() {
window.setTimeout(this.callback.bind(this), 1000); // Okay now we are now invoking .callback method on the object and
//passing the same object to bind.
// The keyword this inside newly return function (as a result of bind) will now refer to object
// we passed as argument to bind and we should not be able to access name property of our object.
// Note : Here both this keywords refers to same object ie on which which are calling .bloom.
//Note : we are no longer using passing callback function defined below. Instead we are now passing
// and exact copy of it but configuring it in such a way that keyword this start refering to object we passed.
};
LateBloomer.prototype.callback = function() {console.log(this.name);}
发布者:admin,转转请注明出处:http://www.yc00.com/questions/1743581903a4474377.html
评论列表(0条)