Object oriented stuff and browsers related thing

L

Luke Matuszewski

Here are some questions that i am interested about and wanted to here
an explanation/discussion:
1. (general) Is the objectness in JavaScript was supported from the
very first version of it (in browsers) ? What about the new syntax of
creating a object using { 'propName1':'propValue1',
'propName2':'propValue2', 'propName3':{ /* another object */ } } - from
what version of JScript/JavaScript it was supported (from what browsers
versions) ?

2. (object-oriented) Every object has a prototype (and so on the
toString(), (other)... methods inherited from it). When i do sth like
this:

function MyConstr() {
var thisVar = this; /* Protected pattern */
var someProtected = 3; /* Protected pattern */
var this.thisVar = this; /* Public pattern */
/* here 'this' specifies the reference to the created object via 'new'
keyword */
this.myFunc = function () { /* Privilaged pattern */
/* here 'this' specifies the reference to ... what ?
1. to function myFunc context - so it points no more to the newly
created object via new MyConstr()
(thus someone could say it is buggy and should use thisVar)
2. to newly created object via new MyConstr();
*/

}

}

MyConstr.myFunc2 = function () { /* Public pattern */
/* here 'this' specifies the reference to ... what ?
1. to function myFunc2 context - so it points no more to the newly
created object via new MyConstr()
(thus someone could say it is buggy and should use this.thisVar)
2. to newly created object via new MyConstr();
*/
}

MyConstr.prototype.myFunc3 = function () {
/* here 'this' references to what object/contex ?
*/
}

Questions:
2.1 What is the difference between the myFunc and myFunc2 ? I know that
inserting function inside constructor takes more memory when
instantiating new objects than outside like myFunc2... but myFunc has
acces to someProtected variable and myFunc2 does not. Can anyone point
other differences ?
2.2 What about the issues with 'this' keyword ? (see more comments
about it in source code provided above - especially concerning about
what object/contex 'this' references)
2.3 Properties added outside the constructor body are accessible
without first creating an object right ? so one could say they are
static... is this correct ? (any other issues).
2.4 Any other suggestions on OOP in JS ? please write sth or provide a
link (i have read faq_notes on jiberring).

3. I have heard that statement
MyConstr.myFunc2 = function ()
was bad supported in IE5 ? (or maybe a new Function(...) construction).
Please provied a link/comment ?

Thats all i remember folks :)
Waitin for reply.
 
L

Luke Matuszewski

