Questions about 'new' : is this pattern legit?

T

Thomas 'PointedEars' Lahn

nick said:
What about arguments.callee? That's good enough for returning a
reference to the same function.

But a function is not necessarily a method of the same object. You need to
keep a reference to the object that has the function as a method, or you
will end up having `this' refer to the global object on subsequent calls.
(Unless, of course, all your methods are global, but then you have another
problem to solve first.)
Granted, but how much more expensive,
Much.

and what's the tradeoff?
Pardon?

If average joe web designer screws up the first example 25% less than the
second, it might be worth those few extra milliseconds per page load.

I do not write for "joe web designer". I write for people who can make
proper use of their brain.

(Polite people ask for clarification differently. See also my [not so
random] sig ;-))

An extra comma in the right place should remove the ambiguity:

BTW, few would consider spoiling the current execution context's
namespace declaring functions when using Array initializers,
as anonymous function expressions would be readily available then.
This means the register function must be more complex, unless you want
to register a single key handler like this: register([[key,func]])

With the self-calling approach the register() method must be more
complex instead; it must use a closure to work on the initial calling
object when self-called.

this.register = function (key, onPress, onRelease) {
if (!initted) init();
if (!onPress && !onRelease) me.unregister(key);
callbacks[toCharCode(key)] = [onPress, onRelease];

But where does `callbacks' come from?
return arguments.caller;

You are confused.
}

// or //

this.register = function (key, onPress, onRelease) {
if (!initted) init();
if (typeof key == 'array') {

You are *very* confused.
for (int i=key.length, i--;)
^^^
Is this supposed to be JScript .NET, AFAIK only available server-side, or
are you only incompetent instead?
[...]
You don't know what you are talking about. Incidentally, not even the
crappy jQuery promotes this ridiculous pattern, the chaining there goes
$(...).method(...).method(...) instead (which is only slightly less
inefficient, error-prone and hard to debug).

I don't know what you are talking about :)

That much is obvious.


PointedEars
 
T

Thomas Allen

Looking at this code itself we see a call to (what is assumed to be) a
function, and then a call to whatever is returned from that first
call, and then a call to whatever is returned from that. We might also
observe a similarity in the arguments.

That is all the information available in the code. In order to
determine that this actually represents three calls to the same
function it will be necessary to find the code for a - Cufon -
definition, or the code for whatever function is assigned to - Cufon -
at any given time. Otherwise (even if 'Cfon' were instead an
Identifier that described what the function did) the nature/process of
the second and third function calls remains unknown. It is not even
hinted at by the code above, and that is an objective fact.

To be fair, I think that code intended for other developers' use
should be well-documented. So, in my opinion, your concern about the
"nature/process of the second and third function calls" is
unwarranted, provided that the function's return value (and usage too,
given the bizarre operation nick wants) is explained adequately.

Thomas
 
T

Thomas 'PointedEars' Lahn

johnwlockwood said:
Asen Bozhilov wrote:


Isn't this done so you can reference the this from a closure function?
like:
function MyObject(id)
{
var me = this;
me.id = id;
me.getId_ = function()
{
return me.getId();
};
};

Unless you want to call the function as method of another object and keep
the reference to the original object, there is no point in using `me' here.
var MyObject.prototype.getId = function()

Syntax error, see below.
{
var me = this;
return me.id;
}

var myObject = MyObject("test");

var getMyObjectId = myObject.getId_;

You must not have tested that.
// or assign myObject.getId_ as a callback

alert(getMyOjbectId());

// alert should display "test"

Just because you wish for a thing that does not make it so.
I was told there was a bug in one of the browsers that caused a
problem if you didn't use the me=this.

You have been told nonsense. It's not a bug, it's a feature, and whether
it matters at all depends on the context.
function MyObject(id)
{
this.id = id;
this.getId_ = function()
{
return this.getId();
};
};

The `this' in the method definition is OK; the method definition is
pointless, of course, as both `getId_' and `getId' would be visible
outside of the constructor's execution context.
var MyObject.prototype.getId = function() ^^^^^^^^^^^^^
{
return this.id;
}

This is obviously a very contrived example.

More, it is syntactically invalid, and pointless if fixed. `MyObject.…'
can never be produced by /Identifier/. (If you lost the `var', it would
only be slightly less pointless, see above.) Maybe you were looking for

function MyObject(id)
{
var _id = id;
this.getId = function () {
return _id;
};
}


PointedEars
 
J

johnwlockwood

