Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.javascript > #32133 > unrolled thread

Empty function

Started byAndrew Poulos <ap_prog@hotmail.com>
First post2017-01-08 16:49 +1100
Last post2017-01-08 23:21 +0100
Articles 9 — 5 participants

Back to article view | Back to comp.lang.javascript


Contents

  Empty function Andrew Poulos <ap_prog@hotmail.com> - 2017-01-08 16:49 +1100
    Re: Empty function Martin Honnen <martin.honnen@gmx.de> - 2017-01-08 08:29 +0100
      Re: Empty function Andrew Poulos <ap_prog@hotmail.com> - 2017-01-08 20:05 +1100
        Re: Empty function Thomas 'PointedEars' Lahn <PointedEars@web.de> - 2017-01-08 23:40 +0100
          Re: Empty function Andrew Poulos <ap_prog@hotmail.com> - 2017-01-09 10:47 +1100
            Re: Empty function Thomas 'PointedEars' Lahn <PointedEars@web.de> - 2017-01-09 01:10 +0100
    Re: Empty function JJ <jj4public@vfemail.net> - 2017-01-08 20:53 +0700
    Re: Empty function "Michael Haufe (TNO)" <tno@thenewobjective.com> - 2017-01-08 10:02 -0800
    Re: Empty function Thomas 'PointedEars' Lahn <PointedEars@web.de> - 2017-01-08 23:21 +0100

#32133 — Empty function

FromAndrew Poulos <ap_prog@hotmail.com>
Date2017-01-08 16:49 +1100
SubjectEmpty function
Message-ID<UPqdnRaDtOBAT-zFnZ2dnUU7-RHNnZ2d@westnet.com.au>
I'm needing to edit some code that's been given to me. Apparently its 
been written a decade or so ago. Paraphrased, the code follows:

var Drag = {
   obj : null,
   init: function(o) {
     o.onmousedown = Drag.start;
     o.root.onDrag = function() {}; //--> what does this line do?
   },
   start: function(e) {
     document.onmousemove = Drag.drag;
     document.onmouseup = Drag.end;
     return false;
   },
   drag: function(e) {
     Drag.obj.root.onDrag(nx, ny);
     return false;
   },
   end: function() {
     document.onmousemove = null;
     document.onmouseup   = null;
   }
};

What I don't follow is what the line
     o.root.onDrag = function() {};
is doing. If I comment the line out the code "doesn't work". What's the 
purpose of setting an event to an empty function?

Andrew Poulos

[toc] | [next] | [standalone]


#32134

FromMartin Honnen <martin.honnen@gmx.de>
Date2017-01-08 08:29 +0100
Message-ID<o4sppl$ub7$1@news.albasani.net>
In reply to#32133
On 08.01.2017 06:49, Andrew Poulos wrote:

> var Drag = {
>   obj : null,
>   init: function(o) {
>     o.onmousedown = Drag.start;
>     o.root.onDrag = function() {}; //--> what does this line do?
>   },
>   start: function(e) {
>     document.onmousemove = Drag.drag;
>     document.onmouseup = Drag.end;
>     return false;
>   },
>   drag: function(e) {
>     Drag.obj.root.onDrag(nx, ny);
>     return false;
>   },
>   end: function() {
>     document.onmousemove = null;
>     document.onmouseup   = null;
>   }
> };
>
> What I don't follow is what the line
>     o.root.onDrag = function() {};
> is doing. If I comment the line out the code "doesn't work". What's the
> purpose of setting an event to an empty function?


Is that the complete code? I don't see any nx or ny variables declared 
anywhere that are used in
   Drag.obj.root.onDrag(nx, ny)
so I guess somewhere else the onDrag function is assigned or can be 
assigned a handler that does have a body doing something.

[toc] | [prev] | [next] | [standalone]


#32135

