Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Javascript > binding member functions

Reply
Thread Tools

binding member functions

 
 
Jens Thiele
Guest
Posts: n/a
 
      04-13-2004
i want to bind a member function
i hope this example will explain what i want to do
(it seems my solution works - but is there a better way?)

// first a simple function variable example
function foo(){
print("foo");
}
// prints foo and foo
function simpleTest(){
foo();
var x=foo;
x();
}
simpleTest();

// now i want to bind a member function to a function variable
// this will not work:
// x=foo.bar; (since "this" will be wrong)

function Foo(bar){
this.b=bar;
}
Foo.prototype.bar=function()
{
print (this.b);
}

function test() {
var foo=new Foo("bar");
foo.bar(); // print bar

// bind method - is there a simpler way ????
var x=function(y){var z=y;return function(){z.bar();}}(foo);

x(); // print bar
}

test();

 
Reply With Quote
 
 
 
 
Douglas Crockford
Guest
Posts: n/a
 
      04-13-2004
Jens Thiele wrote:

> i want to bind a member function
> i hope this example will explain what i want to do
> (it seems my solution works - but is there a better way?)
>
> // first a simple function variable example
> function foo(){
> print("foo");
> }
> // prints foo and foo
> function simpleTest(){
> foo();
> var x=foo;
> x();
> }
> simpleTest();
>
> // now i want to bind a member function to a function variable
> // this will not work:
> // x=foo.bar; (since "this" will be wrong)
>
> function Foo(bar){
> this.b=bar;
> }
> Foo.prototype.bar=function()
> {
> print (this.b);
> }
>
> function test() {
> var foo=new Foo("bar");
> foo.bar(); // print bar
>
> // bind method - is there a simpler way ????
> var x=function(y){var z=y;return function(){z.bar();}}(foo);
>
> x(); // print bar
> }
>
> test();


function bind(o, f) {
if (!isFunction(f)) {
f = o[f];
}
return isFunction(f) ? function () {
return f.apply(o, arguments);
} : null;
}

var x = bind(foo, 'bar');

http://www.crockford.com/javascript/remedial.html
 
Reply With Quote
 
 
 
 
Richard Cornford
Guest
Posts: n/a
 
      04-13-2004
Jens Thiele wrote:
<snip>

So what you want to do is call a function as a method of a particular
object instance, using a reference to a function.

