On Dec 24, 2010, at 8:44 PM, Garrett Smith wrote:

> On 12/24/10, fernando trasvina <trasv...@gmail.com> wrote:
>> 
>> On Dec 24, 2010, at 6:43 PM, Garrett Smith wrote:
>> 
>>> On 12/24/10, Michael Haufe (TNO) <t...@thenewobjective.com> wrote:
>>>> On Dec 24, 3:05 pm, Garrett Smith <dhtmlkitc...@gmail.com> wrote:
>>>> 
>>>>> I rather have it one way or the other. e.g.
>>>>> 
>>>>> makePoint(x, y);
>>>>> 
>>>>> - OR -
>>>>> 
>>>>> new Point(x, y);
>>>>> 
>>>>> I just don't like seeing any extra if/else in the code. I also don't
>>>>> want to handle the case where somebody might be relying on an anomaly
>>>>> of calling the constructor as a function call.
>>>> 
>>>> If defensive programming isn't necessary, of course. But since JS
>>>> can't statically enforce such things it may be necessary to do so.
>>>> 
>>> If a factory is used, then that's irrelevant. Toy example:
>>> 
>>> function getAPoint(x, y) {
>>> 
>>> }
>>> The worst the client could do would be to use `new getAPoint`. That
>>> would be a problem if the API expects `this` to be global object.
>>> 
>>> Methods can be shared in scope, but the x and y properties can be
>>> instance properties.
>>> 
>>> function getAPoint(x, y) {
>>> function distanceFromOrigin() {
>>>   return Math.sqrt((this.x * this.x) + (this.y * this.y));
>>> }
>>> getAPoint = function(x, y) {
>>>   return {
>>>     x : x,
>>>     y : y,
>>>     distanceFromOrigin: distanceFromOrigin
>>>   };
>>> };
>>> return getAPoint(x, y);
>>> }
>>> getAPoint(4, 0).distanceFromOrigin();
>> 
>> I would say that coding this way should not be done unless there is an
>> extreme requirement for it.
>>> 
>>> The downside to that is `distanceFromOrigin` is hanging off the VO, so
>>> it looks like a private static method, so what is `this`?
>>> 
>>> It might be OK to "leak" a little implementation detail in this case:
>>> 
>>> function getAPoint(x, y) {
>>> function Point(x, y) {
>>>   this.x = +x;
>>>   this.y = +y;
>>> }
>>> Point.prototype = {
>>>   distanceFromOrigin : function() {
>>>     return Math.sqrt((this.x * this.x) + (this.y * this.y));
>>>   }
>>> };
>>> 
>>> getAPoint = function(x, y) {
>>>   return new Point(x, y);
>>> };
>>> 
>>> return getAPoint(x, y);
>>> }
>> 
>> this should be done this way. you should not be defining the constructor
>> function every time you run your factory,
> 
> You're making a statement about the code that is false. The example
> uses a technique that is known as "function rewriting" or "russian
> doll" or I've explained it with more elaboration below.
> 
> this what is
>> really doing is creating a new constructor function every time and building
>> an instance for it completely useless because because
>> then how would you do instanceof? never put this type of closures for
>> factories unless really needed.
>> 
> 
> Your conclusion follows your analysis, which unfortunately is
> incorrect. Please see my explanation below.
> 
>> var Point = function(){};
>> 
>> var getAPoint = function(x,y){
>>      return new Point(x,y);
>> }
>> 
> What's missing from that example?
    are you making up a point of a rhetorical question in here? nothing is 
missing, you can run the code and get an instance of Point

please run it and you will se that this is correct

alert (getAPoint(1,2) instanceof Point);

it is pointless to write the implementation of Point because it is not needed 
to probe that the resultant object is correct.

> 
> Here is my explanation:
>>> 
>>> The Point constructor is cached on the VO of the outer getAPoint.
>>> Outer getAPoint identifier gets assigned to inner getAPoint identifier
>>> but the scope chain of the inner getAPoint function has the Point
>>> constructor and prototype.

