Replacing 'new'?

T

Thomas 'PointedEars' Lahn

Stefan said:
function Food (calories) {
this.calories = calories;
}

Food.prototype = {
countCalories: function () {
return this.calories;
}
};

function makeMeASandwich (slices) {
var CALORIES = 345;
function SandwichConstr () {
this.countSlices = function () {
return slices;
};
}
SandwichConstr.prototype = Food.prototype;
var sw = new SandwichConstr();
Food.call(sw, CALORIES);
return sw;
}

var sandwich = makeMeASandwich(2);
print(sandwich.countSlices());
print(sandwich.countCalories());


This should work, but it removes much of the elegance and ease of use.

Working and quite elegant approaches to set up a prototype chain have been
discussed here before. In a nutshell:

/* ... */

Function.prototype.extend = (function() {
var D = function() {};

return function(C, oProtoProps) {
D.prototype = C.prototype;
this.prototype = new D();

/* TODO: Augment the prototype object here from oProtoProps */

this.prototype.constructor = this;

/*
* Omit the prototype assignment if you want faster for-in
* iteration but harder to maintain/slower constructors
*/
this._super = this.prototype._super = C;

return this;
};
})();

var Sandwich = (function(slices, calories) {
this._super.call(this, calories);

this.countSlices = function() {
return slices;
};
}).extend(Food);

var sandwich = new Sandwich(2, 345);
print(sandwich.countSlices());
print(sandwich.countCalories());


PointedEars
 
T

Thomas 'PointedEars' Lahn

Thomas said:
[...]
/*
* Omit the prototype assignment if you want faster for-in
* iteration but harder to maintain/slower constructors
*/
this._super = this.prototype._super = C;

Sorry, the comment is misleading. I should have copy-pasted more from
object.js and re-invented less ...
return this;
};
})();

var Sandwich = (function(slices, calories) {
this._super.call(this, calories);

The reason I dropped this approach already in favor of

arguments.callee._super.call(this, calories);

or, in general,

arguments.callee._super.apply(this, arguments);

is that the this._super version works only with one inheritance level (in
constructors). The "parent" constructor called as a method of `this' every
time would result in infinite recursion otherwise.

IOW: The user-defined `_super' property of non-Function instances should
only ever be used if you need to call a prototype property directly; in the
call that calls another constructor, the user-defined `_super' property of
the constructor should be used.


PointedEars
 
D

Dmitry A. Soshnikov

Sorry, the comment is misleading.  I should have copy-pasted more from
object.js and re-invented less ...
The reason I dropped this approach already in favor of

  arguments.callee._super.call(this, calories);

or, in general,

  arguments.callee._super.apply(this, arguments);

is that the this._super version works only with one inheritance level (in
constructors).  The "parent" constructor called as a method of `this' every
time would result in infinite recursion otherwise.

btw, the more elegant is to use just this._super() in every overloaded
method. It can be achieved by creating a new function object for child
methods with same name. In this wrapped function we set correct
this._super property (on the parent method with the same name), then
call original method, then restore original this._super and back
result of the original method.

Thus, in every child-method with the same name we can use simply
this._super(arguments), but not that long arguments.callee._super.apply
(this, arguments);

If you'll be needed an example, let me know.
 
T

Thomas 'PointedEars' Lahn

Dmitry said:
btw, the more elegant is to use just this._super() in every overloaded
method.

No, it isn't. That is not always desired, it is likely to be less
efficient, it creates a maintenance nightmare, and it would not set
up the prototype chain properly.
Thus, in every child-method with the same name we can use simply
this._super(arguments), but not that long arguments.callee._super.apply
(this, arguments);

By contrast, that "long" thing is called only on instantiation.
If you'll be needed an example, let me know.

No, thanks. By contrast, I know what I am doing here.


PointedEars
 
D

Dmitry A. Soshnikov

No, it isn't.  That is not always desired, it is likely to be less
efficient, it creates a maintenance nightmare, and it would not set
up the prototype chain properly.

What "No, it isn't"? If u don't completely understand what u talking
about - why talking in such categorical confirming manner? ;)

Yeah, sure, it will use more resources (actually, a new wrapper
function for each child function with the same name).
it creates a maintenance nightmare
Demagogy.

and it would not set
up the prototype chain properly.

Would. Prototype chain would be set correctly.
By contrast, that "long" thing is called only on instantiation.


No, thanks.  By contrast, I know what I am doing here.

Just suggested, as you wish ;)
 
