I'm learning javascript right now, seems like beautiful functional language to me, it is wonderful move from PHP, I should have done this earlier. Although, I cannot figure this one out:
var v1 = (/[abc]/).test;
v1('a');
says test method called on incompatible undefined, I'm trying to store the test method of that regex into variable and invoke it later.
but it works with my own functions:
function foo(){
return 'I\'m foo';
}
var f = foo;
f(); // returns I'm foo
It should work on methods too, since functions are just methods of parent object anyway, right?
Ultimately, the reason I'm trying this is to be able to write something like this:
var a = ['a', 'b', 'c'];
a.every( (/[abc]/).test );
to check each array member against that regex.
Why doesn't this work? Is it limitation in passing built-in functions around? Or am I just doing something wrong?
PS: If you grind your teeth now and muffling something about bad practices, screw good practices, I'm just playing. But I'd like to hear about them too.
it works with my own functions
You are not using this inside the function. Consider this example:
var obj = {
foo: 42,
bar: function() {
alert(this.foo);
}
};
var f = obj.bar;
f(); // will alert `undefined`, not `42`
It should work on methods too, since functions are just methods of parent object anyway, right?
"Method" is just a colloquial term for a function assigned to a property on object. And functions are standalone values. There is no connection to the object a function is assigned to. How would this even be possible, since a function could be assigned to multiple objects?
Why doesn't this work?
What this refers to inside a function is determined at run time. So if you assign the function to a variable and call it later
var v1 = (/[abc]/).test;
v1('a');
this inside the function will refer to window, not to the regular expression object.
What you can do is use .bind [MDN] to explicitly bind this to a specific value:
var a = ['a', 'b', 'c'];
var pattern = /[abc]/;
a.every(pattern.test.bind(pattern));
Note though that since .bind returns a function, the only advantage over using a function expression is that it is a tad shorter to write.
Is it limitation in passing built-in functions around?
No, the problem exists for every method/function because that's how functions work. The nice thing about built-in functions though is that they often explicitly tell you when this is referring to the wrong type of object (by throwing an error).
Learn more about this.
If you store just a method, it does not carry with it a reference to your object - it just stores a reference to the .test method, but no particular object. Remember, a method is "just" a property on an object and storing a reference to a method doesn't bind it to that object, it just stores a reference to the method.
To invoke that method on a particular object, you have to call it with that object.
You can make your own function that calls the method on the desired object like this:
var v1 = function(x) {
return /[abc]/.test(x);
}
Then, when you do this:
v1('a');
It will execute the equivalent of this in your function:
/[abc]/.test('a');
But, it isn't entirely clear why you're doing that as you could also just define the regex and call .test() on it several times:
var myRegex = /[abc]/;
console.log(myRegex.test('a'));
console.log(myRegex.test('b'));
console.log(myRegex.test('z'));
The test function expects this to be a regular expression. The expression /[abc]/.test gives an unbound function (it does not remember that it belongs to /[abc]/). When you invoke it like you do, this will be undefined and the function will fail.
You can use bind to make the function remember the object it belongs to:
var v1 = /[abc]/.test.bind(/[abc]/);
or
var v1 = RegExp.prototype.test.bind(/[abc]/);
Your reference to the method has lost its knowledge of what it was a method of.
This isn't so much good practice as just the way JS works.
You can do:
var v1 = /[abc]/;
v1.test('a');
If you must encapsulate the test method, then you could do:
var v1 = function(str){
return /[abc]/.test(str);
};
v1('a');
I don't know if this is an acceptable solution, but you can do:
v1 = function(exp) { return (/[abc]/).test(exp); }
v1('a');
Related
Is there an easier way to call filter on a prototype method without an anonymous function?
I wonder if there is an equivalent to myArray.filter(function(it){ it.method() }).
This looks close to what might work (it doesn't):
function X() {}
X.prototype.method = function() { console.log(this); }
[new X(), new X()].filter(X.prototype.method.call);
Instead I get a TypeError in both latest Firefox and Chrome, it's because it doesn't quite do what I want:
x = function() { console.log(this) }
x.call(123) //logs 123
y = x.call //reports that y is of type function in console
y(123) //TypeError: Function.prototype.call called on incompatible undefined
y.call(x, 123); //this is what you really need
I tried using bind, maybe I'm missing it, but if it's not a one-liner, it's not any better than the anonymous method form:
function X() {}
X.prototype.method = function() { console.log(this); }
y = X.prototype.method.call
y.bind(X.prototype.method)
[new X(), new X()].filter(y);
Let's set up some variables:
var method = X.prototype.method,
array = [new X(), new X()];
Your attempt can now be written as:
array.filter(method.call);
The problem is that call is getting called but with no this. It needs a this of method. method.call is precisely the same as the raw Function.prototype.call, with no binding to any this. Merely saying method.call does not give you a version of call bound to method. To arrange for call to be bound to the right this, namely method, you need to, well, bind it:
array.filter(method.call.bind(method));
Walking through this:
method.call.bind(method) returns a new
version of Function#call which is bound to X#method; think of it as
method.call(waiting), which is waiting to be called with a
value which will call X#method against a particular instance of X.
Array#filter passes each argument in the array to that bound version
of Function#call, which results in method.call(elt, remaining_args...),
which is the equivalent of elt.method(remaining_args...).
Output:
> array.filter(method.call.bind(method));
X {method: function}
X {method: function}
Some sugar
One could make this more semantic and readable with a little wrapper, which we will call thisify:
function thisify(fn) { return fn.call.bind(fn); }
array.filter(thisify(method));
Using the context parameter to filter
You could use the little-used context parameter of filter and its brethren (except reduce), essentially, letting filter do the binding for you, if you choose to look at it that way, since
Array#filter(fn, context) === Array#filter(fn.bind(context))
So we can just write:
array.filter(method.call, method);
That actually looks cleaner to me. I doubt if it could get much simpler than that.
Other than tricking existing functions that already implement this as something, why would you want to write a javascript function so that you need to alter its context (via .call or .apply) rather than explicitly passing the "context" as another parameter? Is there a performance benefit?
Example:
function tryIncrement(inc, context) {
context = context || this; // just so we can reuse same fn for the example
if( typeof context.val!= typeof 1|| typeof inc != typeof 1 ) return false;
context.val += inc;
return true;
}
var a = {name: 'A', val: 5}, b = {name: 'B', val: 20};
// reassign internal context
for(var i = 0, n = [1,3,"not a num",5]; i < n.length; i++) {
if( tryIncrement.call(a, n[i]) ) console.log('incremented', i, n[i], a);
else console.log('failed to increment', i, n[i], a);
}
// provide explicit context;
// could just as easily declared function so context was first param
// so it looked the same as previous implementation
for(var i = 0, n = [1,3,"not a num",5]; i < n.length; i++) {
if( tryIncrement(n[i], b) ) console.log('incremented', i, n[i], b);
else console.log('failed to increment', i, n[i], b);
}
There are many cases where you may wish to use this instead of passing an extra parameter. Consider the following function for example:
Function.prototype.async = function () {
setTimeout.bind(null, this, 0).apply(null, arguments);
};
This function allows us to defer a function call as follows:
alert.async("This will display later.");
alert("This will display first.");
You can see the demo here: http://jsfiddle.net/AjwQu/
Instead of binding the function to this we could have passed it as a parameter instead:
function async(funct) {
setTimeout.bind(null, funct, 0).apply(null, [].slice.call(arguments, 1));
}
We would use it like this now:
async(alert, "This will display later.");
alert("This will display first.");
The result is the same: http://jsfiddle.net/63dBF/
However to get the arguments we have to use [].slice.call(arguments, 1) instead. In the first example we could simply use arguments as the function was not a part of the argument list.
Everything has it's advantages and disadvantages. You just need to know what to use when. Hope this helps a bit.
Bonus: It's really easy to convert a function that uses this into a function that accepts an extra parameter and vice versa. First let's define a few utility functions:
var functProto = Function.prototype;
var bind = functProto.bind;
var bindable = bind.bind(bind);
var callable = bindable(functProto.call);
var appliable = bindable(functProto.apply);
The bindable function allows you to create a bindable version of an existing function which when called returns a new function bound to the given arguments.
The callable function allows you to create a callable version of an existing function which when called calls the existing function with the given arguments and this pointer.
The appliable function allows you to create an appliable version of an existing function which when called applies the given arguments and this pointer to the existing function.
Then given the function in the first example we can create the function in the second example as follows:
var async = callable(functProto.async);
See the demo here: http://jsfiddle.net/3dSBS/
Similarly we can convert the function in the second example into the function in the first example as follows:
Function.prototype.async = function () {
return async.apply(null, [this].concat([].slice.call(arguments)));
};
See the demo here: http://jsfiddle.net/rJQyS/
As you can see it's much easier to write a function using this and then construct the function accepting the context as a parameter from it than the other way around.
As far as I can tell the use of this isn't really any different than
another parameter, it just has a more complicated way of being
modified.
I think the easiest way to answer your question is to imagine if the creator of the base Javascript language had followed your conventions.
A world without this
A world without this is a scary noisy place with lots of excessive duplication:
var arr = [1,2,3,4];
arr.reverse(arr); //4321
More opportunities for misleading or verbose syntax
var str = "stringtobesplit";
"abiglongstringnotbeingsplit".split(str,":");
String.prototype.split(str,":");
And its not at all rid of apply at least:
Math.max.apply(arr); //didn't add the initial `this` since it doesn't exist
Effectively there would be a choice between creating only global functions, or creating functions on prototypes or objects that made assumptions about the types of the arguments it was receiving but didn't enforce those assumptions. For instance imagine the toString method in our fantasy world.
You could either create a global toString method which would take in an object of every type ever, and try to make them all work, or you could have a function on the prototypes of each type as it works currently, with no enforcement that it would be called on that type. Someone could call
Array.prototype.toString(str)
And we would need to handle it gracefully (for what its worth doing this with apply seems to revert to the Object.prototype.toString and returns [Object String]). So we would need to identify the correct prototype method to call in those cases, which means my guess is that the convention would be to call
str.toString(str)
or something along those lines.
So whats the point?
this is built to handle the common case for javascript methods on the prototype chain. It gives us a shorthand to allow an object to act on itself without duplicating the call to it or having to know exactly what its prototype is. Without it, we would either have to have no functions on objects, or would have to explicitly call the function on itself every time, introducing extra syntax and potential errors.
call and apply are the exception cases, and apply at least would have uses even if this went away. Its never a good idea to write your apis to the exception cases. If you're creating object oriented code, you should use this as an easy way to refer to the object that is the context for the call. If you write this well, then call and apply should be used rarely and in special situations.
TL;DR - this was designed as part of Javascript for a reason, use it when you're creating methods on objects for more clear and understandable syntax.
When you do object oriented programming your functions WILL depend on the context and it does not make sense do provide it as a parameter, as this would deafeat the purpose of object oriented programming.
It also makes sense to provide an implicit context for callbacks. You do not have to remember the correct order of the parameters if you only need the context. You would not have to use parameters at all in that case. So instead of
function mayCallback(param1, param2, context)
you could just write
function myCallback()
and use this, if you do not need param1 and param2.
To address my main purpose -- is there a performance benefit using this over a function parameter? -- the answer seems to be no:
http://jsperf.com/function-context-vs-parameter
Although there seems to be a slight benefit (may not be significant, however) around using parameter values instead of instance (this) variables within objects.
(Please test for yourself and comment if it's different)
Regarding the purpose being addressed by the other answers: there are some neat use cases as pointed out by #Aadit, maintainability is debatably a personal preference, but like #ben336 said if you're working with Objects (and thus OOP) then this can be more useful.
The ECMAScript 5th-edition native function bind may be an interesting bridge between the two worlds, or at least a time-sucking tangent to explore.
The instance vs parameter values test referenced above may also be a good example of my point -- if you're building a static library of functionality, you can "hijack" obj.callback2 by scoping to a different this, or just call obj.callback directly on your alternate context.
I study JavaScript Proxy Pattern, but I still do not get, where I can benefit from it. I would therefore like to provide you with two examples and kindly ask you to point at the difference between them.
Please, take a look at the code below:
What is the difference between the two addEventListener calls? One of them calls handleDrop in regular way. The other uses Proxy Pattern.
What will I gain using Proxy pattern approach?
I tested both functions, and they both call handleDrop successfully.
DndUpload.prototype.buildDropZone = function ()
{
var self = this,
this.dropZone.addEventListener('drop', function (e) { self.handleDrop.call(self, e) }, false);
this.dropZone.addEventListener('drop', self.handleDrop, false);
DndUpload.prototype.handleDrop = function (e)
{
alert("test");
...
};
}
You can provide me with good reference which contains very clear explanation of Proxy Pattern in JavaScript.
So what you're describing in your example isn't so much a demonstration of the Proxy pattern as much as a demonstration of confusion regarding the "calling object" and how it works in JavaScript.
In JavaScript, functions are "first-class." This essentially means that functions are data just like any other data. So let's consider the following situation:
var fn = (function () { return this.x; }),
a = {
x : 1,
fn : fn,
},
x = 2,
nothing = (function (z) { return z; });
So, we have an object a, which has two properties: fn and x. We also have variables x, fn (which is a function returning this.x), and nothing (which returns whatever it gets passed).
If we evaluate a.x, we get 1. If we evaluate x, we get 2. Pretty simple, eh? Now, if we evaluate nothing(a.x), then we get 1. That's also very simple. But it's important to realize that the value 1 associated with the property a.x is not in any way connected to the object a. It exists independently and can be passed around simply as a value.
In JavaScript, functions work the same way. Functions that are properties (often called "methods") can be passed as simple references. However, in doing so, they can become disconnected from their object. This becomes important when you use the this keyword inside a function.
The this keyword references the "calling object." That's the object that is associated with a function when that function is evaluated. There are three basic ways to set the calling object for a function:
If the function is called using the dot operator (e.g. a.fn()), the relevant object (in the example, a) is set as the calling object.
If the function is called using the function's call or apply properties, then you can explicitly set the calling object (we'll see why this is useful in a second).
If no calling object is set through method 1 or method 2, the global object is used (in a browser, this is typically called window).
So, back to our code. If we call a.fn(), it will evaluate as 1. That's expected because the this keyword in the function will be set to a due to the use of the dot operator. However, if we call simply fn(), it will return 2 because it is referencing the x property of the global object (meaning our global x is used).
Now, here's where things get tricky. What if you called: nothing(a.fn)()? You might be surprised that the result is 2. This is because passing a.fn into nothing() passes a reference to fn, but does not retain the calling object!
This is the same concept as what's going on in your coding example. If your function handleDrop were to use the this keyword, you would find it has a different value depending on which handler form you use. This is because in your second example, you're passing a reference to handleDrop, but as with our nothing(a.fn)() example, by the time it gets called, the calling object reference is lost.
So let's add something else to the puzzle:
var b = {
x : 3
};
You'll note that while b has an x property (and therefore satisfies the requirements for fn's use of this), it doesn't have a property referencing fn. So if we wanted to call the fn function with its this set to b, it might seem we need to add a new property to b. But instead we can use the aforementioned apply method on fn to explicitly set b as the calling object:
fn.apply(b); //is 3
This can be used to "permanently" bind a calling object to a function by creating a new function "wrapper." It's not really permanently binding, it's just creating a new function that calls the old function with the desired calling object. Such a tool is often written like so:
Function.prototype.bind = function (obj) {
var self = this;
return function() {
return self.apply(obj, arguments);
};
};
So after executing that code, we could do the following:
nothing(a.fn.bind(a))(); //is 1.
It's nothing tricky. In fact, the bind() property is built into ES5 and works pretty much like the simple code above. And our bind code is actually a really complicated way to do something that we can do more simply. Since a has fn as a property, we can use the dot operator to call it directly. We can skip all the confusing use of call and apply. We just need to make sure when the function gets called, it gets called using the dot operator. We can see how to do it above, but in practice, it's far simpler and more intuitive:
nothing(function () { return a.fn(); })(); //is 1
Once you have an understanding of how data references can be stored in closure scope, how functions are first-class objects, and how the calling object works, this all becomes very simple to understand and reasonably intuitive.
As for "proxies," those also exploit the same concepts to hook into functions. So, let's say that you wanted to count the number of times a.fn gets called. You can do that by inserting a proxy, like so (making use of some concepts from our bind code from above):
var numCalls = (function () {
var calls = 0, target = a.fn;
a.fn = (function () {
calls++;
return target.apply(a, arguments);
});
return (function () {
return calls;
});
}());
So now, whenever you call numCalls(), it will return the number of times a.fn() was called without actually modifying the functionality of a.fn! which is pretty cool. However, you must keep in mind that you did change the function referenced by a.fn, so looking way back to the beginning of our code, you'll notice that a.fn is no longer the same as fn and can't be used interchangeably anymore. But the reasons should now be pretty obvious!
I know that was basically a week of JavaScript education in a couple pages of text, but that's about as simple as it gets. Once you understand the concepts, the functionality, usefulness, and power of many JavaScript patterns become very simple to understand.
Hope that made things clearer!
UPDATE: Thanks to #pimvdb for pointing out my unnecessary use of [].slice.call(arguments, 0). I have removed it because it's, well, unnecessary.
Basically, passing self.handleDrop directly is functionally equivalent to passing the following function:
function() {
return self.handleDrop.apply(this, arguments);
}
because everything is passed through to the original function:
The this value
The arguments
The return value
With this in mind, compare your functions as follows:
function(e) { self.handleDrop.call(self, e) }
function() { return self.handleDrop.apply(this, arguments); }
The difference with your proxy way is:
It doesn't pass the return value through.
It doesn't pass all arguments through (only the first, e)
It doesn't pass the this value through, but uses a predefined one: self.
Now, the first two items don't make a difference here, because addEventListener doesn't care about the return value, and it also only passes one argument anyway.
But the third item is important: it sets a different this value in the function. By default, this is the element you bind the event to (it it set by the browser). Using the proxy way, you can set another this value.
Now, in your snippet it is not fully clear why you're setting a prototype function each time buildDropZone is called. Usually you define prototype functions only once. But when your handler handleDrop is called using the proxy way, this refers to the DndUpload instance, which is consistent with prototype functions in general.
Consider the code below:
function printThis() {
console.log(this);
}
var someObject = {
performTest : function() {
var self = this;
someOtherObject.higherOrderFunction(printThis);
someOtherObject.higherOrderFunction(function(){printThis.call(self)});
}
}
var someOtherObject = {
higherOrderFunction : function(f) {
f();
}
}
What will someOtherObject.higherOrderFunction(printThis) return?
How about someOtherObject.higherOrderFunction(function(){printThis.call(self)})
The answer to the first question depends on who and how you call someObject.performTest(). If I just call someObject.performTest() from a global context, it will probably print Window.
The second one will always print the someObject instance no matter what.
The closures or 'proxy pattern' as you call it comes in handy when you want to control exactly the execution context of a function.
Note: this in javascript does not behave like it does in other languages(in Java for example).
I'm using the following JavaScript code:
var emp= new Object();
emp["name"]="pooja";
emp["salary"]=725;
emp["paycheck"]=function()
{
var monthly=this["salary"]/12;
alert(this["name"]+":"+monthly);
};
emp["paycheck"](); --work properly
document.write("<br/>");
var f=emp["paycheck"]; --dosen't work
f();
f() have to get reference on emp["paycheck"] function and display a suitable answer.
but insted i get NaN.
As i understood f() dosen't see the property of emp object("name" and "salary").
My question is why f() dosen't see the properties?
You refer to salary as this["salary"]. If you store the function and call it later, the this value is lost. It is only bound to the object if you directly call it, as in emp.paycheck(). You could pass the this value explicitly, though:
f.call(emp);
But you might rather want to refer to salary in the function as emp["salary"], since that will always work.
Note that instead of foo["bar"] you can use foo.bar, and that the new Object() part can just be:
var emp = {
name: "pooja",
salary: 725,
paycheck: function() {
...
}
};
The reason why is you are calling the function without a this parameter. You need to use apply to pass it an explicit this on which it can call the name and salary properties.
f.apply(emp);
you reference on a function, not on all object.
f = emp;
f.paycheck();
You didn't copy those properties to f. There are, unfortunately, no native ways to do this in JavaScript. See How do I correctly clone a JavaScript object? or What is the most efficient way to deep clone an object in JavaScript?, look at jQuery's extend(), or google "javascript deep copy object" or "javascript clone object".
Others have explained what's going on and how you don't pass this.
However, if you want to do something like this (a custom from Python perhaps?), you can make a helper function:
function makeDelegate(obj, fun) {
return function() {
fun.apply(obj, arguments);
};
}
Then use it like this:
var f = makeDelegate(emp, emp["paycheck"]);
f();
I know PHP has call_user_func, I was just wondering if JavaScript had something similar, where the method I want to call is, for example: object.set$fieldID($fieldValue)
I would rather not go through if/else/switch blocks just to execute one line of code properly.
If it helps, I am using jQuery.
object["set" + $fieldID]($fieldValue);
Some reading material for the above: Member Operators on MDC.
Some advanced methods include Function.prototype.call and Function.prototype.apply. The first is somehow equivalent to PHP's call_user_func() while the latter is somehow equivalent to PHP's call_user_func_array().
The difference between PHP's functions and JavaScript's is that JavaScript allows you to call methods of some object in the context of another object. This is done through the use of the first argument of call() and apply().
An equivalent for the above example, but using call() and apply() looks like this:
object["set" + $fieldID].call(object, $fieldValue);
object["set" + $fieldID].apply(object, [$fieldValue]);
The first argument must be object otherwise the method will be executed with the this pointer bound to the global object, window in the case of browsers.
#lonut is correct. More generally though, if you want to call functions that aren't a part of an explicit object (e.g.: global), you can call them on the window object:
var foo = function() { alert(1); };
window['foo']();
since all objects are contained in window.
Another example:
var object = function() { this.method = function() { alert(2); }; }
var instance = new object();
window['instance']['method']();