Unless you want to call the function as method of another object and keep
the reference to the original object, there is no point in using `me' here.

Thank you for the clarification.

The `this' in the method definition is OK; the method definition is
pointless, of course, as both `getId_' and `getId' would be visible
outside of the constructor's execution context.
  ^^^^^^^^^^^^^

Okay, syntactically corrected:
var alert;
function MyObject(id)
{
var me = this;
me.id = id;
me.getId_ = function()
{
return me.getId();
};
}

MyObject.prototype.getId = function()
{
var me = this;
return me.id;
};

var myObject1;
myObject1 = new MyObject("test");
// ^^^^
var getMyObjectId;
getMyObjectId = myObject1.getId_;
alert(getMyObjectId());

More, it is syntactically invalid, and pointless if fixed.  `MyObject.…'
can never be produced by /Identifier/.  (If you lost the `var', it would
only be slightly less pointless, see above.)  Maybe you were looking for

  function MyObject(id)
  {
    var _id = id;
    this.getId = function () {
      return _id;
    };
  }

This does behave the same as my version, and it is more brief, but it
is my understanding that defining methods of and object using
prototype was a good thing. And if getId is defined under the Object
prototype: In order to say, specify the myObject.getId function as a
event handler, you must make a private member a function that calls
the prototype method, or else 'this' will be the global context.

-John
 
A

Asen Bozhilov

johnwlockwood said:
var alert;

Why do you define variable in global execution context with Identifier
`alert`? Your program works is questionable. Because you cannot be
sure where is defined `alert`. Your program will work only if `alert`
property is property of Global Object, because during variable
instantiation for global code will be used Global Object as Variable
Object. And by rules for variable declaration value of property
`alert` isn't replaced if Global Object has that property
already.
function MyObject(id)
{
  var me = this;
  me.id = id;
  me.getId_ = function()
  {
    return me.getId();
  };

}

MyObject.prototype.getId = function()
{
 var me = this;
 return me.id;

};

var myObject1;
myObject1 = new MyObject("test");
//          ^^^^
var getMyObjectId;
getMyObjectId = myObject1.getId_;
alert(getMyObjectId());

In order to say, specify the myObject.getId function as a
event handler, you must make a private member a function that calls
the prototype method, or else 'this' will be the global context.

In handler function developer can do whatever he need. Your object
interface shouldn't care about developer misconceptions. If he need to
invoke some of your methods in handler, he will invoke in handler.
Your method not need to know how will be invoked. For proper works of
your method only need proper invocation from developer. It's enough.

Regards.
 
T

Thomas 'PointedEars' Lahn

johnwlockwood said:
Thomas 'PointedEars' Lahn wrote:

Thank you for the clarification.

You are welcome.
Okay, syntactically corrected:
var alert;

You don't want to do that.
function MyObject(id)
{
var me = this;
me.id = id;
me.getId_ = function()
{
return me.getId();
};
}

MyObject.prototype.getId = function()
{
var me = this;
return me.id;
};

You do see that this does not make sense anyway, don't you?
var myObject1;
myObject1 = new MyObject("test");
// ^^^^

Your point being? Besides

var myObject1 = new MyObject("test");

suffices.
var getMyObjectId;
getMyObjectId = myObject1.getId_;

var getMyObjectId = myObject1.getId_;
alert(getMyObjectId());

That is precisely the exception to the rule that I have mentioned.
You would be calling the function as method of the Global Object.
This does behave the same as my version,

No, it does not.
and it is more brief,

Which is entirely besides the point.
but it is my understanding that defining methods of
and object using prototype was a good thing.

If you make use of the prototype chain that makes sense. You do not.
You are calling a prototype method from a method of an instance here when
you should have called the prototype method *as* method of the instance
instead (so that lookup along the prototype chain would have called that
method automatically).
And if getId is defined under the Object prototype: In order to say,
specify the myObject.getId function as a event handler, you must make a
private member a function that calls the prototype method, or else 'this'
will be the global context.

You use the terms without understanding their meaning. I don't even know
where to begin correcting this nonsense.


PointedEars
 
J

johnwlockwood

                                              ^^^^^^^^^^^^^^^^^^^^^^^^>> pointless, of course, as both `getId_' and `getId' would be visible

   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^>> outside of the constructor's execution context.


You don't want to do that.

Ok, the only reason I did is jslint.com gave the error "Implied
global: alert"
You do see that this does not make sense anyway, don't you?