FromAndrew Poulos <ap_prog@hotmail.com>
Date2017-01-08 20:05 +1100
Message-ID<l-ednZuM5IV2ne_FnZ2dnUU7-SXNnZ2d@westnet.com.au>
In reply to#32134
On 8/01/2017 6:29 PM, Martin Honnen wrote:
> On 08.01.2017 06:49, Andrew Poulos wrote:
>
>> var Drag = {
>>   obj : null,
>>   init: function(o) {
>>     o.onmousedown = Drag.start;
>>     o.root.onDrag = function() {}; //--> what does this line do?
>>   },
>>   start: function(e) {
>>     document.onmousemove = Drag.drag;
>>     document.onmouseup = Drag.end;
>>     return false;
>>   },
>>   drag: function(e) {
>>     Drag.obj.root.onDrag(nx, ny);
>>     return false;
>>   },
>>   end: function() {
>>     document.onmousemove = null;
>>     document.onmouseup   = null;
>>   }
>> };
>>
>> What I don't follow is what the line
>>     o.root.onDrag = function() {};
>> is doing. If I comment the line out the code "doesn't work". What's the
>> purpose of setting an event to an empty function?
>
>
> Is that the complete code? I don't see any nx or ny variables declared
> anywhere that are used in
>   Drag.obj.root.onDrag(nx, ny)
> so I guess somewhere else the onDrag function is assigned or can be
> assigned a handler that does have a body doing something.
>
>
No it's not complete (I'd paraphrased it). Here is the complete code

var Drag = {
   obj: null,
   init: function(o, posX, posY, minX, minY) {
     if (!o) return;
     o.onmousedown = Drag.start;
     o.root = o;
     o.root.style.left = posX + "px";
     o.root.style.top = posY + "px";
     o.minX = minX;
     o.minY = minY;
     o.root.onDragStart = function() {};
     o.root.onDragEnd = function() {};
     o.root.onDrag = function() {};
   },
   start: function(e) {
     e = e || window.event;
     var o = Drag.obj = this,
         y = parseInt(o.root.style.top, 10),
         x = parseInt(o.root.style.left, 10);
     o.root.onDragStart(x, y);
     o.lastMouseX = e.clientX;
     o.lastMouseY = e.clientY;
     o.minMouseX = e.clientX - x + o.minX;
     o.maxMouseX = o.minMouseX - o.minX;
     o.minMouseY = e.clientY - y + o.minY;
     o.maxMouseY = o.minMouseY - o.minY;
     document.onmousemove = Drag.drag;
     document.onmouseup = Drag.end;
     return false;
   },
   drag: function(e) {
     e = e || window.event;
     var o = Drag.obj,
         ex = e.clientX,
         ey = e.clientY,
         y = parseInt(o.root.style.top, 10),
         x = parseInt(o.root.style.left, 10),
         nx,
         ny;
     ex = Math.max(ex, o.minMouseX);
     ex = Math.min(ex, o.maxMouseX);
     ey = Math.max(ey, o.minMouseY);
     ey = Math.min(ey, o.maxMouseY);
     nx = x + (ex - o.lastMouseX);
     ny = y + (ey - o.lastMouseY);
     Drag.obj.root.style.left = nx + "px";
     Drag.obj.root.style.top = ny + "px";
     Drag.obj.lastMouseX	= ex;
     Drag.obj.lastMouseY	= ey;
     Drag.obj.root.onDrag(nx, ny);
     return false;
   },
   end: function() {
     document.onmousemove = null;
     document.onmouseup = null;
     var nx = parseInt(Drag.obj.root.style.left, 10),
         ny = parseInt(Drag.obj.root.style.top, 10);
     Drag.obj.root.onDragEnd(nx, ny);
     Drag.obj = null;
   }
};


Andrew Poulos

[toc] | [prev] | [next] | [standalone]


#32143

FromThomas 'PointedEars' Lahn <PointedEars@web.de>
Date2017-01-08 23:40 +0100
Message-ID<1552504.VLH7GnMWUR@PointedEars.de>
In reply to#32135
Andrew Poulos wrote:

> […] Here is the complete code
> 
> var Drag = {
>    obj: null,
>    init: function(o, posX, posY, minX, minY) {
>      if (!o) return;
>      o.onmousedown = Drag.start;
>      o.root = o;
>      o.root.style.left = posX + "px";
>      o.root.style.top = posY + "px";
>      o.minX = minX;
>      o.minY = minY;
>      o.root.onDragStart = function() {};
>      o.root.onDragEnd = function() {};
>      o.root.onDrag = function() {};

As indicated by “o.root.style”, “o.root” appears to store a reference to a 
DOM element object.  In that case, the latter three lines are error-prone:

They would only work in the MSHTML DOM before version 9 and any DOM 
compatible to it.  In addition, the names of the standard event-handler 
properties are all-lowercase; so in a W3C DOM implementation the referred 
object does not have those properties.  It is a host object, and assigning 
to potentially non-existing property of a host object, thereby attempting
to augment it with properties, is a recipe for disaster.

Since DOM element objects usually do not have “minX” and “minY” properties, 
the latter possibility is more likely.

>    },
>    start: function(e) {
>      e = e || window.event;
>      var o = Drag.obj = this,
>          y = parseInt(o.root.style.top, 10),
>          x = parseInt(o.root.style.left, 10);
>      o.root.onDragStart(x, y);

Given the augmented code, this line suggests that the author attempted to 
augment a host object (see above), and that they have no clue how to 
properly dispatch an event to such an object.

-- 
PointedEars
FAQ: <http://PointedEars.de/faq> | <http://PointedEars.de/es-matrix>
<https://github.com/PointedEars> | <http://PointedEars.de/wsvn/>
Twitter: @PointedEars2 | Please do not cc me./Bitte keine Kopien per E-Mail.

[toc] | [prev] | [next] | [standalone]


#32147

FromAndrew Poulos <ap_prog@hotmail.com>
Date2017-01-09 10:47 +1100
Message-ID<04OdnQ527cwRUu_FnZ2dnUU7-bXNnZ2d@westnet.com.au>
In reply to#32143
On 9/01/2017 9:40 AM, Thomas 'PointedEars' Lahn wrote:
> Andrew Poulos wrote:
>
>> […] Here is the complete code
>>
>> var Drag = {
>>    obj: null,
>>    init: function(o, posX, posY, minX, minY) {
>>      if (!o) return;
>>      o.onmousedown = Drag.start;
>>      o.root = o;
>>      o.root.style.left = posX + "px";
>>      o.root.style.top = posY + "px";
>>      o.minX = minX;
>>      o.minY = minY;
>>      o.root.onDragStart = function() {};
>>      o.root.onDragEnd = function() {};
>>      o.root.onDrag = function() {};
>
> As indicated by “o.root.style”, “o.root” appears to store a reference to a
> DOM element object.  In that case, the latter three lines are error-prone:
>
> They would only work in the MSHTML DOM before version 9 and any DOM
> compatible to it.  In addition, the names of the standard event-handler
> properties are all-lowercase; so in a W3C DOM implementation the referred
> object does not have those properties.  It is a host object, and assigning
> to potentially non-existing property of a host object, thereby attempting
> to augment it with properties, is a recipe for disaster.
>
> Since DOM element objects usually do not have “minX” and “minY” properties,
> the latter possibility is more likely.
>
>>    },
>>    start: function(e) {
>>      e = e || window.event;
>>      var o = Drag.obj = this,
>>          y = parseInt(o.root.style.top, 10),
>>          x = parseInt(o.root.style.left, 10);
>>      o.root.onDragStart(x, y);
>
> Given the augmented code, this line suggests that the author attempted to
> augment a host object (see above), and that they have no clue how to
> properly dispatch an event to such an object.

Thanks, I've stripped the references to onDragStart..., changed the 
event handler properties to all lowercase and it "works" in IE9+, Chrome...

Andrew Poulos

[toc] | [prev] | [next] | [standalone]


#32148

FromThomas 'PointedEars' Lahn <PointedEars@web.de>
Date2017-01-09 01:10 +0100
Message-ID<3015126.QJadu78ljV@PointedEars.de>
In reply to#32147
Andrew Poulos wrote:

> On 9/01/2017 9:40 AM, Thomas 'PointedEars' Lahn wrote:
>> Andrew Poulos wrote:
>>> […]
>>> var Drag = {
>>>    obj: null,
>>>    init: function(o, posX, posY, minX, minY) {
>>>      if (!o) return;
>>>      o.onmousedown = Drag.start;
>>>      o.root = o;
>>>      o.root.style.left = posX + "px";
>>>      o.root.style.top = posY + "px";
>>>      o.minX = minX;
>>>      o.minY = minY;
>>>      o.root.onDragStart = function() {};
>>>      o.root.onDragEnd = function() {};
>>>      o.root.onDrag = function() {};
>>
>> As indicated by “o.root.style”, “o.root” appears to store a reference to
>> a DOM element object.  In that case, the latter three lines are
>> error-prone:
>> […]
>>>    },
>>>    start: function(e) {
>>>      e = e || window.event;
>>>      var o = Drag.obj = this,
>>>          y = parseInt(o.root.style.top, 10),
>>>          x = parseInt(o.root.style.left, 10);
>>>      o.root.onDragStart(x, y);
>>
>> Given the augmented code, this line suggests that the author attempted to
>> augment a host object (see above), and that they have no clue how to
>> properly dispatch an event to such an object.
> 
> Thanks, I've stripped the references to onDragStart..., changed the
> event handler properties to all lowercase and it "works" in IE9+,
> Chrome...

You’re welcome.  But given that “o.root” refers to a host object to which 
the Law of Demeter does not fully apply (because it cannot safely be 
augmented with a method), there should be a method on the wrapper object 
with which to set the relevant “on…” properties of the wrapped object to 
retain the supposed functionality of the wrapper.

The problem here is that the current approach does not use a wrapping object 
in the first place but attempts to modify the target host object directly 
when init() is called.  The code needs to be refactored to avoid that, e. g.

  var my = Object.create(null);

  my.Dragable = function (target) {
    this.init(target);
  };

  Object.assign(my.Dragable.prototype, {
    /* to allow the wrapper to be reused for a different target */
    init: function (target) {
      if (this.target) this.clearEventListeners();

      this.target = target;
    },

    setEventListener: function (type, listener) {
      /* simplified */
      this.target["on" + type] = listener;
    }
  });

-- 
PointedEars
FAQ: <http://PointedEars.de/faq> | <http://PointedEars.de/es-matrix>
<https://github.com/PointedEars> | <http://PointedEars.de/wsvn/>
Twitter: @PointedEars2 | Please do not cc me./Bitte keine Kopien per E-Mail.

[toc] | [prev] | [next] | [standalone]


#32136

FromJJ <jj4public@vfemail.net>
Date2017-01-08 20:53 +0700
Message-ID<1hy8ho67luxo3.1oeplmib5x4ex.dlg@40tude.net>
In reply to#32133
On Sun, 8 Jan 2017 16:49:16 +1100, Andrew Poulos wrote:
> I'm needing to edit some code that's been given to me. Apparently its 
> been written a decade or so ago. Paraphrased, the code follows:
> 
> var Drag = {
>    obj : null,
>    init: function(o) {
>      o.onmousedown = Drag.start;
>      o.root.onDrag = function() {}; //--> what does this line do?
>    },
>    start: function(e) {
>      document.onmousemove = Drag.drag;
>      document.onmouseup = Drag.end;
>      return false;
>    },
>    drag: function(e) {
>      Drag.obj.root.onDrag(nx, ny);
>      return false;
>    },
>    end: function() {
>      document.onmousemove = null;
>      document.onmouseup   = null;
>    }
> };
> 
> What I don't follow is what the line
>      o.root.onDrag = function() {};
> is doing. If I comment the line out the code "doesn't work". What's the 
> purpose of setting an event to an empty function?
> 
> Andrew Poulos

Looks like the onDrag() method is a dummy function as default. It was set to
a do-nothing function because Drag.drag() and Drag.end() assume that the
onDrag object member a function.

[toc] | [prev] | [next] | [standalone]


#32138

From"Michael Haufe (TNO)" <tno@thenewobjective.com>
Date2017-01-08 10:02 -0800
Message-ID<326aebab-45ff-42aa-93b3-420c89de7d9d@googlegroups.com>
In reply to#32133
On Saturday, January 7, 2017 at 11:49:28 PM UTC-6, Andrew Poulos wrote:
> I'm needing to edit some code that's been given to me. Apparently its 
> been written a decade or so ago. Paraphrased, the code follows:
> 
> var Drag = {
>    obj : null,
>    init: function(o) {
>      o.onmousedown = Drag.start;
>      o.root.onDrag = function() {}; //--> what does this line do?
>    },
>    start: function(e) {
>      document.onmousemove = Drag.drag;
>      document.onmouseup = Drag.end;
>      return false;
>    },
>    drag: function(e) {
>      Drag.obj.root.onDrag(nx, ny);
>      return false;
>    },
>    end: function() {
>      document.onmousemove = null;
>      document.onmouseup   = null;
>    }
> };
> 
> What I don't follow is what the line
>      o.root.onDrag = function() {};
> is doing. If I comment the line out the code "doesn't work". What's the 
> purpose of setting an event to an empty function?

This may simply be a default no-op to avoid having to perform existence checks across the code. For example in the drag method:

Drag.obj.root.onDrag(nx, ny);

Without the dummy function you would have had to write:

if(Drag.obj.root.onDrag)
    Drag.obj.root.onDrag(nx, ny);

[toc] | [prev] | [next] | [standalone]


#32140

FromThomas 'PointedEars' Lahn <PointedEars@web.de>
Date2017-01-08 23:21 +0100
Message-ID<8026292.CDJkKcVGEf@PointedEars.de>
In reply to#32133
Andrew Poulos wrote:

> I'm needing to edit some code that's been given to me. Apparently its
> been written a decade or so ago. Paraphrased, the code follows:
> 
> var Drag = {
>    obj : null,
>    init: function(o) {
>      o.onmousedown = Drag.start;
>      o.root.onDrag = function() {}; //--> what does this line do?
>    },
>    start: function(e) {
>      document.onmousemove = Drag.drag;
>      document.onmouseup = Drag.end;
>      return false;
>    },
>    drag: function(e) {
>      Drag.obj.root.onDrag(nx, ny);
>      return false;
>    },
>    end: function() {
>      document.onmousemove = null;
>      document.onmouseup   = null;
>    }
> };
> 
> What I don't follow is what the line
>      o.root.onDrag = function() {};
> is doing. If I comment the line out the code "doesn't work". What's the
> purpose of setting an event to an empty function?

That “onDrag” is an "event" is your jump to conclusions, and a wrong one at 
that (read up on events).  It could merely be an event-_handler property_, 
and then it would be a user-defined or proprietary one (AFAIK, all standard 
event-handler properties have all-lowercase names).  For now, however, it is 
just the name of an ordinary property.  In the drag() method of the object 
referred to by “Drag”, that property needs to be callable.  That is why the 
code “doesn’t work” if you comment out the initialization (as you could have 
seen in the error console; see the FAQ).

This appears to be a lazy person’s approach to avoid feature tests in the 
drag() method.  It is error-prone as long as the property that is supposed 
to be callable there is (publicly) writable (and it appears to be so here), 
because then when the “drag” method is called, the “onDrag” property value 
can be any (even a non-callable) value even if the init() method had been 
called before.  It is also memory-inefficient because even if an onDrag() 
method is never required to be called, heap memory is being reserved for 
storing the Function instance referred to by onDrag().

The code also appears to violate the Law of Demeter because it performs a 
write access to a property of an object referred to by one of the properties 
of an object whose reference was passed to the init() method.  The init() 
method should delegate that action by calling a method of the referred 
object instead.


Contrary to common misconception, it is also insufficient and potentially  
error-prone (not all host object’s methods take kindly to that test) to test 
a property for being a true-value in order to ascertain that it is callable:

  foo.bar = 42;

  /* Do not do this */
  if (foo.bar)
  {
    foo.bar();
  }

The safest way is to subject it(s value) to a “typeof” test; should that 
operation yield "function", then it is very likely that the property value 
is callable (since ECMAScript Ed. 5 it is a requirement even for host 
object’s methods to behave this way):

  /*
   * You can also use “===”, but it is not strictly necessary
   * (no pun intended) due to the result of the “typeof” operation
   */
  if (typeof foo.bar == "function")
  {
    foo.bar();
  }

[Although it is tempting to wrap that test in a method because it can become 
tedious to write and it takes more space, it turned out that doing so 
actually reduces the runtime efficiency of the code because of the overhead 
of the method’s identifier resolution, property lookup, and method call when 
compared to the simple operation.  Therefore, a wrapping method should only 
be used if it accomplishes more than this simple test.  For example, 
jsx.object.isNativeMethod()/.areNativeMethods() prevails in JSX:object.js 
because it can test along a “property path” and multiple “leaf” properties 
in one call.  Work is in progress to remove all unnecessary calls to this 
method from JSX.]

The only completely safe solution regarding a call, however less backwards-
compatible and error-prone because it can result in false negatives, is to 
use a try…catch statement in which to attempt the call:

  try
  {
    foo.bar();
  }
  catch (e)
  {
    if (e instanceof TypeError)
    {
      /* handle problem */
    }
  }

It is error-prone because, in theory, the called method and any method that 
is called by it could throw a TypeError exception.  Also, one must be 
careful not to catch too many exceptions with one try…catch statement, 
making the source code harder to debug.

-- 
PointedEars
FAQ: <http://PointedEars.de/faq> | <http://PointedEars.de/es-matrix>
<https://github.com/PointedEars> | <http://PointedEars.de/wsvn/>
Twitter: @PointedEars2 | Please do not cc me./Bitte keine Kopien per E-Mail.

[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.javascript


csiph-web