Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.javascript > #28095 > unrolled thread

What technique I use in functions?

Started byAngel Rodriguez <cimadelmundo3000@gmail.com>
First post2015-06-14 14:38 -0700
Last post2015-06-16 00:08 +0200
Articles 7 — 2 participants

Back to article view | Back to comp.lang.javascript


Contents

  What technique I use in functions? Angel Rodriguez <cimadelmundo3000@gmail.com> - 2015-06-14 14:38 -0700
    Re: What technique I use in functions? Angel Rodriguez <cimadelmundo3000@gmail.com> - 2015-06-14 18:16 -0700
      Re: What technique I use in functions? Thomas 'PointedEars' Lahn <PointedEars@web.de> - 2015-06-15 23:31 +0200
        Re: What technique I use in functions? Angel Rodriguez <cimadelmundo3000@gmail.com> - 2015-06-15 17:54 -0700
          Re: What technique I use in functions? Thomas 'PointedEars' Lahn <PointedEars@web.de> - 2015-06-16 08:49 +0200
    Re: What technique I use in functions? Thomas 'PointedEars' Lahn <PointedEars@web.de> - 2015-06-15 23:31 +0200
      Re: What technique I use in functions? Thomas 'PointedEars' Lahn <PointedEars@web.de> - 2015-06-16 00:08 +0200

#28095 — What technique I use in functions?

FromAngel Rodriguez <cimadelmundo3000@gmail.com>
Date2015-06-14 14:38 -0700
SubjectWhat technique I use in functions?
Message-ID<0714ecc6-40b5-4500-b2f6-324bf75692b6@googlegroups.com>
I'm working on a project, and I am defining my style of programming functions in javascript. With what I have studied, I have seen three methods for working with functions and I would like to know what kind of method you would use considering scalability, performance, maintenance, etc.

// METHOD 1. Only Prototyping the Methods

function a() {
  this.mySecret = 5;
  this.myOtherSecret = 7;
}
a.prototype.someThingA = function() {
  return this.mySecret + this.myOtherSecret;
}
a.prototype.someThingElseA = function() {
  return 100 + this.someThingA();
}

// METHOD 2. Prototyping and Encapsulating the Methods

function b() {
  this.mySecret = 5;
  this.myOtherSecret = 7;
}
(function() {
  this.someThingB = function() {
    return this.mySecret + this.myOtherSecret;
  }
  this.someThingElseB = function() {
    return 100 + this.someThingB();
  }
}).call(b.prototype);

// METHOD 3. Using an Object !

var myObj = {

    mySecret: 5,
    myOtherSecret: 7,
    someThing: function(){
        return this.mySecret + this.myOtherSecret;
    },
    someThingElse: function(){
        return 100 + this.someThing();  
    }
};

// Invoking the functions

var methodA = new a();
console.log( methodA.someThingElseA() );

var methodB = new b();
console.log( methodB.someThingElseB() );

console.log(myObj.someThingElse());

Thanks

[toc] | [next] | [standalone]


#28097

FromAngel Rodriguez <cimadelmundo3000@gmail.com>
Date2015-06-14 18:16 -0700
Message-ID<823162b9-b450-4b07-81bb-f5626cadd871@googlegroups.com>
In reply to#28095
Excellent !! Thanks !! I agree about the prototypes !!

[toc] | [prev] | [next] | [standalone]


#28101

FromThomas 'PointedEars' Lahn <PointedEars@web.de>
Date2015-06-15 23:31 +0200
Message-ID<8343492.rtYbBpSFQF@PointedEars.de>
In reply to#28097
Angel Rodriguez wrote:

> Excellent !! Thanks !! I agree about the prototypes !!

Do not believe everything that you read.

-- 
PointedEars
FAQ: <http://PointedEars.de/faq> | SVN: <http://PointedEars.de/wsvn/>
Twitter: @PointedEars2 | ES Matrix: <http://PointedEars.de/es-matrix>
Please do not cc me. / Bitte keine Kopien per E-Mail.

[toc] | [prev] | [next] | [standalone]


#28104

FromAngel Rodriguez <cimadelmundo3000@gmail.com>
Date2015-06-15 17:54 -0700
Message-ID<b121e191-d7c3-4327-bbe0-63429e43327b@googlegroups.com>
In reply to#28101
> > Excellent !! Thanks !! I agree about the prototypes !!
> 
> Do not believe everything that you read.
> 
> -- 

I don't !!

