Still have a question about a common JavaScript routine

L

lorlarz

I still have a question regarding the following code,
in a commonly used routine. First, Here's the code in
question:

Function.prototype.bind = function(){
var fn = this, args = Array.prototype.slice.call(arguments), object =
args.shift();
return function(){
return fn.apply(object,
args.concat(Array.prototype.slice.call(arguments)));


};
};


var myObject = {};
function myFunction(){
return this == myObject;


}

In the code,
return fn.apply(object,
args.concat(Array.prototype.slice.call(arguments)));
,
it seems apply is getting an extra,
array element (because the first element in arguments
is still the object (the one setting the context of "this).

In short, it looks to me like the object element which
sets the context of "this" is in the final args array
twice (twice at the beginning of the array).

This can't be. I must be wrong, Please explain .
 
D

dhtml

lorlarz said:
I still have a question regarding the following code,
in a commonly used routine. First, Here's the code in
question:

Function.prototype.bind = function(){
var fn = this, args = Array.prototype.slice.call(arguments), object =
args.shift();
return function(){
return fn.apply(object,
args.concat(Array.prototype.slice.call(arguments)));


};
};


var myObject = {};
function myFunction(){
return this == myObject;


}

In the code,
return fn.apply(object,
args.concat(Array.prototype.slice.call(arguments)));
,
it seems apply is getting an extra,
array element (because the first element in arguments
is still the object (the one setting the context of "this).

The anonymous function's arguments object is not the same arguments
object of the enclosing bind function.

In short, it looks to me like the object element which
sets the context of "this" is in the final args array
twice (twice at the beginning of the array).

It would seem to be less confusing to pass in an actual parameter
variable for the context, and include a comment:-

/**
* @param {Object} context - the - this - value to be used.
* @param {arguments} [1..n] optional arguments that are prepended
* to returned function's call.
* @return {Function} a function that applies the original
* function with - context - as the thisArg.
*/
Function.prototype.bind = function(context){
...
}

This will affect the args variable and the way you call slice.

Take a closer look at args.shift, too.

http://bclary.com/2004/11/07/#a-15.4.4.9


Garrett
 
L

lorlarz

lorlarz said:
I still have a question regarding the following code,
in a commonly used routine.  First, Here's the code in
question:
Function.prototype.bind = function(){
var fn = this, args = Array.prototype.slice.call(arguments), object=
args.shift();
return function(){
return fn.apply(object,
args.concat(Array.prototype.slice.call(arguments)));
   };
};
var myObject = {};
function myFunction(){
return this == myObject;

In the code,
return fn.apply(object,
args.concat(Array.prototype.slice.call(arguments)));
,
it seems apply is getting an extra,
array element (because the first element in arguments
is still the object (the one setting the context of "this).

The anonymous function's arguments object is not the same arguments
object of the enclosing bind function.
In short, it looks to me like the object element which
sets the context of "this" is in the final args array
twice (twice at the beginning of the array).

It would seem to be less confusing to pass in an actual parameter
variable for the context, and include a comment:-

/**
  * @param {Object} context - the - this - value to be used.
  * @param {arguments} [1..n] optional arguments that are prepended
  * to returned function's call.
  * @return {Function} a function that applies the original
  * function with - context - as the thisArg.
  */
Function.prototype.bind = function(context){
  ...

}

This will affect the args variable and the way you call slice.

Take a closer look at args.shift, too.

http://bclary.com/2004/11/07/#a-15.4.4.9

Garrett

Your clarification was great and I understand and I
agree with your input as well. Thank you.
 
D

dhtml

lorlarz said:
lorlarz said:
I still have a question regarding the following code,
in a commonly used routine. First, Here's the code in
question:
Function.prototype.bind = function(){
var fn = this, args = Array.prototype.slice.call(arguments), object =
args.shift();
return function(){
return fn.apply(object,
args.concat(Array.prototype.slice.call(arguments)));
};
};
var myObject = {};
function myFunction(){
return this == myObject;
}
In the code,
return fn.apply(object,
args.concat(Array.prototype.slice.call(arguments)));
,
it seems apply is getting an extra,
array element (because the first element in arguments
is still the object (the one setting the context of "this).
The anonymous function's arguments object is not the same arguments
object of the enclosing bind function.
In short, it looks to me like the object element which
sets the context of "this" is in the final args array
twice (twice at the beginning of the array).
It would seem to be less confusing to pass in an actual parameter
variable for the context, and include a comment:-

/**
* @param {Object} context - the - this - value to be used.
* @param {arguments} [1..n] optional arguments that are prepended
* to returned function's call.
* @return {Function} a function that applies the original
* function with - context - as the thisArg.
*/
Function.prototype.bind = function(context){
...

}

This will affect the args variable and the way you call slice.

Take a closer look at args.shift, too.

http://bclary.com/2004/11/07/#a-15.4.4.9

Garrett

Your clarification was great and I understand and I
agree with your input as well. Thank you.

Well I didn't really help you all that much. But you could post up some
code to show us.

There may also be the consideration that this method does two things:
1) partial apply
2) bind

Most of the you won't usually need all of this functionality together.
And will just need a bind.

There are a few potential problems with adding Function.prototype.bind:

If, for example, the next version of EcmaScript includes
Function.prototype.bind, and it does it differently than your
user-defined one, it might confuse other programmers who looked at the
calls to the would-be non-standard bind.

Some versions of bind that I've seen just a bind (fast), while others
use partialApply + bind (slower).

Existing code stuck with a partialApply + bind assinged to
Function.prototype.bind could be tweaked for efficiency, refactored to
use some other approach that is efficient and uses a safer name,
allowing for the possibility of deprecating (not removing) the old
Function.prototype.bind.

Garrett
 
L

lorlarz

lorlarz said:
lorlarz wrote:
I still have a question regarding the following code,
in a commonly used routine.  First, Here's the code in
question:
Function.prototype.bind = function(){
var fn = this, args = Array.prototype.slice.call(arguments), object =
args.shift();
return function(){
return fn.apply(object,
args.concat(Array.prototype.slice.call(arguments)));
   };
};
var myObject = {};
function myFunction(){
return this == myObject;
}
In the code,
return fn.apply(object,
args.concat(Array.prototype.slice.call(arguments)));
,
it seems apply is getting an extra,
array element (because the first element in arguments
is still the object (the one setting the context of "this).
The anonymous function's arguments object is not the same arguments
object of the enclosing bind function.
In short, it looks to me like the object element which
sets the context of "this" is in the final args array
twice (twice at the beginning of the array).
It would seem to be less confusing to pass in an actual parameter
variable for the context, and include a comment:-
/**
  * @param {Object} context - the - this - value to be used.
  * @param {arguments} [1..n] optional arguments that are prepended
  * to returned function's call.
  * @return {Function} a function that applies the original
  * function with - context - as the thisArg.
  */
Function.prototype.bind = function(context){
  ...
}
This will affect the args variable and the way you call slice.
Take a closer look at args.shift, too.
http://bclary.com/2004/11/07/#a-15.4.4.9
Garrett
Your clarification was great and I understand and I
agree with your input as well.  Thank you.

Well I didn't really help you all that much. But you could post up some
code to show us.

There may also be the consideration that this method does two things:
1) partial apply
2) bind

Most of the you won't usually need all of this functionality together.
And will just need a bind.

There are a few potential problems with adding Function.prototype.bind:

If, for example, the next version of EcmaScript includes
Function.prototype.bind, and it does it differently than your
user-defined one, it might confuse other programmers who looked at the
calls to the would-be non-standard bind.

Some versions of bind that I've seen just a bind (fast), while others
use partialApply + bind (slower).

Existing code stuck with a partialApply + bind assinged to
Function.prototype.bind could be tweaked for efficiency, refactored to
use some other approach that is efficient and uses a safer name,
allowing for the possibility of deprecating (not removing) the old
Function.prototype.bind.

Garrett- Hide quoted text -

- Show quoted text -

Here is a script to put in a web page and run, using the
new bind method of functions:


Function.prototype.bind = function(){
var fn = this, args = Array.prototype.slice.call(arguments), object =
args.shift();
return function(){
return fn.apply(object,
args.concat(Array.prototype.slice.call(arguments)));


};



};


var myObject = {};
function myFunction(thename){

alert(thename);
return this == myObject;



}
alert((myFunction.bind(myObject, "joe"))());

Since the returned function gets all its arguments from
myFunction (the object using the new Function bind methed),
the second argument sent the returned function's first --
after the object is stripped of as its context.
 
L

lorlarz

lorlarz said:
lorlarz wrote:
I still have a question regarding the following code,
in a commonly used routine.  First, Here's the code in
question:
Function.prototype.bind = function(){
var fn = this, args = Array.prototype.slice.call(arguments), object =
args.shift();
return function(){
return fn.apply(object,
args.concat(Array.prototype.slice.call(arguments)));
   };
};
var myObject = {};
function myFunction(){
return this == myObject;
}
In the code,
return fn.apply(object,
args.concat(Array.prototype.slice.call(arguments)));
,
it seems apply is getting an extra,
array element (because the first element in arguments
is still the object (the one setting the context of "this).
The anonymous function's arguments object is not the same arguments
object of the enclosing bind function.
In short, it looks to me like the object element which
sets the context of "this" is in the final args array
twice (twice at the beginning of the array).
It would seem to be less confusing to pass in an actual parameter
variable for the context, and include a comment:-
/**
  * @param {Object} context - the - this - value to be used.
  * @param {arguments} [1..n] optional arguments that are prepended
  * to returned function's call.
  * @return {Function} a function that applies the original
  * function with - context - as the thisArg.
  */
Function.prototype.bind = function(context){
  ...
}
This will affect the args variable and the way you call slice.
Take a closer look at args.shift, too.
http://bclary.com/2004/11/07/#a-15.4.4.9
Garrett
Your clarification was great and I understand and I
agree with your input as well.  Thank you.

Well I didn't really help you all that much. But you could post up some
code to show us.

There may also be the consideration that this method does two things:
1) partial apply
2) bind

Most of the you won't usually need all of this functionality together.
And will just need a bind.

There are a few potential problems with adding Function.prototype.bind:

If, for example, the next version of EcmaScript includes
Function.prototype.bind, and it does it differently than your
user-defined one, it might confuse other programmers who looked at the
calls to the would-be non-standard bind.

Some versions of bind that I've seen just a bind (fast), while others
use partialApply + bind (slower).

Existing code stuck with a partialApply + bind assinged to
Function.prototype.bind could be tweaked for efficiency, refactored to
use some other approach that is efficient and uses a safer name,
allowing for the possibility of deprecating (not removing) the old
Function.prototype.bind.

Garrett- Hide quoted text -

Here is a script to put in a web page and run, using the
new bind method of functions:

Function.prototype.bind = function(){
var fn = this, args = Array.prototype.slice.call(arguments), object =
args.shift();
return function(){
return fn.apply(object,
args.concat(Array.prototype.slice.call(arguments)));

};

};

var myObject = {};
function myFunction(thename){

alert(thename);
return this == myObject;

}

alert((myFunction.bind(myObject, "joe"))());

Since the returned function gets all its arguments from
myFunction (the function using the new Function bind methed),
the second argument is the returned function's first --
after the object is stripped of as its context.
 
D

dhtml

I did not type that ^. Are you using Google Groups?

Here is a script to put in a web page and run, using the
new bind method of functions:

Function.prototype.bind = function(){
var fn = this, args = Array.prototype.slice.call(arguments), object =
args.shift();
return function(){
return fn.apply(object,
args.concat(Array.prototype.slice.call(arguments)));

};

};

var myObject = {};
function myFunction(thename){

alert(thename);
return this == myObject;

}

alert((myFunction.bind(myObject, "joe"))());

Since the returned function gets all its arguments from
myFunction (the function using the new Function bind methed),
the second argument is the returned function's first --
after the object is stripped of as its context.

Correct.

But why not pass in a parameter for the context?

Function.prototype.bind = function(context) {

};

I understood you were in agreement with what I wrote (not that you have
to be), and that was what I wrote in my initial reply.

The benefit would be that the code would be clearer because you wouldn't
have to call args.shift(). It would also be a little faster.

(It will be much easier to read your code if you indent your code with
spaces.)

Garrett
 
L

lorlarz

I did not type that ^. Are you using Google Groups?










Correct.

But why not pass in a parameter for the context?

Function.prototype.bind = function(context) {

};

I understood you were in agreement with what I wrote (not that you have
to be), and that was what I wrote in my initial reply.

The benefit would be that the code would be clearer because you wouldn't
have to call args.shift(). It would also be a little faster.

(It will be much easier to read your code if you indent your code with
spaces.)

Garrett

I do agree with you. I am just presenting a code example
from an upcoming book from a javascript expert, which I
have an early copy of. He did not explain the code, so
I came to this newsgroup to get a full understanding of
it as is. In my own work (if I need to) I will be sure
to use your variations on the routine, which I agree are
better.

I am watching google more closely now, to correctly
quote you (and others); sorry, I missed that one
misquote (though it was of something empty, so
your good reputation is hopefully fully intact).
Still, I will police google, as you and others have
requested and not make the error again.

Thanks for you help. You have my respect.
 
D

dhtml

lorlarz said:
I do agree with you. I am just presenting a code example
from an upcoming book from a javascript expert, which I
have an early copy of. He did not explain the code, so
I came to this newsgroup to get a full understanding of
it as is. In my own work (if I need to) I will be sure
to use your variations on the routine, which I agree are
better.

So you're editing a book that you need help understanding.

The code is written in a complicated that way confuses you. You agree
that the code should be changed to be less confusing. As a technical
editor, it would seem to be a part of your role to make sure that a
method had the correct parameters, was formatted properly, and had
explanatory comment.
I am watching google more closely now, to correctly
quote you (and others); sorry, I missed that one
misquote (though it was of something empty, so
your good reputation is hopefully fully intact).
Still, I will police google, as you and others have
requested and not make the error again.

The issue with "-show quoted text-" (at least to me) makes it look like
there is something else there and if there is, then what is it and are
you replying to that?

You could try a newsreader. Thunderbird works pretty well. There are
free news servers that you can use.

Garrett
 
L

lorlarz

So you're editing a book that you need help understanding.

The code is written in a complicated that way confuses you. You agree
that the code should be changed to be less confusing. As a technical
editor, it would seem to be a part of your role to make sure that a
method had the correct parameters, was formatted properly, and had
explanatory comment.


The issue with "-show quoted text-" (at least to me) makes it look like
there is something else there and if there is, then what is it and are
you replying to that?

You could try a newsreader. Thunderbird works pretty well. There are
free news servers that you can use.

Garrett

Actually, Manning Publishers have a program where
anyone can buy a book in the process of being
written (and give feedback) and then also get
the completed book as soon as it is done -- all
for one pretty good price.

I am a friend of the author, not an official editor.
But, I did nonetheless make a suggestion that
the author do some good explanation of the code (and
perhaps he should also generate an example, like
I did). As to taking the parameter: I am not
willing to assume that the way that seems better
to you and I is always better, as the new bind
method of Function will actually be used -- so
I have not passed on that critcism. For one thing,
the function returned (just the original function
expressly set to a context) must be open to
taking other parameters, anyway -- I sent one
parameter other than the object context in the
example I provided. It can be returned and then
immediately called in one fell swoop, if parameters
are passed with each use (whether just the context
parameter is the only one passed or if there are
others). Thus, there is something to argue
against your point.
 
D

dhtml

(Use === when comparing objects. It will avoid conversion to string and
will also be faster in some implementations).
Actually, Manning Publishers have a program where
anyone can buy a book in the process of being
written (and give feedback) and then also get
the completed book as soon as it is done -- all
for one pretty good price.

If the book is anything like any of the other JavaScript books on
Manning, it won't be worth the paper it is written on.
I am a friend of the author, not an official editor.
But, I did nonetheless make a suggestion that
the author do some good explanation of the code (and
perhaps he should also generate an example, like
I did). As to taking the parameter: I am not
willing to assume that the way that seems better
to you and I is always better, as the new bind
method of Function will actually be used -- so
I have not passed on that critcism.

Don't assume. Write it out and it should be pretty clear. We'll at least
have two things to compare. Hey, this goes for anyone - call it the
unofficial bind competition.
For one thing,
the function returned (just the original function
expressly set to a context) must be open to
taking other parameters, anyway -- I sent one
parameter other than the object context in the
example I provided. It can be returned and then
immediately called in one fell swoop, if parameters
are passed with each use (whether just the context
parameter is the only one passed or if there are
others). Thus, there is something to argue
against your point.

So now you don't agree about the context parameter.

The method does two things:
1) bind
2) partialApply

The 'context' parameter would be for the bind part. Arguments 1-n would
be the partialApply part.

This self-documenting approach (formal parameter) would make it clearer
that the method can be used for two different things. Adding a comment
will make the code even clearer.

If 'context' were arguments[0], then shift() would not need to be
called. Instead, the call to slice(arguments) would require an
adjustment the startIndex.

If the method is written out using 'context' we will be able to compare
the two of them for aesthetics (by looking at the code) and performance
wise (by testing).

If the caller doesn't pass in any varargs (1..n), then the returned
function can skip the concat part. We can then performance-test the
returned function.

Garrett
 
L

lorlarz

If the book is anything like any of the other JavaScript books on
Manning, it won't be worth the paper it is written on.

I think that 2 recent Manning Publishers books were excellent:

ASP.NET AJAX in Action
and
jQuery in Action

(and for whatever reason, even though I have read about 150 technical
books, these seem to be the only 2 by Manning Publishing).


[snip]
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,535
Members
45,007
Latest member
obedient dusk

Latest Threads

Top