T

Thomas 'PointedEars' Lahn

Dmitry said:
What "No, it isn't"? If u don't completely understand what u talking
^ ^
about - why talking in such categorical confirming manner? ;)

To make you think. I suggest you learn to talk before talking about talking.
Yeah, sure, it will use more resources (actually, a new wrapper
function for each child function with the same name).

What matters regarding efficiency is that it is going to be considerably
slower than the alternative.
Demagogy.

You don't know what you are talking about. If you changed the inherited
method all prototype methods that call it would need to be checked for
necessary changes. Even those that you do not have written. How elegant is
that? How easy to maintain?
Would. Prototype chain would be set correctly.

Only if you adopt the philosophy that any property added in a constructor
cannot be inherited or, in other words, that only prototype properties are
inherited. It is an interesting concept no doubt (emulating Java's `final',
for example), but seldom practical in ECMAScript implementations.


PointedEars
 
J

JR

Maybe (?):
var someObj = {
  a: function (b) {
    this.b = b;
    return this;
  },
  say: function () {
    window.alert(this.b);
  }
};
someObj.a('Hi, Dude!').say(); // returns 'Hi, Dude!'

Excuse me, but that's horrible. You're dynamically creating a property
when some random method is called - that's hardly new, nor is it good
style. What's more, you only ever have one |someObj| object. If you only
need one instance of an object, sure, you don't need |new|. The only
thing you added was support for method chaining (which has its own
problems, and its own popular library containing these problems ;-).
It's very difficult to get (totally) rid of 'this' keyword. Check
Douglas Crockford's website about the 'new' keyword.

To be honest, I'd rather listen to Peter Michaux, who wrote about this
subject, too, and (I think) more reasonably. I can't find the relevant
blog entry at the moment, but it was something along the lines of "be on
your guard when you see lots of [list of words like 'instanceof', 'new',
 etc]". If I remember correctly, he did not advocate writing programs
entirely without |new|.

FWIW, I personally use factory methods when I need 1-10 objects, and
proper constructors with |new| when I expect to create a lot of objects.
I hardly ever use inheritance in the sense it's normally used; I use
mixins instead. If your derived object needs methods from a base object,
just borrow them with call() or apply().

cheers,
stefan

Hi Stefan,
Yeah, that was a bad example ... as well it´s really a bad idea to
avoid the 'new' prefix operator. You're wasting your time in writing a
lot of code to try to implement all the things the 'new' prefix
already does. After reading what Richard Cornford and RobG said in
this topic, I started to disbelieve in Douglas Crockford´s 'Good
Parts' book... Douglas criticised the 'new' prefix but didn't give
valid or useful alternatives to it. What's the problem in using 'new'
prefix anyway?

Cheers,
JR

just because Douglas Crockford defined it as a 'bad' idea
 
D

Dmitry A. Soshnikov

                          ^                                 ^


To make you think.  I suggest you learn to talk before talking abouttalking.

Thx for advise ;)
What matters regarding efficiency is that it is going to be considerably
slower than the alternative.



You don't know what you are talking about.

Oh, thx, i "appreciated" your meaning about me ;) But, it's doesn't
actually matter anyway, as it's not the truth.
 If you changed the inherited
method all prototype methods that call it would need to be checked for
necessary changes.  Even those that you do not have written.  How elegant is
that?  How easy to maintain?

k, let me leave you alone with your misunderstanding as you don't
wanna (or can't?) understand how it works.
Only if you adopt the philosophy that any property added in a constructor
cannot be inherited or, in other words, that only prototype properties are
inherited.  It is an interesting concept no doubt (emulating Java's `final',
for example), but seldom practical in ECMAScript implementations.

no, sorry, u didn't get it correctly, so i may not disturb you
anymore; take a deeper look into ES ;)

/ds
 
G

Garrett Smith