[toc] | [prev] | [next] | [standalone]


#28105

FromThomas 'PointedEars' Lahn <PointedEars@web.de>
Date2015-06-16 08:49 +0200
Message-ID<1947616.Fnk4fZVVHx@PointedEars.de>
In reply to#28104
Angel Rodriguez wrote:

>> > Excellent !! Thanks !! I agree about the prototypes !!
>> 
>> Do not believe everything that you read.
>> 
>> --
> 
> I don't !!

You called a very unwise approach “excellent”, you thanked the person 
presenting it for it, and you wrote that you ”agree” with it.  So there is 
strong indication that you do.

You are having the common problem of a beginner who does not have enough 
experience to judge the quality of what they are reading.  There are two 
possible mutually exclusive approaches to this problem: a) believe 
everything that you read (which evidentially you do), or get the necessary 
experience first.  One of those approaches is a recipe for disaster.

Please read the FAQ on quoting.

-- 
PointedEars
FAQ: <http://PointedEars.de/faq> | SVN: <http://PointedEars.de/wsvn/>
Twitter: @PointedEars2 | ES Matrix: <http://PointedEars.de/es-matrix>
Please do not cc me. / Bitte keine Kopien per E-Mail.

[toc] | [prev] | [next] | [standalone]


#28100

FromThomas 'PointedEars' Lahn <PointedEars@web.de>
Date2015-06-15 23:31 +0200
Message-ID<2878487.iBXhT1CByJ@PointedEars.de>
In reply to#28095
Stefan Ram wrote:

> Angel Rodriguez <cimadelmundo3000@gmail.com> writes:
>> I'm working on a project, and I am defining my style of
>> programming functions in javascript. With what I have
>> studied, I have seen three methods for working with functions
>> and I would like to know what kind of method you would use
>> considering scalability, performance, maintenance, etc.
> 
>   There are actually 28 ways to create objects in JavaScript.

In your dreams.

> […]
>   I want to define a simple counter object that has
>   a method that can count upwards by 1.

And unsurprisingly, in your infinite hubris you have managed to find and 
suggest the least compatible, most error-prone, least efficient way to do 
that.

>   JavaScript is prototype-based, not constructor-based.

Those are not exclusive concepts.  A constructor is a way to *initialize* an 
instance independent of its prototype.

>   So, we can always ignore constructors and just work
>   with the prototypes!
> 
>   I create my global prototype:
> 
> var counterPrototype = Object.create( Object.prototype );

… in an unnecessary complicated way, introducing an unnecessary dependency 
on an implementation of ECMAScript Edition 5 and later.  Any of

  var counterPrototype = {};

  var counterPrototype = new Object();

  var counterPrototype = Object();

is equivalent to that; with increasing compatibility, but actually also 
increasing error-proneness (the “Object” property can be overwritten).

>   . I add my counter method »inc« to the prototype:
> 
> Object.defineProperty
> ( counterPrototype, "inc",
>   { value: function()
>     { "use strict"; return this.v++; },
>     configurable: true,
>     enumerable: false,
>     writable: true });

Which you could have done in the first step, and a readable manner 
corresponding to anything that resembles recommended JavaScript code style, 
of course:

  var counterPrototype = Object.create(Object.prototype, {
    inc: {
      value: function () { "use strict"; return this.v++; },
      configurable: true,
      writable: true
    }
  });

whereas {enumerable: false} is the default, therefore can be omitted.

And even suppose it is supported, the "use strict" declaration serves *no* 
purpose there.  Backwards-compatible (because the string literal can be 
ignored), but overkill.

>   . I create new object from my prototype:
> 
> var newCounter = Object.create( counterPrototype );
> 
>   . It still needs a field »v« with the counter value:
> 
> Object.defineProperty
> ( newCounter, "v",
>   { value: 0, configurable: true, enumerable: true, writable: true });

Again, incompatible overkill.  The same can be achieved with

  newCounter.v = 0;

as those property attribute values are the defaults for a simple assignment.

>   . Done! I can now count:
> 
> newCounter.inc();
> 
> newCounter.inc();
> 
> newCounter.inc();

You don’t say…

>   . We have not used constructors, so »newCounter.constructor.name«
>   is »Object«.

Which, almost needless for me to say, is _not_ a good idea.  It is useful to 
be able to tell apart types of objects.  The Google V8 JavaScript console 
and Chromium Dev Tools inspector use the prototype chain to get the type, 
and the “constructor” property is an efficient way to do that in one’s own 
code:

  if (!(this instanceof this.constructor))
  {
    throw new Error("Method called on incompatible object");
  }