Oh yeah, I didn't write it to make sense, just a short illustration of
my understanding of how I should create methods and make them a
closure.
I learned this style mostly from working with
http://gmaps-utility-library.googlecode.com/svn/trunk/markermanager/1.0/src/markermanager.js
If you make use of the prototype chain that makes sense.  You do not.
Okay.

You are calling a prototype method from a method of an instance here when
you should have called the prototype method *as* method of the instance\
instead (so that lookup along the prototype chain would have called that
method automatically).

I don't understand. Are you saying I should have written:
var getMyObjectId = myObject1.getId;
which "getMyObjectId();" will call MyObject.prototype.getId?

You use the terms without understanding their meaning.  I don't even know
where to begin correcting this nonsense.

Sorry about using the wrong terms for what I mean, I will work on
improving my understanding of the correct terms.
By 'global context', I meant that 'this' would be of the Global
object.

-John
 
S

Scott Sauyet

nick said:
Look at this code:

  myApp.keys.register
    ('w', panNorth)
    ('s', panSouth)
    ('a', panWest)
    ('d', panEast);


What else could it possibly be doing besides registering a bunch of
key handlers? It works and it makes sense, so it's not entirely
ridiculous. And, really, how is it any worse than something like this:

  myApp.keys.register([
    ['w', panNorth],
    ['s', panSouth],
    ['a', panWest],
    ['d', panEast]
  ]);

I agree with the other posters that it is in fact less clear. But
there are other options as well:

myApp.keys.register({
'w': panNorth,
's': panSouth,
'a': panWest,
'd': panEast
});

or

myApp.keys.register(
'w', panNorth,
's', panSouth,
'a', panWest,
'd', panEast
);

either of which feels a little more normal Javascript-y to me.


-- Scott
 
A

Antony Scriven

nick said:
Look at this code:
myApp.keys.register
('w', panNorth)
('s', panSouth)
('a', panWest)
('d', panEast);
What else could it possibly be doing besides
registering a bunch of key handlers? It works and it
makes sense, so it's not entirely ridiculous. And,
really, how is it any worse than something like this:
myApp.keys.register([
['w', panNorth],
['s', panSouth],
['a', panWest],
['d', panEast]
]);

I agree with the other posters that it is in fact less
clear. But there are other options as well:

myApp.keys.register({
'w': panNorth,
's': panSouth,
'a': panWest,
'd': panEast
});

or

myApp.keys.register(
'w', panNorth,
's', panSouth,
'a', panWest,
'd', panEast
);

either of which feels a little more normal Javascript-y to me.

Agreed. You could also probably do the following.

myApp.keys = {
'w': panNorth,
's': panSouth,
'a': panWest,
'd': panEast
};

--Antony
 
T

Thomas 'PointedEars' Lahn

johnwlockwood said:
Ok, the only reason I did is jslint.com gave the error "Implied
global: alert"

You probably get the error because you called

alert(...);

not because you have not declared it. Call

window.alert(...);

and take everything jslint says with a handful of salt.
Oh yeah, I didn't write it to make sense, just a short illustration of
my understanding of how I should create methods and make them a
closure.

What are you talking about? There is exactly *no* point of having
me.getId_() here as both

(new MyObject("a")).getId_()

and

(new MyObject("a")).getId()

work and do *exactly* the same. You can also lose the bogus `me' in
getId().
I learned this style mostly from working with
http://gmaps-utility-
library.googlecode.com/svn/trunk/markermanager/1.0/src/markermanager.js

They are _not_ defining instance methods there that call prototype methods.
Anyhow, take everything client-side from Google with a handful of salt, if
at all. For example, all the outer `me's can be `this's --

/**
* Removes all currently displayed markers
* and calls resetManager to clear arrays
*/
MarkerManager.prototype.clearMarkers = function() {
var me = this;
me.processAll_(me.shownBounds_, me.removeOverlay_);
me.resetManager_();
};

is particularly clueless.
I don't understand. Are you saying I should have written:
var getMyObjectId = myObject1.getId;
which "getMyObjectId();" will call MyObject.prototype.getId?

No, of course you should have written

var id = myObject1.getId();
Sorry about using the wrong terms for what I mean, I will work on
improving my understanding of the correct terms.
By 'global context', I meant that 'this' would be of the Global
object.