Stefan said:
Now checkSlices() is accessible to any user of my Sandwich. I'd rather
hide it, because I may want to change it later
Yes, sure, but saying that, you again think about encapsulation in
"security" reason, afraid that some can change something that you
don't wanna be changed. If someone wants to change encapsulating data
- he will do it. Just opens your source code and make this method
public. The reason is - user needs it. More than, as you know, such
"encapsulated vars" is not 100% hidden [...]

Being able to clearly define an object's public interface is the heart
of the matter. Using underscore doesn't do that.
That's not why I'm hiding the details. I'm not concerned about people
changing or accessing parts of my code against my will. The reason why I
want to keep the hypothetical checkSlices() function from being exposed
as a "public" method is that I need to be able to change its
implementation, or remove it entirely, without worrying about any other
code which may use my object. If they don't see the method, they won't
be tempted to use it, and won't be affected by its change or removal.

That simplifies the object's public interface. Helps ease refactoring.
Also results in the scoped identifiers getting "munged" so the file
size gets squished. Also can help speed up identifier resolution, and
especially in Chrome.
Given the choice, I'd still hide them, because you can present a cleaner
interface to your object.

I agree.

A typical example for a private field would be
a data source (like a database connection object, or an XHR wrapper
object). If the purpose of your object is to present a facade for data
access, the data source will likely be stored as an object property, so
that the facade's methods can access it. From the outside this could
look like:

myObject:
Function loadRecord (loads a record)
Function createRecord (creates a record)
...
Object dataSource (please don't use me)

Responsible users won't call myObject.dataSource.send("raw query")
directly, but IMO the dataSource has no place in myObject's API.

Defining the object's interface is not just about "other" users, but
about the API. An API with dependencies where the dependent parts may be
accessing parts of that API that were "pretend private". When the API is
refactored, the "pretend private" parts can't really be treated as real
private. However, with internal identifiers, the scope of what is
using those identifiers is limited to, well, the "scope".
The other benefit of the makeMeASandwich() type of object generation is
that all methods can access the generator function's scope, and can
easily share data without resorting to this._mySharedObject.

I see three benefits to using generator function's scope:
1) Simple public interface
2) improved performance (fast scope resolution)
3) munge-able local identifiers.

#2 may be doubted by some, and in that case, this was discussed recently
in "where do I define my variables", "Primitive Re-definition"
"[[Delete]]'ing window properties".
I agree, it's good enough. And I'm aware of the memory issue.

What is the memory issue?

This can be deferred and the "private static prototype" methods can
be hidden away, only added when the first call to the "make sandwich"
method.
That's fine by me. If access to a property is required, it was probably
my mistake not to make it public in the first place.

The sandwich generator isn't the perfect match in every situation, and
it isn't required in any, but in some cases it's a useful pattern.

I use this pattern for widgets that decorate HTMLElement, and use
it with a "get or create" or "lazy initialization" pattern, as
"getById". I call it "createFactory".

But getting back to the Sandwich example, the pattern would be used to
create a "SandwichBuilderFactory", where the factory would return a
SandwichBuilder, which would be used to build Sandwiches, which keep
track of calories and contents (cheese, peanut butter, etc).

The SandwichBuilderFactory would be use as such:-

var fatty = SandwichBuilderFactory.create("fatty");

fatty.add("provolone", 100)
.add("bread", 200)
.add("mustard", 5);

Now we have SandwichBuilder "fatty" which should have 305 calories and
"provolone", "bread", and "mustard".

It is worth considering having "bread" be in the constructor if all
sandwiches are going to have bread (a likely design requirement). That
could be possible by using a "newApply" function, but requires more
explanation of both the context, the consequences of that decision, and
and the technical implementation of newApply, which is beside the point
here.

Here is how the SandwichBuilderFactory is implemented:

var SandwichBuilderFactory;

(function(){
SandwichBuilderFactory = createFactory(SandwichBuilder,
createSandwichPrototype);

/* constructor */
function SandwichBuilder(id, baseCalories){
this.id = id;
this.calories = baseCalories||0;
this.contents = [];
}

function createSandwichPrototype() {

/* Private static prototype members area. */
function checkSlices(upperSlice, lowerSlice) {
if (upperSlice.size != lowerSlice.size) {
throw new BreadException();
}
}

/* prototype */
return {
add : function(name, calories) {
this.calories += calories;
this.contents.push(name);
return this;
}
};
}
})();

