inheritance in JavaScript

S

shlomi.schwartz

Q: is it possible to inherit from a native object?

I tried to use Date object as the base object like so:

x.prototype = Date.prototype;
x.prototype.constructor = x;

function x(){
//constructor
}

var obj = new x();

ERROR ----> x.getDate();

is there another way?
 
V

VK

Q: is it possible to inherit from a native object?


Q: is it possible to inherit from a native object?

JavaScript/JScript native objects are "protected" in the best meanning
of OOP. You can initially spoof constructor by doing something like:
....
this.getTime = Date.prototype.getTime;
....
But it will fail on the first method call (caller object type doesn't
match).

Also there is not too much sense to extend Date as it doesn't
autoupdate time: it will be always the time of the creation. Thus it is
much better to:

function XDate() {
this.getTime = function() {
return (new Date()).getTime();
}
// my other methods
}
 
V

VK

For memory management safety:

function XDate() {
this.getTime = function() {
var d = new Date();
return d.getTime();
}
// my other methods
}
 
T

Thomas 'PointedEars' Lahn

Q: is it possible to inherit from a native object?

AFAIK only from Object.
I tried to use Date object as the base object like so:

x.prototype = Date.prototype;

ReferenceError: x is not defined.
x.prototype.constructor = x;

function x(){
//constructor
}

var obj = new x();

ERROR ----> x.getDate();

If the constructor comes before everything else (to avoid the ReferenceError
above), that is rightfully

TypeError: x.getDate is not a function
is there another way?

One way to inherit from another prototype is

function inheritFrom(o)
{
var Dummy = function() {};
Dummy.prototype = new o();
return new Dummy();
}

function MyDate()
{
// whatever
}

MyDate.prototype = inheritFrom(Date);

var d = new MyDate();