`this' could refer to the Global Object at most. And that would be bad
style.


PointedEars
 
N

nick

I agree with the other posters that it is in fact less clear.  But
there are other options as well:

Is it really so much less clear that you'd really spend any
significant time wondering what that code did? I mean, I see what you
guys are saying but I just don't see what else that code could
possibly be doing. The name of the function appears once, and all the
arg lists look the same, so I feel like it's pretty safe to assume
(to someone reading chained code like this) that the same function is
getting all the arg lists.
  myApp.keys.register({
    'w': panNorth,
    's': panSouth,
    'a': panWest,
    'd': panEast
  });

That example isn't too bad. The issue is that 'register' can take more
parameters... another onRelease callback, and I'll probably add some
kind of flags enum or something for modifier keys (still trying to
decide how to expose that). So this:

var keys = myApp.keys;
keys.register
('w', panNorth, endPanNorth, keys.CTRL | keys.SHIFT)
('s', panSouth, endPanSouth, keys.CTRL | keys.SHIFT)
('a', panWest, endPanWest, keys.CTRL | keys.SHIFT)
('d', panEast, endPanEast, keys.CTRL | keys.SHIFT);

....Now becomes something like this:

var keys = myApp.keys;
keys.register({
  'w': [panNorth, endPanNorth, keys.CTRL | keys.SHIFT],
  's': [panSouth, endPanSouth, keys.CTRL | keys.SHIFT],
  'a': [panWest, endPanWest, keys.CTRL | keys.SHIFT],
  'd': [panEast, endPanEast, keys.CTRL | keys.SHIFT]
});

....Which is still pretty decent I guess. You could even make the inner
arrays into options so you could have named parameters. Luckily the
way I am doing it now is flexible enough to incorporate something like
this if I decide to do it later ;)
or

  myApp.keys.register(
    'w', panNorth,
    's', panSouth,
    'a', panWest,
    'd', panEast
  );

It would be hard to do much with that given the optional args, I
think.
either of which feels a little more normal Javascript-y to me.

  -- Scott

I'm sure you're right about that ;)
 
N

nick

...

Agreed. You could also probably do the following.

   myApp.keys = {
      'w': panNorth,
      's': panSouth,
      'a': panWest,
      'd': panEast
   };

--Antony

It would be something like myApp.keys.callbacks = {...}

The problems I have with that approach are:

- The keys are indexed as numeric keycodes, not strings.
The 'register' function allows user to pass either.

- Makes error handling / input cleaning more difficult.

- User might inadvertently wipe out the callbacks object
when they really just meant to add some stuff to it.
 
A

Antony Scriven

It would be something like myApp.keys.callbacks = {...}

That's not important; it's just an example. I'm not going to
try to second-guess your entire codebase. You'll have to
extrapolate from the example yourself.
The problems I have with that approach are:

 - The keys are indexed as numeric keycodes, not strings.
   The 'register' function allows user to pass either.

Using magic numbers in your code isn't helpful.
 - Makes error handling / input cleaning more difficult.

How? / huh?
 - User might inadvertently wipe out the callbacks object
   when they really just meant to add some stuff to it.

Then that user shouldn't be writing Javascript.

Something else to bear in mind is that if you have
references to the functions in an easily accessible object
then they can be easily manipulated. E.g.

var keys = myApp.keys.callbacks;
var oldKeyW = keys.w;
keys.w = function(){
doSomethingNew();
oldKeyW();
};

If, on the other hand, you don't want the functions to be
easily manipulated then see my first comment. --Antony
 
G

Garrett Smith

Thomas said:
You probably get the error because you called

alert(...);

not because you have not declared it. Call

window.alert(...);

and take everything jslint says with a handful of salt.
s/handful/bucket.
 
N

nick

On Apr 2, 3:07 am, nick wrote:
...
 > It would be something like myApp.keys.callbacks = {...}

That's not important; it's just an example. I'm not going to
try to second-guess your entire codebase. You'll have to
extrapolate from the example yourself.

Whoa, easy there. I only pointed that out to avoid confusion.
 > The problems I have with that approach are:
 >
 >  - The keys are indexed as numeric keycodes, not strings.
 >    The 'register' function allows user to pass either.

Using magic numbers in your code isn't helpful.

I'm not using 'magic numbers.' Either the argument is a number, and it
is interpreted as a keycode, or it is a string, and it is interpreted
as a character representation of a key, or it is something else and it
is ignored (for now).
 >  - Makes error handling / input cleaning more difficult.

How? / huh?

Because the user sets a property of an object directly instead of
calling a function to alter an internal object. Intermediate stuff can
be done in the function before altering the object. The difference
should be obvious.
 >  - User might inadvertently wipe out the callbacks object
 >    when they really just meant to add some stuff to it.

Then that user shouldn't be writing Javascript.

in before 'or javascript'
^
Something else to bear in mind is that if you have
references to the functions in an easily accessible object
then they can be easily manipulated. E.g.

   var keys = myApp.keys.callbacks;
   var oldKeyW = keys.w;
   keys.w = function(){
       doSomethingNew();
       oldKeyW();
   };

Right, except it's not .w, it's [87], because it's indexed by the char
code (so all key events can be trapped, eg bksp, f5).

There's a function keys.list() that will return the callbacks object
if the user really wants to manipulate it directly. Or, you could call
keys.list('w') and it will return callbacks[87] for you.
If, on the other hand, you don't want the functions to be
easily manipulated then see my first comment. --Antony

Functions? Not sure what you mean by that.
 
A

Antony Scriven

Whoa, easy there. I only pointed that out to avoid
confusion.

I made the remark because I sensed you were dwelling on
details rather than concepts. I didn't mean it harshly.
I'm not using 'magic numbers.' Either the argument is
a number, and it is interpreted as a keycode, or it is
a string, and it is interpreted as a character
representation of a key, or it is something else and it
is ignored (for now).

Why use 107 when you can use 'k'? (Or whatever the code is.)
I'm not saying you shouldn't use numbers, just that there
appears to be no obvious reason to do so given the code
you've presented so far. If you're dead set on implementing
it your way then just snip this paragraph in your reply.
How? / huh?

Because the user sets a property of an object directly
instead of calling a function to alter an internal
object. Intermediate stuff can be done in the function
[the function that register the keypress handlers] before
altering the object [that stores the handlers]. The
difference should be obvious.

Well of course. But I don't see how that applies to error
handling. And I've no idea what you mean by `input
cleaning'.
in before 'or javascript'