I have re-written my createFactory in a way that is a little simpler
not using newApply, but being limited to working with 1-arg constructor.

/* get an object with a "create" method that new's constr */
function createFactory(constr, createPrototype){
var instances;

// constructor function
function F(){}

return {create:create};
function create(id) {
var instance;
if(!instances) {
instances = {};
if(typeof createPrototype == "function") {
constr.prototype = createPrototype();
}
}
if(!(id in instances)){
instance = instances[id] = new constr(id);
}
return instance;
}
}

The create method above passes 1 argument to the constructor: id.

AISB, a constructor with multiple parameters can be made to work if the
createFactory is changed to use a newApply. The implementation of that
would look like:-

// Bread is 200 calories.
var pbj = SandwichBuilderFactory.create("pbj", 200);

If factories for constructors of variable argument length
are wanted, then create needs to pass on those arguments. A newApply
method makes that possible.

The context of this pattern is a very important consideration in
its usage, and particularly with multiple arguments.

The |create| method gets an object from any one place in the code. The
first time the object is gotten, the constructor is called. The second
time it is gotten, the constructor is not called. Since the object is
identified by the |id|, that means the following:-

var pbj = SandwichBuilderFactory.create("pbj", 0);
pbj = SandwichBuilderFactory.create("pbj", 200);

would result in pbj.calories === 0.

That does not make the pattern useless but it is an important
consideration. In some contexts, multiple parameter variables with a get
or create method is useful.

This pattern is useful when a callback needs to get an Adapter for an
element.

The benefits are that it allows for lazy instantiation of the object and
prototype.
 
D

Dmitry A. Soshnikov

Stefan said:
Now checkSlices() is accessible to any user of my Sandwich. I'd rather
hide it, because I may want to change it later
Yes, sure, but saying that, you again think about encapsulation in
"security" reason, afraid that some can change something that you
don't wanna be changed. If someone wants to change encapsulating data
- he will do it. Just opens your source code and make this method
public. The reason is - user needs it. More than, as you know, such
"encapsulated vars" is not 100% hidden [...]

Being able to clearly define an object's public interface is the heart
of the matter. Using underscore doesn't do that.

Does anyone say different meaning? I mean, that's simple *abstracted*
public API to the outside - is a good constructed system? I've already
repeated not at once, that i think that's a good. But i wanted to
remind the general meaning of encapsulation (abstraction != security
hidden).

Here's could be misunderstanding and mixing up terminology and
meanings. When speaking outside API, in mind we can think about API
for users which can call something, can break something ("yep, sure,
they see that methods (methods are not hidden) - they will call them
and breake everything"). Such meaning treats users as *exactly users*,
e.g. users of money-terminal. And meaning public "API" - we can mean
some interface buttons for user such as "Insert card", "Insert money",
"Get change". And saying, "why method "Get all money from terminal"
should be public for user?". But that's just mixing up terminology and
demagogy (no more). Public interface for *user* - is totally different
thing then abstract system (provided by encapsulation) for
*programmers* (author of code - programmer, and users of code -
programmers). But not the users as "end users" of the system. Where
security stuff is (believe) not the "private, protected, public", but
more secure modules (which are also can be broken if will be needed).

Sure, i repeat, "sugar" as "private, protected, public" - is very
useful "sugar" to build more abstract and stable system. And if
there's no such sugar (repeat again), some organizational measures
(such as underscore naming convention) can be also treated as
encapsulation.
That simplifies the object's public interface. Helps ease refactoring.
Also results in the scoped identifiers getting "munged" so the file
size gets squished. Also can help speed up identifier resolution, and
especially in Chrome.




I agree.

But who will not agree? That's not logical do not agree.

What is the memory issue?

This all discussion about encapsulation was started from creating own
methods from objects in constructor. Sure, there could be joined
objects optimization (but in real practice code, the [[Scope]]
property can be always different - can the same structure, but
different values in it, so by description, there can be no joined
objects; but, anyway, i think realizations make some optimization
anyway, but we can't say accurate as we need to analyze all the source
codes of ES-engine realizations), but every created object will have
own properties.
 
T

Thomas 'PointedEars' Lahn

kangax said:
I don't see a reason to use function expression here.

Personal preference?

Unlikely, as the original code uses a function declaration.

However, the function expression scores over the function declaration in
flexibility of use. And I might have thought here that as we are in a
function expression already, why bother? It could also have been a Freudian
typo, or not. Sometimes a cigar is just a cigar :)