OMG lectures again?

just run your code

function getAPoint(x, y) {
function Point(x, y) {
  this.x = +x;
  this.y = +y;
}
Point.prototype = {
  distanceFromOrigin : function() {
    return Math.sqrt((this.x * this.x) + (this.y * this.y));
  }
};

getAPoint = function(x, y) {
  return new Point(x, y);
};

return getAPoint(x, y);
}

console.log(getAPoint(1,2)) //Object { x=1, y=2}
console.log(getAPoint(1,2) instanceof Point) //false

please check that you so called function rewriting is accomplished by returning 
tthe execution of inner getPoint which results always in an instance of inner 
Point, which is useless for introspection.

>>> 
> 
> That's my explanation. VO = "Variable Object".
> 
> I've added two alerts and some explanatory comments. Generally, I
> would not want to see such comments cluttering up the code but I added
> them to help explain how the code works.
> 
> The following example has two alerts: one in the outer "getAPoint"
> function and one in the inner function, which is reassigned to
> "getAPoint". Only the first call to getAPoint(1, 2); results in the
> `getAPoint` function being called. When that getAPoint function is
> first called, it reassigns the
> 
> function getAPoint(x, y) {
>  alert('in outer getAPoint');
>  function Point(x, y) {
>    this.x = +x;
>    this.y = +y;
>  }
>  Point.prototype = {
>    distanceFromOrigin : function() {
>      return Math.sqrt((this.x * this.x) + (this.y * this.y));
>    }
>  };
> 
> // When this statement is reached,
> // getAPoint is resolved up the scope chain
> // and assigned the value of the FunctionExpression.
> // That FunctionExpression's scope chain has Point on it,
> // and so the Point constructor can still be accessed.
>  getAPoint = function(x, y) {
>    alert("in inner getAPoint");
>    return new Point(x, y);
>  };
> 
> // This statement is called in the original getAPoint
> // function. That only happens once because the
> // previous statement changed the value of getAPoint
> // to point to the inner function.
>  return getAPoint(x, y);
> }
> 
> getAPoint(4,0); // outer alert, inner alert.
> getAPoint(4,0); // inner alert.
> 
> You can see that the outer function is called only once. The `Point`
> constructor function is cached on the scope of the inner function.
> That's what we want here.
> 
> The caveat to this pattern is that you get caching of everything on
> the VO automatically. Be careful and set things you don't need to keep
> around null. Otherwise, you'll have memory leaks.
> 
> A common memory leak example is when the outer function creates
> elements to perform a feature test, saving those elements on the VO.
> Those identifiers are available on the scope chain of any nested
> functions. The reference to the element from that identifier can be
> broken by assinging those identifiers the value `null`.
> 
> function outer() {
>  var div = document.createElement("div");
>  function inner() {
>    // alert(div); // Its available on the scope chain
>  }
>  outer = inner;
>  return inner();
> }
> 
> That memory leak of `div` can be fixed by either setting `div` to null
> or by declaring `div` inside a function that doesn't expose any nested
> functions (so that `div` can be GC'd when that function completes).
> 
> [snipped signatures]
> -- 
> Garrett
> 
> -- 
> To view archived discussions from the original JSMentors Mailman list: 
> http://www.mail-archive.com/jsmentors@jsmentors.com/
> 
> To search via a non-Google archive, visit here: 
> http://www.mail-archive.com/jsmentors@googlegroups.com/
> 
> To unsubscribe from this group, send email to
> jsmentors+unsubscr...@googlegroups.com

-- 
To view archived discussions from the original JSMentors Mailman list: 
http://www.mail-archive.com/jsmentors@jsmentors.com/

To search via a non-Google archive, visit here: 
http://www.mail-archive.com/jsmentors@googlegroups.com/

To unsubscribe from this group, send email to
jsmentors+unsubscr...@googlegroups.com

Reply via email to