Ok i have done some testing and i want to here am i right:
1. Constructors can be called like functions and when they are the
'this' keyword points to global object or 'outer' this in terms of
[[scope]] chain (so points to outer object when called inside living
object);
In functions assigned to constructor outside like:
MyArray.myFunc = function () {
this.d = "Wow";
}
'this' keyword points to MyArray context, so MyArray.d is "Wow".
(so shortly 'this' points to 'nearest' object in scope chain of
execution contexts, here we see that for myFunc function 'nearest'
object is in MyArray object (which is function object).

2. Keyword 'this' in constructor points to object created via 'new'
keyword (and here are some remarks that this should be put in some
variable - like thisRef (var thisRef = this;) for accessing 'this' in
functions avoiding some buggs in some browsers - like early IE);

3. Keyword 'this' in function added to prototype point to prototype
object so doing:
MyArray.prototype.myFunc3 = function () {
this.protoMy = 5;
}
, and then invoking
MyArray.prototype.myFunc3()
'this' points to prototype object (which is, when not touched, the pure
Object).
This prototype object assigned to constructor is shared among other
newly (via 'new') created objects, so changing its properties later
will affect all object created before and after changes of it.
If you assign new object to prototype then objects created before will
not be affected and only newly created objects will have new prototype
object (here we feel that in JavaScript we deal with references and
primitives).

I have also tried to do smt like this:
MyArray.prototype = 3; /* this is probably an error, but it assigns
properly the value 3 */
MyArray.prototype.myFunc3 = function () {
this.protoMy = 5;
}
, then new objects are created but with 'standard' prototype (which is
Object... without myFunc3).
var myArray1 = new MyArray();
.... some other checks
typeof(myArray1.prototype) == undefined; /* so objects doesn't have
named property 'prototype' */
typeof(MyArray) == function;
typeof(MyArray1) == object;

If objects doesn't have named property 'prototype' so they 'use'
prototype of its constructor.

This is all i figured, any suggestions/comments ?
Please reply.
Best regards.
 
T

Thomas 'PointedEars' Lahn

Luke said:
Here are some questions that i am interested about and wanted to here
an explanation/discussion:
1. (general) Is the objectness in JavaScript was supported from the
very first version of it (in browsers) ?

Yes, with Netscape 2.0 being the first (and only) browser to support
JavaScript 1.0. It is also supported since JScript 1.0 and specified
since ECMAScript Edition 1.

JavaScript < 2/JScript < 7/ECMAScript are object-oriented programming
languages using prototype-based inheritance.

JavaScript 2/JScript 7 (.NET)/ECMAScript 4 are object-oriented programming
languages supporting both prototype-based and class-based inheritance.
(However, there are only proposals and test implementations of those for
the first and the last yet.)
What about the new syntax of
creating a object using { 'propName1':'propValue1',
'propName2':'propValue2', 'propName3':{ /* another object */ } } - from
what version of JScript/JavaScript it was supported (from what browsers
versions) ?

Documentation (see e.g. <URL:http://jibbering.com/faq/>,
<URL:http://mozilla.org/js/language/>,
<URL:http://developer.mozilla.org/javascript/>
and
<URL:http://msdn.microsoft.com/library/d...cript7/html/jslrfjscriptlanguagereference.asp>)
states that such Object (object) literals are supported from

JavaScript version 1.3 (NN 4.06, Mozilla/5.0),
JScript version 3.0 (IE/Win 4+, IIS 4+),
ECMAScript Edition 3

on. The same goes for Array (object) literals: [..., ...].

Now that you mentioned it: Since I asked such questions myself often and
finally did not want to bother checking all references every time, I have
begun to create a support matrix on my local Web server and now have
uploaded the latest version of it to be accessible at

<http://www.PointedEars.de/scripts/js-version-info>

I intend to correct/complete it with the help of further tests,
documentation and posters of this group. (If the scrolling table
is garbled in Firefox, just increase text size via the View menu
or Ctrl++ and decrease it again (with Ctrl+-). That is a Firefox
bug I was willing to accept for local use.)
2. (object-oriented) Every object has a prototype (and so on the
toString(), (other)... methods inherited from it). When i do sth
like this:

function MyConstr() {
var thisVar = this; /* Protected pattern */
var someProtected = 3; /* Protected pattern */
var this.thisVar = this; /* Public pattern */
^^^^^^^^^
This (*g*) is a syntax error. It should be

this.thisVar = this; /* Public pattern */
/* here 'this' specifies the reference to the created object via 'new'
keyword */

True, iff MyConstr() is called as a constructor (with the NewExpression).
this.myFunc = function () { /* Privilaged pattern */
/* here 'this' specifies the reference to ... what ?
1. to function myFunc context - so it points no more to the newly
created object via new MyConstr()
(thus someone could say it is buggy and should use thisVar)
2. to newly created object via new MyConstr();
*/

2., unless Function.prototype.call() is used. But if you referred to `this'
as within the method definition, that would not be 2. because it is within
the constructor, but because the method is that of what will be the calling
object.
}

}

MyConstr.myFunc2 = function () { /* Public pattern */
/* here 'this' specifies the reference to ... what ?
1. to function myFunc2 context - so it points no more to the newly
created object via new MyConstr()
(thus someone could say it is buggy and should use this.thisVar)
2. to newly created object via new MyConstr();
*/
}

Neither one. It refers to `MyConstr' as that would be the
calling object, unless Function.prototype.call() is used.
MyConstr.prototype.myFunc3 = function () {
/* here 'this' references to what object/contex ?
*/
}

`this' refers to the object that `MyConstr' is the constructor of or that
is derived from `MyConstr', unless Function.prototype.call() is used. So
it refers to the calling object again.
Questions:
2.1 What is the difference between the myFunc and myFunc2 ? I know that
inserting function inside constructor takes more memory when
instantiating new objects than outside like myFunc2... but myFunc has
acces to someProtected variable and myFunc2 does not. Can anyone point
other differences ?

I think we have clarified this about 15 minutes before your posting
in <URL:Since it was posted via Google Groups, it should already be archived
there.
2.2 What about the issues with 'this' keyword ? (see more comments
about it in source code provided above - especially concerning about
what object/contex 'this' references)

It refers to the calling or created object or to the Global Object
if there is none of the former.
2.3 Properties added outside the constructor body are accessible
without first creating an object right ? so one could say they are
static... is this correct ? (any other issues).
Correct.

2.4 Any other suggestions on OOP in JS ? please write sth or provide a
link (i have read faq_notes on jiberring).

For example said:
3. I have heard that statement
MyConstr.myFunc2 = function ()
was bad supported in IE5 ? (or maybe a new Function(...) construction).
Please provied a link/comment ?

The function operator (first line) is documented to be supported from

JavaScript version 1.5 (see above; however it works in NN 4.8 as well)
JScript ?
ECMAScript Edition 3

on. The Function constructor (second line) is documented to be supported
from

JavaScript version 1.1 (NN 3.0, NES 2.0)
JScript version 2.0 (IE/Win 3, IIS 3)
ECMAScript Edition 1

on.


HTH

PointedEars
 
M

Michael Winter

On 18/11/2005 18:05, Luke Matuszewski wrote:

[snip]
1. (general) Is the objectness in JavaScript was supported from the
very first version of it (in browsers) ?

Yes, though that's irrelevant. It would be rare enough to come across a
client implementing only JavaScript 1.3 (and its equivalents), let alone
1.0.
What about the new [object literal] syntax [...]

It isn't new. Again, don't worry about it. Any browser that old is
unlikely to provide an object model worth scripting.

[snip]
function MyConstr() {
var thisVar = this; /* Protected pattern */
var someProtected = 3; /* Protected pattern */
var this.thisVar = this; /* Public pattern */

That last statement will throw a run-time exception. A var statement is
a comma-separated list of identifiers, with optional initialisers. A
full-stop (.) is not allowed in an identifier. You meant

this.thisVar = this;

though that's entirely redundant.

[snip]
this.myFunc = function () { /* Privilaged pattern */
/* here 'this' specifies the reference to ... what ?

The value of the this operator, in the context of functions, varies
depending on the way in which a function is called.

If a function is called using a member expression (that is, as a
property of some object), the this operator will reference its object:

object.myMethod(); /* this = object */

Any function called /directly/ will have a this value that refers to the
global object, even if that function was the property of another object:

var myMethod = object.myMethod;

function myFunction() {}

myMethod(); /* In both cases,
myFunction(); * this = global object
*/

Finally, a script may provide a custom object using the built-in
Function.prototype.call or apply methods:

myMethod.call(object); /* Identical to first example */
myMethod.call(anotherObject); /* this = anotherObject */

However, it should be noted that JScript doesn't implement these methods
until version 5.5 (though they can be emulated, if need be).

There are a couple of important implications here if one extends these
ideas further. The first involves transferring methods from one object
to another:

function A() {}
A.prototype.myMethod = function() {};
function B() {}

var a = new A(),
b = new B();

b.myMethod = a.myMethod;

At this point, 'b' has a reference to a method that previously belonged
to 'a'. Calling that method through 'b'

b.myMethod();

means that the this operator will refer to 'b', not 'a'.

This is of interest when trying to use object methods as event
listeners. Assigning a method to an element as an event listener
produces precisely the same effect as that above.

Another consequence involves private instance methods:

function MyObject() {
function privateMethod() {}

this.publicMethod = function() {
privateMethod();
};
}

When publicMethod calls privateMethod, the this operator will refer to
the global object meaning that privateMethod (as is) cannot access any
public properties.

One solution, and potentially the nicest, would be to use the call
method in publicMethod and pass the this operator as its first argument.
The this operator in privateMethod would then refer to the object
instance as well. However, as I noted above, previous versions of
JScript in IE don't implement it, so the next best thing is to create a
private instance member, which private methods can access, that
references the object. The first thisVar member in the code posted is an
example.

function MyObject() {
var self = this;

function privateMethod() {
/* Use self to refer to public
* properties of this instance.
*/
}

this.publicMethod = function() {
privateMethod();
};
}

[snip]
MyConstr.myFunc2 = function () { /* Public pattern */
/* here 'this' specifies the reference to ... what ?

The same behaviour described above also applies here. However, the
method in this instance is static: a property of the constructor itself,
not any instance.

var object = new MyConstr();

MyConstr.myFunc2(); /* OK */
object.myFunc2(); /* myFunc2 undefined -> Run-time error */

[snip]
MyConstr.prototype.myFunc3 = function () {
/* here 'this' references to what object/contex ?

Again, the same behaviour will be observed, but this situation is closer
to the first approach.

There are two key differences between adding methods in the constructor
and via the prototype object.

1. Privileged methods that access private instance members can
only be created within the context of the constructor
function.

function MyObject() {
var privateMember = 'private instance';

this.privilegedMethod = function() {
return privateMember;
};
}
MyObject.prototype.prototypedMethod = function() {
return privateMember;
};

var o = new MyObject();

o.privilegedMethod(); /* 'private instance' */
o.prototypedMethod(); /* [run-time error] */

Prototyped methods can be used to access private static
methods, though:

var MyObject = (function() {
var staticMember = 'private static';

/* This function is the actual constructor function
* used to create MyObject instances. It is returned
* later so that other code can access, and call, it.
*
* A function expression (above) wraps around this
* constructor and the private static member, creating
* a separate execution context in which to store these
* variables.
*/
function constructor() {
var privateMember = 'private instance';

this.constructorMethod = function() {
/* ... */
};
}
constructor.prototype.prototypedMethod = function() {
/* ... */
};
return constructor;
})();

MyObject.prototype.unprivilegedMethod = function() {
/* ... */
};

In this example, instances created from the MyObject
constructor function will have three public methods:
constructorMethod, prototypedMethod, and unprivilegedMethod.
The first, constructorMethod, has access to both the
privateMember and staticMember variables. The second,
prototypedMethod, has access to the staticMember variable.
Finally, unprivilegedMethod has access to none of them. It
will only be able to access public members.

2. Prototyped methods are shared by all instances of an object,
whereas methods created by a function expression and
assigned in the constructor are created anew with each
instance.

If a prototyped method modifies a variable in its scope
chain, all instances will use that modified value later.
This isn't necessarily a bad thing - it's precisely how the
private static example works - but it should be remembered.

[snip]
2.1 What is the difference between the myFunc and myFunc2 ?

Hopefully, you'll considered that answered already: myFunc is an
instance method, and myFunc2 is a static method.
I know that inserting function inside constructor takes more memory when
instantiating new objects than outside like myFunc2...

It also takes longer as the function expression has to be evaluated each
time.

[snip]
3. I have heard that statement
MyConstr.myFunc2 = function ()
was bad supported in IE5 ? (or maybe a new Function(...) construction).
Please provied a link/comment ?

I can't say that I've noticed any problems.

[snip]

Mike
 
M

Michael Winter

On 18/11/2005 23:25, Luke Matuszewski wrote:

[snip]
1. Constructors can be called like functions

Constructors /are/ functions, though they're not often written in a way
that allows them to be called normally with useful results.

When the new operator is used, the constructor will eventually be
called. However, an object is first created, the prototype property of
the constructor forms the prototype chain, and this new object is used
for the this operator. When the constructor returns, the object is the
result of the new operator unless the constructor returns its own object
(which is used instead).
and when they are the 'this' keyword points to global object

If called directly, yes. See my other post, if you haven't yet.
or 'outer' this in terms of [[scope]] chain (so points to outer
object when called inside living object);

I'm not sure what point you're trying to make here, so I can't say
whether it's right or not.
In functions assigned to constructor outside like:
MyArray.myFunc = function () {
this.d = "Wow";
}
'this' keyword points to MyArray context

"MyArray context"? Again, you seem to be using terms that are confusing
the issue.

If the myFunc method is called thus:

MyArray.myFunc();

then the this operator will refer to MyArray.
so MyArray.d is "Wow".
Yes.

(so shortly 'this' points to 'nearest' object in scope chain of
execution contexts, here we see that for myFunc function 'nearest'
object is in MyArray object (which is function object).

No. The this operator has nothing to do with the scope chain. When
considering functions, it's value is determined entirely by how the
function is called.
2. Keyword 'this' in constructor points to object created via 'new'
keyword (and here are some remarks that this should be put in some
variable - like thisRef (var thisRef = this;) for accessing 'this' in
functions avoiding some buggs in some browsers - like early IE);

There is a bug in IE's event model regarding the this operator and the
attachEvent method, but none, as I recall, with its object model.
3. Keyword 'this' in function added to prototype point to prototype
object so doing:
MyArray.prototype.myFunc3 = function () {
this.protoMy = 5;
}
, and then invoking
MyArray.prototype.myFunc3()
'this' points to prototype object (which is, when not touched, the pure
Object).
Correct.

This prototype object assigned to constructor is shared among other
newly (via 'new') created objects, so changing its properties later
will affect all object created before and after changes of it.

Correct.

When an object is created, the prototype property of the constructor is
copied to the internal [[prototype]] property of the object (if the
prototype property is an object). As this copied value is a reference,
both the prototype property and internal [[prototype]] property will
refer to the same object. If the properties of that object are modified,
both previously instantiated and newly instantiated objects will be
affected.
If you assign new object to prototype then objects created before will
not be affected and only newly created objects will have new prototype
object [...]

Yes. The prototype property and the internal [[prototype]] properties of
previously instantiated objects will now refer to different objects.
Altering the properties of one will not affect the other.

[snip]
I have also tried to do smt like this:
MyArray.prototype = 3; /* this is probably an error, but it assigns
properly the value 3 */

It's not an error, but it won't react properly because the prototype
property is now a number value, not an object.

MyArray.prototype = new Number(3);

is a different matter.
MyArray.prototype.myFunc3 = function () {
this.protoMy = 5;
}

As the prototype property from your code above is not an object, you
cannot add properties to it. So, the number value will temporarily be
converted to a Number object, and a new property will be added to that
object. However, it is only this temporary object that will possess the
property, and it almost immediately ceases to exist.
then new objects are created but with 'standard' prototype (which is
Object... without myFunc3).

Yes. If the prototype property does not reference an object, it is
ignored and the 'original' Object prototype object will be used instead.

[snip]

Mike
 

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,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top