PointedEars
 
G

Garrett Smith

Dmitry said:
[...]
What is the memory issue?

This all discussion about encapsulation was started from creating own
methods from objects in constructor. Sure, there could be joined
objects optimization (but in real practice code, the [[Scope]]
property can be always different - can the same structure, but
different values in it, so by description, there can be no joined
objects; but, anyway, i think realizations make some optimization
anyway, but we can't say accurate as we need to analyze all the source
codes of ES-engine realizations), but every created object will have
own properties.
An own property can be be reused, regardless of its value being or not
being a function. That should be obvious and eing joined or other
speculations of implementation internal optimization doesn't even
come into the picture. It should not take more than 15 LOC to prove that.

Where is the memory issue?
 
D

Dmitry A. Soshnikov

Dmitry said:
On 24 Ñен, 16:52, Thomas 'PointedEars' Lahn <[email protected]>
wrote:
btw, the more elegant is to use just this._super() in every overloaded
method. It can be achieved by creating a new function object for child
methods with same name. In this wrapped function we set correct
this._super property (on the parent method with the same name), then
call original method, then restore original this._super and back
result of the original method.
Thus, in every child-method with the same name we can use simply
this._super(arguments), but not that long arguments.callee._super.apply
(this, arguments);

That is in fact an elegant approach, but its elegance is somewhat
crippled by a couple of well-known problems.

