Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.javascript > #32133 > unrolled thread
| Started by | Andrew Poulos <ap_prog@hotmail.com> |
|---|---|
| First post | 2017-01-08 16:49 +1100 |
| Last post | 2017-01-08 23:21 +0100 |
| Articles | 9 — 5 participants |
Back to article view | Back to comp.lang.javascript
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
| From | Andrew Poulos <ap_prog@hotmail.com> |
|---|---|
| Date | 2017-01-08 16:49 +1100 |
| Subject | Empty 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]
| From | Martin Honnen <martin.honnen@gmx.de> |
|---|---|
| Date | 2017-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]
| From | Andrew Poulos <ap_prog@hotmail.com> |
|---|---|
| Date | 2017-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]
| From | Thomas 'PointedEars' Lahn <PointedEars@web.de> |
|---|---|
| Date | 2017-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]
| From | Andrew Poulos <ap_prog@hotmail.com> |
|---|---|
| Date | 2017-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]
| From | Thomas 'PointedEars' Lahn <PointedEars@web.de> |
|---|---|
| Date | 2017-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]
| From | JJ <jj4public@vfemail.net> |
|---|---|
| Date | 2017-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]
| From | "Michael Haufe (TNO)" <tno@thenewobjective.com> |
|---|---|
| Date | 2017-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]
| From | Thomas 'PointedEars' Lahn <PointedEars@web.de> |
|---|---|
| Date | 2017-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