Say I have an object called FieldEdit. I define the function constructor for this object, instantiate it via. var obj = new FieldEdit(), and define its methods by FieldEdit.prototype.<method name> = function() { ... }.
Under what situations would calling this object's methods within the objects' other methods (via. this.<method name>();) fail?
Note that I want to avoid posting a code sample for this if I can since I think this is simply a problem with my understanding of Javascript more than anything, really. I'm pretty sure my code is sound, to the best of my knowledge (and it's my knowledge that's the question here, besides).
The most likely scenario where this would reference an object other than FieldEdit during execution of FieldEdit methods is within a nested scope like a closure, an event handler, or any function or method called explicitly with .call(someOtherScope) or .apply(someOtherScope, args).
You can work around that, of course, by maintaining a variable reference to the FieldEdit instance and using FieldEditInstance.<method>() instead.
PrototypeJS allows you to wrap functions with Function.bind for this purpose, but it's easily accomplished otherwise, either with:
var FieldEditInstance = this;
obj.methodThatUsesACallback(function() {
// use that instead of this
});
OR
var FieldEditInstance = this;
var callback = function() {
// ...
};
// This is more or less what PrototypeJS' Function.bind produces
var boundCallback = function() {
return callback.apply(FieldEditInstance, arguments);
};
obj.methodThatUsesACallback(boundCallback);
Related
I'm trying to get under the covers a little bit and get to understanding and not regurgitating code. I'm aware that bind, call and apply change the execution context by modifying what this points to. What I do not understand, is are arenas in which these methods are indispensable and/or lead to much shorter code. Consider the following:
var person = {
firstName: 'john',
lastName: 'doe',
fullName: function () {
console.log(this.firstName + " " + this.lastName);
}
}
//#1, binder is an html button
$('#binder').click(person.fullName.bind(person)); //john doe
//#2, anonymous is an html button
$('#anonymous').click(function () {
person.fullName(); //john doe
});
//seems strange I see this application a lot 'borrowing' a method
//why?
var o = { firstName: 'obj', lastName: 'ect' };
person.fullName.call(o); //obj ect to console
I would like to know some general paradigms about when it's good practice and/or a huge time saver to use call and apply (and bind outside of the not using anonymous functions a la function #1)
To focus on where each of these features are indispensable, I would say
apply is most useful when dealing with variadic functions. It lets you convert an array of values into an argument list.
function logwrapper(f){
return function(){
console.log("called");
return f.apply(this, arguments);
}
}
var bar = function(){ ... }
var foo = logwrapper(bar);
bind is most useful when you want to pass a method into some code that expects just a function. A common example is settimeout and other functions that expect callbacks:
setTimeout(function(){ obj.meth(); }, 100); //handwritten callback
setTimeout(obj.meth.bind(obj), 100); //Function.prototype.bind
setTimeout(bind(obj, "meth"), 100); //Some JS libraries have functions that
//let you write the object only once.
Just keep in mind that IE <=8 does not support the native Function.prototype.bind. You might need to use a polyfill or helper library in that case.
call is mostly useful for borrowing methods, as you already noticed. If this is going to be useful or not is going to depend a lot on your particular use case but an important use that is very common is using array methods on the arguments. For historical reasons, arguments doesn't have any of the usual array methods (slice, map, etc) so you need to borrow them:
function myvariadic(x){
var rest = [].slice.call(x, 1);
}
Another example you might see is the hasOwnProerty method:
for(k in obj){
if(Object.prototype.hasOwnProperty.call(obj, k)){
....
}
}
This lets you call the real hasOwnProperty method even if the object shadows it with a hasOwnProperty key of its own.
Frankly I don't give a twopenny toss about good or bad practices.
If your aim is to understand anything at all, you'd better forget about them.
This being said, to understand when it is appropriate to use call/apply or bind, what you have to understand is closures, and the specific closure of this.
I use a broad definition of closure here. Not the one you will usually get in JavaScript technical chats, where we usually talk about lexical closures.
For the purpose of this little post, let's say a closure will be anything that provides a value for any variable (this included) that lives outside the current scope of the function you're focusing on.
bind, call and apply are basically there to supply a value for this (and some other arguments as an option).
It is only useful for two things:
invoke functions or methods of a given class to an object of a different class (or no class at all).
more on that later
supply a value for this in case the current closure does not suit your needs.
For instance, passing a reference to a method loses the connection to the underlying object instance. Or using a class prototype function. Or being called in the context of an event handler where JS has set this to the DOM element that caught the event.
call & apply
call will simply set this to the value of its first argument for this particular execution of the function.
Since creating objects is so easy in JS, you might want to do something like:
Worker = function ()
{
this.things_done = 0;
}
Worker.prototype = {
do_something: function (count)
{
this.things_done += count;
}
}
var worker= new Worker(); // Worker object
var wanabee_worker = { things_done: 100 }; // classless object
Et voilà! You've just created something that has no class relation with Worker but still can use Worker methods, since it has all the required properties defined.
worker.do_something.call (wanabee_worker, 10);
allows wanabee_worker to borrow unrelated object Worker's methods.
The opposite can also be used:
function reset_work_count ()
{
this.things_done = 0;
}
reset_work_count.call (worker);
Here we have a plain function that does not have anything to do with Worker, except it uses the same properties. call allows to apply it to a Worker object.
apply does exactly the same as far as this is concerned. The only difference is the way other arguments are passed.
bind
bind will create an internal closure and return a new wrapper function that will use the parameter passed to bind as a value for this.
Typical example: bind an event handler to a specific object.
$('#binder').click(person.fullName.bind(person));
Beneath the JQuery goo, what the code does eventually is
binder.addEventListener ('click', person.fullName.bind(person), false);
If the handler was simply defined as person.fullName, it would be called with this set to the DOM element that caught the event.
In that particular case, the closure of this provided by the JS engine does not suit our needs, so we provide an alternative one using bind.
Instead of person.fullName.bind(person), you could have used:
function() { person.FullName(); }
except that
the lambda function is cumbersome and obfucates the code,
bind is an internal construct that does the closure a bit more efficiently.
You could also imagine that the object used to handle the event will be dynamically allocated/computed by some proxy function. In that case, using bind would be useless since what we want is access to the methods that will allow us to use a lambda object as one of a working class.
function event_handler (param)
{
var obj = compute_lambda_obj ();
Worker.prototype.do_something.call (ojb, param);
}
(Obviously I'm not sure what the title of this should be.)
I'd like to be able to modify the prototypes of native objects with minimal risk (because trust me; I have heard over and over again how it's a mortal javascript sin).
My train of thought goes something like this: I can greatly reduce the possibility of conflicts if I can add my custom functions to a single object on a prototype rather than directly adding them to the prototype itself.
If I have the code,
String.prototype.foo = function() {
//do stuff
};
...obviously the keyword this references the string that called it. However, if I do something like,
String.prototype.foo = {};
String.prototype.foo.bar = function() {
//do stuff
};
...the keyword this references the object foo.
If there some way to overcome this?
The only way to overcome this would be to override the context using call:
String.prototype.foo.bar.call('hello'))
which works, but is pretty ridiculous.
You're better off (as you've already heard) avoiding modifying native prototypes, and instead having an object with your methods accepting the string as a parameter.
Well, there's a couple of ways to do this, depending on how much work you want to put in.
Using bind is the most straightforward way, but you have to define the string as a variable so you can pass a reference of it to bind:
String.prototype.foo = function() { console.log(this); }
String.prototype.foo.bar = function() { console.log(this); }
var g = "hi there";
g.foo() // Yields g
g.foo.bar() // Yields String.prototype.foo()
g.foo.bar.bind(g)() // Yields g again.
There may be another very hackish way to produce the desired result by creating getters and setters on String.prototype.foo so that String.prototype.foo.bar activates a function that returns a function bound to the instance that foo refers to. ??? Confusing.
What might be the best solution to reduce the possibility of conflicts, is to take advantage of prototypal inheritance and create your own sub prototype of the native String.
function MyString(string) {
this.foo = function() { //whatever };
this.foo.bar = (function() {}).bind(this);
this.toString = function() { return string; } // because toString is not generic.
}
MyString.prototype = new String();
Here, you're creating your own "sub-prototype" of the String prototype. It inherits all the properties of the String prototype and adds its own, all without altering the native strings at all. BONUS: this.foo and this.foo.bar will both refer to your instance.
var instance = new MyString("hi");
instance.foo(); // this == instance
instance.foo.bar(); // this == instance
instance.replace("i", "e"); // returns "he"
This maybe wasn't the answer you were looking for, but hopefully it will at least be helpful.
I'm reading the source from mongoose
Collection.prototype.onOpen = function () {
var self = this;
this.buffer = false;
self.doQueue();
};
I don't understand why the author assigns this to self and runs self.doQueue(). Why not just run:
this.buffer = false;
this.doQueue();
I'm new to javascript, thanks for help.
You're right, in this instance they could have simply used this.
The use of me or self is a bit of a hack to ensure the correct context of this is used, as within JavaScript the scope of this is variant. If for example you have an event trigger a function within your class, this would be different, and wouldn't be your object that houses the function, but instead the object that called the function. To resolve this people often use me or self to ensure they're referring to the correct object... this, as in the actual object.
Just to give more clarity to #richard said earlier,
Collection.prototype.onOpen = function () {
var self = this;
this.buffer = false;
this.onclick = function(){
//do some other operations here
//if you refer `this` here then, `this` will refer to present function not the above. so to make sure it is referring to exact object people pass this to `me` or `self`
self.doQueue();
}
};
The only reason you would usually do that is if the call to doQueue() is inside a block that will change the value of this such as another function.
In this case however it doesn't serve any purpose and was probably a remnant of older code that was not changed back.
Most likely the developer wanted consistency, but failed at doing so.
Otherwise you'd be using this in some functions, self in other functions and a mix of both in other functions, depending on where you use the object and if you use nested functions/callbacks.
By always assigning this to self and then using the latter you have one additional assignment at the very beginning of each function but you always use self to access the object.
However, what the developer did in the code you posted does not make much sense. He should either use self or this both times instead of a mix that is not even necessary.
self is a copy of 'this',but it always refer to the right object,and 'this' may not.
I want to create a javascript object that I can call any method on, without having to define them. Ideally i could call it as if it were a function, and it would call one function i've defined with the name of the function called as its argument.
So i would define an object with a callMethod(methodName) method, and when i called
thisObject.doAThing();
It would call thisObject.callMethod("doAThing");
is this possible in javascript?
No, that isn't possible. If a JavaScript object doesn't have a property then you can't treat the undefined value as a method.
In Firefox at least, you can use the magic method __noSuchMethod__ to accomplish your goal:
var o = {}
o.__noSuchMethod__ = function(id, args) { alert(id + args); }
o.foo(2,3) //will alert "foo" and "2,3"
Please note that this is not standard and is under consideration for removal, so it will not be added to V8.
Original Post (sorry, should have asked this question in q comments):
I'm having trouble seeing the point. If callMethod has access to a 'doAThing' method somewhere, why couldn't you just plug that in on instantiation of the object or whenever callMethod's sources had a new method added?
Not trying to badger you. Just trying to see if maybe somewhere in the mad mad mad world of the call/apply/prototype paradigm it's possible to accomodate what you're hoping to achieve some other way.
Edit added after this comment:
I want to create a proxy object that delegates its calls to another
object. – msfeldstein
Okay, prototype may be the answer then as it basically does act as a fallback for methods the object itself doesn't have. Every function has a prototype property that's just a plain vanilla object basically. When functions are used as constructors, methods and properties assigned to the constructor prototype become a fallback for constructor instances when you call properties on them that they don't have. You can add properties to that prototype object and they will effectively become available to instances that have already been created. So I'm thinking something like this in the case of associated objects:
//A js constructor is just a function you intend to invoke with the 'new' keyword
//use of 'this.property' will make that property public in the instance
//var effectively makes it private
//Constructors funcs differ from classes in that they don't auto-handle inheritance down to other constructors. You have to come up with a prototype merging scheme to do that.
function MyFacadeConstructor(){ //expected args are objects to associate
var i = arguments.length; //arguments is a collection of args all funcs have
while(i--){
var thisObj = arguments[i];
associateObjMethods(thisObj);
}
//makes it public method but allows function hoisting internally
this.associateObjMethods = associateObjMethods;
function associateObjMethods(obj){
for(var x in obj){
if(obj[x].constructor.name === 'Function'){ //normalize for <= IE8
MyFacadeConstructor.prototype[x] = obj[x];
//or if we literally want the other method firing in its original context
//MyFacadeConstructor.prototype[x] = function(arg){ obj[x](arg); }
//Not sure how you would pass same number of arguments dynamically
//But I believe it's possible
//A workaround would be to always pass/assume one arg
//and use object literals when multiple are needed
}
}
}
}
function FirstNameAnnouncer(){
this.alertFirst = function(){
alert('Erik');
}
}
var fNamer = new FirstNameAnnouncer();
var newFacade = new MyFacadeConstructor(fNamer);
//newFacade.alertFirst should work now;
newFacade.alertFirst();
//but we can also associate after the fact
function LastNameAnnouncer(){
this.alertLast = function(){ alert('Reppen'); }
}
var lNamer = new LastNameAnnouncer();
newFacade.associateObjMethods(lNamer);
//now newFacade.alertLast should work
newFacade.alertLast();
Now, if you want the context of the calling object to matter, I would recommend an event driven interface, which is something JS is very well suited to. Let me know if there's any aspects of the facade approach you're looking for that I haven't implemented here.
You can use Proxy object to intercept any method call.
function proxifyMethodCalls(obj) {
const handler = {
get(target, prop, receiver) {
return function (...args) {
console.log(`Intercepted '${prop}' with arguments ${JSON.stringify(args)}`);
target.callMethod(prop);
};
}
};
return new Proxy(obj, handler);
}
let obj = {
callMethod: (methodName) => {
console.log(`'callMethod' called with '${methodName}'`);
}
};
obj = proxifyMethodCalls(obj);
obj.doAThing(true);
I am trying to create a prototype/class that inherits from the object that is returned by a specific function. But I dont know what that object's name is?
For the instance var xhr = XMLHttpRequest(); what object is returned by xhr.responseXML;? Is it XMLDocument? Or maybe XMLDOM?
Also if I create the object var xmlDoc = new ActiveXObject("Microsoft.XMLDOM"); and call xmlDoc.load("xmlFile.xml" ); will it return the same type of object as xhr.responseXML;?
I am trying to do the following:
function XMLHandler()
{
this.xmlFile = "defaultXML.xml";
}
// Make XMLHandler inherit from Javascript object
XMLHandler.prototype = new XMLDocument();
XMLHandler.prototype.constructor = XMLDocument;
You shouldn't include unrelated questions in the same post. To address your second question about declaring a function within a "class":
Your first syntax, declaring it within the constructor, will pointlessesly overwrite myClass.prototype.publicFunct to point to a newly created function every time the constructor is called. That is, you will be creating an extra copy of the function with each call to the constructor, with myClass.prototype.publicFunct always pointing to the most recently created copy - or undefined until the constructor has been called at least once. Don't do this.
Your second option is simply invalid syntax in JavaScript.
Your third syntax is prefered. This will add the function to the prototype once.
Remember: JavaScript doesn't have classes as such, though you can sort of simulate them if you think it is worth the bother.
I can tell by your recent questions that you are thinking like Java, which this is not.
First question:
responseXML is different for each browser. Firefox gives a nsIDOMDocument, IE gives an IXMLDOMDocument and Webkit browsers depend on the responseType setting but will probably be Document. Since you cannot predict what it will be stop trying to extend it. In most cases the type isn't made available by the browser's API so javascript cannot extend it anyway.
Moreover, since JavaScript's inheritance is not class based you are forced into doing this:
XMLHandler.prototype = new XMLDocument();
...which simply does not work for your purpose. Any instance of XMLHandler will be built on an unrelated, empty document and not the document returned by responseXML. You have to use a wrapper here.
Second Question:
Of your 3 methods the first is equivalent to the last but more wasteful because it repeatedly sets the same function to the same prototype. The second is nonsensical, the syntax is broken. These are your real options:
// Instance method, every instance is given a copy of the function upon "new"
function MyClass()
{
this.publicFunct = function()
{
alert("public function");
};
}
// Prototypal method, only one copy of the function shared by all instances
function MyClass()
{
}
MyClass.prototype.publicFunct = function()
{
alert("public function");
};
// Shorthand method, same as prototypal but handy for several members at once
// It prevents MyClass from being a descendent of another type
function MyClass()
{
}
MyClass.prototype = {
// A colon is only acceptable in object notation
publicFunct: function()
{
alert("public function");
}
};
I would go with a prototypal method for efficiency unless you need to selectively add functions to a class. Your use of "public function" (also "class") seems like another symptom of an OOP background, there aren't any private functions in JavaScript so "public" has no place, all member functions are public. If at some point you do need a private function you can fake the effect with a closure.
(function() {
// Assignments are mostly global
MyClass = function() {};
MyClass.prototype.publicFunct = function()
{
privateFunct();
};
// These statements affect local scope
var foo = 'bar';
function privateFunct()
{
alert("public function");
}
})(); // These extra brackets cause the contents to be executed immediately
Having said that it is rare to need private functions and all JavaScript is visible anyway so it's not secret really. The above could be thwarted like this:
thief = {};
MyClass.prototype.publicFunct.call(thief);
// privateFunct is called by publicFunct in the context of the thief
You might as well accept that functions are public. You can go a step further and give up on classes altogether. Objects are just objects that happen to have some functions and those functions can even be shared with completely different objects.