FYI, it is used in Prototype.js for a couple of years now (based on Alex
Arnell's work) and in Resig's implementation (inspired by Prototype.js)
-http://ejohn.org/blog/simple-javascript-inheritance/

First problem is performance. When compared to other implementations,
this one really comes in last. The fact that inherited method is
burdened with additional closure and needs to go through pre- and post-
processing just to set up proper `super` reference *on every call* is
very much noticeable (see it for yourself -http://www.broofa.com/blog/2009/02/javascript-inheritance-performance/).

Problem #2 is that to determine which method needs to be wrapped, people
often rely on *function decompilation*; for example, by checking name of
first argument (as in Prototype.js) or by sniffing function
representation for occurrence of "_super" (in Resig's implementation).

This is done with good intentions - not to wrap methods that don't need
to be wrapped (i.e. not inherited ones) - but done in inherently
unreliable manner.

Exactly for these reasons, we ditch this "elegant" approach from
Prototype.js in the near future (replacing it with something similar to
Thomas' approach - having super reference on a function object itself).

You might also be interested in this post
(http://blog.niftysnippets.org/2009/09/simple-efficient-supercalls-in....)

[...]

Yes, thanks, I know about that, I sure understand performance issue.
But regarding human development it's really easier to write |this.super
()| than e.g. in ExtJS approach - that long - |
Ext.MyNamespace.MyModule.MyClass.supperclass.constructor.call(this)| -
and all the code in ExtJS is penetrated with that long lines (yeah,
influence of Java Swing is appreciable in all that framework).

About the "elegance", sure it's only for the human's "conversation"
with the code. That's like in Ruby which is not so good by performance
(expect maybe version 1.9.*) if to compare with other realizations of
the same features, but it provides some useful *syntactic sugar* to
write less as |this._super()| and the price for that - is performance.

And all the issues you mentioned above and links gave, yeah, thanks, I
know about that and saw it before. And approach with
ConstructorName.super.prototype.methodName.call(this); is also well
known for me (more than I use it myself, and elegance of "this._super
()" have mentioned just to show alternative, and in human development
- this is really more useful than that long lines).
 
D

Dmitry A. Soshnikov

Dmitry said:
Stefan Weiss wrote:
On 23/09/09 18:30, Dmitry A. Soshnikov wrote:
Now checkSlices() is accessible to any user of my Sandwich. I'd rather
[...]




And if there's no this *sugar* as private and protected,
keeping in mind that "that's not allowed" and maybe using some naming
conventions as underscore - is quite good encapsulation. At least,
you'll not eat much memory.
I agree, it's good enough. And I'm aware of the memory issue.
What is the memory issue?
This all discussion about encapsulation was started from creating own
methods from objects in constructor. Sure, there could be joined
objects optimization (but in real practice code, the [[Scope]]
property can be always different - can the same structure, but
different values in it, so by description, there can be no joined
objects; but, anyway, i think realizations make some optimization
anyway, but we can't say accurate as we need to analyze all the source
codes of ES-engine realizations), but every created object will have
own properties.

An own property can be be reused, regardless of its value being or not
being a function. That should be obvious and eing joined or other
speculations of implementation internal optimization doesn't even
come into the picture. It should not take more than 15 LOC to prove that.

Where is the memory issue?
[...]

And to what here it? What's the big sense regarding that in one case:
(a) every object will have own function-object (k, let's leave joined
objects optimization) and in other case: (b) will be delegation to
prototype to get the missed own property? In first case it will be |n|
function objects for |n| object, in the second one - 1 function object
for |n| objects.
 
G

Garrett Smith

Dmitry said:
Dmitry said:
Stefan Weiss wrote:
On 23/09/09 18:30, Dmitry A. Soshnikov wrote:
Now checkSlices() is accessible to any user of my Sandwich. I'd rather [...]





And if there's no this *sugar* as private and protected,
keeping in mind that "that's not allowed" and maybe using some naming
conventions as underscore - is quite good encapsulation. At least,
you'll not eat much memory.
I agree, it's good enough. And I'm aware of the memory issue.
What is the memory issue?
This all discussion about encapsulation was started from creating own
methods from objects in constructor. Sure, there could be joined
objects optimization (but in real practice code, the [[Scope]]
property can be always different - can the same structure, but
different values in it, so by description, there can be no joined
objects; but, anyway, i think realizations make some optimization
anyway, but we can't say accurate as we need to analyze all the source
codes of ES-engine realizations), but every created object will have
own properties.
An own property can be be reused, regardless of its value being or not
being a function. That should be obvious and eing joined or other
speculations of implementation internal optimization doesn't even
come into the picture. It should not take more than 15 LOC to prove that.

Where is the memory issue?
[...]

And to what here it? What's the big sense regarding that in one case:
(a) every object will have own function-object (k, let's leave joined
objects optimization) and in other case: (b) will be delegation to
prototype to get the missed own property? In first case it will be |n|
function objects for |n| object, in the second one - 1 function object
for |n| objects.

This can be shown to be false by showing a case where, in your theory, n
!= n.

1) create a function m.
2) create an object o with a property m with value m (Result(1))
3) create an object o2 with a property m with value m (Result(1))

This will result in creation of 1 function object and 2 objects. Next:
4) Compare o.m and o2.m using ===.
5) compare o and o2 using ===.

Result(4) is true and Result(5) is false. What does that show? It shows
that two objects were created and one function object created.
 
D

Dmitry A. Soshnikov

Dmitry said:
Dmitry A. Soshnikov wrote:
Stefan Weiss wrote:
On 23/09/09 18:30, Dmitry A. Soshnikov wrote:
Now checkSlices() is accessible to any user of my Sandwich. I'd rather
[...]
And if there's no this *sugar* as private and protected,
keeping in mind that "that's not allowed" and maybe using some naming
conventions as underscore - is quite good encapsulation. At least,
you'll not eat much memory.
I agree, it's good enough. And I'm aware of the memory issue.
What is the memory issue?
This all discussion about encapsulation was started from creating own
methods from objects in constructor. Sure, there could be joined
objects optimization (but in real practice code, the [[Scope]]
property can be always different - can the same structure, but
different values in it, so by description, there can be no joined
objects; but, anyway, i think realizations make some optimization
anyway, but we can't say accurate as we need to analyze all the source
codes of ES-engine realizations), but every created object will have
own properties.
An own property can be be reused, regardless of its value being or not
being a function. That should be obvious and eing joined or other
speculations of implementation internal optimization doesn't even
come into the picture. It should not take more than 15 LOC to prove that.
Where is the memory issue?