It is also the most efficient, most refactoring-friendly way to clone an 
object –

  return new this.constructor(this);

– or to access "static", non-inherited properties shared among all instances 
in prototype or instance methods:

  this.constructor.foo

>   If you often create objects in this manner, of course, you can
>   put some parts of the above into a library, so that you then can
>   create objects in this way even more easily.

More overkill.

>   Advantages of this method: You have more control of the details.
>   For example, instead of »Object.prototyp« above, I could have
>   used »null«. Everything above would still work, but now
>   »newCounter.constructor.name« would be undefined. And at some of
>   the places above I could have used other values for »configurable«,
>   »enumerable« or »writable«.

Object.create(null) is primarily useful for *data* objects as they would be 
missing the .toString() and .valueOf() methods inherited from 
Object.prototype by default.

-- 
PointedEars
FAQ: <http://PointedEars.de/faq> | SVN: <http://PointedEars.de/wsvn/>
Twitter: @PointedEars2 | ES Matrix: <http://PointedEars.de/es-matrix>
Please do not cc me. / Bitte keine Kopien per E-Mail.

[toc] | [prev] | [next] | [standalone]


#28102

FromThomas 'PointedEars' Lahn <PointedEars@web.de>
Date2015-06-16 00:08 +0200
Message-ID<2007292.BycLjHjpcD@PointedEars.de>
In reply to#28100
Thomas 'PointedEars' Lahn wrote:

> Stefan Ram wrote:
>>   . We have not used constructors, so »newCounter.constructor.name«
>>   is »Object«.

Only partially true.  Historically, Function instances as the one referred 
by “newCounter.constructor” did not have a “name” property per 
Specification.  This property was implementation-dependent, namely it had 
been introduced as a feature of Netscape JavaScript that was later 
implemented in Mozilla JavaScript, Opera ECMAScript, and Google V8 
JavaScript as well; but according to test results not, for example, in 
Microsoft JScript:

<http://PointedEars.de/es-matrix/?filter=Function.prototype.name>

This is going to change with ECMAScript Edition 6/2015 where the “name” 
property of Function instances is specified (section 19.2.4.2 of the final 
draft).

> Which, almost needless for me to say, is _not_ a good idea.  It is useful
> to be able to tell apart types of objects.  The Google V8 JavaScript 
> console and Chromium Dev Tools inspector use the prototype chain to get 
> the type, and the “constructor” property is an efficient way to do that in 
> one’s own code:
> 
>   if (!(this instanceof this.constructor))
>   {
>     throw new Error("Method called on incompatible object");
>   }

This particular suggestion is not completely wrong, but may be misleading.  
Usually 

  (this instanceof this.constructor) === true

so you cannot use that to test the object type /per se/.  In an instance or 
prototype method you would need a closure to hold a reference to the 
original constructor.  I thought it would work for (i.e., exclude) data 
objects (“Object.create(null))”), but in Chromium:

| >>> Foo.prototype.bar.call(Object.create(null))
| Uncaught TypeError: Expecting a function in instanceof check, but got 
| undefined
|   at Foo.bar (<anonymous>:2:80)
|   at <anonymous>:2:19
|   at Object.InjectedScript._evaluateOn (<anonymous>:895:140)
|   at Object.InjectedScript._evaluateAndWrap (<anonymous>:828:34)
|   at Object.InjectedScript.evaluate (<anonymous>:694:21)

This is probably due to section “12.9.4 Runtime Semantics: 
InstanceofOperator(O, C)” in the ES6/2015 final draft, and corresponding 
sections in earlier Editions.

The remedy appears to be

  if (!(this.constructor && this instanceof this.constructor))

and for strict mode

  if (!(this && this.constructor && this instanceof this.constructor))

But again, this would only prevent execution with data objects or objects 
where the constructor property has been modified inappropriately.

Also, TypeError is the more appropriate exception type here, although it 
appears to be a good idea to define one’s own exception type for this case.

-- 
PointedEars
FAQ: <http://PointedEars.de/faq> | SVN: <http://PointedEars.de/wsvn/>
Twitter: @PointedEars2 | ES Matrix: <http://PointedEars.de/es-matrix>
Please do not cc me. / Bitte keine Kopien per E-Mail.

[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.javascript


csiph-web