www.webdeveloper.com
Page 2 of 2 FirstFirst 12
Results 16 to 19 of 19

Thread: Best way to create a reusable object/class

  1. #16
    Join Date
    Jan 2007
    Location
    Wisconsin
    Posts
    2,120
    @rnd_me

    I understand your points, but they're not terribly relevant. This is a question of efficiency and memory footprint. If you absolutely need closure, you'll obviously use a syntax that provides closure. Otherwise you need to balance between maintainability (self-documenting, well-organized code) and efficiency. Most modern language do a great job of making things things the same. But even then, as is the case with JavaScript, there are nuances that have a clear edge.

    Whether those edges are noticeable when they account for less than 1% of your execution time ... ?

    keep in mind that there is a higher property-name resolution cost on prototypes than there is on own properties. If a prototype get chained 2 or 3 (or 20) levels deeps, there's a lot of potentials to strike off the list before the correct prototype appears.
    An interesting concern. I'm not 100% sure it's valid though. Even in a true OOP language, I would expect most compilers to stuff a reference to the most relevant versions of a method directly in the end-class. And, since JavaScript has no implicit mechanism for inheritance, I'm not sure how this would prototype chain would occur unless you explicitly built it.

    Could you show us what inheritance pattern(s) lead to this sort of prototype chaining? I'd be interested to benchmark it.
    Jon Wire

    thepointless.com | rounded corner generator

    I agree with Apple. Flash is just terrible.

    Use CODE tags!

  2. #17
    Join Date
    Jan 2007
    Location
    Wisconsin
    Posts
    2,120
    This syntax is actually not bad from an organizational standpoint, and it uses the prototype without the help of a library.

    var MyClass = function() {};
    MyClass.prototype = {
    constructor: function(p) {
    this.p = p || 123;
    },

    add: function(a) {
    return this.p + a;
    },

    subtract: function(a) {
    return this.p - a;
    }
    }
    Still left to figure out a mechanism for inheritance ...
    Jon Wire

    thepointless.com | rounded corner generator

    I agree with Apple. Flash is just terrible.

    Use CODE tags!

  3. #18
    Join Date
    Jul 2008
    Location
    urbana, il
    Posts
    2,787
    Quote Originally Posted by svidgen View Post
    And, since JavaScript has no implicit mechanism for inheritance, I'm not sure how this would prototype chain would occur unless you explicitly built it.

    does prototypal inheritance not count in your book or what did you mean to say instead? it also has lexical inheritance for inner functions, complete with closure. i'd call that pretty good support for inheritance myself, but i guess we all have opinions...
    the chain it the game, it's one of the first things JavaScripts learn. my tagline for years has been "working on the chain..."; the prototype chain. i guess that one went over your head.. maybe i should be more humanistic, or stop trying to be funny; it often fails.


    Quote Originally Posted by svidgen View Post
    Could you show us what inheritance pattern(s) lead to this sort of prototype chaining? I'd be interested to benchmark it.
    sure. basic javascript tutorials offer a very common inheritance chain pattern:

    Code:
    function life(){
     this.alive=true;
     this.die=function(){this.alive=false;}
    }
    
    function mammal(){
     this.hair=true;
    }mammal.prototype=new life;
    
    
    function human(){
     this.thumb=true;
    }human.prototype=new mammal;
    
    
    bob=new human;
    alert(bob.alive)

    for bob.alive to not be undefined, it had to check:
    Code:
    bob.own
    human.proto
    mammal.proto
    life.proto

    compare the chain for
    Code:
     bob.die
    vs
    Code:
     methods:{die: function die(){this.alive=false}}; methods.die.call(bob)
    there, we jump right to methods.own, no prorotype hopping required. so it is faster.

    i'd bet your test would flush out the theory, given a sufficient production testing environment and not just a simple loop-based bench mark that JIT and tracing cheats at...


    so, bob can build faster without prototype (as your testing confirmed), it uses less memory to not have the die method on any instances, and if the bundled pure function avoids other-wise present closures, it's sure to execute faster as well...
    Last edited by rnd me; 07-06-2011 at 03:24 PM.

  4. #19
    Join Date
    Jan 2007
    Location
    Wisconsin
    Posts
    2,120
    This is starting to detract from my focus at work ...

    Remember that part of the issue is writing clear, well organized code. Jeff's claim is that you can accomplish this without sacrificing on performance. Also, your final example (method:{ ... }), while it would seem to provide the most efficient solution, actually benchmarks poorly on method calls -- a 15.5% hit (possibly because all your method calls go through call() or apply()). And more importantly, it doesn't lend itself well to well-organized, maintainable code, in my opinion.

    I would actually argue that it's messier than just using the prototypes -- which actually benchmarked on par with local methods. If you read up, you'll see that it's object instantiation that suffers the big hit without prototyping (twice as long to create SIMPLE objects). The only issue noted with local methods is the risk of flooding the memory, which could eventually cause paging, crashes, or nasty messages about runaway scripts.

    i'd bet your test would flush out the theory, given a sufficient production testing environment and not just a simple loop-based bench mark that JIT and tracing cheats at...
    While you need to be careful to consider the effects of the benchmark's simplicity and take it with a grain of salt, using something more complicated than a loop can "covertly" introduce unforeseen bias, which may ultimately never be noticed in the benchmark analysis. That said, the simplistic benchmark is more likely to reveal a difference with an identifiable source. However, a more complex benchmark, such testing component variation A vs B in product X will reveal how each will actually perform in X. But, if A and B will each require a great deal of work to hack in (such as changing the entire manner in which you deal with Classes/objects), it seems best to me to have the results from an over-simplistic benchmark to set me in the presumably more efficient and maintainable direction.

    I also ran another very quick benchmark to local variable access versus one several steps up the prototype chain. The difference isn't detectable within the first million calls. Ramping the test up to 5 million calls made it detectable, but it's only about a 0.1% loss for using elements from a prototype 3 links up the chain. Validation that you could see significant efficiency concerns if you have a very long prototype chain (I wouldn't expect to see any real impact before 20 or 30 ancestors are in play). It's a negligible difference for most of us--and very likely offset by the memory footprint concerns at that point where it becomes a concern.

    so, bob can build faster without prototype (as your testing confirmed)
    Opposite of that. Bob builds much faster with prototype. Over 2 times faster with simple classes. Likely more than 2 time faster with larger classes. No property copying required. And presumably very little memory allocation required.

    And back to the beginning ...
    does prototypal inheritance not count in your book or what did you mean to say instead?
    OK. Prototypes provide some inheritance. But, it's really a stretch to equate it with more common notions of inheritance. It doesn't provide clean access to base/super methods.

    So, the OP is about efficiency. The most efficient solution, to the extent that I have been able to benchmark, is to use prototypes "properly." The biggest performance difference is in object instantiation, wherein the gap STARTS and around 100% difference for simple classes. (It presumably widens as the classes become more complex.) Helper libraries and techniques can introduce some efficiency hits; however, they can also offer much cleaner looking code while saving the BIG 100+% object instantiation and memory footprint hits. And they can also offer mechanisms that are otherwise unnatural, such as this.method() containing a call to this.$super.method()--moot point if those sorts of "normal" inheritance mechanisms aren't required.
    Jon Wire

    thepointless.com | rounded corner generator

    I agree with Apple. Flash is just terrible.

    Use CODE tags!

Thread Information

Users Browsing this Thread

There are currently 1 users browsing this thread. (0 members and 1 guests)

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
HTML5 Development Center



Recent Articles