And to what here it? What's the big sense regarding that in one case:
(a) every object will have own function-object (k, let's leave joined
objects optimization) and in other case: (b) will be delegation to
prototype to get the missed own property? In first case it will be |n|
function objects for |n| object, in the second one - 1 function object
for |n| objects.

This can be shown to be false by showing a case where, in your theory, n
!= n.

1) create a function m.
2) create an object o with a property m with value m (Result(1))
3) create an object o2 with a property m with value m (Result(1))

This will result in creation of 1 function object and 2 objects. Next:
4) Compare o.m and o2.m using ===.
5) compare o and o2 using ===.

Result(4) is true and Result(5) is false. What does that show? It shows
that two objects were created and one function object created.

Yeah, sure, that's true. But you're speaking about speculation of my
words, but make speculation yourself ;) Of course if to make binding
to the same object from out of scope. I remind - we were talking about
creating methods in *constructor* to achieve the main goal - *pseudo-
encapsulation* - to have the access to the closured data which are in
the [[Scope]] of the functions, created inside.

But in example mentioned by you, all this stuff with *pseudo-
encapsulation* is not taking the place, you're talking about
completely different thing.

Yes, sure:

function a() {}
function OurConstruct() {
this.test = a;
}

var a = new OurConstruct();
var b = new OurConstruct();
alert(a.test === b.test); // true

But this is *not* the thing we were talking about - this out of |
OurConstruct| scope function |a| makes no sense in theme of *pseudo-
encapsulation*, from which we've started the topic about memory issue.

More than, |a| and |b| will have own properties anyway.

But about the optimization with joined objects: if the [[Scope]] of
the inner functions will be identical, realization can create *joined*
function object reuse *the same* function object. For example:

function OurConstruct() {
var a = 100;
this.test = function () {
alert(a);
};
}

var a = new OurConstruct();
var b = new OurConstruct();

In here |a.test| and |b.test| have identical [[Scope]] internal
property - identical by *structure* and by the *state*, which means
that could be the *same* function objects. But we can't say accurate,
as it's just *suggestion* of the spec, but not the requirement*. More
than, spec says:

-- If objects O and P are joined, they compare as == and === to each
other. -- (13.1.2)

-- In practice it's likely to be productive to join two Function
objects only in the cases where an
implementation can prove that the *differences between their [[Scope]]
* properties are *not observable*, so
one object can be reused. -- (13.2)

But in practice we don't see it:

alert(a.test == b.test); // false
alert(a.test === b.test); // false

P.S.> I'm not completely sure, but new draft provides a [
Code:
]
internal property, which I suppose can be *reused* in case of
immutable function body (e.g. Function Declaration (FD) or Function
Expression (FE), but not the function created via constructor Function
as its body is dynamic and mutable).

I think it will be like in Python now (sorry, if you don't know the
Python's syntax, but actually it doesn't matter, I'll show the same
example as in ECMAScript):

class A(object):

def test(self):
pass

a = A()
b = A()

a.test == b.test # False.

False. But does it mean we have two different function objects? Nope,
but we have two different *method* objects (which are much smaller,
than function object - they just have binding of |self|-value (it's |
this|-value in ES) and other stuff, but methods *reuse* the *same*
function body):

a.test.__func__ == b.test.__func__ # True

Where |__funct__| property - is the function object joined with two
small method objects. More than, function objects themselves have the |
__code__| properties which are also equal:

a.test.__func__.__code__ == b.test.__func__.__code__ # True

So, I suppose, in the ES5 will be the same approach. And now, in ES3,
optimization with joined object maybe makes similar operations.

/ds
 
D

Dmitry A. Soshnikov

On Oct 2, 11:35 am, "Dmitry A. Soshnikov" <[email protected]>
wrote:
[...]
But about the optimization with joined objects: if the [[Scope]] of
the inner functions will be identical, realization can create *joined*
function object reuse *the same* function object. For example:
^^^^^^^^^^^^
This above should be read: "create *joined* function object OR reuse
*the same*"
 
G

Garrett Smith

Stefan said:
Stefan Weiss wrote:
[...]

[...]

This is an interesting pattern. I'll have to experiment with it some more.

It is interesting! I was really happy when I figured this one out.

Prototype is created after an object is created. If no prototype is
created then none of the methods in the prototype are created.