That doesn't make sense, sorry.
Something else to bear in mind is that if you have
references to the functions in an easily accessible
object then they can be easily manipulated. E.g.
var keys = myApp.keys.callbacks;
var oldKeyW = keys.w;
keys.w = function(){
doSomethingNew();
oldKeyW();
};

Right, except it's not .w, it's [87], because it's
indexed by the char code (so all key events can be
trapped, eg bksp, f5).

Again, that is not the issue; this is just an example.
Change the `.w' to `[87]' if you want, it's completely
beside the point.
There's a function keys.list() that will return the
callbacks object if the user really wants to manipulate
it directly. Or, you could call keys.list('w') and it
will return callbacks[87] for you.

So then when you change a callback (to use your teminology)
you're bypassing your register() function?
Functions? Not sure what you mean by that.

One of these: function(){} :) The term callback doesn't
make a lot of sense in Javascript if you ask me, and it's
not one I've heard used with reference to Javascript before.
Maybe the term `event handler' would be more natural. --Antony
 
L

Lasse Reichstein Nielsen

To nitpick out of context:
2. Several function calls will be always more expensive than just one and
the creation of an Array instance.

That's not a given.

It's possible that four function calls take longer than creating an Array
and calling one function that loops over the array and extracts the elements
again (possible, but not given), but the latter also allocates space for the
array. If this happens often enough, the memory overhead will also cause
earlier garbage collection.

After writing that, I decided a test was in order, instead of relying on
intuition. The following code is attempted written without obvious
inefficiencies in either test case (all variables are local, loop
invariant expressions are lifted, etc.).
I have run it in Opera 10.51, Chrome 5(dev), Firefox 3.6.2 and IE 9 preview.

<script type="text/javascript">
function Obj() {
this.props = {};
var self = this;
this.setChained = function setProp(name, value) {
self.props[name] = value;
return setProp;
};
};
Obj.prototype.setProp = function (name,value) {
this.props[name] = value;
};
Obj.prototype.setProps = function (arr) {
var props = this.props;
for (var i = 0, n = arr.length; i < n; i += 2) {
props[arr] = props[arr[i+1]];
}
};

function test1() {
var o = new Obj();
var t0 = new Date();
for (var i = 0; i < 100000; i++) {
o.setProp("a", i);
o.setProp("b", i);
o.setProp("c", i);
o.setProp("d", i);
}
var t1 = new Date();
return t1-t0;
}

function test2() {
var o = new Obj();
var t0 = new Date();
for (var i = 0; i < 100000; i++) {
o.setChained("a", i)("b", i)("c", i)("d", i);
}
var t1 = new Date();
return t1-t0;
}

function test3() {
var o = new Obj();
var t0 = new Date();
for (var i = 0; i < 100000; i++) {
o.setProps(["a", i, "b", i, "c", i, "d", i]);
}
var t1 = new Date();
return t1-t0;
}

alert([test1(), test2(), test3()]);
</script>


In the first three browsers (not IE), doing four calls is consistently
faster than creating one eight-element array and doing one call. And
not by a small amount - it is between 1.75 and 3 times as fast.
In IE9, they take about the same time.

Using the chained way of calling the setter is about the same as just
doing the four calls in Firefox and Chrome, and somewhat slower in
Opera, but not as slow as using an Array. In IE9, this approach is
actually the fastest. Go figure.

In summary: Function calls aren't significantly slower than other
language features like object creation and property lookup.
Object creation, and inspection, spends a lot of time in memory
access, where function calls probably uses the stack (which is
very fast memory, because it's almost always in the first level
cache of the processor).

/L
 
L

Lasse Reichstein Nielsen

nick said:
What about arguments.callee? That's good enough for returning a
reference to the same function.

If performance is important, don't use "arguments" at all.

"arguments.callee" always referes to the function being executed.
You can just give that function a name and refer to it by that name.

I.e.,
DON'T: function (args) { ... arguments.callee ... }
DO : function foo(args) { ... foo ... }

/L
 
S

Scott Sauyet

nick said:
Is it really so much less clear that you'd really spend any
significant time wondering what that code did?

Perhaps not. I would definitely wonder *how* it's doing what it does,
though, and that's a distraction too. Chaining like this wouldn't
surprise me at all:

myApp.keys
.register('w', panNorth)
.register('s', panSouth)
.register('a', panWest)
.register('d', panEast);

There I would know exactly what's going on, and I'd understand how it
works too.

I mean, I see what you
guys are saying but I just don't see what else that code could
possibly be doing. The name of the function appears once, and all the
arg lists look the same, so  I feel like it's pretty safe to assume
(to someone reading chained code like this) that the same function is
getting all the arg lists.

I guess if the args all look so similar to one another as these ones
do, I'd probably make the same assumption, but the minute they start
looking different, I would likely get confused.

That example isn't too bad. The issue is that 'register' can take more
parameters...

That does make a substantial difference. With that I would definitely
go with the chained calls to the named function, myApp.keys.register(/
* ... */).register(/* ... */) or even the most explicit

myApp.keys.register(/* ... */);
myApp.keys.register(/* ... */);
another onRelease callback, and I'll probably add some
kind of flags enum or something for modifier keys (still trying to
decide how to expose that). So this:

  var keys = myApp.keys;
  keys.register
    ('w', panNorth, endPanNorth, keys.CTRL | keys.SHIFT)
    ('s', panSouth, endPanSouth, keys.CTRL | keys.SHIFT)
    ('a', panWest, endPanWest, keys.CTRL | keys.SHIFT)
    ('d', panEast, endPanEast, keys.CTRL | keys.SHIFT);

...Now becomes something like this:

  var keys = myApp.keys;
  keys.register({
    'w': [panNorth, endPanNorth, keys.CTRL | keys.SHIFT],
    's': [panSouth, endPanSouth, keys.CTRL | keys.SHIFT],
    'a': [panWest, endPanWest, keys.CTRL | keys.SHIFT],
    'd': [panEast, endPanEast, keys.CTRL | keys.SHIFT]
  });

...Which is still pretty decent I guess. You could even make the inner
arrays into options so you could have named parameters. Luckily the
way I am doing it now is flexible enough to incorporate something like
this if I decide to do it later ;)

While this is certainly possible, it starts to look ugly enough to me
that I wouldn't really want it on a public, shared API if I have any
real choice. If you're the only one using the API, then whatever you
think will remain easily readable to you after some time away from it
is fine.
It would be hard to do much with that given the optional args, I
think.

Yes, and that's the weakness of this method in general, but it's quite
nice when you don't face that possibility.

-- Scott
 
T

Thomas 'PointedEars' Lahn

Lasse said:
If performance is important, don't use "arguments" at all.

"arguments.callee" always referes to the function being executed.
You can just give that function a name and refer to it by that name.

I.e.,
DON'T: function (args) { ... arguments.callee ... }
DO : function foo(args) { ... foo ... }

A recommendation to make maintenance harder than it needs to be while
ignoring a known bug with named function expressions in several versions of
the most widespread implementation available. DO NOT do this.


PointedEars
 

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
474,079
Messages
2,570,574
Members
47,207
Latest member
HelenaCani

Latest Threads

Top