> function test() {
> var foo=new Foo("bar");
> foo.bar(); // print bar
>
> // bind method - is there a simpler way ????
> var x=function(y){var z=y;return function(){z.bar();}}(foo);

<snip>

That is the pattern that works, but could be simpler as function
parameters act much like local variables (they both exist as named
properties of the Activation/Variable object belonging to the execution
context of their containing function call). So the code could be
simplified to:-

var x=function(y){return function(){y.bar();}}(foo);

Or made in to a general external function with a consequent reduction in
the number of function objects that need to be created during the
process. For example:-

function associateObjWithEvent(obj, methodName){
return (function(e){
e = e||window.event;
return obj[methodName](e, this);
});
}

- is a version I use for associating objects with DOM element event
handlers. It might be called in your context as:-

var x = associateObjWithEvent(foo, 'bar');

Though it was designed to have the returned function assigned to an
event handling property, so normal use would be:-

elRef.onclick = associateObjWithEvent(foo, 'bar');

- but you don't seem to want the parameter handling in the method call,
or the flexibility in method names used. So maybe:-

function associateObjWithBarCall(obj){
return (function(){
obj.bar();
});
}

- used as:-

var x = associateObjWithBarCall(foo);

Richard.


 
Reply With Quote
 
Jens Thiele
Guest
Posts: n/a
 
      04-14-2004
> That is the pattern that works, but could be simpler as function
> parameters act much like local variables (they both exist as named
> properties of the Activation/Variable object belonging to the execution
> context of their containing function call). So the code could be
> simplified to:-
>
> var x=function(y){return function(){y.bar();}}(foo);


Ah!
I still have many misconceptions about the language it seems.
It is indeed quite similar to scheme. But now I do not understand why
the following happens.

x=function(text){return function(){print(text);};}("hello world");
x(); // will print hello world as expected
foo={x:1,y:2}
foo.watch("x",x);
foo.x=10; // will print undefined and not hello world

i don't quite understand this
it seems in the second case the context is different

i tried the following:
x=function(text){return
function(){print("this:"+this);print("this.foomem: "+this.y);print("text:"+text);};}("hello
world");
x();
foo={x:1,foomem:2}
foo.watch("x",x);
foo.x=10;

output:
this:[object global]
this.foomem:undefined
text:hello world
this:[object Object]
this.foomem:undefined
text:undefined

=> the first time this is the global object the second time it is foo
does it matter?
text is not in the global object

I get something wrong here
any help?

 
Reply With Quote
 
Richard Cornford
Guest
Posts: n/a
 
      04-15-2004
Jens Thiele wrote:
<snip>
> ... . But now I do not understand why
> the following happens.
>
> x=function(text){return function(){print(text);};}("hello world");
> x(); // will print hello world as expected
> foo={x:1,y:2}
> foo.watch("x",x);


You have stumbled into a grey area here, the - watch - method of objects
did not make it into ECMA 262 and so does not have a public formal
specification. So exactly how it will behave where implemented is
uncertain.

My copy of the Netscape JavaScript 1.4 documentation says that -
obj.watch('propName', handler) - will call the - handler - when an
assignment is made to the property of - obj - with the specified name.
Calling it as - handler('propName' oldval, newval) and assigning the
function's return value to the property of - obj.

If the handler is an inner function then it should still have the
Activation/Variable object of its outer function's execution context in
its scope chain when it is called.

> foo.x=10; // will print undefined and not hello world
>
> i don't quite understand this
> it seems in the second case the context is different
>
> i tried the following:
> x=function(text){return
> function(){print("this:"+this);print("this.foomem: "+this.y);
> print("text:"+text);};}("hello world");
> x();
> foo={x:1,foomem:2}
> foo.watch("x",x);
> foo.x=10;
>
> output:
> this:[object global]


So which javascript implementation are you using? I don''t recall the
toString method of a global object ever returning that particular string
(not that I look at that string value often).

> this.foomem:undefined
> text:hello world


That all conforms to my expetations.

> this:[object Object]


But this is interesting, for the - this - keyword to refer to an object
the handler must have been called as a method of that object, and the
Netscape JavaScript 1.4 documentation does not mention that at all, the
expectation would be that - this - remained a reference to the global
object.

> this.foomem:undefined


However, the object that is being referred to by - this - is not the
object on which the - watch - method was called, else - this.foomem -
would not be undefined.

> text:undefined


By ECMA specification the only way that the - text - property of the
Activation/Variable object from the execution context of the outer
function, on the scope chain of the inner function, could be returning -
undefined - in the inner function is if an object higher in the scope
chain for the inner function's execution context had a defined property
named - text - that had an undefined value, masking the original -
text - parameter property.

It is not impossible for an implementation to add objects to the scope
chain of a function call, it is even common with event handling
functions generated from HTML attribute strings, but there doesn't seem
to be any reason for doing so in the context of - watch.

On the other hand, without a formal specification for - watch - it is
impossible to say what it should be doing when executing - handler -, it
could call - handler - as a method of some arbitrary object, and add any
number of unknown objects to the scope chain for the function call. And
nobody could say it was wrong for doing so.

> => the first time this is the global object the second time it is foo


It is not - foo - else - this.foomem - would return the value 2 rather
than undefined.

> does it matter?
> text is not in the global object
>
> I get something wrong here


You may be wrong to have expectation of methods outside of the ECMA
specification, though the behaviour of the implementation you are using
is certainly unexpected.

> any help?


There can be no help without knowing what you are trying to achieve.

Richard.


 
Reply With Quote
 
Jens Thiele
Guest
Posts: n/a
 
      04-15-2004
Richard Cornford wrote:
> You have stumbled into a grey area here, the - watch - method of objects
> did not make it into ECMA 262 and so does not have a public formal
> specification. So exactly how it will behave where implemented is
> uncertain.


it should get into ECMA - it is really useful

> My copy of the Netscape JavaScript 1.4 documentation says that -
> obj.watch('propName', handler) - will call the - handler - when an
> assignment is made to the property of - obj - with the specified name.
> Calling it as - handler('propName' oldval, newval) and assigning the
> function's return value to the property of - obj.
>
> If the handler is an inner function then it should still have the
> Activation/Variable object of its outer function's execution context in
> its scope chain when it is called.


yes this was my problem
with the example below I tried to understand why it does not work.
I am using spidermonkey - and this was a bug which is now fixed
(thanks to brendan)
see also:
<(E-Mail Removed)>
and
http://bugzilla.mozilla.org/show_bug.cgi?id=240577

>>foo.x=10; // will print undefined and not hello world
>>
>>i don't quite understand this
>>it seems in the second case the context is different
>>
>>i tried the following:
>>x=function(text){return
>>function(){print("this:"+this);print("this.foome m:"+this.y);


i had a bug here ^
this should be this.fooomem and not this.y
sorry for this one

> So which javascript implementation are you using? I don''t recall the
> toString method of a global object ever returning that particular string
> (not that I look at that string value often).


I am using spidermonkey and embedding it.

>>this.foomem:undefined
>>text:hello world

>
>
> That all conforms to my expetations.


yep to mine, too


>>this:[object Object]

>
>
> But this is interesting, for the - this - keyword to refer to an object
> the handler must have been called as a method of that object, and the
> Netscape JavaScript 1.4 documentation does not mention that at all, the
> expectation would be that - this - remained a reference to the global
> object.
>
>
>>this.foomem:undefined

>
>
> However, the object that is being referred to by - this - is not the
> object on which the - watch - method was called, else - this.foomem -
> would not be undefined.


this was my mistake see above (i do print this.y instead of this.foomem)
- sorry again


>>I get something wrong here

>
>
> You may be wrong to have expectation of methods outside of the ECMA
> specification, though the behaviour of the implementation you are using
> is certainly unexpected.


okay with the patch to spidermonkey, everthing works like expected
for the record (the script without my bug and the output of a fixed
spidermonkey version):

// first test
print ("First test output");
x=function(text){return function(){print(text);};}("hello world");
x(); // will print hello world as expected
foo={x:1,y:2}
foo.watch("x",x);
foo.x=10; // now will print hello world

// second test
print ("Second test output");
x=function(text){
return function(){
print("this:"+this);
print("this.foomem:"+this.foomem);
print("text:"+text);
};
}("hello world");
x();
foo={x:1,foomem:2}
foo.watch("x",x);
foo.x=10;

First test output
hello world
hello world
Second test output
this:[object global]
this.foomem:undefined
text:hello world
this:[object Object]
this.foomem:2
text:hello world

thanks
i am really happy now
(it works, and more important to me, my expectations were reasonable,
I thought that I still did not understand some basic language concept)

 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
overloading non-template member functions with template member functions Hicham Mouline C++ 1 04-24-2009 07:47 AM
overloading non-template member functions with template member functions Hicham Mouline C++ 0 04-23-2009 11:42 AM
Weak binding of member functions Vinay C++ 4 07-02-2004 01:31 AM
Data Binding - using inline code vs. functions vs. straight binding Jordan ASP .Net 2 02-10-2004 08:32 PM
How would I use qsort to sort a struct with a char* member and a long member - I want to sort in order of the long member Angus Comber C Programming 7 02-05-2004 06:41 PM



Advertisments