An object can be created on a bubbled event, lazily.
Out of curiosity, is there a reason why you don't return the
SandwichBuilderFactory directly from the anonymous function?

var SandwichBuilderFactory = (function() {
//...
return createFactory(SandwichBuilder, createSandwichPrototype);
})();

Probably out of habit.
F is probably no longer required when the function receives the
constructor as an argument.

For this function, yes. The code was borrowed from APE.createFactory,
which uses a newApply. When I was trying to explain the factory, I
wanted to simplify the example. I first considered to use a newApply
inline, but then decided to explain the function without newApply.
[snip]
The |create| method gets an object from any one place in the code. The
first time the object is gotten, the constructor is called. The second
time it is gotten, the constructor is not called. Since the object is
identified by the |id|, that means the following:-

var pbj = SandwichBuilderFactory.create("pbj", 0);
pbj = SandwichBuilderFactory.create("pbj", 200);

would result in pbj.calories === 0.

Which makes it more than just a factory (maybe a mix between a factory
and a registry).

Yes, an Abstract Factory with a Registry.

This is useful when the program needs an adapter based on an element.
The Adapter's ID matches the HTML Element's ID.

I know that both are required sometimes, but I'm not
sure I'd want them in the same function; or at least I'd probably name
the function something else than "createFactory". This had me confused
for a while when I first looked over your example.

What else to call it?
Another unexpected turn was that although a SandwichPrototype is used,
each new object gets a fresh prototype object; the prototypes don't
share any properties.

No, that is not true; the prototype is created only once. The prototype
also gets some static hidden functions/properties.

SandwichBuilderFactory.create("pbj", 3).add ===
SandwichBuilderFactory.create("cheese", 3).add;

is true.

There /is/ a bug in the code, though it is not the one you mention. I'd
like to explain that. The createPrototype function is called *once* only.

function createFactory(constr, createPrototype){
// Local hidden instances, available to nested "create" function.
// This variable serves as a Registry but also as a flag. It
// is initually undefined and does not get initialized until
// the Registry is created.
var instances;

// constructor function
function F(){}

return {create:create};
function create(id) {
var instance;
// If "instances" is undefined, that means we've not called
// createPrototype.
if(!instances) {
instances = {};
if(typeof createPrototype == "function") {
constr.prototype = createPrototype();
}
}

// This fixes a bug in the previous example.
return instances[id] || (instances[id] = new constr(id));
}
}
This sounds interesting, could I ask you for a short example?

Yeah. My Calendar, Draggable, Scroller, Placeholder all use it.
APE.createFactory uses a newApply:
http://github.com/GarrettS/ape-javascript-library/blob/master/build/APE.js
/** Creates a Factory method out of a function.
* @param {Function} constructor
* @param {Function} createPrototype function to lazily create the
* prototype.
* @memberOf APE
*/
function createFactory(ctor, createPrototype) {
return{
getById : getOrCreate,
getByNode : getOrCreate
};

function getOrCreate(id) {
if(typeof id.id === "string") {
// Modifying - id - modifies the arguments object;
// but not in poor Safari 2.x.
id = arguments[0] = getId(ctor, id);
}
var instances = this[INSTANCES];
if(!instances) {
instances = this[INSTANCES] = {};
if(typeof createPrototype === "function") {
ctor[PROTOTYPE] = createPrototype();
}
}
return instances[id] ||
(instances[id] = newApply(ctor, arguments));
}
}

Here is Calendar:
http://github.com/GarrettS/ape-javascript-library/blob/master/build/widget/Calendar/Calendar.js

The source code call to createFactory:
APE.createFactory(Calendar, createCalendarPrototype);

The Constructor:
function Calendar( id ) {
this.id = id;
if(IS_NATIVE) return;
readDateFromInput(this);
this.initEvents();
}

The implementation of that looks like:
APE.widget.Calendar.getById( "start" );

Here is an example:
http://dhtmlkitchen.com/ape/example/widget/calendar/

The implementation there uses onload to initialize the calendars.
Instead, it could use a delegated focus event. I need to write an
adapter for that.
cheers,
stefan

BTW - Thanks for help on c.l.java. I didn't get round to fixing the
performance issues yet.
 

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

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top