This allows MyDate objects such as `d' to inherit Date.prototype.getDate(),
as

alert(d.getDate);

shows. However,

alert(d.getDate());

results in

TypeError: Date.prototype.getDate called on incompatible Object.

So it is not possible to inherit from Date directly and use the
inherited methods. There are two possible workarounds I know of:

A) Encapsulate a Date object in the user-defined object

function MyDate()
{
this.date = new Date();
}

MyDate.prototype.getDate = function()
{
return this.date.getDate();
}

// ...

alert(new MyDate().getDate());

B) Extend the Date prototype and use a Date object:

Date.prototype.isLeapYear = function(y)
{
return (new Date(y || this.getFullYear(), 1, 29).getMonth() == 1);
}

alert(new Date().isLeapYear());


PointedEars
 
T

Thomas 'PointedEars' Lahn

VK said:
For memory management safety:

function XDate() {
this.getTime = function() {
var d = new Date();
return d.getTime();
}
// my other methods
}

What "memory management safety" are you talking about? In your previous

function XDate()
{
this.getTime = function() {
return (new Date()).getTime();
}
// my other methods
}

the Date object would be allowed to be subject to Garbage Collection
after the execution context of the getTime() method was left as would
it be if there were a local variable referencing it.

Regarding memory management, it is more memory-efficient to make the
getTime() method a property of the XData prototype instead of its
instances.

Still your getTime() method would be fundamentally different from the
getTime() method of the Date object, as not the current time is used
for the latter for its return value but the time set for that object:

var
d = new Date(2005, 11, 18),

// let us assume you call the Date constructor in the XDate constructor
x = new XDate(2005, 11, 18);

alert(d.getTime() != x.getTime()); // always true


PointedEars
 
R

Richard Cornford

Q: is it possible to inherit from a native object?

Yes of course you can, but not necessarily in the way you mean here.
I tried to use Date object as the base object like so:

x.prototype = Date.prototype;

It is normal to 'inherit' the behaviour of an object by assigning an
instance of that object to the prototype of a constructor. Here you are
assigning a reference to another constructor's prototype. You will
inherit the methods and properties of the prototype in this way, but
that may not be sufficient in all cases.
x.prototype.constructor = x;

However, this is a dubious thing to do. By assigning a value to the
'constructor' property of the prototype of - x - you are also assigning
the value to the 'constructor' property of the prototype of - Date -. As
a result Date objects will look like - x - objects if you use their
'constructor' property to test for that.
function x(){
//constructor
}

var obj = new x();

ERROR ----> x.getDate();

This is what you have done. You have defined a function - x - as a
constructor and assigned the Date prototype to its 'prototype' property,
and then used - x - to construct a new object. That object will
'inherit' the methods defined on the Date prototype, but doing so is not
necessarily useful. The ECMA 262 definition of, for example, the getDate
method is:-

<quote cite="ECMA 262, 3rd edition; Section 15.9.5.14">
15.9.5.14 Date.prototype.getDate ( )
1. Let t be this time value.
2. If t is NaN, return NaN.
3. Return DateFromTime(LocalTime(t)).
</quote>

- and the first line in the algorithm for the method is 'Let t be this
time value', that is; the time value of the - this - object. If we look
at the definition of constructor for Date we find (for example):

<quote cite="ECMA 262, 3rd edition; Section 15.9.3.3">
15.9.3.3 new Date ( )
The [[Prototype]] property of the newly constructed object is set to
the original Date prototype object, the one that is the initial
value of Date.prototype (section 15.9.4.1).

The [[Class]] property of the newly constructed object is set to
"Date".

The [[Value]] property of the newly constructed object is set to the
current time (UTC).
</quote>
(all other variations of Date construction include these steps)

So the 'time value' of a Date object is the value assigned to its
internal [[Value]] property. The problem with inheriting the methods of
the Date object through its prototype is that your - x - constructors is
not capable of setting the internal [[Value]] property of the objects it
creates (ECMAScript has no mechanism for making such an assignment).
The - this - object constructed with - x - has no 'time value'. You can
inherit the method of Date through an object's prototype, but those
methods are useless to the constructed object, and will almost certainly
error if used.

Other native objects have method defined for their prototypes that may
explicitly be used with other objects. For example, nearly all String
object methods may be used by other objects. Where applicable the ECMA
262 includes a note along the lines of "The xxxxxxxx function is
intentionally generic; ..."

However, it is generally not that productive to attempt to inherit from
native objects through the prototype chain. Partly because not all of
the native objects methods are suitable for use with other types of
object but mostly because implementation bugs (particularly in IE) and
specification ambiguities (mostly relating to the interpretation of "If
this object does not have a property named by Result(n) ...") mean that
many methods that should be generic in theory are not in practice.
is there another way?

There are at least half a dozen other ways. Javascript is a very
flexible language, and because it has no classes (so all notions of
sub-classing are conceptual) approaches are better related to achieving
outcomes than following any single pre-defined pattern. For example, if
what you want is instances of a type of object that has all of the
behaviour of Date objects plus some additional features (effectively a
'sub-class' of Date) it is completely reasonable to have a 'factory'
function that passes arguments on to the Date constructor to create a
new Date instance and then augments that Date instance with additional
methods, etc. before returning it. E.G:-

function modifiedDateFactory(yearOrValue, month, date, h, m, s, ms){
var d = new Date (yearOrValue, month, date, h, m, s, ms);
// modify the new Date object here, by adding extra methods and
//properties or overloading existing public methods and properties.
return d;
}

(For information, when reading this group it is worth baring in mind
that VK's posts mostly consist of the fictional products of a deranged
mind. They are almost exclusively false, incomplete, misconceived or
represent the worst possible advice in any given situation)

Richard.
 
R

Richard Cornford

Thomas 'PointedEars' Lahn wrote:
ReferenceError: x is not defined.
<snip>

No error should result from placing a constructor function in the form
of a FunctionDeclaration after an assignment to its prototype.
FunctionDeclarations are processed during Variable Instantiation, as
code enters an execution context (including the global execution
context(s)) and that precedes any function body or inline code
execution, so the function - x - will be defined at the point of the
assignment to its prototype.

Though, while the lexical sequence of the assignment operation and
FunctionDeclaration will not effect the behaviour of the code source has
got to be easier to understand where constructor function declarations
appear before operations performed upon their prototypes.

Richard.
 
T

Thomas 'PointedEars' Lahn

Richard said:
Thomas said:
ReferenceError: x is not defined.
<snip>

No error should result from placing a constructor function in the form
of a FunctionDeclaration after an assignment to its prototype. [...]

True. It appears that the JavaScript Panel of ContextMenu Extensions
4.0.2005082201 which I used to do quick tests is flawed in the regard
that it evaluates each statement or expression after the other, and
not in context. The ReferenceError exception is not thrown when the
same script code is passed to SpiderMonkey version 1.5 (stand-alone)
or 1.6 (embedded in Firefox 1.5).


PointedEars
 
V

VK

VK said:
JavaScript/JScript native objects are "protected" in the best meanning
of OOP. You can initially spoof constructor by doing something like:
...
this.getTime = Date.prototype.getTime;
...
But it will fail on the first method call (caller object type doesn't
match).

You've spent a lot of words for the same information. It is nice to
know every single detail of the background mechanics as it should be.
It doesn't nullify though the previous answer and result/explanation of
something like
this.getTime = Date.prototype.getTime;
function XDate() {
this.getTime = function() {
return (new Date()).getTime();
}
// my other methods
}

It is a perfectly working solution which is easy to sheck. Yes -
XDate.getTime() will return the actual time on each call instead of
frozen "object creation time". It may be considered as a disadvantage
or as a benefit of extended Date object model depending on the intended
use. After all we don't know exactly why and how OP wants to extend the
Date object.

Richard said:
(For information, when reading this group it is worth baring in mind
that VK's posts mostly consist of the fictional products of a deranged
mind. They are almost exclusively false, incomplete, misconceived or
represent the worst possible advice in any given situation)

Taking the above into account could we add some netiquette in our
postings please?

"This code is a f***** sick sh** because x doesn't equal to y ... etc"
- it is completely OK not to say welcome :)

"This code is a f***** sick sh** because X wrote it" or "because a
non-native English speaker wrote it" - IMHO it smells bad from the
point of view of the common communication practice. IMHO
 
R

Richard Cornford

Meaningless drivel!

The last time we spoke of "protected" you demonstrated that you do not
understand its meaning in the context of OO programming. And indeed have
demonstrated only a superficial grasp of OO at all.

Meaningless drivel!

May or may not fail depending on what - this - refers to.
You've spent a lot of words for the same information.

No, I have spent words on information, your contribution is not
information. Though, because your thought processes are so superficial
you may have deluded yourself into believing that you have said
something worthwhile here, but as usual you are wrong.
It is nice to know every single detail of the background
mechanics as it should be.

Yes it is. Understanding how and why things work enables people to see
what can be done, and how they should/could go about doing them. While
the mystical fictions you promote contribute nothing.
It doesn't nullify though the previous answer and
result/explanation of something like
this.getTime = Date.prototype.getTime;

That assignment expression conveys nothing. It was nullified from the
moment you wrote it.

Yet another example of the stupid use of an inner function where it
serves no purpose. Another example of how when having a choice of
implementation strategies you invariable choose the worst for any given
context.
It is a perfectly working solution

Solution to what? No specific problem was proposed beyond inheriting
from native objects, and this is certainly not an example of inheriting
from native object (or even something resembling it.
which is easy to sheck. Yes - XDate.getTime() will
return the actual time on each call instead of
frozen "object creation time".

No it will not. XDate is a function object and has no - getTime - method
defined here. You will get a runtime error. Why am I not surprised to
read you asserting that code that will inevitably produce a runtime
error as "working"?
It may be considered as a disadvantage or as a benefit
of extended Date object model depending on the
intended use.

It is not extending the Date object at all.
After all we don't know exactly why and how OP wants to
extend the Date object.
Taking the above into account could we add some netiquette
in our postings please?

"This code is a f***** sick sh** because x doesn't equal to y
... etc" - it is completely OK not to say welcome :)

And exactly how often do you expect people to tell you why your code is
sh** when you never pay any attention to what is said to you? It is
inevitable that if you keep posting garbage code and nonsense
explanations after you have been repeatedly corrected the nature of the
responses to you 'contributions' will change towards the exclusively
negative. If you refuse to learn anything then there is little point in
anyone attempting to teach you anything.
"This code is a f***** sick sh** because X wrote it" or
"because a non-native English speaker wrote it" - IMHO
it smells bad from the point of view of the common
communication practice. IMHO

For most people you could not equate poor code authoring and that
individual because they would be expected to learn to write better code
(even good code). However, in your case the manifest evidence of your
unwillingness to learn anything about javascript dooms you to never
being able to write better code than you do now, and what you write now
is rubbish (so bad that it can usually be regarded as providing examples
of how not to do things). So in your case your code will be bad code
because it was you who wrote it, and that will continue to be the case
for as long as you resist learning to understand javascript.

If you don't like people publicly stating that you are a terribly bad
programmer trying to promote your fictitious and mystical misperception
of javascript because any form of technical understanding of the subject
exceeds your limited intellectual capabilities then you should try
shutting the f**k up, because that is the only way in which your
nonsense will cease to be subject to criticism.

And in case you were wondering, you opinion, honest or otherwise, has no
value at all.

Richard.
 
S

shlomi.schwartz

Hi guys ..

Thanks for your reply, I liked the factory idea and I'm gonna use it.

thanks again.
 
J

Jambalaya

V

VK

Jambalaya said:
Richard said:
[snip]
(For information, when reading this group it is worth baring in mind
that VK's posts mostly consist of the fictional products of a deranged
mind. They are almost exclusively false, incomplete, misconceived or
represent the worst possible advice in any given situation)

So mean and yet so true. His post in this thread
<url:http://groups.google.com/group/comp.lang.javascript/browse_thread/thread/ad6edf1c361da55a>
convinced me of it...

Eh?
The only words I *ever* pronounced in that thread were:
<quote>
I did not look your code through (it's big :)
Just for hell of it:
instead of:
var randomNumber = Math.floor(Math.random() * 9999999);
try:
var randomNumber = (new Date()).getTime();
</quote>

Just a humble advise to eliminate any possibility of client-side
caching. It can be a prove of ignorance only to someone who's not aware
of *pseudo*-random nature of Math.random(), its seeding mechanics (only
once on each engine load) and some other things you've get your fingers
bourned with enough of "practical development". I explicetly stated
though that I was not sure at all that it had any connection with the
OP's problem. And it indeed did not have such connection - so what
crime is that?

You know - on the long run you may have much more luck with jumping on
my typos.
 

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,995
Messages
2,570,230
Members
46,819
Latest member
masterdaster

Latest Threads

Top