admin管理员组文章数量:1417420
Is it possible to create an alternate of Array.forEach that automatically sets the context "this" to be the same context as when the method was invoked?
For example (not working, not sure why):
Array.prototype.each = function(fn) {
return this.forEach(fn, arguments.callee.caller);
}
function myFunction() {
this.myVar = 'myVar';
[1,2,3].each(function() {
console.log(this.myVar); // logs 'myVar'
});
}
Is it possible to create an alternate of Array.forEach that automatically sets the context "this" to be the same context as when the method was invoked?
For example (not working, not sure why):
Array.prototype.each = function(fn) {
return this.forEach(fn, arguments.callee.caller);
}
function myFunction() {
this.myVar = 'myVar';
[1,2,3].each(function() {
console.log(this.myVar); // logs 'myVar'
});
}
Share
Improve this question
asked Jun 5, 2014 at 4:43
Kirk OuimetKirk Ouimet
28.4k44 gold badges130 silver badges183 bronze badges
5
- Why would you want to do this? Seems like an XY problem to me... – elclanrs Commented Jun 5, 2014 at 4:51
- So I don't have to remember to bind or pass "this" everytime I loop over an array – Kirk Ouimet Commented Jun 5, 2014 at 18:41
-
1
The answer is clearly "no", a JavaScript function cannot determine the value of
this
in the caller. That's whyFunction.bind()
and arrow functions exist. – Wladimir Palant Commented Jul 17, 2014 at 10:15 - @WladimirPalant you should make that an answer and I'll accept it – Kirk Ouimet Commented Jul 24, 2014 at 3:23
- @Kirk: There are plenty of answers already, I'm not going to repeat what other people said. For example, thefourtheye said pretty much the same thing as me. – Wladimir Palant Commented Jul 24, 2014 at 5:57
5 Answers
Reset to default 9Array.forEach already takes a context argument as the optional last parameter,
(function() {
this.myvar = "myvar";
[1,2,3,4].forEach(function(v) {
console.log("v:"+v);
console.log("myvar="+this.myvar);
}, this);
})();
See MDN forEach
Also, the above examples (if we're not dealing with methods on instances regarding this
) work without using bind
or the optional context argument for forEach
, the following also works correctly:
function myFunction() {
this.myVar = 'myVar';
[1,2,3].forEach(function() {
console.log(this.myVar); // logs 'myVar'
});
}
myFunction();
Because javascript is functionally scoped, so the anonymous function can access the parent function's scope using this
and it logs correctly. this
only really bees problematic as a context when dealing with instance methods.
The answer is no, a JavaScript function cannot determine the value of this
in the caller.
You can bind the function passed with the current object, like this
function myFunction() {
this.myVar = 'myVar';
[1,2,3].forEach(function() {
console.log(this.myVar); // logs 'myVar'
}.bind(this));
}
In ECMA Script 6, you can use an Arrow function, like this
[1,2,3].forEach(() => {
console.log(this.myVar); // logs 'myVar'
});
An alternative to messing with the this
variable when passing around callbacks, you could always just assign this
to a new variable so child scoped functions can access it:
Array.prototype.each = function(fn) {
return this.forEach(fn, arguments.callee.caller);
}
function myFunction() {
var me = this;
me.myVar = 'myVar';
[1,2,3].each(function() {
console.log(me.myVar); // logs 'myVar'
});
}
now you don't have to remember to pass this
as a second parameter
Firstly, it must be pointed out that myFunction
is a constructor. Yet, the first letter in the identifier is not capitalized. Please call it MyFunction
.
If a constructor is called without the new
operator, this
is bound to the global object, i.e. window
in browsers. This makes the capitalization convention our only way of spotting such mishaps.
The following lines of code demonstrate this:
// After the original code...
myFunction();
console.log(window.myVar); // logs "myVar"
Secondly, to be able to apply functions on any array, instead of changing Array.prototype
, consider the following:
var utils = {array: {}}; // utils.array is a container for array utilities.
utils.array.each = function (array, func) {
var i;
for (i = 0; i < array.length; i += 1) { func(array[i]); }
};
utils.write = function (s) {
console.log(s); // Alternatively, document.write(s);
};
utils.array.each([1, 2, 3], utils.write); // prints 1 2 and 3 (on separate lines)
Notice that we didn't use this
and new
. They make JavaScript look like Java, apart from that, they rarely serve a useful purpose.
While libraries may modify Object.prototype
and Array.prototype
, end-developers shouldn't.
Also, we should (ideally) be able to do something like:
utils.array.each([1, 2, 3], console.log);
orutils.array.each([1, 2, 3], document.write);
.
But most browsers won't allow it.
Hope this helped.
If I understand your requirement correctly, then you are trying to override the "this". I think this can help you.
本文标签: javascriptModifying ArrayforEach to Automatically Set the Context to be the CallerStack Overflow
版权声明:本文标题:javascript - Modifying Array.forEach to Automatically Set the Context to be the Caller - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1745266379a2650627.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论